Android audio之alsa移植

本文主要是簡略的介紹下移植的過程

1.Alsa主要包括3個文件夾

haraware/alsa_sound  硬件抽象層部分

external\alsa-lib   主要是提供一些音頻庫

external\alsa-utils 工具部分,配合調試之類的,可以不用


2.獲取源碼的方式:

首先,cd到Android源碼樹根目錄下:

cd /home/***/gin:

1).從Android主頁下載ALSA聲卡的相關源碼:

git clone git://android.git.kernel.org/platform/external/alsa-lib.git

git clone git://android.git.kernel.org/platform/external/alsa-utils.git

git clone git://android.git.kernel.org/platform/hardware/alsa_sound.git

這樣下載完之後的各個包將會自動放到合適的地方。

2).一般的源碼包裏面可能自帶了ALSA這幾個包,最好使用原有的包,這些包是經過廠商的修改會減少很多問題。

之前我使用方式1,直接git clone了這幾個包,結果使用中出現了問題,登錄優酷網頁播放視頻的時候會一卡一卡的現象,停頓時間很頻繁,聲音畫面完全不同步,最好不得不放棄使用ALSA。是由於ALSA導致的,一時不知道怎麼修改,這個修改我隨後會發出來。


3.開始配置:

1)首先配置BoardConfig.mk

   這個文件裏面有2個地方
   a.BOARD_USES_ALSA_AUDIO := true  主要是宏定義,切換使用到ALSA
     BUILD_WITH_ALSA_UTILS := true

   b.打開3G模塊的文件系統配置,這個根據不同的需求配置不同,各人看情況而定。


2)將第一步裏面的3個包放到指定的位置。

  大部分情況下external\alsa-lib及external\alsa-utils 不需要改動,直接使用即可。但是haraware/alsa_sound 有時候還是需要有所改動的。

  因爲android支持的設備有以下一些:

  enum audio_devices {
        // output devices
        DEVICE_OUT_EARPIECE = 0x1,
        DEVICE_OUT_SPEAKER = 0x2,
        DEVICE_OUT_WIRED_HEADSET = 0x4,
        DEVICE_OUT_WIRED_HEADPHONE = 0x8,
        DEVICE_OUT_BLUETOOTH_SCO = 0x10,
        DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
        DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
        DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
        DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
        DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
        DEVICE_OUT_AUX_DIGITAL = 0x400,
        DEVICE_OUT_DEFAULT = 0x8000,
        DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET |
                DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
                DEVICE_OUT_BLUETOOTH_SCO_CARKIT | DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
                DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL | DEVICE_OUT_DEFAULT),
        DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
                DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),


        // input devices
        DEVICE_IN_COMMUNICATION = 0x10000,
        DEVICE_IN_AMBIENT = 0x20000,
        DEVICE_IN_BUILTIN_MIC = 0x40000,
        DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000,
        DEVICE_IN_WIRED_HEADSET = 0x100000,
        DEVICE_IN_AUX_DIGITAL = 0x200000,
        DEVICE_IN_VOICE_CALL = 0x400000,
        DEVICE_IN_BACK_MIC = 0x800000,
        DEVICE_IN_DEFAULT = 0x80000000,


        DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT | DEVICE_IN_BUILTIN_MIC |
                DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET | DEVICE_IN_AUX_DIGITAL |
                DEVICE_IN_VOICE_CALL | DEVICE_IN_BACK_MIC | DEVICE_IN_DEFAULT)
    };

    但是有時候像平板部分是沒有聽筒的,所以需要在alsa_default.cpp文件裏static status_t s_open(alsa_handle_t *handle, uint32_t devices, int mode)函數裏修改

if (devices == AudioSystem::DEVICE_OUT_EARPIECE) {
devices = AudioSystem::DEVICE_OUT_SPEAKER; 
}

   即:如果是聽筒的話,直接設置爲喇叭設備,強制設置,呵呵,這個有點不地道,但是修改方式簡單快捷。

3).修改asound.conf

