Msm8960(APQ8064)平台的MSM-AOSP-kitkat编译适配(6):音频

这一篇是全系列文章的重点,故笔者会多啰嗦一些原理,多问几个为什么,请读者见谅。

笔者以android 4.4.2_r1 KOT49H为例的msm-aosp来适配,此文章则需要cm的代码来辅助理解音频的配置
请读者自行下载cm的源代码,最好与自己下载的msm-aosp相近。
例如与笔者这个相近的就是cm11-m4~m7,那么笔者就下载了cm11-m7 KVT49L的代码来参考。
本文用到的仅仅是源码目录下的hardware目录,所以笔者也单独提供了这个目录的压缩文档,以方便读者实践:
http://download.csdn.net/detail/benjaminwan/8452249

一、对比cm与msm-aosp的hardware/qcom目录

记得对比选项里要钩基础规则对比
这里写图片描述
左边为cm的hardware,右边边为msm-aosp的hardware
首先请读者思考一个问题:
分别把左边的audio与右边的audio文件夹对比,以及左边的audio-caf与右边的audio文件夹对比,这2种情况下,左边哪个文件夹与右边代码最相似。
当然读者会发现左边的audio-caf代码与右边的audio最为相似
如果读者也同步了google-aosp的代码,就会发现cm的audio文件夹与google-aosp的audio文件夹最相似。
从这里我们可以总结得出:cm实际上集成了google以及高通,二者的audio代码
那么就有了第二个问题,cm如何通过配置来选择使用哪种音频代码?

二、对比audio目录

接下来就把cm的qcom/audio-caf与msm-aosp的qcom/audio目录对比
以下文章的内容都默认以cm的audio-caf来讲解了
对比audio/Android.mk
这里写图片描述
首先可以看出cm比aosp多了这个语句
ifeq ($(TARGET_QCOM_AUDIO_VARIANT),caf)
这个语句作用就是cm用来选择是audio还是audio-caf的
解释一下:如果在BoardConifg.mk里有TARGET_QCOM_AUDIO_VARIANT := caf那么就选择audio-caf文件夹来编译,相反,如果不配置此项,则默认使用audio文件夹

分析完左边的cm,再来研究右边的msm-aosp
cm11多出来的是一些其它平台的代码,msm8660,msm8610之类的
接下来只看红框中的共通项

ifeq ($(BOARD_USES_LEGACY_ALSA_AUDIO),true)
include $(MY_LOCAL_PATH)/legacy/Android.mk
else
include $(MY_LOCAL_PATH)/hal/Android.mk
endif

这是一个选择语句,那么到底该选择legacy文件夹或者是hal文件夹呢?

接下来要讲一个小知识,音频hw实际上分为2种,如上看到的legacy以及hal
官方rom的话,msm8960平台使用legacy,而msm8974平台使用hal
来讲讲这2种hw驱动在官方rom里可以看到什么区别
legacy驱动,需要在etc里有个snd_soc_msm文件夹,里面放音频配置文件
而hal驱动,则会在etc下有个mixer_patchs.xml
而且legacy的系统lib下没有libaudioroute.so,相反hal驱动则有
举个例子,泛泰A910,msm8974平台
这里写图片描述
msm8960平台的例子,请读者自己打开官方rom查看一下便知。

接下来第二个提示要点,对比cm与msm-aosp的hal文件夹,可以发现msm-aosp的hal文件夹缺了许多代码并感觉残缺不全,对,因为我们当前同步的msm-aosp代码仅针对msm8960平台,所以实际上hal文件夹代码是缺失的。
如果读者后续也同步了msm8974平台的msm-aosp,那么对比一下就知道怎么回事了。

回答前面提到的问题,从官方rom得到的提示以及对比cm的hal文件夹,我们应该选择legacy文件夹来编译
所以必须在BoardConfig.mk里添加BOARD_USES_LEGACY_ALSA_AUDIO := true

小知识:因为cm集成了全部的音频代码(包括google、高通各个平台),所以编译cm时,即使msm8960平台也可以选择hal来编译。

三、对比legacy文件夹

这里写图片描述
cm还集成了msm7x30以及msm8660平台的代码,这2个可以不管
只看右边红框的共通项
从逻辑上分析,legacy文件夹下的Android.mk里只有这么一个选择项
那么它就必须要选中,否则上一级选中了legacy文件夹就失去了作用
所以Boardconfig.mk里就必须要有
BOARD_USES_ALSA_AUDIO := true

在原来的Boardconfig.mk里,高通在范例里配置了
BOARD_USES_GENERIC_AUDIO := true,这行可以删掉了
这是android自带的通用音频驱动,当然无法正确驱动高通平台

四、对比4个文件夹

这里写图片描述
4个文件夹,有3个不一样,那么从最简单的、相同的那个开始看
audiod文件夹是最简单的,而且与cm11的代码完全一样

五、对比audiod文件夹

这里写图片描述
截图里面3个红框的部分是一般我们需要注意或者需要看的地方
第一个红框:选择语句就不再解释了
第二个红框:代表依赖的共享lib,也就是说编译这个audio依赖这4个lib
第三个红框:LOCAL_MODULE:= audiod,这句表示此模块编译后生成的文件名为audiod

