4. MTK 平台双喇叭实现

 

  

 

MTK 平台双喇叭实现

当前V618上使用的双喇叭接法是:

(1)       听筒的声音从PMU MT6328的AU_HPL和AU_HPR输出到图(1)的外置功放1,由AUDIO_EN1控制外置功放1的使能,然后经由外置功放1输出到SPK_P1和SPK_N1,最后输出到喇叭1上;

(2)       媒体音乐的声音从PMU MT6328的AU_HPL和AU_HPR输出到图(1)和图(2)的外置功放1和外置功放2,由AUDIO_EN1控制外置功放1的使能并且由CTRL1控制外置功放2的使能,然后经由外置功放1输出到SPK_P1和SPK_N1并且经由外置功放2输出到SPK_P和SPK_N,最后输出到喇叭1和喇叭2上;

 

图(1)

 

图(2)

也就是说,喇叭1既做听筒用又做喇叭用,喇叭2只做喇叭用。做听筒用时只控制AUDIO_EN1,做媒体音乐输出时要控制AUDIO_EN1和CTRL1,这和v118上只有一个喇叭既做听筒用又做喇叭用的控制稍有不同,v118上只有一个功放,做听筒和做媒体音乐输出时使能功放即可。

软件实现

(一)   通过audio ALSA架构的kcontrol方式,实现喇叭1的功放AUDIO_EN1使能,实现听筒的声音输出

37_n_base\update\alps\vendor\mediatek\proprietary\hardware\audio\mt6735\aud_drv\AudioALSAHardwareResourceManager.cpp

status_t AudioALSAHardwareResourceManager::OpenReceiverPath(const uint32_t SampleRate __unused)

{

             #ifndef KST_AUDIO_SUPPORT_2IN1_SPEAKER

                            mDeviceConfigManager->ApplyDeviceTurnonSequenceByName(AUDIO_DEVICE_RECEIVER);

        #else

                            mDeviceConfigManager->ApplyDeviceTurnonSequenceByName(AUDIO_DEVICE_HEADPHONE);

                            #ifdef KST_TWO_SPEAKER

                            mDeviceConfigManager->ApplyDeviceTurnonSequenceByName(AUDIO_DEVICE_RECEIVER_SPEAKER);

                            #else

                       mDeviceConfigManager->ApplyDeviceTurnonSequenceByName(AUDIO_DEVICE_EXT_SPEAKER);

                            #endif

             #endif

}

status_t AudioALSAHardwareResourceManager::CloseReceiverPath()

{

             #ifndef KST_AUDIO_SUPPORT_2IN1_SPEAKER

                            mDeviceConfigManager->ApplyDeviceTurnoffSequenceByName(AUDIO_DEVICE_RECEIVER);

        #else

                            #ifdef KST_TWO_SPEAKER

                            mDeviceConfigManager->ApplyDeviceTurnoffSequenceByName(AUDIO_DEVICE_RECEIVER_SPEAKER);

                            #else

                            mDeviceConfigManager->ApplyDeviceTurnoffSequenceByName(AUDIO_DEVICE_EXT_SPEAKER);

                            #endif

                       mDeviceConfigManager->ApplyDeviceTurnoffSequenceByName(AUDIO_DEVICE_HEADPHONE);

             #endif

}

 

37_n_base\update\alps\vendor\mediatek\proprietary\hardware\audio\common\V3\include\AudioALSADeviceConfigManager.h

#define AUDIO_DEVICE_HEADPHONE           "headphone_output"

#define AUDIO_DEVICE_RECEIVER_SPEAKER         "receiver_speaker_output"

 

37_n_base\update\alps\device\mediatek\mt6735\audio_device.xml

<!--headphone output-->

    <path name="headphone_output" value="turnon">

        <kctl name="Audio_Amp_R_Switch" value="On" />

        <kctl name="Audio_Amp_L_Switch" value="On" />

    </path>

    <path name="headphone_output" value="turnoff"> 

        <kctl name="Audio_Amp_R_Switch" value="Off" />

        <kctl name="Audio_Amp_L_Switch" value="Off" />     

</path>

...

<!--receiver_speaker output-->

<path name="receiver_speaker_output" value="turnon">

        <kctl name="Receiver_Speaker_Switch" value="On" />

    </path>

    <path name="receiver_speaker_output" value="turnoff">

        <kctl name="Receiver_Speaker_Switch" value="Off" />

</path>

 

37_n_base\update\alps\kernel-3.18\sound\soc\mediatek\mt_soc_audio_v3\mt_soc_codec_63xx.c

