----------------------------------------------------------------------------------------------------------------------------
开发板 :NanoPC-T4开发板eMMC :16GBLPDDR3 :4GB显示屏 :15.6英寸HDMI接口显示屏u-boot :2023.04linux :6.3----------------------------------------------------------------------------------------------------------------------------
在Rockchip RK3399 - ALSA子系统我们介绍了ALSA子系统的软件架构,同时介绍了ALSA CORE核心数据结构和相关API。本节我们将会介绍ASoC软件体系中音频三大驱动模块(codec、platform 和machine)中的codec。
Codec driver它不应包含任何特定于目标平台或设备的代码。所有特定于平台和设备的代码应分别添加到平台和机器驱动程序中,codec driver提供了配置编解码器、FM、MODEM、BT或外部DSP,以提供音频捕获和播放功能。
每个codec driver必须提供以下功能:
- Codec DAI和PCM的配置信息;
- Codec的控制接口,如I2C/SPI;
- Mixer和其它音频控件;
- Codec的音频操作;
- DAPM描述信息;
- DAPM事件处理程序;
可选地,codec driver还可以提供:
- DAC数字静音控制;
一、核心数据结构
每个codec driver都必须有一个struct snd_soc_dai_driver 结构体,用于定义其 DAI 和 PCM 的能力和操作。该结构体被导出,以便machine driver可以将其注册到ASoC CORE中。
描述codec的最主要的几个数据结构分别是:snd_soc_dai,snd_soc_dai_driver、snd_soc_component、snd_soc_component_driver,其中:
- snd_soc_dai:描述codec端的dai;
- snd_soc_dai_driver:描述codec端的dai驱动;
- snd_soc_component:ASoC使用同一的数据结构来描述codec设备和platform设备,该数据结构就是snd_soc_component;也就是说, 不管是platform、codec,核心层现在都统一用struct snd_soc_component来管理了, 一个component对应一个模块;
- snd_soc_component_driver:与snd_soc_component对应的驱动数据结构就是snd_soc_component_driver;
关于snd_soc_dai,snd_soc_dai_driver数据结构具体参考:Rockchip RK3399 - ASoC Machine驱动基础 dai相关内容。
1.1 struct snd_soc_component
ASoC使用snd_soc_component来描述codec设备,定义在include/sound/soc-component.h:
struct snd_soc_component {
const char *name;
int id;
const char *name_prefix;
struct device *dev;
struct snd_soc_card *card;
unsigned int active;
unsigned int suspended:1; /* is in suspend PM state */
struct list_head list;
struct list_head card_aux_list; /* for auxiliary bound components */
struct list_head card_list;
const struct snd_soc_component_driver *driver;
struct list_head dai_list;
int num_dai;
struct regmap *regmap;
int val_bytes;
struct mutex io_mutex;
/* attached dynamic objects */
struct list_head dobj_list;
/*
* DO NOT use any of the fields below in drivers, they are temporary and
* are going to be removed again soon. If you use them in driver code
* the driver will be marked as BROKEN when these fields are removed.
*/
/* Don't use these, use snd_soc_component_get_dapm() */
struct snd_soc_dapm_context dapm;
/* machine specific init */
int (*init)(struct snd_soc_component *component);
/* function mark */
void *mark_module;
struct snd_pcm_substream *mark_open;
struct snd_pcm_substream *mark_hw_params;
struct snd_pcm_substream *mark_trigger;
struct snd_compr_stream *mark_compr_open;
void *mark_pm;
struct dentry *debugfs_root;
const char *debugfs_prefix;
};
其中:
- name:名称,音频数据链路可以通过这个字段到全局链表component_list中查找与之匹配的component;
- dapm:dapm域;
- dev:一般为codec设备对应的struct device;
- regmap:regmap实例,regmap一种通用的接口来操作底层硬件寄存器;
- name_prefix:名称前缀,如果使用设备树的话,取自dev设备节点的属性"sound-name-prefix";
- card:ASoC声卡设备;
- dai_list:保存dai的链表;链表中的数据元素类型为struct snd_soc_dai;
- num_dai:dai_list链表的长度;
- driver:component driver;
- list:用于构建链表节点,将当前节点添加到全局链表component_list;
- card_list:用于构建链表节点,将当前节点添加到声卡的component_dev_list链表;
1.2 struct snd_soc_component_driver
ASoC使用snd_soc_component_driver来描述codec driver,定义在include/sound/soc-component.h:
struct snd_soc_component_driver {
const char *name;
/* Default control and setup, added after probe() is run */
const struct snd_kcontrol_new *controls;
unsigned int num_controls;
const struct snd_soc_dapm_widget *dapm_widgets;
unsigned int num_dapm_widgets;
const struct snd_soc_dapm_route *dapm_routes;
unsigned int num_dapm_routes;
int (*probe)(struct snd_soc_component *component);
void (*remove