Linux ALSA声卡驱动之三:component、dai、codec以及platform之间的关系

一、背景概述

        上节说到platform_device加载,触发mt76xx_i2s_driver、soc_driver、mt76xx_pcm_driver驱动程序的probe,这里面做了哪些工作,如下图

二、snd_soc_component与snd_soc_dai的关系

1、mt76xx_i2s_drv_probe的实现

        

        在mt76xx_i2s_driver的probe函数里,执行了snd_soc_register_component这个函数,这里面即初始化struct snd_soc_dai *dai和struct snd_soc_component component的结构体,并建立联系,如下图

        dai->list挂载在以component->dai_list为头部的链表里,即可通过component的地址反推出dai的地址,component->name="mt76xx-i2s",dai->driver指向component->dai_drv,即指向&mt76xx_i2s_dai,注意mt76xx_i2s_dai很重要,如下图

        mt76xx_i2s_dai主要功能即设置采样率、采样bit位数、信道数量,以及数据传输的控制等,总之配置寄存器都在CPU端,因此,后面把这块内容归类到cpu_dai里面。最后component->list挂载到以&component_list为头的链表上,这个很重要,后面会详细说明。

2、wm8960_i2c_probe的实现

        

        在wm8960_i2c_driver的probe函数里,执行了snd_soc_register_codec这个函数,这里面即初始化struct snd_soc_dai *dai、struct snd_soc_component component和struct snd_soc_codec *codec的结构体,并建立联系,如下图

         dai->list挂载在以component->dai_list为头部的链表里,即可通过component的地址反推出dai的地址,dai->component=component,dai->codec=codec,即只要知道dai,就知道另外两个结构体,此外codec->list也挂载在codec_list为头的链表上(详细内容下节解释),component->name="wm8960-hifi",dai->driver指向component->dai_drv,即指向&wm8960_dai,wm8960_dai很如下图

        wm8960_dai主要功能即设置wm8960的采样率、采样bit位数、stream的数量,以及声卡音量、增益等控制等(前面mt76xx_i2s_dai功能是设置i2s的采样率、采样bit以及数据传输,主要是在cpu端,wm8960主要是在codec端,两端都要设置),该codec主要是通过i2c进行配置,因此,后面把这块内容归类到codec_dai里面。最后component->list挂载到以&component_list为头的链表上,跟前面的i2s相关的component挂载在同一个链表上。

3、mt76xx_platform_drv_probe的实现

    

        在mt76xx_pcm_driver的probe函数里,执行了snd_soc_register_platform这个函数,这里面即初始化struct snd_soc_platform *platform和struct snd_soc_component component的结构体,并建立联系,如下图

        platform->list挂载在以platform_list为头部的链表里,platform->component=component,component->name="mt76xx-pcm",platform->driver=&mt76xx_soc_platform,mt76xx_soc_platform如下图

        mt76xx_soc_platform主要功能即协调应用层和底层控制,按照一定规则有序的录制或者播放PCM格式的音频数据,包括建立环形缓冲、指针同步、mmap映射等,因此,后面把这块内容归类到platform里面。最后component->list挂载到以&component_list为头的链表上,跟前面的i2s相关的component挂载在同一个链表上。

三、整体关系架构图

        由图可见,三个不同的component都挂载在component_list为头的链表上,后面使用的时候只需在链表上搜索与其相对应的name,就可以直接搜索到相应的component和dai,进行操作,后面会详细解释如果调用、匹配。