aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/soc-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r--sound/soc/soc-core.c99
1 files changed, 79 insertions, 20 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index ffae370b45d..717db0e6499 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -780,30 +780,54 @@ static int soc_resume(struct platform_device *pdev)
#define soc_resume NULL
#endif
-/* probes a new socdev */
-static int soc_probe(struct platform_device *pdev)
-{
- int ret = 0, i;
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_card *card = socdev->card;
- struct snd_soc_platform *platform = card->platform;
- struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
-
- /* Bodge while we push things out of socdev */
- card->socdev = socdev;
+static void snd_soc_instantiate_card(struct snd_soc_card *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_platform *platform;
+ struct snd_soc_dai *dai;
+ int i, found, ret;
+
+ 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;
+ }
- /* Bodge while we unpick instantiation */
- card->dev = &pdev->dev;
- ret = snd_soc_register_card(card);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to register card\n");
- return ret;
+ 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;
+ }
}
+ /* 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 ret;
+ return;
}
for (i = 0; i < card->num_links; i++) {
@@ -834,7 +858,9 @@ static int soc_probe(struct platform_device *pdev)
INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
#endif
- return 0;
+ card->instantiated = 1;
+
+ return;
platform_err:
if (codec_dev->remove)
@@ -849,8 +875,38 @@ cpu_dai_err:
if (card->remove)
card->remove(pdev);
+}
- return ret;
+/*
+ * Attempt to initialise any uninitalised cards. Must be called with
+ * client_mutex.
+ */
+static void snd_soc_instantiate_cards(void)
+{
+ struct snd_soc_card *card;
+ list_for_each_entry(card, &card_list, list)
+ snd_soc_instantiate_card(card);
+}
+
+/* probes a new socdev */
+static int soc_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_card *card = socdev->card;
+
+ /* Bodge while we push things out of socdev */
+ card->socdev = socdev;
+
+ /* Bodge while we unpick instantiation */
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "Failed to register card\n");
+ return ret;
+ }
+
+ return 0;
}
/* removes a socdev */
@@ -1994,6 +2050,7 @@ static int snd_soc_register_card(struct snd_soc_card *card)
mutex_lock(&client_mutex);
list_add(&card->list, &card_list);
+ snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);
dev_dbg(card->dev, "Registered card '%s'\n", card->name);
@@ -2039,6 +2096,7 @@ int snd_soc_register_dai(struct snd_soc_dai *dai)
mutex_lock(&client_mutex);
list_add(&dai->list, &dai_list);
+ snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);
pr_debug("Registered DAI '%s'\n", dai->name);
@@ -2117,6 +2175,7 @@ int snd_soc_register_platform(struct snd_soc_platform *platform)
mutex_lock(&client_mutex);
list_add(&platform->list, &platform_list);
+ snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);
pr_debug("Registered platform '%s'\n", platform->name);