音频代码涉及面很广,这篇文档介绍如何封装音频控件给HAL层使用。这里以AW87519芯片调试为例进行介绍封装音频控件和使用的方法。在最初接出到高通音频基础功能调试的时候,都是从tinyalsa指令/mixer_paths文件配置开始。因为单独一个音频设备的调试,都对应一条音频链路的打通。比如以下链接上高通平台基础音频输入输出设备调试:
【Qualcomm音频】Speaker 调试记录 https://blog.csdn.net/crow_ch/article/details/103841550
【Qualcomm音频】Microphone 调试记录 https://blog.csdn.net/crow_ch/article/details/103841600
【Qualcomm音频】Headset 调试记录 https://blog.csdn.net/crow_ch/article/details/103841630
【Qualcomm音频】Receiver 调试记录 https://blog.csdn.net/crow_ch/article/details/103841646
【Qualcomm音频】Lineout 调试记录 https://blog.csdn.net/crow_ch/article/details/103841661
话不多说直接上代码,安卓7,8937平台代码
vendor/qcom/opensource/audio-kernel/asoc/msm8952.c
extern unsigned char aw87519_audio_speaker(void);
extern unsigned char aw87519_audio_off(void);
static const char *const ext_speaker_amp_function[] = { "Off", "On" };
static int ext_speaker_amp_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = aw87519_spk_control;
pr_debug("%s: aw87519_spk_control = %d\n", __func__,
aw87519_spk_control);
return 0;
}
static int ext_speaker_amp_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
if(ucontrol->value.integer.value[0] == aw87519_spk_control)
return 1;
aw87519_spk_control = ucontrol->value.integer.value[0];
if(ucontrol->value.integer.value[0]) {
aw87519_audio_speaker();
} else {
aw87519_audio_off();
}
pr_debug("%s: value.integer.value = %ld\n", __func__,
ucontrol->value.integer.value[0]);
return 0;
}
static const struct soc_enum msm_snd_enum[] = {
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_bit_format_text),
rx_bit_format_text),
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mi2s_ch_text),
mi2s_ch_text),
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(loopback_mclk_text),
loopback_mclk_text),
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(btsco_rate_text),
btsco_rate_text),
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(proxy_rx_ch_text),
proxy_rx_ch_text),
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(vi_feed_ch_text),
vi_feed_ch_text),
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mi2s_rx_sample_rate_text),
mi2s_rx_sample_rate_text),
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ext_speaker_amp_function),
ext_speaker_amp_function),
};
static const struct snd_kcontrol_new msm_snd_controls[] = {
SOC_ENUM_EXT("MI2S_RX Format", msm_snd_enum[0],
mi2s_rx_bit_format_get, mi2s_rx_bit_format_put),
SOC_ENUM_EXT("MI2S_TX Channels", msm_snd_enum[1],
msm_ter_mi2s_tx_ch_get, msm_ter_mi2s_tx_ch_put),
SOC_ENUM_EXT("MI2S_RX Channels", msm_snd_enum[1],
msm_pri_mi2s_rx_ch_get, msm_pri_mi2s_rx_ch_put),
SOC_ENUM_EXT("Loopback MCLK", msm_snd_enum[2],
loopback_mclk_get, loopback_mclk_put),
SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_snd_enum[3],
msm_btsco_rate_get, msm_btsco_rate_put),
SOC_ENUM_EXT("PROXY_RX Channels", msm_snd_enum[4],
msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
SOC_ENUM_EXT("VI_FEED_TX Channels", msm_snd_enum[5],
msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
SOC_ENUM_EXT("MI2S_RX SampleRate", msm_snd_enum[6],
mi2s_rx_sample_rate_get, mi2s_rx_sample_rate_put),
SOC_ENUM_EXT("Ext_Speaker_Amp", msm_snd_enum[7],
ext_speaker_amp_get, ext_speaker_amp_put),
};
上述代码
1. 把AW87519芯片的使能和关闭函数声明为全局。
2. 新增ext_receiver_amp_get, ext_receiver_amp_put函数,这里就对应tinymix操作直接调用的函数接口。
3. 在两个结构体数组中添加该音频控件信息
最后还剩下一步就是把配置出来的Ext_Speaker_Amp填写到speaker的路由配置中去。
注意:初始化配置中默认为Off,使用speaker时再设置为On
对应代码文件为:hardware/qcom/audio/configs/msm8953/mixer_paths_qrd_sku3.xml
<ctl name="Ext_Speaker_Amp" value="Off" />
<path name="speaker">
<ctl name="MI2S_RX Channels" value="Two" />
<ctl name="RX1 MIX1 INP1" value="RX1" />
<ctl name="RX2 MIX1 INP1" value="RX2" />
<ctl name="RDAC2 MUX" value="RX2" />
<ctl name="HPHL" value="Switch" />
<ctl name="HPHR" value="Switch" />
<ctl name="Ext_Speaker_Amp" value="On" />
</path>