最近一直在研究 ALSA 驱动,停了一段时间,突然发现Asla 驱动不是一天两天能讲清楚的。
ASoC (ALSA System on Chip) ,是建立在标准ALSA驱动层上,为了更好地支持嵌入式处理器和移动设备中的音频Codec的一套软件体系。在ASoc出现之前,内核对于SoC中的音频已经有部分的支持,不过会有一些局限性:
ASoC正是为了解决上述种种问题而提出的,目前已经被整合至内核的代码树中:sound/soc。ASoC不能单独存在,他只是建立在标准ALSA驱动上的一个它必须和标准的ALSA驱动框架相结合才能工作。
嵌入式设备的音频系统可以被划分为板载硬件(Machine)、Soc(Platform)、Codec三大部分,如下图所示:
注释:对于现在的很多嵌入式平台,内部集成了codec,我们在分析时也可以将其划分到codec 上,不同的Soc 内部Codec 有所不同,同时亦可兼容内部codec 和 外部Codec。
在软件层面,ASoC也把嵌入式设备的音频系统同样分为3大部分,Machine,Platform和Codec。
Codec DAI 和 PCM的配置信息;Codec的IO控制方式(I2C,SPI等);Mixer和其他的音频控件;Codec的ALSA音频操作接口;
必要时,也可以提供以下功能:
通常一个声卡设备,大概包含以下几个物理设备或者外设:
对于大多数平台,dma 和 i2s/pdm 等集成在一个soc 上,有些甚至集成了Codec。
音频数据的数据流,大致如下。我们可以看到,不同的硬件平台,其声卡设备的硬件逻辑和数据流大致一致,故抽象ASoc 很有必要。
如下是笔者根据自己理解划分 Alsa 声卡驱动各个部分:
Machine:驱动顶层和入口,处理声卡操作。包括声卡创建,音频流的传输与控制。
platform:主要负责Soc 平台的DMA 和 CPU_DAI 操作。
Codec:主要负责Codec driver 和 Codec_dai 操作。
可以看到一个ALSA 声卡驱动是十分复杂的,包含了各种复杂驱动。
我们以 linux-kernel-4.4.94 为例子来分析 ASoc 驱动。限于篇幅,我们只分析 Machine 驱动框架,对于Codec 驱动和其他设备驱动,有时间再分析。
ASoc Machine 驱动调用如下:
/* ASoC platform driver */
static struct platform_driver soc_driver = {
.driver = {
.name = "soc-audio",
.pm = &snd_soc_pm_ops,
},
.probe = soc_probe,.remove = soc_remove,
};
最顶层入口是soc_probe,位于 sound/soc/soc-core.c,不同的Machine 位置可能不同。大部分在soc/xxx/下。
/* probes a new socdev */
static int soc_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
/*
¦* no card, so machine driver should be registering card
¦* we should not be here in that case so ret error
¦*/
if (!card)
return -EINVAL;
dev_warn(&pdev->dev,
¦"ASoC: machine %s should use snd_soc_register_card()\n",
¦card->name);
/* Bodge while we unpick instantiation */
card->dev = &pdev->dev;
return snd_soc_register_card(card);
}
最关键的就是 snd_soc_register_card 这个函数了。详细分析看上图uml 时许图。
ASoc 数据结构如上图。最顶层我们构建了snd_soc_card。贯穿整个驱动生命周期中,snd_soc_pcm_runtime,至关重要。 dai_link 关联着dai_driver 和 compoent_driver snd_soc_codec:codec 相关 snd_soc_paltform:platform 相关 snd_soc_dai:cpu_dai 和 codec_dai 相关操作 snd_soc_component:关联dai_driver 和 component_driver。关联platform_driver 和 component_driver snd_soc_ops/snd_soc_dai_ops/snd_pcm_ops:比较关键的几个ops
对于刚开始学习ASLA 驱动时,我们先关注这几个结构体就行。后续将从音频流和控制两大块,详细分析整个数据流和控制的调用过程。
本文详细的介绍了ALSA 驱动最关键的一环ASoC ,理解了ASoc 顶层设计框架对于我们后续深入学习ASLA 驱动至关重要。
当我们熟悉了一个平台的驱动框架后,再去看另外一个平台就知道哪些是我们需要关注的,哪些是linux 内核已经实现的,从而达到事半功倍的作用。
希望本文,对读者朋友学习理解Alsa 驱动有所帮助!
有关uml 时序图和类图需要高清大图,原图文件比较大,可后台私信我【UML 高清图】单发。