一. ALSA的ASoC框架简介
按照 ASoC如下图1,框架的设计理念,源码文件应该分为 3 个部分,分别是 Platform Driver、Machine Driver、Codec Driver,这 3 者为并行关系,各对应一份源码。其中,
- Platform Driver 相关的源码主要实现 DMA 功能和 DAI,即 DSP 模块的 I2S 数据传输功能,并导出相应变量或操作函数接口;
2.Codec Driver 相关的源码主要实现 I/O 控制、DAPM 和 PCM 配置,并导出相应变量或操作函数接口;
3.Machine Driver 相关的源码则将前 2 个文件中导出的接口绑定在一起。内核启动后,以模块的形式加载 3 个驱动。
图:1
二. 驱动源码分析:
1. 板级设备 (arch/arm/mach-mx6/board_xx.c)
“imx-sgtl5000”(Machine device)注册
Static struct mxc_audio_platform_data mx6_sabresd_sgtl5000_audio_data = {
.ssi_num = 1,
.src_port = 2,
.ext_port = 4,
.init = mx6_sabresd_sgtl5000_init,
.hp_gpio = -1,
};
static struct platform_device mx6_sabresd_audio_sgtl5000_device = {
.name = "imx-sgtl5000",
};
mxc_register_device(&mx6_sabresd_audio_sgtl5000_device,
&mx6_sabresd_sgtl5000_audio_data);
//这个设备的初始化主要为sgtl5000提供始终有源晶振,16MHZ时钟 还有相关regulator设备注册就不详述了.
i2c设备注册 通过配置相关寄存器起控制sgtl5000作用
static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
{
I2C_BOARD_INFO("sgtl5000", 0x0a),
},
i2c_register_board_info(1, mxc_i2c1_board_info,
ARRAY_SIZE(mxc_i2c1_board_info));
2. 板级驱动(sound/soc/imx/imx-sgtl5000.c)
作用:板级驱动(machine (or board) driver)是将platform驱动和codec驱动粘合在一起的代码
我们可以通过通过以下关键变量查找粘合代码位置:
//imx_sgtl5000_audio_driver 匹配板级设备.
static struct platform_driver imx_sgtl5000_audio_driver = {
.probe = imx_sgtl5000_probe,
.remove = imx_sgtl5000_remove,
.driver = {
.name = "imx-sgtl5000",
},
};
//板级DAI配置比较复杂也是涉及代码量最多的
//The machine DAI configuration glues all the codec and CPU DAIs together
//将所有codec和cpu的DAIs通过下面的名字匹配将的驱动粘合在一起
//如果声卡没有注册成功可以查看以下name是否probe到相应的driver
static struct snd_soc_dai_link imx_sgtl5000_dai[] = {
{
.name = "HiFi",
.stream_name = "HiFi",
/*
codec_dai, codec的驱动都在sound/soc/codec/sgtl5000.c注册
具体可在snd_soc_register_codec函数中
可以填添加log查看name查看具体的名字
*/
.codec_dai_name = "sgtl5000",
.codec_name = "sgtl5000.1-000a",
//imx-ssi 兼容I2S接口 代码位置:kernel/linux-3.0.35/sound/soc/imx/imx-ssi.c
.cpu_dai_name = "imx-ssi.1", //cpu 接口
//platform PCM DMA 代码位置: kernel/linux-3.0.35/sound/soc/imx/imx-pcm-dma-mx2.c
.platform_name = "imx-pcm-audio.1",
//系统时钟和I2S通讯协议格式初始化
.init = imx_3stack_sgtl5000_init,
//dapm 小控件初始化
.ops = &imx_sgtl5000_hifi_ops,
},
};
//注册声卡变量 起组织作用 可以从此自顶向下分析ASAL驱动,这样ASAL驱动架构就比较清晰了,模块化的设计,各司其职
static struct snd_soc_card imx_sgtl5000 = {
.name = "sgtl5000-audio",
.dai_link = imx_sgtl5000_dai,
.num_links = ARRAY_SIZE(imx_sgtl5000_dai),
};
3.sgtl5000.c 的 i2c codec 驱动挂载
//sgtl5000_i2c_probe 外加注册codec_name 驱动 snd_soc_register_codec
static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct sgtl5000_priv *sgtl5000;
int ret;
debug_sgtl("i2c\n");
sgtl5000 = kzalloc(sizeof(struct sgtl5000_priv), GFP_KERNEL);
if (!sgtl5000)
return -ENOMEM;
i2c_set_clientdata(client, sgtl5000);
/*注册codec驱动和 DAIS驱动 */
ret = snd_soc_register_codec(&client->dev,
&sgtl5000_driver, &sgtl5000_dai, 1);
if (ret) {
dev_err(&client->dev, "Failed to register codec: %d\n", ret);
kfree(sgtl5000);
return ret;
}
return 0;
}
snd_soc_register_codec
int snd_soc_register_codec(struct device *dev,
const struct snd_soc_codec_driver *codec_drv,
struct snd_soc_dai_driver *dai_drv,
int num_dai)
{
````````
````````
/* register any DAIs */
/*DAIS驱动名与I2C设备名一致*/
if (num_dai) {
ret = snd_soc_register_dais(dev, dai_drv, num_dai);
if (ret < 0)
goto fail;
}
mutex_lock(&client_mutex);
list_add(&codec->list, &codec_list);
snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);
/*这里可以看到注册的codec 驱动名*/
pr_debug("Registered codec '%s'\n", codec->name);
return 0;
``````
``````
}
4.使用alsa-utils的
amixer
aplay arecord 设置 播放 录音
1. 编译 alsa-lib alsa-utils 移植进文件系统 ,可以使用ltib 会简单快速很多,省去很多编译与配置的麻烦
2.终端敲入命令
#播放音乐
amixer sset 'Headphone' 126
aplay audio16k16S.wav
#录音
amixer cset numid=10,iface=MIXER, name='Capture Switch' on
amixer sset 'Capture' 20
# 录制 -d 10秒
arecord -r 44100 -f S16_lE -c 2 -d 10 record.wav
5.深入分析
具体驱动代码在哪里已经清楚了,可以通过阅读 alsa-lib alsa-utils alsa驱动源码,使用strace alsa-utils 命令,根据例如 ioctl 宏, 分析驱相关函数是如何调用的。
三. 参考
http://www.alsa-project.org/main/index.php/Main_Page
i.MX 6 Linux Reference Manual.pdf (Advanced Linux Sound Architecture (ALSA) System on a Chip (ASoC) Sound Driver)
imx-test-3.0.35-4.1.0/test/mxc_ssi_test/doc
http://blog.csdn.net/qidi_huang/article/details/51935942
http://blog.csdn.net/droidphone/article/details/6409983