DSP

imx6q sgtl5000 alsa驱动分析与调试

2019-07-13 19:56发布

一. 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 "); 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 ", 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' ", 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