参照元†
- struct snd_soc_card *card
返り値†
/**
* snd_soc_register_card - Register a card with the ASoC core
*
* @card: Card to register
*
*/
int snd_soc_register_card(struct snd_soc_card *card)
{
int i, j, ret;
if (!card->name || !card->dev)
return -EINVAL;
for (i = 0; i < card->num_links; i++) {
struct snd_soc_dai_link *link = &card->dai_link[i];
ret = snd_soc_init_multicodec(card, link);
if (ret) {
dev_err(card->dev, "ASoC: failed to init multicodec\n");
return ret;
}
for (j = 0; j < link->num_codecs; j++) {
/*
* Codec must be specified by 1 of name or OF node,
* not both or neither.
*/
if (!!link->codecs[j].name ==
!!link->codecs[j].of_node) {
dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n",
link->name);
return -EINVAL;
}
/* Codec DAI name must be specified */
if (!link->codecs[j].dai_name) {
dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n",
link->name);
return -EINVAL;
}
}
/*
* Platform may be specified by either name or OF node, but
* can be left unspecified, and a dummy platform will be used.
*/
if (link->platform_name && link->platform_of_node) {
dev_err(card->dev,
"ASoC: Both platform name/of_node are set for %s\n",
link->name);
return -EINVAL;
}
/*
* CPU device may be specified by either name or OF node, but
* can be left unspecified, and will be matched based on DAI
* name alone..
*/
if (link->cpu_name && link->cpu_of_node) {
dev_err(card->dev,
"ASoC: Neither/both cpu name/of_node are set for %s\n",
link->name);
return -EINVAL;
}
/*
* At least one of CPU DAI name or CPU device name/node must be
* specified
*/
if (!link->cpu_dai_name &&
!(link->cpu_name || link->cpu_of_node)) {
dev_err(card->dev,
"ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n",
link->name);
return -EINVAL;
}
}
dev_set_drvdata(card->dev, card);
snd_soc_initialize_card_lists(card);
card->rtd = devm_kzalloc(card->dev,
sizeof(struct snd_soc_pcm_runtime) *
(card->num_links + card->num_aux_devs),
GFP_KERNEL);
if (card->rtd == NULL)
return -ENOMEM;
card->num_rtd = 0;
card->rtd_aux = &card->rtd[card->num_links];
for (i = 0; i < card->num_links; i++) {
card->rtd[i].card = card;
card->rtd[i].dai_link = &card->dai_link[i];
card->rtd[i].codec_dais = devm_kzalloc(card->dev,
sizeof(struct snd_soc_dai *) *
(card->rtd[i].dai_link->num_codecs),
GFP_KERNEL);
if (card->rtd[i].codec_dais == NULL)
return -ENOMEM;
}
for (i = 0; i < card->num_aux_devs; i++)
card->rtd_aux[i].card = card;
INIT_LIST_HEAD(&card->dapm_dirty);
INIT_LIST_HEAD(&card->dobj_list);
card->instantiated = 0;
mutex_init(&card->mutex);
mutex_init(&card->dapm_mutex);
ret = snd_soc_instantiate_card(card);
if (ret != 0)
return ret;
/* deactivate pins to sleep state */
for (i = 0; i < card->num_rtd; i++) {
struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int j;
for (j = 0; j < rtd->num_codecs; j++) {
struct snd_soc_dai *codec_dai = rtd->codec_dais[j];
if (!codec_dai->active)
pinctrl_pm_select_sleep_state(codec_dai->dev);
}
if (!cpu_dai->active)
pinctrl_pm_select_sleep_state(cpu_dai->dev);
}
return ret;
}
コメント†