函数snd_soc_register_dais()主要作用是向ASoC core注册DAIs(Digital Audio Interface).
一个codec可能支持多种DAIs(Digital Audio Interface),如AC97,I2S,PCM,最近的项目中,一般只使用I2S。但是,代码中是支持多个DAIs(Digital Audio Interface),函数的第3个参数”count“就是DAIs(Digital Audio Interface)的数目。
下面一起来看看这个函数是如何运行的,
1. 上面我们提到,代码中是支持多个DAIs(Digital Audio Interface),函数的第3个参数”count“就是DAIs(Digital Audio Interface)的数目。函数刚开始就有一个for循环来实现这个功能,
for (i = 0; i < count; i++) {
2. 下面是为DAIs(Digital Audio Interface)设备的结构体申请内核空间并初始化,
dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
if (dai == NULL) {
ret = -ENOMEM;
goto err;
}
3. 下面是为每一个DAIs(Digital Audio Interface)创建一个名称
/* create DAI component name */
dai->name = fmt_multiple_name(dev, &dai_drv[i]);
if (dai->name == NULL) {
kfree(dai);
ret = -EINVAL;
goto err;
}
4. 下面是对DAIs(Digital Audio Interface)设备结构体的初始化,包括dev/driver/id
dai->dev = dev;
dai->driver = &dai_drv[i];
if (dai->driver->id)
dai->id = dai->driver->id;
else
dai->id = i;
dai->dapm.dev = dev;
if (!dai->driver->ops)
dai->driver->ops = &null_dai_ops;
5. 下面首先从列表(list)获取codec设备,并与DAI(Digital Audio Interface)关联起来,之后把DAI(Digital Audio Interface)也存放到列表中。
list_for_each_entry(codec, &codec_list, list) {
if (codec->dev == dev) {
dev_dbg(dev, "ASoC: Mapped DAI %s to "
"CODEC %s\n", dai->name, codec->name);
dai->codec = codec;
break;
}
}
if (!dai->codec)
dai->dapm.idle_bias_off = 1;
list_add(&dai->list, &dai_list);
至此,DAI(Digital Audio Interface)与codec也已经关联起来。函数snd_soc_register_dais()到此结束。
下面是snd_soc_dai结构体定义,
/*
* Digital Audio Interface runtime data.
*
* Holds runtime data for a DAI.
*/
struct snd_soc_dai {
const char *name;
int id;
struct device *dev;
void *ac97_pdata; /* platform_data for the ac97 codec */
/* driver ops */
struct snd_soc_dai_driver *driver;
/* DAI runtime info */
unsigned int capture_active:1; /* stream is in use */
unsigned int playback_active:1; /* stream is in use */
unsigned int symmetric_rates:1;
struct snd_pcm_runtime *runtime;
unsigned int active;
unsigned char probed:1;
struct snd_soc_dapm_widget *playback_widget;
struct snd_soc_dapm_widget *capture_widget;
struct snd_soc_dapm_context dapm;
/* DAI DMA data */
void *playback_dma_data;
void *capture_dma_data;
/* Symmetry data - only valid if symmetry is being enforced */
unsigned int rate;
/* parent platform/codec */
struct snd_soc_platform *platform;
struct snd_soc_codec *codec;
struct snd_soc_card *card;
struct list_head list;
struct list_head card_list;
};
/*
* Digital Audio Interface Driver.
*
* Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97
* operations and capabilities. Codec and platform drivers will register this
* structure for every DAI they have.
*
* This structure covers the clocking, formating and ALSA operations for each
* interface.
*/
struct snd_soc_dai_driver {
/* DAI description */
const char *name;
unsigned int id;
int ac97_control;
unsigned int base;
/* DAI driver callbacks */
int (*probe)(struct snd_soc_dai *dai);
int (*remove)(struct snd_soc_dai *dai);
int (*suspend)(struct snd_soc_dai *dai);
int (*resume)(struct snd_soc_dai *dai);
/* compress dai */
bool compress_dai;
/* ops */
const struct snd_soc_dai_ops *ops;
/* DAI capabilities */
struct snd_soc_pcm_stream capture;
struct snd_soc_pcm_stream playback;
unsigned int symmetric_rates:1;
/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
};