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平台的双喇叭项目,也可以参照以上方法实现。
浙公网安备 33010602011771号