static const struct snd_kcontrol_new mt6331_snd_controls[] = {

         SOC_ENUM_EXT("Audio_Amp_R_Switch", Audio_DL_Enum[0], Audio_AmpR_Get, Audio_AmpR_Set),

         SOC_ENUM_EXT("Audio_Amp_L_Switch", Audio_DL_Enum[1], Audio_AmpL_Get, Audio_AmpL_Set),

         SOC_ENUM_EXT("Receiver_Speaker_Switch", Audio_DL_Enum[11], Receiver_Speaker_Switch_Get,

                        Receiver_Speaker_Switch_Set),

};

 

static int Audio_AmpR_Set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)

{

         mutex_lock(&Ana_Ctrl_Mutex);

 

         pr_warn("%s()\n", __func__);

         if ((ucontrol->value.integer.value[0] == true)

             && (mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_HEADSETR] == false)) {

                   Audio_Amp_Change(AUDIO_ANALOG_CHANNELS_RIGHT1, true);

                   mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_HEADSETR] =

                       ucontrol->value.integer.value[0];

         } else if ((ucontrol->value.integer.value[0] == false)

                      && (mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_HEADSETR] ==

                          true)) {

                   mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_HEADSETR] =

                       ucontrol->value.integer.value[0];

                   Audio_Amp_Change(AUDIO_ANALOG_CHANNELS_RIGHT1, false);

         }

         mutex_unlock(&Ana_Ctrl_Mutex);

         return 0;

}

 

static int Audio_AmpL_Set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)

{

         mutex_lock(&Ana_Ctrl_Mutex);

 

         pr_warn("%s() gain = %ld\n ", __func__, ucontrol->value.integer.value[0]);

         if ((ucontrol->value.integer.value[0] == true)

             && (mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_HEADSETL] == false)) {

                   Audio_Amp_Change(AUDIO_ANALOG_CHANNELS_LEFT1, true);

                   mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_HEADSETL] =

                       ucontrol->value.integer.value[0];

         } else if ((ucontrol->value.integer.value[0] == false)

                      && (mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_HEADSETL] ==

                          true)) {

                   mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_HEADSETL] =

                       ucontrol->value.integer.value[0];

                   Audio_Amp_Change(AUDIO_ANALOG_CHANNELS_LEFT1, false);

         }

         mutex_unlock(&Ana_Ctrl_Mutex);

         return 0;

}

 

static int Receiver_Speaker_Switch_Set(struct snd_kcontrol *kcontrol,

                                            struct snd_ctl_elem_value *ucontrol)

{

         pr_debug("%s()\n", __func__);

         if ((ucontrol->value.integer.value[0] == true)

             && (mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_RECEIVER_SPEAKER_SWITCH] ==

                   false)) {

                   Receiver_Speaker_Switch_Change(true);

                   mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_RECEIVER_SPEAKER_SWITCH] =

                       ucontrol->value.integer.value[0];

         } else if ((ucontrol->value.integer.value[0] == false)

                      && (mCodec_data->

                          mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_RECEIVER_SPEAKER_SWITCH] ==

                          true)) {

                   mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_RECEIVER_SPEAKER_SWITCH] =

                       ucontrol->value.integer.value[0];

                   Receiver_Speaker_Switch_Change(false);

         }

         return 0;

}

 

static void Receiver_Speaker_Switch_Change(bool enable)

{

         if (enable){

                   //printk("Receiver_Speaker_Switch_Change ON+ \n");

                   #if defined(CONFIG_KST_BOARD_V618)

                   mt_audgpio_set_gpio_receiver_speaker_switch(0);

             mt_audgpio_set_gpio_receiver_speaker_switch(1);

             mt_audgpio_set_gpio_receiver_speaker_switch(0);

             mt_audgpio_set_gpio_receiver_speaker_switch(1);

                   #else

                   mt_audgpio_set_gpio_receiver_speaker_switch(1);

                   #endif

         }

         else{

                   //printk("Receiver_Speaker_Switch_Change OFF- \n");

                   mt_audgpio_set_gpio_receiver_speaker_switch(0);

         }

}

 

int mt_audgpio_set_gpio_receiver_speaker_switch(u32 level)

