MTK 外部PA功放的驱动设置
- 使能脚的配置
一般情况下,外部功放都有一个使能脚直接控制
如这里的AUDIO_PA_EN,我们需要将这个引脚配置成GPIO输出模式
- dts配置
AUD_pins_extamp_high: audexamphigh {
pins_cmd_dat {
pins = <PINMUX_GPIO2__FUNC_GPIO2>;
slew-rate = <1>;
output-high;
};
};
AUD_pins_extamp_low: audexamplow {
pins_cmd_dat {
pins = <PINMUX_GPIO2__FUNC_GPIO2>;
slew-rate = <1>;
output-low;
};
- 内核代码的调用
sound/soc/mediatek/mt_soc_audio_v3/AudDrv_Gpio.c
int AudDrv_GPIO_EXTAMP_Select(int bEnable)
{
` int retval = 0;
if (bEnable == 1) {
if (aud_gpios[GPIO_EXTAMP_HIGH].gpio_prepare) {
retval =
pinctrl_select_state(pinctrlaud, aud_gpios[GPIO_EXTAMP_HIGH].gpioctrl);
if (retval)
pr_err("could not set aud_gpios[GPIO_EXTAMP_HIGH] pins\n");
}
} else {
if (aud_gpios[GPIO_EXTAMP_LOW].gpio_prepare) {
retval =
pinctrl_select_state(pinctrlaud, aud_gpios[GPIO_EXTAMP_LOW].gpioctrl);
if (retval)
pr_err("could not set aud_gpios[GPIO_EXTAMP_LOW] pins\n");
}
}
return retval;
}
这里Android 上层每次播放音乐的时候就会对函数AudDrv_GPIO_EXTAMP_Select传入不同的 bEnable 值,从而间接的控制了外部PA功放的使能脚.
Android的上层调用流程
/vendor/mediatek/proprietary/hardware/audio/common/V3/aud_drv/AudioALSADeviceConfigManager.cpp
里面调用AudioALSADeviceConfigManager::ApplyDeviceTurnonSequenceByName
status_t AudioALSADeviceConfigManager::ApplyDeviceTurnonSequenceByName(const char *DeviceName)
{
int count = 0;
DeviceCtlDescriptor *descriptor = GetDeviceDescriptorbyname(DeviceName);
if (descriptor == NULL)
{
ALOGE("%s DeviceName = %s descriptor == NULL", __FUNCTION__, DeviceName);
return INVALID_OPERATION;
}
ALOGD("%s() DeviceName = %s descriptor->DeviceStatusCounte = %d", __FUNCTION__, DeviceName, descriptor->DeviceStatusCounter);
if (descriptor->DeviceStatusCounter == 0)
{
for (count = 0; count < descriptor->mDeviceCltonVector.size(); count += 2)
{
String8 cltname = descriptor->mDeviceCltonVector.itemAt(count);
String8 cltvalue = descriptor->mDeviceCltonVector.itemAt(count + 1);
ALOGD("cltname = %s cltvalue = %s", cltname.string(), cltvalue.string());
if (mixer_ctl_set_enum_by_string(mixer_get_ctl_by_name(mMixer, cltname.string()), cltvalue.string()))
{
ALOGE("Error: ApplyDeviceTurnonSequence cltname.string () = %s cltvalue.string () = %s", cltname.string(), cltvalue.string());
ASSERT(false);
}
}
}
descriptor->DeviceStatusCounter++;
return NO_ERROR;
}
这里会传入
AudioALSADeviceConfigManager: cltname = Ext_Speaker_Amp_Switch cltvalue = On
并且调用mixer_ctl_set_enum_by_string
根据关键字Ext_Speaker_Amp_Switch
在内核文件kernel-3.18/sound/soc/mediatek/mt_soc_audio_v3/mt_soc_codec_63xx.c
SOC_ENUM_EXT("Ext_Speaker_Amp_Switch", Audio_DL_Enum[11], Ext_Speaker_Amp_Get, | -mt6331_snd_Speaker_controls
Ext_Speaker_Amp_Set),
与函数Ext_Speaker_Amp_Set
绑定.
static int Ext_Speaker_Amp_Set(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | -Ext_Speaker_Amp_Set(struct snd_
{ | -GetAdcStatus(void)
| GetDLNewIFFrequency(unsigned in
pr_debug("%s() gain = %ld\n ", __func__, ucontrol->value.integer.value[0]); | -GetDLStatus(void)
if (ucontrol->value.integer.value[0]) { | -GetDacStatus(void)
Ext_Speaker_Amp_Change(true); | GetULFrequency(uint32 frequency
mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_EXTSPKAMP] = | -Handset_PGA_Get(struct snd_kcon
ucontrol->value.integer.value[0]; | -Handset_PGA_Set(struct snd_kcon
} else { | -HeadsetVoloumeRestore(void)
mCodec_data->mAudio_Ana_DevicePower[AUDIO_ANALOG_DEVICE_OUT_EXTSPKAMP] = | -HeadsetVoloumeSet(void)
ucontrol->value.integer.value[0]; | -Headset_PGAL_Get(struct snd_kco
Ext_Speaker_Amp_Change(false); | -Headset_PGAL_Set(struct snd_kco
} | -Headset_PGAR_Get(struct snd_kco
return 0; | -Headset_PGAR_Set(struct snd_kco
}
继续调用AudDrv_GPIO_EXTAMP_Select
来完成对外部功放使能脚的控制.
参考:https://blog.csdn.net/carolven/article/details/79315551