本文主要是简略的介绍下移植的过程
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[] 里面注册的信息。