[Linux Audio Driver] ACDB文件加载流程(二)

1.概述

上篇文章,我们通过分析snd_card_name = mixer_get_name(adev->mixer);这句代码,我们拿到了声卡名字,详情见以下超链接:
ACDB文件加载流程(一)
然后今天接着分析void *platform_init(struct audio_device *adev)函数,分析我们拿到声卡名之后的一波骚操作;

其代码路径是:

hardware\qcom\audio\hal\msm8916\platform.c

2.代码调用流程

下面的信息量可能比较大,你们用SI追下代码,以下是代码注解;

//把声卡名包含的平台信息提取,存储到hardware_info结构里面,最终存到platform_data 结构里面

static void update_hardware_info_8x16(struct hardware_info *hw_info, 
                     const char *snd_card_name)
      --> my_data->hw_info = hw_info_init(snd_card_name);
               -> update_hardware_info_8x16(hw_info, snd_card_name);

   //根据声卡名字,绑定对应的codec以及mixer_path XML文件
      --> query_platform(snd_card_name, mixer_xml_path);
                 ->  audio_extn_read_xml(adev, snd_card_num, mixer_xml_path,
   MIXER_XML_PATH_AUXPCM) == -ENOSYS)
//如果找到这个蓝牙驱动ath3k   if (!strncmp(bt_soc, "ath3k", sizeof("ath3k")))    
                        ->adev->audio_route = audio_route_init(mixer_card, 
                        mixer_xml_path_auxpcm);存到audio_device
//否则走下面
                       -> adev->audio_route = audio_route_init(mixer_card, mixer_xml_path);
 //这个根据声卡名把外部coedec的标志位置1:is_external_codec = true;
     -->update_codec_type(snd_card_name);
      


 //这是是配置立体声的,对应高通acdb里面的stereo音效
    -->check_and_get_wsa_info((char *)snd_card_name, &wsaCount, &is_wsa_combo_supported)
    //高通hifi音效需要收费,这个没接触过
    -->ret = audio_extn_is_hifi_audio_supported();
    -->my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
                                                    "acdb_loader_init_v2");

代码走到这一步就特么找到重点了,HAL的platform.c会 通过dlsym加载私有代码库的acdb_loader_init_v2函数,

acdb_loader_init_v2函数原型在下面,路径如下:

vendor\qcom\proprietary\mm-audio\audio-acdb-util\acdb-loader\src\family-b\acdb-loader.c

audio_route_init函数在system\media\audio_route\audio_route.c它会被封装成libaudioroute.so库,
该文件用于解析用户空间的音频通道配置文件(mixer_xml_path对应的XML由声卡名字绑定),
然后由ALSA来配置音频通道。

3. 重点函数原型

static void update_hardware_info_8x16(struct hardware_info *hw_info, 
                                        const char *snd_card_name)
{
    if (!strcmp(snd_card_name, "msm8x16-snd-card")) {
        strlcpy(hw_info->type, "", sizeof(hw_info->type));
        strlcpy(hw_info->name, "msm8x16", sizeof(hw_info->name));
        hw_info->snd_devices = NULL;
        hw_info->num_snd_devices = 0;
        strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
        ....
        
}  
void *hw_info_init(const char *snd_card_name)
{
    struct hardware_info *hw_info;

    hw_info = malloc(sizeof(struct hardware_info));
    if (!hw_info) {
        ALOGE("failed to allocate mem for hardware info");
        return NULL;
    }

    if (strstr(snd_card_name, "msm8x16") || strstr(snd_card_name, "msm8939") ||
        strstr(snd_card_name, "msm8909") || strstr(snd_card_name, "msm8952") ||
        strstr(snd_card_name, "msm8976") || strstr(snd_card_name, "msm8953") ||
        strstr(snd_card_name, "msm8937") || strstr(snd_card_name, "msm8917") ||
        strstr(snd_card_name, "msm8940") || strstr(snd_card_name, "msm8920") ||
        strstr(snd_card_name, "msmfalcon")) {
        ALOGV("8x16 - variant soundcard");
        update_hardware_info_8x16(hw_info, snd_card_name);
    } else {
        ALOGE("%s: Unsupported target %s:",__func__, snd_card_name);
        free(hw_info);
        hw_info = NULL;
    }

    return hw_info;
}
static void query_platform(const char *snd_card_name,
                                      char *mixer_xml_path)
{
    if (!strncmp(snd_card_name, "msm8x16-snd-card-mtp",
                 sizeof("msm8x16-snd-card-mtp"))) {
        strlcpy(mixer_xml_path, MIXER_XML_PATH_MTP,
                sizeof(MIXER_XML_PATH_MTP));

        msm_device_to_be_id = msm_device_to_be_id_internal_codec;
       msm_be_id_array_len  =
       
      sizeof(msm_device_to_be_id_internal_codec) / 
                sizeof(msm_device_to_be_id_internal_codec[0]);
    ....
  }
int32_t audio_extn_read_xml(struct audio_device *adev, uint32_t mixer_card,
                            const char* mixer_xml_path,
                            const char* mixer_xml_path_auxpcm)
{
    char bt_soc[128];
    bool wifi_init_complete = false;
    int sleep_retry = 0;

    while (!wifi_init_complete && sleep_retry < MAX_SLEEP_RETRY) {
        property_get("qcom.bluetooth.soc", bt_soc, NULL);
        if (strncmp(bt_soc, "unknown", sizeof("unknown"))) {
            wifi_init_complete = true;
        } else {
            usleep(WIFI_INIT_WAIT_SLEEP*1000);
            sleep_retry++;
        }
    }

    if (!strncmp(bt_soc, "ath3k", sizeof("ath3k")))
        adev->audio_route = audio_route_init(mixer_card, mixer_xml_path_auxpcm);
    else
        adev->audio_route = audio_route_init(mixer_card, mixer_xml_path);

    return 0;
}

4. 补充说明

#ifndef AUXPCM_BT_ENABLED
#define audio_extn_read_xml(adev, mixer_card, MIXER_XML_PATH, \
                            MIXER_XML_PATH_AUXPCM)               (-ENOSYS)
#else
int32_t audio_extn_read_xml(struct audio_device *adev, uint32_t mixer_card,
                            const char* mixer_xml_path,
                            const char* mixer_xml_path_auxpcm);
#endif /* AUXPCM_BT_ENABLED */

这里补充说明:ath3k is the Linux Bluetooth driver for Atheros AR3011/AR3012 Bluetooth chipsets.

我觉得这个ath3k是一个AUX接口相关的蓝牙驱动,这个一般是用在汽车上的,目前我没有接触到,而且解析对应的这个XML文件mixer_paths_auxpcm.xml文件没有从高通的源代码中找到,但是驱动是存在的,代码位置是:

LA.UM.5.6\kernel\msm-3.18\drivers\bluetooth\ath3k.c
MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Atheros AR30xx firmware driver");
MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(ATH3K_FIRMWARE);

本文到此结束,下一篇重点分析acdb_loader_init_v2函数以及把acdb的调用做个总结.

5. 作者注

/******
@article{Linux Audio Driver,
Author = { 1byte ≠ 8bit},
Year = { 2020},
}
******/
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值