aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-03-14 17:18:39 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-01 06:28:23 -0400
commitb19e6e7b763c7144bfe2ceccf988b64d66d6dd0a (patch)
treec80e0ad8c6f7f3d857345f7016627e7bb168ac76
parent2667b4b8bef8598917adb1b4af46ed2b7d4fa0d7 (diff)
ASoC: core: Use driver core probe deferral
In version 3.4 the driver core acquired probe deferral which is a core way of doing essentially the same thing as ASoC has been doing since forever to make sure that all the devices needed to make up the card are present without needing open coding in the subsystem. Make basic use of this probe deferral mechanism for the cards, removing the need to handle partially instantiated cards. We should be able to remove even more code than this, though some of the checks we're currently doing should stay since they're about things like suppressing unneeded DAPM runs rather than deferring probes. In order to avoid robustness issues with our teardown paths (which do need quite a bit of TLC) add a check for aux_devs prior to attempting to set things up, this means that we've got a reasonable idea that everything will be there before we start. As with the removal of partial instantiation support more work will be needed to make this work neatly. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@ti.com>
-rw-r--r--include/sound/soc.h1
-rw-r--r--sound/soc/soc-core.c147
2 files changed, 62 insertions, 86 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index b8163ddf94d2..9e238fa2eb17 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -896,7 +896,6 @@ struct snd_soc_pcm_runtime {
896 enum snd_soc_pcm_subclass pcm_subclass; 896 enum snd_soc_pcm_subclass pcm_subclass;
897 struct snd_pcm_ops ops; 897 struct snd_pcm_ops ops;
898 898
899 unsigned int complete:1;
900 unsigned int dev_registered:1; 899 unsigned int dev_registered:1;
901 900
902 long pmdown_time; 901 long pmdown_time;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 61b51b673d49..cab72f87c194 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -54,7 +54,6 @@ EXPORT_SYMBOL_GPL(snd_soc_debugfs_root);
54#endif 54#endif
55 55
56static DEFINE_MUTEX(client_mutex); 56static DEFINE_MUTEX(client_mutex);
57static LIST_HEAD(card_list);
58static LIST_HEAD(dai_list); 57static LIST_HEAD(dai_list);
59static LIST_HEAD(platform_list); 58static LIST_HEAD(platform_list);
60static LIST_HEAD(codec_list); 59static LIST_HEAD(codec_list);
@@ -785,15 +784,9 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
785 struct snd_soc_dai *codec_dai, *cpu_dai; 784 struct snd_soc_dai *codec_dai, *cpu_dai;
786 const char *platform_name; 785 const char *platform_name;
787 786
788 if (rtd->complete)
789 return 1;
790 dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num); 787 dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num);
791 788
792 /* do we already have the CPU DAI for this link ? */ 789 /* Find CPU DAI from registered DAIs*/
793 if (rtd->cpu_dai) {
794 goto find_codec;
795 }
796 /* no, then find CPU DAI from registered DAIs*/
797 list_for_each_entry(cpu_dai, &dai_list, list) { 790 list_for_each_entry(cpu_dai, &dai_list, list) {
798 if (dai_link->cpu_dai_of_node) { 791 if (dai_link->cpu_dai_of_node) {
799 if (cpu_dai->dev->of_node != dai_link->cpu_dai_of_node) 792 if (cpu_dai->dev->of_node != dai_link->cpu_dai_of_node)
@@ -804,18 +797,15 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
804 } 797 }
805 798
806 rtd->cpu_dai = cpu_dai; 799 rtd->cpu_dai = cpu_dai;
807 goto find_codec;
808 } 800 }
809 dev_dbg(card->dev, "CPU DAI %s not registered\n",
810 dai_link->cpu_dai_name);
811 801
812find_codec: 802 if (!rtd->cpu_dai) {
813 /* do we already have the CODEC for this link ? */ 803 dev_dbg(card->dev, "CPU DAI %s not registered\n",
814 if (rtd->codec) { 804 dai_link->cpu_dai_name);
815 goto find_platform; 805 return -EPROBE_DEFER;
816 } 806 }
817 807
818 /* no, then find CODEC from registered CODECs*/ 808 /* Find CODEC from registered CODECs */
819 list_for_each_entry(codec, &codec_list, list) { 809 list_for_each_entry(codec, &codec_list, list) {
820 if (dai_link->codec_of_node) { 810 if (dai_link->codec_of_node) {
821 if (codec->dev->of_node != dai_link->codec_of_node) 811 if (codec->dev->of_node != dai_link->codec_of_node)
@@ -837,28 +827,28 @@ find_codec:
837 dai_link->codec_dai_name)) { 827 dai_link->codec_dai_name)) {
838 828
839 rtd->codec_dai = codec_dai; 829 rtd->codec_dai = codec_dai;
840 goto find_platform;
841 } 830 }
842 } 831 }
843 dev_dbg(card->dev, "CODEC DAI %s not registered\n",
844 dai_link->codec_dai_name);
845 832
846 goto find_platform; 833 if (!rtd->codec_dai) {
834 dev_dbg(card->dev, "CODEC DAI %s not registered\n",
835 dai_link->codec_dai_name);
836 return -EPROBE_DEFER;
837 }
847 } 838 }
848 dev_dbg(card->dev, "CODEC %s not registered\n",
849 dai_link->codec_name);
850 839
851find_platform: 840 if (!rtd->codec) {
852 /* do we need a platform? */ 841 dev_dbg(card->dev, "CODEC %s not registered\n",
853 if (rtd->platform) 842 dai_link->codec_name);
854 goto out; 843 return -EPROBE_DEFER;
844 }
855 845
856 /* if there's no platform we match on the empty platform */ 846 /* if there's no platform we match on the empty platform */
857 platform_name = dai_link->platform_name; 847 platform_name = dai_link->platform_name;
858 if (!platform_name && !dai_link->platform_of_node) 848 if (!platform_name && !dai_link->platform_of_node)
859 platform_name = "snd-soc-dummy"; 849 platform_name = "snd-soc-dummy";
860 850
861 /* no, then find one from the set of registered platforms */ 851 /* find one from the set of registered platforms */
862 list_for_each_entry(platform, &platform_list, list) { 852 list_for_each_entry(platform, &platform_list, list) {
863 if (dai_link->platform_of_node) { 853 if (dai_link->platform_of_node) {
864 if (platform->dev->of_node != 854 if (platform->dev->of_node !=
@@ -870,20 +860,16 @@ find_platform:
870 } 860 }
871 861
872 rtd->platform = platform; 862 rtd->platform = platform;
873 goto out;
874 } 863 }
875 864 if (!rtd->platform) {
876 dev_dbg(card->dev, "platform %s not registered\n", 865 dev_dbg(card->dev, "platform %s not registered\n",
877 dai_link->platform_name); 866 dai_link->platform_name);
878 return 0; 867 return -EPROBE_DEFER;
879
880out:
881 /* mark rtd as complete if we found all 4 of our client devices */
882 if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) {
883 rtd->complete = 1;
884 card->num_rtd++;
885 } 868 }
886 return 1; 869
870 card->num_rtd++;
871
872 return 0;
887} 873}
888 874
889static void soc_remove_codec(struct snd_soc_codec *codec) 875static void soc_remove_codec(struct snd_soc_codec *codec)
@@ -1346,6 +1332,20 @@ static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec)
1346} 1332}
1347#endif 1333#endif
1348 1334
1335static int soc_check_aux_dev(struct snd_soc_card *card, int num)
1336{
1337 struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
1338 struct snd_soc_codec *codec;
1339
1340 /* find CODEC from registered CODECs*/
1341 list_for_each_entry(codec, &codec_list, list) {
1342 if (!strcmp(codec->name, aux_dev->codec_name))
1343 return 0;
1344 }
1345
1346 return -EPROBE_DEFER;
1347}
1348
1349static int soc_probe_aux_dev(struct snd_soc_card *card, int num) 1349static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
1350{ 1350{
1351 struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; 1351 struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
@@ -1366,7 +1366,7 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
1366 } 1366 }
1367 /* codec not found */ 1367 /* codec not found */
1368 dev_err(card->dev, "asoc: codec %s not found", aux_dev->codec_name); 1368 dev_err(card->dev, "asoc: codec %s not found", aux_dev->codec_name);
1369 goto out; 1369 return -EPROBE_DEFER;
1370 1370
1371found: 1371found:
1372 ret = soc_probe_codec(card, codec); 1372 ret = soc_probe_codec(card, codec);
@@ -1416,7 +1416,7 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
1416 return 0; 1416 return 0;
1417} 1417}
1418 1418
1419static void snd_soc_instantiate_card(struct snd_soc_card *card) 1419static int snd_soc_instantiate_card(struct snd_soc_card *card)
1420{ 1420{
1421 struct snd_soc_codec *codec; 1421 struct snd_soc_codec *codec;
1422 struct snd_soc_codec_conf *codec_conf; 1422 struct snd_soc_codec_conf *codec_conf;
@@ -1426,19 +1426,18 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
1426 1426
1427 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT); 1427 mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
1428 1428
1429 if (card->instantiated) {
1430 mutex_unlock(&card->mutex);
1431 return;
1432 }
1433
1434 /* bind DAIs */ 1429 /* bind DAIs */
1435 for (i = 0; i < card->num_links; i++) 1430 for (i = 0; i < card->num_links; i++) {
1436 soc_bind_dai_link(card, i); 1431 ret = soc_bind_dai_link(card, i);
1432 if (ret != 0)
1433 goto base_error;
1434 }
1437 1435
1438 /* bind completed ? */ 1436 /* check aux_devs too */
1439 if (card->num_rtd != card->num_links) { 1437 for (i = 0; i < card->num_aux_devs; i++) {
1440 mutex_unlock(&card->mutex); 1438 ret = soc_check_aux_dev(card, i);
1441 return; 1439 if (ret != 0)
1440 goto base_error;
1442 } 1441 }
1443 1442
1444 /* initialize the register cache for each available codec */ 1443 /* initialize the register cache for each available codec */
@@ -1458,10 +1457,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
1458 } 1457 }
1459 } 1458 }
1460 ret = snd_soc_init_codec_cache(codec, compress_type); 1459 ret = snd_soc_init_codec_cache(codec, compress_type);
1461 if (ret < 0) { 1460 if (ret < 0)
1462 mutex_unlock(&card->mutex); 1461 goto base_error;
1463 return;
1464 }
1465 } 1462 }
1466 1463
1467 /* card bind complete so register a sound card */ 1464 /* card bind complete so register a sound card */
@@ -1470,8 +1467,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
1470 if (ret < 0) { 1467 if (ret < 0) {
1471 pr_err("asoc: can't create sound card for card %s: %d\n", 1468 pr_err("asoc: can't create sound card for card %s: %d\n",
1472 card->name, ret); 1469 card->name, ret);
1473 mutex_unlock(&card->mutex); 1470 goto base_error;
1474 return;
1475 } 1471 }
1476 card->snd_card->dev = card->dev; 1472 card->snd_card->dev = card->dev;
1477 1473
@@ -1611,7 +1607,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
1611 card->instantiated = 1; 1607 card->instantiated = 1;
1612 snd_soc_dapm_sync(&card->dapm); 1608 snd_soc_dapm_sync(&card->dapm);
1613 mutex_unlock(&card->mutex); 1609 mutex_unlock(&card->mutex);
1614 return; 1610
1611 return 0;
1615 1612
1616probe_aux_dev_err: 1613probe_aux_dev_err:
1617 for (i = 0; i < card->num_aux_devs; i++) 1614 for (i = 0; i < card->num_aux_devs; i++)
@@ -1626,18 +1623,10 @@ card_probe_error:
1626 1623
1627 snd_card_free(card->snd_card); 1624 snd_card_free(card->snd_card);
1628 1625
1626base_error:
1629 mutex_unlock(&card->mutex); 1627 mutex_unlock(&card->mutex);
1630}
1631 1628
1632/* 1629 return ret;
1633 * Attempt to initialise any uninitialised cards. Must be called with
1634 * client_mutex.
1635 */
1636static void snd_soc_instantiate_cards(void)
1637{
1638 struct snd_soc_card *card;
1639 list_for_each_entry(card, &card_list, list)
1640 snd_soc_instantiate_card(card);
1641} 1630}
1642 1631
1643/* probes a new socdev */ 1632/* probes a new socdev */
@@ -3072,7 +3061,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
3072 */ 3061 */
3073int snd_soc_register_card(struct snd_soc_card *card) 3062int snd_soc_register_card(struct snd_soc_card *card)
3074{ 3063{
3075 int i; 3064 int i, ret;
3076 3065
3077 if (!card->name || !card->dev) 3066 if (!card->name || !card->dev)
3078 return -EINVAL; 3067 return -EINVAL;
@@ -3136,14 +3125,11 @@ int snd_soc_register_card(struct snd_soc_card *card)
3136 mutex_init(&card->mutex); 3125 mutex_init(&card->mutex);
3137 mutex_init(&card->dapm_mutex); 3126 mutex_init(&card->dapm_mutex);
3138 3127
3139 mutex_lock(&client_mutex); 3128 ret = snd_soc_instantiate_card(card);
3140 list_add(&card->list, &card_list); 3129 if (ret != 0)
3141 snd_soc_instantiate_cards(); 3130 soc_cleanup_card_debugfs(card);
3142 mutex_unlock(&client_mutex);
3143 3131
3144 dev_dbg(card->dev, "Registered card '%s'\n", card->name); 3132 return ret;
3145
3146 return 0;
3147} 3133}
3148EXPORT_SYMBOL_GPL(snd_soc_register_card); 3134EXPORT_SYMBOL_GPL(snd_soc_register_card);
3149 3135
@@ -3157,9 +3143,6 @@ int snd_soc_unregister_card(struct snd_soc_card *card)
3157{ 3143{
3158 if (card->instantiated) 3144 if (card->instantiated)
3159 soc_cleanup_card_resources(card); 3145 soc_cleanup_card_resources(card);
3160 mutex_lock(&client_mutex);
3161 list_del(&card->list);
3162 mutex_unlock(&client_mutex);
3163 dev_dbg(card->dev, "Unregistered card '%s'\n", card->name); 3146 dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
3164 3147
3165 return 0; 3148 return 0;
@@ -3256,7 +3239,6 @@ int snd_soc_register_dai(struct device *dev,
3256 3239
3257 mutex_lock(&client_mutex); 3240 mutex_lock(&client_mutex);
3258 list_add(&dai->list, &dai_list); 3241 list_add(&dai->list, &dai_list);
3259 snd_soc_instantiate_cards();
3260 mutex_unlock(&client_mutex); 3242 mutex_unlock(&client_mutex);
3261 3243
3262 pr_debug("Registered DAI '%s'\n", dai->name); 3244 pr_debug("Registered DAI '%s'\n", dai->name);
@@ -3338,9 +3320,6 @@ int snd_soc_register_dais(struct device *dev,
3338 pr_debug("Registered DAI '%s'\n", dai->name); 3320 pr_debug("Registered DAI '%s'\n", dai->name);
3339 } 3321 }
3340 3322
3341 mutex_lock(&client_mutex);
3342 snd_soc_instantiate_cards();
3343 mutex_unlock(&client_mutex);
3344 return 0; 3323 return 0;
3345 3324
3346err: 3325err:
@@ -3398,7 +3377,6 @@ int snd_soc_register_platform(struct device *dev,
3398 3377
3399 mutex_lock(&client_mutex); 3378 mutex_lock(&client_mutex);
3400 list_add(&platform->list, &platform_list); 3379 list_add(&platform->list, &platform_list);
3401 snd_soc_instantiate_cards();
3402 mutex_unlock(&client_mutex); 3380 mutex_unlock(&client_mutex);
3403 3381
3404 pr_debug("Registered platform '%s'\n", platform->name); 3382 pr_debug("Registered platform '%s'\n", platform->name);
@@ -3557,7 +3535,6 @@ int snd_soc_register_codec(struct device *dev,
3557 3535
3558 mutex_lock(&client_mutex); 3536 mutex_lock(&client_mutex);
3559 list_add(&codec->list, &codec_list); 3537 list_add(&codec->list, &codec_list);
3560 snd_soc_instantiate_cards();
3561 mutex_unlock(&client_mutex); 3538 mutex_unlock(&client_mutex);
3562 3539
3563 pr_debug("Registered codec '%s'\n", codec->name); 3540 pr_debug("Registered codec '%s'\n", codec->name);