那么问题来了,这个audiod需要编译吗?
提示:
1.官方rom是我们唯一可以参考的;
2.LOCAL_MODULE代表编译后这个模块最终生成的文件名;
3.笔者也不知道读者的机型是否需要编译audiod模块;

OK,答案揭晓了:
既然知道这个模块编译之后,文件名叫做audiod,那么在官方rom里找一找,有没有叫做audiod的文件,如果没有就是不需要,如果有就是需要
当然,泛泰a870是不需要的,所以这部分就不添加任何语句

六、对比mm-audio文件夹

这个文件夹基本上与cm一样,仅有2处稍有区别,cm11的更改肯定有它的道理,读者只要知道与cm有些许区别就行。

这个文件夹下的Android.mk里,并没有提供选择题
include $(call all-subdir-makefiles)
这个就是全选,不需要我们再手工配置指定

七、对比libalsa-intf文件夹

重点来了
这里写图片描述
这里写图片描述
看上下2个截图,左右的区别,重点在于TARGET_USES_QCOM_MM_AUDIO这个配置项的形式不同。
右边的代码形式是ifeq ($(strip $(TARGET_USES_QCOM_MM_AUDIO)),true)
左边的代码形式是ifneq ($(TARGET_USES_QCOM_COMPRESSED_AUDIO),false)
为何cm与msm-aosp有差异,或者cm为何要从ifeq更改为 ifneq?
读者理解了cm为何要这么改,后面的最后一个文件夹也就能立刻理解了

现在讲解一下:
ifneq (AAA,false)
这种语句,在不配置AAA或AAA不等于false(也就是等于true)时,就满足if条件
换句话来讲也就是cm改成了:即使不配置,也默认启用此项
因为cm代码是面对的所有机型,那么最终就说明这个项目对所有机型都是有用的
除非你在BoardConfig.mk里手工指定了这项为fasle,否则默认都是启用的

ok,回到右边msm-aosp的代码
msm-aosp这个选项与cm语法不一样,它确实要求我们选择是否配置
但因为从cm代码得知,这个项目一般都是需要选中的,所以我们需要在BoardConfig.mk里增加TARGET_USES_QCOM_MM_AUDIO := true

八、对比alsa_sound文件夹

这是音频最后一个文件夹
这里写图片描述
从截图我们可以看到cm做了许多更改,主要是把ifeq(true)改为ifneq(false)的形式
那么从前一个要点可以知道,这种形式的更改,会导致不配置也默认启用。
ok,进入正题
cm改动的项目,都是aosp必须打开的项目,所以最终还要在BoardConfig.mk里的#Audio节里添加

QCOM_ACDB_ENABLED := true
QCOM_ANC_HEADSET_ENABLED := true
QCOM_AUDIO_FORMAT_ENABLED := true
QCOM_CSDCLIENT_ENABLED := true
QCOM_PROXY_DEVICE_ENABLED := true
QCOM_OUTPUT_FLAGS_ENABLED := true
QCOM_USBAUDIO_ENABLED := true
QCOM_ADSP_SSR_ENABLED := true
QCOM_FLUENCE_ENABLED := true
QCOM_TUNNEL_LPA_ENABLED := true

九、音频部分总结

BOARD_USES_GENERIC_AUDIO := true,这行删除
添加如下内容

BOARD_USES_LEGACY_ALSA_AUDIO := true
BOARD_USES_ALSA_AUDIO := true
TARGET_USES_QCOM_MM_AUDIO := true
QCOM_ACDB_ENABLED := true
QCOM_ANC_HEADSET_ENABLED := true
QCOM_AUDIO_FORMAT_ENABLED := true
QCOM_CSDCLIENT_ENABLED := true
QCOM_PROXY_DEVICE_ENABLED := true
QCOM_OUTPUT_FLAGS_ENABLED := true
QCOM_USBAUDIO_ENABLED := true
QCOM_ADSP_SSR_ENABLED := true
QCOM_FLUENCE_ENABLED := true
QCOM_TUNNEL_LPA_ENABLED := true

十、关于编译错误的处理

改完BoardConfig.mk就可以开始重新编译了
在编译的过程中可能会碰到几次编译错误

1.缺intermediates错误

需要目标"out/target/product/a870/obj/SHARED_LIBRARIES/libacdbloader_intermediates/export_includes”

对于这种错误,需要在device/pantech/a870/Android.mk里添加

$(shell mkdir -p $(OUT)/obj/SHARED_LIBRARIES/libacdbloader_intermediates/)
$(shell touch $(OUT)/obj/SHARED_LIBRARIES/libacdbloader_intermediates/export_includes)

注意:linux是区分大小写的,OUT必须是大写
这个语句是用来hack的,让编译系统误以为我们有libacdloader源代码(但实际上我们没有,我们只有从官方rom里提取的lib)

然后修改proprietary-blobs.txt添加libacdbloader.so
然后修改setup-makefiles.sh,取消下面语句的注释,用于把proprietary-blobs.txt提取的lib复制到obj目录

