参照元†
- struct snd_soc_card *card
返り値†
static void snd_soc_instantiate_card()
{
struct platform_device *pdev = container_of(card->dev,
struct platform_device,
dev);
struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev;
struct snd_soc_codec *codec;
struct snd_soc_platform *platform;
struct snd_soc_dai *dai;
int i, found, ret, ac97;
if (card->instantiated)
return;
found = 0;
list_for_each_entry(platform, &platform_list, list)
if (card->platform == platform) {
found = 1;
break;
}
if (!found) {
dev_dbg(card->dev, "Platform %s not registered\n",
card->platform->name);
return;
}
ac97 = 0;
for (i = 0; i < card->num_links; i++) {
found = 0;
list_for_each_entry(dai, &dai_list, list)
if (card->dai_link[i].cpu_dai == dai) {
found = 1;
break;
}
if (!found) {
dev_dbg(card->dev, "DAI %s not registered\n",
card->dai_link[i].cpu_dai->name);
return;
}
if (card->dai_link[i].cpu_dai->ac97_control)
ac97 = 1;
}
for (i = 0; i < card->num_links; i++) {
if (!card->dai_link[i].codec_dai->ops)
card->dai_link[i].codec_dai->ops = &null_dai_ops;
}
/* If we have AC97 in the system then don't wait for the
* codec. This will need revisiting if we have to handle
* systems with mixed AC97 and non-AC97 parts. Only check for
* DAIs currently; we can't do this per link since some AC97
* codecs have non-AC97 DAIs.
*/
if (!ac97)
for (i = 0; i < card->num_links; i++) {
found = 0;
list_for_each_entry(dai, &dai_list, list)
if (card->dai_link[i].codec_dai == dai) {
found = 1;
break;
}
if (!found) {
dev_dbg(card->dev, "DAI %s not registered\n",
card->dai_link[i].codec_dai->name);
return;
}
}
/* Note that we do not current check for codec components */
dev_dbg(card->dev, "All components present, instantiating\n");
/* Found everything, bring it up */
if (card->probe) {
ret = card->probe(pdev);
if (ret < 0)
return;
}
for (i = 0; i < card->num_links; i++) {
struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
if (cpu_dai->probe) {
ret = cpu_dai->probe(pdev, cpu_dai);
if (ret < 0)
goto cpu_dai_err;
}
}
if (codec_dev->probe) {
ret = codec_dev->probe(pdev);
if (ret < 0)
goto cpu_dai_err;
}
codec = card->codec;
if (platform->probe) {
ret = platform->probe(pdev);
if (ret < 0)
goto platform_err;
}
/* DAPM stream work */
INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work);
#ifdef CONFIG_PM
/* deferred resume work */
INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
#endif
for (i = 0; i < card->num_links; i++) {
if (card->dai_link[i].init) {
ret = card->dai_link[i].init(codec);
if (ret < 0) {
printk(KERN_ERR "asoc: failed to init %s\n",
card->dai_link[i].stream_name);
continue;
}
}
if (card->dai_link[i].codec_dai->ac97_control)
ac97 = 1;
}
snprintf(codec->card->shortname, sizeof(codec->card->shortname),
"%s", card->name);
snprintf(codec->card->longname, sizeof(codec->card->longname),
"%s (%s)", card->name, codec->name);
/* Make sure all DAPM widgets are instantiated */
snd_soc_dapm_new_widgets(codec);
ret = snd_card_register(codec->card);
if (ret < 0) {
printk(KERN_ERR "asoc: failed to register soundcard for %s\n",
codec->name);
goto card_err;
}
mutex_lock(&codec->mutex);
#ifdef CONFIG_SND_SOC_AC97_BUS
/* Only instantiate AC97 if not already done by the adaptor
* for the generic AC97 subsystem.
*/
if (ac97 && strcmp(codec->name, "AC97") != 0) {
ret = soc_ac97_dev_register(codec);
if (ret < 0) {
printk(KERN_ERR "asoc: AC97 device register failed\n");
snd_card_free(codec->card);
mutex_unlock(&codec->mutex);
goto card_err;
}
}
#endif
ret = snd_soc_dapm_sys_add(card->socdev->dev);
if (ret < 0)
printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg);
if (ret < 0)
printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
soc_init_codec_debugfs(codec);
mutex_unlock(&codec->mutex);
card->instantiated = 1;
return;
card_err:
if (platform->remove)
platform->remove(pdev);
platform_err:
if (codec_dev->remove)
codec_dev->remove(pdev);
cpu_dai_err:
for (i--; i >= 0; i--) {
struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
if (cpu_dai->remove)
cpu_dai->remove(pdev, cpu_dai);
}
if (card->remove)
card->remove(pdev);
}
コメント†