aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-core.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2012-06-08 14:34:23 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-06-13 08:18:05 -0400
commit62ae68fa5d6d6f93d8ca8d00e21ad7ac410f9d58 (patch)
tree510b2f60d738bb2706dbf22e2930ca26de17cac9 /sound/soc/soc-core.c
parentd12cd198cba7949c70f596296297b772063175c0 (diff)
ASoC: probe CODECs and platforms before DAIs and links
soc_probe_dai_link() currently inter-mixes the probing of CODECs, platforms, and DAIs. This can lead to problems such as a CODEC's DAI being probed before the CODEC, if that DAI is used as the CPU-side of a DAI link without any other of the CODEC's DAIs having been used as the CODEC-side of any DAI link that was probed earlier. To solve this, split soc_probe_dai_link() into soc_probe_link_components() and soc_probe_link_dais(). The former is used to probe all CODECs and platforms used by a card first, and then the latter is used to probe all the DAIs and links later. A similar change is made to soc_remove_dai_links(). Signed-off-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r--sound/soc/soc-core.c129
1 files changed, 95 insertions, 34 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index a539ade477af..fe16135250f8 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -941,11 +941,9 @@ static void soc_remove_codec(struct snd_soc_codec *codec)
941 module_put(codec->dev->driver->owner); 941 module_put(codec->dev->driver->owner);
942} 942}
943 943
944static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order) 944static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order)
945{ 945{
946 struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; 946 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
947 struct snd_soc_codec *codec = rtd->codec;
948 struct snd_soc_platform *platform = rtd->platform;
949 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; 947 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
950 int err; 948 int err;
951 949
@@ -970,16 +968,6 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
970 list_del(&codec_dai->card_list); 968 list_del(&codec_dai->card_list);
971 } 969 }
972 970
973 /* remove the platform */
974 if (platform && platform->probed &&
975 platform->driver->remove_order == order)
976 soc_remove_platform(platform);
977
978 /* remove the CODEC */
979 if (codec && codec->probed &&
980 codec->driver->remove_order == order)
981 soc_remove_codec(codec);
982
983 /* remove the cpu_dai */ 971 /* remove the cpu_dai */
984 if (cpu_dai && cpu_dai->probed && 972 if (cpu_dai && cpu_dai->probed &&
985 cpu_dai->driver->remove_order == order) { 973 cpu_dai->driver->remove_order == order) {
@@ -999,6 +987,38 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
999 } 987 }
1000} 988}
1001 989
990static void soc_remove_link_components(struct snd_soc_card *card, int num,
991 int order)
992{
993 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
994 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
995 struct snd_soc_dai *codec_dai = rtd->codec_dai;
996 struct snd_soc_platform *platform = rtd->platform;
997 struct snd_soc_codec *codec;
998
999 /* remove the platform */
1000 if (platform && platform->probed &&
1001 platform->driver->remove_order == order) {
1002 soc_remove_platform(platform);
1003 }
1004
1005 /* remove the CODEC-side CODEC */
1006 if (codec_dai) {
1007 codec = codec_dai->codec;
1008 if (codec && codec->probed &&
1009 codec->driver->remove_order == order)
1010 soc_remove_codec(codec);
1011 }
1012
1013 /* remove any CPU-side CODEC */
1014 if (cpu_dai) {
1015 codec = cpu_dai->codec;
1016 if (codec && codec->probed &&
1017 codec->driver->remove_order == order)
1018 soc_remove_codec(codec);
1019 }
1020}
1021
1002static void soc_remove_dai_links(struct snd_soc_card *card) 1022static void soc_remove_dai_links(struct snd_soc_card *card)
1003{ 1023{
1004 int dai, order; 1024 int dai, order;
@@ -1006,8 +1026,15 @@ static void soc_remove_dai_links(struct snd_soc_card *card)
1006 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; 1026 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1007 order++) { 1027 order++) {
1008 for (dai = 0; dai < card->num_rtd; dai++) 1028 for (dai = 0; dai < card->num_rtd; dai++)
1009 soc_remove_dai_link(card, dai, order); 1029 soc_remove_link_dais(card, dai, order);
1030 }
1031
1032 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1033 order++) {
1034 for (dai = 0; dai < card->num_rtd; dai++)
1035 soc_remove_link_components(card, dai, order);
1010 } 1036 }
1037
1011 card->num_rtd = 0; 1038 card->num_rtd = 0;
1012} 1039}
1013 1040
@@ -1244,7 +1271,44 @@ out:
1244 return 0; 1271 return 0;
1245} 1272}
1246 1273
1247static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order) 1274static int soc_probe_link_components(struct snd_soc_card *card, int num,
1275 int order)
1276{
1277 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
1278 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1279 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1280 struct snd_soc_platform *platform = rtd->platform;
1281 int ret;
1282
1283 /* probe the CPU-side component, if it is a CODEC */
1284 if (cpu_dai->codec &&
1285 !cpu_dai->codec->probed &&
1286 cpu_dai->codec->driver->probe_order == order) {
1287 ret = soc_probe_codec(card, cpu_dai->codec);
1288 if (ret < 0)
1289 return ret;
1290 }
1291
1292 /* probe the CODEC-side component */
1293 if (!codec_dai->codec->probed &&
1294 codec_dai->codec->driver->probe_order == order) {
1295 ret = soc_probe_codec(card, codec_dai->codec);
1296 if (ret < 0)
1297 return ret;
1298 }
1299
1300 /* probe the platform */
1301 if (!platform->probed &&
1302 platform->driver->probe_order == order) {
1303 ret = soc_probe_platform(card, platform);
1304 if (ret < 0)
1305 return ret;
1306 }
1307
1308 return 0;
1309}
1310
1311static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order)
1248{ 1312{
1249 struct snd_soc_dai_link *dai_link = &card->dai_link[num]; 1313 struct snd_soc_dai_link *dai_link = &card->dai_link[num];
1250 struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; 1314 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
@@ -1292,22 +1356,6 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
1292 list_add(&cpu_dai->card_list, &card->dai_dev_list); 1356 list_add(&cpu_dai->card_list, &card->dai_dev_list);
1293 } 1357 }
1294 1358
1295 /* probe the CODEC */
1296 if (!codec->probed &&
1297 codec->driver->probe_order == order) {
1298 ret = soc_probe_codec(card, codec);
1299 if (ret < 0)
1300 return ret;
1301 }
1302
1303 /* probe the platform */
1304 if (!platform->probed &&
1305 platform->driver->probe_order == order) {
1306 ret = soc_probe_platform(card, platform);
1307 if (ret < 0)
1308 return ret;
1309 }
1310
1311 /* probe the CODEC DAI */ 1359 /* probe the CODEC DAI */
1312 if (!codec_dai->probed && codec_dai->driver->probe_order == order) { 1360 if (!codec_dai->probed && codec_dai->driver->probe_order == order) {
1313 if (codec_dai->driver->probe) { 1361 if (codec_dai->driver->probe) {
@@ -1582,14 +1630,27 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
1582 goto card_probe_error; 1630 goto card_probe_error;
1583 } 1631 }
1584 1632
1585 /* early DAI link probe */ 1633 /* probe all components used by DAI links on this card */
1586 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; 1634 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1587 order++) { 1635 order++) {
1588 for (i = 0; i < card->num_links; i++) { 1636 for (i = 0; i < card->num_links; i++) {
1589 ret = soc_probe_dai_link(card, i, order); 1637 ret = soc_probe_link_components(card, i, order);
1590 if (ret < 0) { 1638 if (ret < 0) {
1591 pr_err("asoc: failed to instantiate card %s: %d\n", 1639 pr_err("asoc: failed to instantiate card %s: %d\n",
1592 card->name, ret); 1640 card->name, ret);
1641 goto probe_dai_err;
1642 }
1643 }
1644 }
1645
1646 /* probe all DAI links on this card */
1647 for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
1648 order++) {
1649 for (i = 0; i < card->num_links; i++) {
1650 ret = soc_probe_link_dais(card, i, order);
1651 if (ret < 0) {
1652 pr_err("asoc: failed to instantiate card %s: %d\n",
1653 card->name, ret);
1593 goto probe_dai_err; 1654 goto probe_dai_err;
1594 } 1655 }
1595 } 1656 }