{

         audgpio_get_gpio_pinctrl();

                  

         if (level == 0)

                   {

                   #ifdef CONFIG_KST_TWO_SPEAKER

                   pinctrl_select_state(audioss_pinctrl, pinctrl_audioss1_low); //对应的GPIO口在dts中配置

                   #endif

                   }

         else

                   {

                   #ifdef CONFIG_KST_TWO_SPEAKER

                   pinctrl_select_state(audioss_pinctrl, pinctrl_audioss1_high); //对应的GPIO口在dts中配置

                   #endif

                   }

         return 0; 

}

 

(二)   通过audio ALSA架构的kcontrol方式,实现两个喇叭的功放使能(即AUDIO_EN1和CTRL1使能),实现播放媒体音乐的声音输出

37_n_base\update\alps\vendor\mediatek\proprietary\hardware\audio\mt6735\aud_drv\AudioALSAHardwareResourceManager.cpp

status_t AudioALSAHardwareResourceManager::OpenSpeakerPath(const uint32_t SampleRate)

{

mDeviceConfigManager->ApplyDeviceTurnonSequenceByName(AUDIO_DEVICE_HEADPHONE);

    mDeviceConfigManager->ApplyDeviceTurnonSequenceByName(AUDIO_DEVICE_EXT_SPEAKER);

}

 

status_t  AudioALSAHardwareResourceManager::CloseSpeakerPath()

{

…    mDeviceConfigManager->ApplyDeviceTurnoffSequenceByName(AUDIO_DEVICE_EXT_SPEAKER);

    mDeviceConfigManager->ApplyDeviceTurnoffSequenceByName(AUDIO_DEVICE_HEADPHONE);

}

 

37_n_base\update\alps\vendor\mediatek\proprietary\hardware\audio\common\V3\include\AudioALSADeviceConfigManager.h

#define AUDIO_DEVICE_HEADPHONE           "headphone_output"

#define AUDIO_DEVICE_EXT_SPEAKER         "ext_speaker_output"

 

37_n_base\update\alps\device\mediatek\mt6735\audio_device.xml

<!--headphone output-->

<path name="headphone_output" value="turnon">

        <kctl name="Audio_Amp_R_Switch" value="On" />

        <kctl name="Audio_Amp_L_Switch" value="On" />

    </path>

    <path name="headphone_output" value="turnoff"> 

        <kctl name="Audio_Amp_R_Switch" value="Off" />

        <kctl name="Audio_Amp_L_Switch" value="Off" />     

</path>

<!--external_speaker output-->

<path name="ext_speaker_output" value="turnon">

        <kctl name="Ext_Speaker_Amp_Switch" value="On" />

    </path>

    <path name="ext_speaker_output" value="turnoff">

        <kctl name="Ext_Speaker_Amp_Switch" value="Off" />

</path> 

 

37_n_base\update\alps\kernel-3.18\sound\soc\mediatek\mt_soc_audio_v3\mt_soc_codec_63xx.c

Audio_Amp_R_Switch和Audio_Amp_L_Switch同上述听筒的部分,不再赘述。

Ext_Speaker_Amp_Switch的如下:

static const struct snd_kcontrol_new mt6331_snd_controls[] = {

         SOC_ENUM_EXT("Ext_Speaker_Amp_Switch", Audio_DL_Enum[11], Ext_Speaker_Amp_Get,

                        Ext_Speaker_Amp_Set),

};

 

static int Ext_Speaker_Amp_Set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)

{

         pr_debug("%s() gain = %ld\n ", __func__, ucontrol->value.integer.value[0]);

         if (ucontrol->value.integer.value[0]) {

                   Ext_Speaker_Amp_Change(true);

                   mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_EXTSPKAMP] =

                       ucontrol->value.integer.value[0];

         } else {

                   mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_EXTSPKAMP] =

                       ucontrol->value.integer.value[0];

                   Ext_Speaker_Amp_Change(false);

         }

         return 0;

}

 

static void Ext_Speaker_Amp_Change(bool enable)

{

         if (enable) {

             …

                   #if defined(CONFIG_KST_BOARD_V618)

                   mt_audgpio_set_gpio(0);

             mt_audgpio_set_gpio(1);

             mt_audgpio_set_gpio(0);

             mt_audgpio_set_gpio(1);

                   #else

                   mt_audgpio_set_gpio(1);

                   #endif

         } else {

                   …

          mt_audgpio_set_gpio(0);

                   …

         }

}

 

int mt_audgpio_set_gpio(u32 level)