# Android ALSA configuration file for TI OMAP3430 reference platform using the TWL4030 ASoC audio.
##
## Mixer Devices
##
ctl.AndroidOut{
type hw
card 0
}
ctl.AndroidIn{
type hw
card 0
}
ctl.AndroidPlayback {
type hw
}
ctl.AndroidRecord {
type hw
}
##
## # Speaker
##
pcm.AndroidPlayback_Speaker_normal {
    type hooks
    slave.pcm {
        type hw
        card 0
        device 0
    }
hooks.0 {
type ctl_elems
hook_args [
{
name 'Speaker Playback Switch'
value [1 1]
}
{
name 'Speaker Playback Volume'
value [4 4]
}
]
}
}
pcm.AndroidPlayback_Speaker_incall{
type hooks
    slave.pcm {
        type hw
        card 0
        device 0
    }
hooks.0 {
type ctl_elems


hook_args [
{
name 'Speaker incall Switch'
value [1 1]
}
{
name 'Speaker incall Volume'
value [2 2]
}
{
name 'MIC1 Mode Control'
value 1
}
{
name 'MIC1 Boost'
value 4
}
]
}
}
pcm.AndroidPlayback_Speaker_ringtone{
type hooks
    slave.pcm {
        type hw
        card 0
        device 0
    }
hooks.0 {
type ctl_elems


hook_args [
{
name 'Speaker ringtone Switch'
value [1 1]
#value "on"
}
{
name 'Speaker ringtone Volume'
value [4 4]
}
]
}
}
##
## # Headset
##
pcm.AndroidPlayback_Headset_normal {
type hooks
    slave.pcm {
        type hw
        card 0
        device 0
    }
hooks.0 {
type ctl_elems
hook_args [
{
name 'HP Playback Switch'
value [1 1]
}
{
name 'Speaker Playback Switch'
value [0 0]
}
{
name 'HP Playback Volume'
value [4 4]
}
]
}
}
pcm.AndroidPlayback_Headset_incall{
type hooks
    slave.pcm {
        type hw
        card 0
        device 0
    }
hooks.0 {
type ctl_elems
hook_args [
{
name 'Headset incall Switch'
value [1 1]
}
{
name 'Headset incall Volume'
value [6 6]
}
{
name 'MIC2 Capture Switch'
value 1
}
{
name 'MIC2 Boost'
value 4
}
]
}
}
pcm.AndroidPlayback_Speaker_Headset_ringtone{
type hooks
    slave.pcm {
        type hw
        card 0
        device 0
    }
hooks.0 {
type ctl_elems
hook_args [
{
name 'Speaker ringtone Switch'
value [1 1]
}
{
name 'Speaker ringtone Volume'
value [4 4]
}
{
name 'Headset incall Switch'
value [1 1]
}
{
name 'Headset incall Volume'
value [6 6]
}
]
}
}
pcm.AndroidPlayback_Speaker_Headset_normal {
        type hooks
    slave.pcm {
        type hw
        card 0
        device 0
    }
        hooks.0 {
                type ctl_elems


                hook_args [
                        {
                                name 'Headset ringtone Switch'
value 0
                        }
                ]
        }
}

##
## # AndroidCapture
##
pcm.AndroidCapture {
type hooks
    slave.pcm {
        type hw
        card 0
        device 0
    }
hooks.0 {
type ctl_elems


hook_args [
{
name 'MIC1 Capture Switch'
value 1
}
{
name 'MIC1 Boost'
value 4
}
{
name 'MIC2 Capture Switch'
value 1
}
{
name 'MIC2 Boost'
value 4
}
]
}
}

這個和內核裏面的soc系統是相關的,是必須和內核的路由結合起來配置,否則肯定出問題。

這裏貼出內核的對應配置:

static const struct snd_kcontrol_new rt5631_snd_controls[] = {


SOC_DOUBLE("Speaker Playback Switch", RT5631_SPK_OUT_VOL,15, 7, 1, 1),
SOC_DOUBLE("Speaker Playback Volume", RT5631_SPK_OUT_VOL, 8, 0, 27, 0),


SOC_DOUBLE("Speaker incall Switch", RT5631_SPK_OUT_VOL,15, 7, 1, 1),
SOC_DOUBLE("Speaker incall Volume", RT5631_SPK_OUT_VOL, 8, 0, 27, 0),
SOC_SINGLE("MIC1 Capture Switch", RT5631_MIC_CTRL_1, 15, 1, 1),
SOC_SINGLE("MIC1 Boost", RT5631_MIC_CTRL_2, 12, 9, 0),


SOC_DOUBLE("Speaker ringtone Switch", RT5631_SPK_OUT_VOL,15, 7, 1, 1),
SOC_DOUBLE("Speaker ringtone Volume", RT5631_SPK_OUT_VOL, 8, 0, 24, 0),


SOC_DOUBLE("HP Playback Switch", RT5631_HP_OUT_VOL,15, 7, 1, 1),
SOC_DOUBLE("HP Playback Volume", RT5631_HP_OUT_VOL, 8, 0, 63, 1),


SOC_DOUBLE("Headset incall Switch", RT5631_HP_OUT_VOL,15, 7, 1, 1),
SOC_DOUBLE("Headset incall Volume", RT5631_HP_OUT_VOL, 8, 0, 63, 1),
SOC_SINGLE("MIC2 Capture Switch", RT5631_MIC_CTRL_1, 7, 1, 1),
SOC_SINGLE("MIC2 Boost", RT5631_MIC_CTRL_2, 8, 9, 0),


SOC_DOUBLE("Headset ringtone Switch", RT5631_HP_OUT_VOL,15, 7, 1, 1),
SOC_DOUBLE("Headset ringtone Volume", RT5631_HP_OUT_VOL, 8, 0, 63, 1),

}

只要文件系統裏面的路由和內核裏面的路由完全匹配,那剩下的就是設置codec的具體信息了,這裏不解釋了


4.如果要在內核裏面查看具體的路由信息,可以到soc-core.c 文件裏面int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)函數去打印kcontrol->id.name這個實時的打印即爲當前的路由信息,不過這個信息也是你之前在rt5631_snd_controls[] 裏面註冊的信息。


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