diff options
-rw-r--r-- | include/sound/soc.h | 1 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 147 |
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 | ||
56 | static DEFINE_MUTEX(client_mutex); | 56 | static DEFINE_MUTEX(client_mutex); |
57 | static LIST_HEAD(card_list); | ||
58 | static LIST_HEAD(dai_list); | 57 | static LIST_HEAD(dai_list); |
59 | static LIST_HEAD(platform_list); | 58 | static LIST_HEAD(platform_list); |
60 | static LIST_HEAD(codec_list); | 59 | static 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 | ||
812 | find_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 | ||
851 | find_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 | |||
880 | out: | ||
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 | ||
889 | static void soc_remove_codec(struct snd_soc_codec *codec) | 875 | static 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 | ||
1335 | static 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 | |||
1349 | static int soc_probe_aux_dev(struct snd_soc_card *card, int num) | 1349 | static 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 | ||
1371 | found: | 1371 | found: |
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 | ||
1419 | static void snd_soc_instantiate_card(struct snd_soc_card *card) | 1419 | static 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 | ||
1616 | probe_aux_dev_err: | 1613 | probe_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 | ||
1626 | base_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 | */ | ||
1636 | static 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 | */ |
3073 | int snd_soc_register_card(struct snd_soc_card *card) | 3062 | int 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 | } |
3148 | EXPORT_SYMBOL_GPL(snd_soc_register_card); | 3134 | EXPORT_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 | ||
3346 | err: | 3325 | err: |
@@ -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); |