{

         audgpio_get_gpio_pinctrl();

                  

         if (level == 0)

                   {

                   pinctrl_select_state(audioss_pinctrl, pinctrl_audioss0_low); //对应的GPIO口在dts中配置

                   #ifdef CONFIG_KST_TWO_SPEAKER

                   pinctrl_select_state(audioss_pinctrl, pinctrl_audioss1_low); //对应的GPIO口在dts中配置

                   #endif

                   }

         else

                   {

                   pinctrl_select_state(audioss_pinctrl, pinctrl_audioss0_high); //对应的GPIO口在dts中配置

                   #ifdef CONFIG_KST_TWO_SPEAKER

                   pinctrl_select_state(audioss_pinctrl, pinctrl_audioss1_high); //对应的GPIO口在dts中配置

                   #endif

                   }

         return 0; 

}

 

(三)   声音的调节

(1)把听筒的音频参数值调低,这样在通话的时候,喇叭1的音量就类似于听筒的音量大小,参照以下修改

--- a/update/alps/kst/drv/audio_para/v118_p3_audio_para/audio_ver1_volume_custom_default.h

+++ b/update/alps/kst/drv/audio_para/v118_p3_audio_para/audio_ver1_volume_custom_default.h

@@ -129,10 +129,10 @@

     32,48,64,80,96,112,128,144,160,176,192,208,224,255,255

 

 #define VER1_AUD_VOLUME_SPH \

-    40,60,80,100,120,130,148,0,0,0,0,0,0,0,0,\

-    40,52,64,76,88,100,112,0,0,0,0,0,0,0,0,\

-    48,60,72,84,96,108,120,0,0,0,0,0,0,0,0,\

-    40,52,64,76,88,100,112,0,0,0,0,0,0,0,0

+    10,15,20,25,30,35,40,0,0,0,0,0,0,0,0,\

+    10,15,20,25,30,35,40,0,0,0,0,0,0,0,0,\

+    100,110,120,130,140,150,160,0,0,0,0,0,0,0,0,\

+    10,15,20,25,30,35,40,0,0,0,0,0,0,0,0

 

(2)把SetReceiverGain改为SetHeadPhoneRGain和SetHeadPhoneLGain,设置听筒的改为设置HeadPhoneR和HeadPhoneL的,否则听筒的声音会时大时小。

37_n_base\update\alps\vendor\mediatek\proprietary\hardware\audio\mt6735\aud_drv\AudioALSAVolumeController.cpp

status_t AudioALSAVolumeController::ApplyVoiceGain(int degradeDb, audio_mode_t mode, uint32_t device)

{

            #ifndef KST_AUDIO_SUPPORT_2IN1_SPEAKER

            SetReceiverGain(VoiceAnalogRange);

            #else

            SetHeadPhoneRGain(VoiceAnalogRange);

            SetHeadPhoneLGain(VoiceAnalogRange);

            #endif

}

int AudioALSAVolumeController::ApplyAudioGainTuning(int Gain, uint32_t mode, uint32_t device)

{

                     #ifndef KST_AUDIO_SUPPORT_2IN1_SPEAKER

                SetReceiverGain(VoiceAnalogRange);

                #else

                SetHeadPhoneRGain(VoiceAnalogRange);

                     SetHeadPhoneLGain(VoiceAnalogRange);

                     #endif

 …

}

 

(四)   宏定义说明,请配置上下面红色字体的宏

37_n_base\update\alps\kst\make\v618_37m_hd_weiye_s8a_b1b3b5b7b8b20_8gb_1d3.mk

#主板型号及内核宏定义配置

KST_KERNEL_BOARD_CUSTOM00 = KST_BOARD_V618

KST_KERNEL_BOARD_CUSTOM01 = KST_HALL_SUPPORT

KST_KERNEL_BOARD_CUSTOM02 = KST_SUB_STROBE_SUPPORT

KST_KERNEL_BOARD_CUSTOM03 = KST_REAL_FLASH_MODE

KST_KERNEL_BOARD_CUSTOM04 = KST_DUAL_CAM_YUV

KST_KERNEL_BOARD_CUSTOM05 = KST_TWO_SPEAKER

KST_KERNEL_BOARD_CUSTOM06 =

KST_KERNEL_BOARD_CUSTOM07 =

KST_KERNEL_BOARD_CUSTOM08 =

KST_KERNEL_BOARD_CUSTOM09 =

 

#Misc 配置

KST_MISC_CUSTOM= KST_SUB_FLASH_SUPPORT KST_AUDIO_SUPPORT_2IN1_SPEAKER KST_TWO_SPEAKER

 

备注:MT6580平台的双喇叭项目,也可以参照以上方法实现。

posted @ 2017-12-15 10:33  新时代老道  阅读(2217)  评论(0)    收藏  举报