PRODUCT_COPY_FILES += \\
    $OUTDIR/proprietary/lib/libacdbloader.so:obj/lib/libacdbloader.so

然后重新生成vendor,再继续编译。

如果碰到其它音频lib文件提示类似的错误,请读者依葫芦画瓢处理。

2.源码编译错误

编译停下来的地方基本上不是发生错误的地方,在终端里搜索关键字error,选向上搜索,找到真正发生错误的地方。
其中一个是libalsa-intf\alsa_ucm.c,错误提示是fatal error: acdb-loader.h : NO such file or directory
对比cm
这里写图片描述
之前说过,我们没有libacdbloader的源代码,所以这个acdb-loader.h也就无法提供了
而cm则更改了这句代码,但msm-aosp需要这样改:
右边注释掉,注意,C代码双斜杠是注释//

//#if defined(QC_PROP)
//    #include "acdb-loader.h"
//#else
//#endif

最终是这个样子
这里写图片描述

另一个错误发生在:alsa_sound/AudioHardwareALSA.cpp
‘PROXY_OPEN_RETRY_COUNT’ was not declared in this scope
错误指向这里
这里写图片描述
参考cm,加上#ifdef QCOM_USBAUDIO_ENABLED和#endif即可

十一、声音配置微调

对于某些有双mic降噪功能的手机,一般会在手机顶部以及底部各有一个mic。
正常底部mic作为主mic,要大声,顶部mic作为降噪mic,要小声。
这个可以用z硬件测试的mic测试功能,分别对着顶部和底部mic讲话,看声音幅度就知道是否有颠倒。
如果颠倒了,我们要调整build.prop里的配置值来修正
persist.audio.handset.mic=digital
改成
persist.audio.handset.mic=analog
或者反之,请读者自行试验

十二、进阶调试

1.耳机插入检测的方式

andoird一共有2种检测方式
方法一:由内核负责检测,设备驱动名为h2w,一般会在/sys/class/switch或/sys/devices/virtual/switch
方法二:由音频系统负责检测,msm8960就属于此种情况,实际由PM8921的GPIO38脚负责
如何知道手机是哪种检测方式?用排除法吧
查看logcat信息:
W/WiredAccessoryObserver( 627): This kernel does not have wired headset support
这样的语句即代表内核不支持耳机检测,所以只能由音频系统来检测了。

2.耳机插入检测GPIO查看

原理图下载:http://download.csdn.net/detail/benjaminwan/8453547
查看原理图第18页
这里写图片描述
PM8921的GPIO38脚,标签ANC_HS_DET即为耳机检测

开adb shell,取得root权限
cat /sys/kernel/debug/gpio
可以看到分成好几段,这是按功能把芯片引脚区分成几个段而已

GPIOs 0-151, platform/msmgpio, msmgpio:
GPIOs 152-195, platform/pm8xxx-gpio, pm-gpio:
GPIOs 196-207, platform/pm8xxx-mpp.0, pm8xxx-mpp:
GPIOs 208-211, platform/pm8xxx-mpp.1, pm8xxx-mpp:

我们要查看原理图里的PM8921的GPIO38脚,在debug信息里如何换算成第几个GPIO呢?
看上面的分段信息,第一段即MSM8960为GPIOs 0-151,共有151脚,第二段就是PM8921,我们要PM8921的第38脚,那么就是151+38= 189脚

查看GPIOs 152-195, platform/pm8xxx-gpio, pm-gpio:这一段
当耳机插入时为高电平
gpio-189 (-- ) in hi 0x05 0x10 0x2a 0x30 0x40 0x58
当耳机未插入时为低电平
gpio-189 (-- ) in lo 0x05 0x10 0x2a 0x30 0x40 0x58

3.输入设备事件查看

开adb shell,取得root权限

cat /proc/bus/input/devices
I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="apq8064-tabla-snd-card Button Jack"
P: Phys=ALSA
S: Sysfs=/devices/platform/soc-audio.0/sound/card0/input2
U: Uniq=
H: Handlers=kbd event2 cpufreq
B: PROP=0
B: EV=3
B: KEY=f8 4 0 0 0 c0000 0 0 0

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="apq8064-tabla-snd-card Headset Jack"
P: Phys=ALSA
S: Sysfs=/devices/platform/soc-audio.0/sound/card0/input3
U: Uniq=
H: Handlers=event3 cpufreq
B: PROP=0
B: EV=21
B: SW=1c054

可以找到如上类似的信息,可能因手机不一样而不一样
其中Headset Jack即为耳机插入检测
Button Jack是耳机线控按钮检测

从信息得知
耳机检测设备路径/devices/platform/soc-audio.0/sound/card0/input3
对应的Handlers为event3

我们来测试一下:
cat /dev/input/event3
执行完命令后就放着,然后插入或拔出耳机,命令行会输出一些调试信息,但我们没有专用的查看工具所以无法查看具体信息,ctrl+C结束

耳机线控按钮检测设备路径/devices/platform/soc-audio.0/sound/card0/input2
对应的Handlers为event2
cat /dev/input/event2
同样地,按下耳机线控按钮,命令行会输出一些调试信息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章