ALSA(二), makefile, Autotools, premake
http://antkillerfarm.github.io/
從Gstreamer到ALSA(續)
4.SOC_SINGLE類宏
這里對SOC_SINGLE類的宏,詳細說明一下,因為只有這些宏才是真正需要驅動開發者添加或修改的。
例如如下的代碼:
SOC_DOUBLE_R_TLV("Digital Playback Volume", JZCODEC_DACLVOL, JZCODEC_DACRVOL,0, 255, 0, jzcodec_tlv),使用amixer命令觀察該代碼的效果:
Simple mixer control 'Digital',0Capabilities: pvolumePlayback channels: Front Left - Front RightLimits: Playback 0 - 255Mono:Front Left: Playback 255 [100%] [0.00dB]Front Right: Playback 255 [100%] [0.00dB]從中可以看出snd_kcontrol_new的name成員的名字是有特定含義的,不能隨便定。
有的音頻芯片,如TAS5086,它的音量寄存器用0xFF表示靜音,而用0x0表示最大音量,這種情況下需要將SOC_SINGLE類宏的invert參數設為1。
5.SOC_SINGLE_TLV類宏
除了SOC_SINGLE類宏之外,還有SOC_SINGLE_TLV類宏。后者和前者的主要區別在于:用TLV數組完成音量到寄存器值之間的轉換。
例如如下代碼:
static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1);-10350是音量的最小值,表示-103.5dB。50是相鄰的兩個寄存器值之間的音量差(即步長),這里表示0.5dB。也就是說這個宏設定的音量值的單位都是0.01dB。
ASOC對多Codec的支持
音頻設計方案
ASOC在Linux 3.X時代最大的改進就是添加了對多codec的支持。這里我們首先描述一下多Codec在音頻設備設計中的意義,以及它的一些實現方案。
上圖是實現方案A,它的特點是:
1.1個MCU通過2個Codec,間接連接了4個Speaker。在當前的音頻設計中,音箱的揚聲器個數越來越多,但是單個Codec所能提供的聲道數量有限。當揚聲器個數超過這一數量限制時,就需要采用多Codec方案了。
2.兩個Codec有獨立的I2C控制通道。這里的“獨立”是邏輯意義上的。在物理上,兩個Codec可掛在同一條I2C總線上,以不同的從機地址加以區分。
3.兩個Codec共享I2S輸入。
上圖是實現方案B,它和方案A的區別為:兩個Codec有獨立的I2S輸入。方案B根據用途,又可分為兩種子方案:
1.方案B1:兩個I2S的輸入相同。
2.方案B2:兩個I2S的輸入不同。
方案A的代碼實現
1.首先討論I2C控制的實現,這里以TAS5731M芯片為例。
在board初始化階段,為兩個codec各自生成一個I2C設備。
static struct i2c_board_info __initdata rtl819xd_i2c_devices[] = {{I2C_BOARD_INFO("tas5731", 0x1a), //TAS5731M Master},{I2C_BOARD_INFO("tas5731", 0x1b), //TAS5731M Sub}, };2.方案A由于共享I2S,因此在驅動角度,必須將兩個codec驅動整合到一個card之中。
相應的machine代碼為:
static struct snd_soc_dai_link rtl819xd_jzcodec_dai[] = {{.name = "JZCODEC_MASTER",.stream_name = "JZCODEC_MASTER",.cpu_dai_name = "rtl8197d-i2s",.codec_name = "tas5731.0-001a",.codec_dai_name = "tas5731_master",.init = rtl819xd_jzcodec_jzcodec_init,.ops = &rtl819xd_jzcodec_ops,.platform_name = "rtl819x-pcm-audio",},{.name = "JZCODEC_SUB",.stream_name = "JZCODEC_SUB",.cpu_dai_name = "rtl8197d-i2s",.codec_name = "tas5731.0-001b",.codec_dai_name = "tas5731_sub",.init = rtl819xd_jzcodec_jzcodec_init,.ops = &rtl819xd_jzcodec_ops,} };相應的codec代碼為:
static struct snd_soc_dai_driver tas5731_dai[] = {{.name = "tas5731_master",.id = 0,.playback = {.stream_name = "Playback",.channels_min = 2,.channels_max = 6,.rates = TAS5731_PCM_RATES,.formats = TAS5731_PCM_FORMATS,},.ops = &tas5731_dai_ops,},{.name = "tas5731_sub",.id = 1,.playback = {.stream_name = "Playback",.channels_min = 2,.channels_max = 6,.rates = TAS5731_PCM_RATES,.formats = TAS5731_PCM_FORMATS,},.ops = &tas5731_dai_ops,} };這里對代碼的要點做一個解釋:
1)codec_name的命名規則。codec_name一般以X.Y-Z的形式命名。
其中X為codec的I2C driver名稱。注意這里的名稱和I2C_BOARD_INFO中定義的名稱不同,后者是根據i2c_device_id中定義的名稱來命名的。
Y表示I2C總線號。如果MCU有超過一條I2C總線的話,需要使用總線號加以區分。
Z表示Codec設備的從機地址。
2)由于兩個Codec共享I2S輸入,因此只需要其中一個Codec定義platform_name即可。
方案B1的代碼實現
和方案A的差別在于:兩個Codec都需要定義自己的platform_name。
方案B2的代碼實現
這種情況用兩個獨立的card來解決就可以了。
makefile
簡單的規則可以查看《GNU makefile指南》一文,Goerge Foot寫的。地址就不貼了,中文版基本到處都是。但是該文只是入門級的,最專業的還是GNU官方的手冊:
http://www.gnu.org/software/make/manual/html_node/index.html
應該說make的語法,除了規則依賴之外,大多數與bash相同。但是make也有一些內置函數,它們的用法就不在bash的范疇了,比如call函數。碰到這樣的情況,可以查閱以下網頁,以快速定位幫助文檔的位置:
http://www.gnu.org/software/make/manual/html_node/Quick-Reference.html
Autotools
概述
autotools是GNU提供的一系列自動配置工具的集合,其主要包括autoconf、automake、pkg-config和libtool等工具。
Makefile雖然規則簡單,但手工書寫makefile卻不是一件容易的事。我這里的不容易指的是:編寫符合規范的makefile不容易。如果只是那種自己平時demo的話,可能還是直接makefile更簡單。畢竟autotools包含那么多工具,每個工具的規則都不盡相同,學習門檻比makefile高多了。如果針對小工程,還不一定有直接makefile來的快。
那么autotools的優點在哪里呢?
1.針對大工程時,手工編寫量較小。比如需要添加的源文件和頭文件,直接autoscan就出來了,不用一個一個的寫。
2.可以檢查編譯環境。這個手工寫,難度太大,我是不會寫的。
3.可移植好。由于第2點的存在,autotools生成的makefile的可移植性非常好。這個優點在本地編譯的時候,體現的并不十分明顯,但如果交叉編譯的話,就很突出了。
參考文檔:
https://autotools.io/index.html
這個網站基本上每個工具都講到了,非常值得一看。
autoconf&automake
這兩個工具是整個autotools工具集的核心,使用的流程也比較復雜。教程中最經典的是:
http://www.ibm.com/developerworks/cn/linux/l-makefile/index.html
但是,這個教程比較老了,有的地方的處理并不符合當前的版本,以下針對這些新老版本的差異,做一個說明。
1.首先給出新版本(2016.2)的示例代碼:
https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/gtk_browser/autotool
2.configure.in在新版本中改叫configure.ac。其中,AM_INIT_AUTOMAKE宏的格式已經和老的不同了。AC_OUTPUT宏雖然還存在,但是部分功能分解給AC_CONFIG_FILES宏。
3.拷貝depcomp和complie文件的過程,現在可以通過命令自動完成,無須手動拷貝。
4.運行automake之前,需要先用autoheader生成config.h文件。
從整個流程來說,autotools相比Cmake無疑復雜的多了。但實際使用中,由于這幾個步驟都是流程化的,簡化起來也比較容易。因此新版本提供了autoreconf命令,用來一站式生成所需的編譯配置文件。其示例如下:
autoreconf -fi
pkg-config
一般來說,如果庫的頭文件不在/usr/include目錄中,那么在編譯的時候需要用-I參數指定其路徑。由于同一個庫在不同系統上可能位于不同的目錄下,用戶安裝庫的時候也可以將庫安裝在不同的目錄下,所以即使使用同一個庫,由于庫的路徑的不同,造成了用-I參數指定的頭文件的路徑和在連接時使用-L參數指定lib庫的路徑都可能不同,其結果就是造成了編譯命令界面的不統一。可能由于編譯,連接的不一致,造成同一份程序從一臺機器copy到另一臺機器時就可能會出現問題。
pkg-config就是用來解決編譯連接界面不統一問題的一個工具。
它的基本思想:pkg-config是通過庫提供的一個.pc文件獲得庫的各種必要信息的,包括版本信息、編譯和連接需要的參數等。需要的時候可以通過pkg-config提供的參數(–cflags, –libs),將所需信息提取出來供編譯和連接使用。這樣,不管庫文件安裝在哪,通過庫對應的.pc文件就可以準確定位,可以使用相同的編譯和連接命令,使得編譯和連接界面統一。
參見:
http://www.mike.org.cn/articles/description-configure-pkg-config-pkg_config_path-of-the-relations-between/
autoconf&automake與pkg-config的協同工作
由于pkg-config是一系列Glib派生項目(如Gstreamer、GTK)所用的配置工具。因此,如何讓autoconf&automake與pkg-config協同工作就成為了一個很重要的課題。多數autotools教程由于只是helloworld型的,并沒有涉及到這方面的內容。
這里仍然使用上一節的示例代碼,進行講解。
協同工作的關鍵在于PKG_CHECK_MODULES宏,這個宏的語法為:
PKG_CHECK_MODULES(prefix, list-of-modules, action-if-found, action-if-not-found)
該宏被執行后,會生成prefix_CFLAGS和prefix_LIBS兩個全局變量。它們在Makefile.am中會用到。
這里的AC_SUBST宏,主要是針對老版本的pkg-config所做的修改,在pkg-config v0.24以后的版本中,加不加都無所謂。
這方面更復雜的例子,可以查看Totem項目的代碼,該項目復雜度中等。如果這個例子還不夠用的話,那就直接查看GTK項目的代碼吧。我相信絕大多數的人,都不可能開發出一個比它更大的項目來。
CMake和pkg-config的協同工作
Cmake雖然主要用于Qt項目,但用于GTK項目,實際上也沒有什么問題。
Cmake使用的pkg_check_modules宏,和上面的PKG_CHECK_MODULES宏,從原理來說,是類似的。這里不再贅述。
參考文檔:
http://francesco-cek.com/cmake-and-gtk-3-the-easy-way/
示例代碼:
https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/gtk_browser/cmake
Autotools細節匯總
1.dnl vs #
dnl和#在autoconf中,都是注釋開始的標志。區別在于,dnl注釋的東西,不會出現在最終的configure腳本中。
2.設置debug版本
CFLAGS的默認設置是-g -O2,可用以下命令修改之:
./configure CFLAGS="-g -O0"
或者也可以用./configure --help查看支持的編譯選項。
比如生成靜態鏈接庫,可使用以下命令:
./configure --enable-shared=no --enable-static=yes
3.設定so文件的導出符號表
libtool --mode=link gcc -o libfoo.la foo.lo -export-symbols=foo.sym
premake
premake是一個輕量級的構建系統。這里所謂的輕量級是和Autotools、CMake相比。
Autotools在Unix平臺的功能最為全面。CMake添加了對Windows平臺的支持,但在Unix平臺上,仍不得不借助部分Autotools工具的功能,比如pkg-config。
這兩個重量級工具,都有很多重量級的使用者,一般不必擔心功能不夠使的情況。它們的缺點是,使用了特殊的DSL(Domain Specific Language),用戶需要花費額外的學習時間來學習這些DSL。
premake使用lua語言編寫,語法比CMake更簡單。它的官網是:
http://premake.github.io/
premake的缺點在于,它基本上是個人作品,全職開發人員太少,導致功能有限,目前尚無特大項目使用該系統,其功能和可靠性受到質疑。
總結
以上是生活随笔為你收集整理的ALSA(二), makefile, Autotools, premake的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cocos2d, Box2D
- 下一篇: DLNA, PulseAudio, di