imx6q sgtl5000 alsa驱动分析与调试

一. ALSA的ASoC框架简介

按照 ASoC如下图1,框架的设计理念,源码文件应该分为 3 个部分,分别是 Platform Driver、Machine Driver、Codec Driver,这 3 者为并行关系,各对应一份源码。其中,

  1. 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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值