summaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-core.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2008-12-04 15:32:53 +0000
committerMark Brown <broonie@opensource.wolfsonmicro.com>2008-12-09 13:30:04 +0000
commit435c5e2588893e3f7aba0bd4de67991bf00b3c9d (patch)
treeaa266a041709ae8a7a014162cf3564aca6c29d3c /sound/soc/soc-core.c
parent64089b84abfe2f26a864ebd968429302dcb071de (diff)
downloadblackbird-op-linux-435c5e2588893e3f7aba0bd4de67991bf00b3c9d.tar.gz
blackbird-op-linux-435c5e2588893e3f7aba0bd4de67991bf00b3c9d.zip
ASoC: Initial framework for dynamic card instantiation
Use the lists of platforms, platform DAIs and cards to check to see that everything has registered. Since relationships are still specified by direct references to the structures in the drivers and the drivers all register everything at modprobe there should be no practical effect yet. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
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 ffae370b45df..717db0e6499b 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);
OpenPOWER on IntegriCloud