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
同樣地,按下耳機線控按鈕,命令行會輸出一些調試信息

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