diff options
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 602 |
1 files changed, 394 insertions, 208 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a1305f827a98..19f7486bf335 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -537,26 +537,75 @@ static inline void snd_soc_debugfs_exit(void) | |||
537 | struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, | 537 | struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, |
538 | const char *dai_link, int stream) | 538 | const char *dai_link, int stream) |
539 | { | 539 | { |
540 | int i; | 540 | struct snd_soc_pcm_runtime *rtd; |
541 | 541 | ||
542 | for (i = 0; i < card->num_links; i++) { | 542 | list_for_each_entry(rtd, &card->rtd_list, list) { |
543 | if (card->rtd[i].dai_link->no_pcm && | 543 | if (rtd->dai_link->no_pcm && |
544 | !strcmp(card->rtd[i].dai_link->name, dai_link)) | 544 | !strcmp(rtd->dai_link->name, dai_link)) |
545 | return card->rtd[i].pcm->streams[stream].substream; | 545 | return rtd->pcm->streams[stream].substream; |
546 | } | 546 | } |
547 | dev_dbg(card->dev, "ASoC: failed to find dai link %s\n", dai_link); | 547 | dev_dbg(card->dev, "ASoC: failed to find dai link %s\n", dai_link); |
548 | return NULL; | 548 | return NULL; |
549 | } | 549 | } |
550 | EXPORT_SYMBOL_GPL(snd_soc_get_dai_substream); | 550 | EXPORT_SYMBOL_GPL(snd_soc_get_dai_substream); |
551 | 551 | ||
552 | static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( | ||
553 | struct snd_soc_card *card, struct snd_soc_dai_link *dai_link) | ||
554 | { | ||
555 | struct snd_soc_pcm_runtime *rtd; | ||
556 | |||
557 | rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL); | ||
558 | if (!rtd) | ||
559 | return NULL; | ||
560 | |||
561 | rtd->card = card; | ||
562 | rtd->dai_link = dai_link; | ||
563 | rtd->codec_dais = kzalloc(sizeof(struct snd_soc_dai *) * | ||
564 | dai_link->num_codecs, | ||
565 | GFP_KERNEL); | ||
566 | if (!rtd->codec_dais) { | ||
567 | kfree(rtd); | ||
568 | return NULL; | ||
569 | } | ||
570 | |||
571 | return rtd; | ||
572 | } | ||
573 | |||
574 | static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd) | ||
575 | { | ||
576 | if (rtd && rtd->codec_dais) | ||
577 | kfree(rtd->codec_dais); | ||
578 | kfree(rtd); | ||
579 | } | ||
580 | |||
581 | static void soc_add_pcm_runtime(struct snd_soc_card *card, | ||
582 | struct snd_soc_pcm_runtime *rtd) | ||
583 | { | ||
584 | list_add_tail(&rtd->list, &card->rtd_list); | ||
585 | rtd->num = card->num_rtd; | ||
586 | card->num_rtd++; | ||
587 | } | ||
588 | |||
589 | static void soc_remove_pcm_runtimes(struct snd_soc_card *card) | ||
590 | { | ||
591 | struct snd_soc_pcm_runtime *rtd, *_rtd; | ||
592 | |||
593 | list_for_each_entry_safe(rtd, _rtd, &card->rtd_list, list) { | ||
594 | list_del(&rtd->list); | ||
595 | soc_free_pcm_runtime(rtd); | ||
596 | } | ||
597 | |||
598 | card->num_rtd = 0; | ||
599 | } | ||
600 | |||
552 | struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, | 601 | struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, |
553 | const char *dai_link) | 602 | const char *dai_link) |
554 | { | 603 | { |
555 | int i; | 604 | struct snd_soc_pcm_runtime *rtd; |
556 | 605 | ||
557 | for (i = 0; i < card->num_links; i++) { | 606 | list_for_each_entry(rtd, &card->rtd_list, list) { |
558 | if (!strcmp(card->rtd[i].dai_link->name, dai_link)) | 607 | if (!strcmp(rtd->dai_link->name, dai_link)) |
559 | return &card->rtd[i]; | 608 | return rtd; |
560 | } | 609 | } |
561 | dev_dbg(card->dev, "ASoC: failed to find rtd %s\n", dai_link); | 610 | dev_dbg(card->dev, "ASoC: failed to find rtd %s\n", dai_link); |
562 | return NULL; | 611 | return NULL; |
@@ -578,7 +627,8 @@ int snd_soc_suspend(struct device *dev) | |||
578 | { | 627 | { |
579 | struct snd_soc_card *card = dev_get_drvdata(dev); | 628 | struct snd_soc_card *card = dev_get_drvdata(dev); |
580 | struct snd_soc_codec *codec; | 629 | struct snd_soc_codec *codec; |
581 | int i, j; | 630 | struct snd_soc_pcm_runtime *rtd; |
631 | int i; | ||
582 | 632 | ||
583 | /* If the card is not initialized yet there is nothing to do */ | 633 | /* If the card is not initialized yet there is nothing to do */ |
584 | if (!card->instantiated) | 634 | if (!card->instantiated) |
@@ -595,13 +645,13 @@ int snd_soc_suspend(struct device *dev) | |||
595 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); | 645 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); |
596 | 646 | ||
597 | /* mute any active DACs */ | 647 | /* mute any active DACs */ |
598 | for (i = 0; i < card->num_rtd; i++) { | 648 | list_for_each_entry(rtd, &card->rtd_list, list) { |
599 | 649 | ||
600 | if (card->rtd[i].dai_link->ignore_suspend) | 650 | if (rtd->dai_link->ignore_suspend) |
601 | continue; | 651 | continue; |
602 | 652 | ||
603 | for (j = 0; j < card->rtd[i].num_codecs; j++) { | 653 | for (i = 0; i < rtd->num_codecs; i++) { |
604 | struct snd_soc_dai *dai = card->rtd[i].codec_dais[j]; | 654 | struct snd_soc_dai *dai = rtd->codec_dais[i]; |
605 | struct snd_soc_dai_driver *drv = dai->driver; | 655 | struct snd_soc_dai_driver *drv = dai->driver; |
606 | 656 | ||
607 | if (drv->ops->digital_mute && dai->playback_active) | 657 | if (drv->ops->digital_mute && dai->playback_active) |
@@ -610,20 +660,20 @@ int snd_soc_suspend(struct device *dev) | |||
610 | } | 660 | } |
611 | 661 | ||
612 | /* suspend all pcms */ | 662 | /* suspend all pcms */ |
613 | for (i = 0; i < card->num_rtd; i++) { | 663 | list_for_each_entry(rtd, &card->rtd_list, list) { |
614 | if (card->rtd[i].dai_link->ignore_suspend) | 664 | if (rtd->dai_link->ignore_suspend) |
615 | continue; | 665 | continue; |
616 | 666 | ||
617 | snd_pcm_suspend_all(card->rtd[i].pcm); | 667 | snd_pcm_suspend_all(rtd->pcm); |
618 | } | 668 | } |
619 | 669 | ||
620 | if (card->suspend_pre) | 670 | if (card->suspend_pre) |
621 | card->suspend_pre(card); | 671 | card->suspend_pre(card); |
622 | 672 | ||
623 | for (i = 0; i < card->num_rtd; i++) { | 673 | list_for_each_entry(rtd, &card->rtd_list, list) { |
624 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 674 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
625 | 675 | ||
626 | if (card->rtd[i].dai_link->ignore_suspend) | 676 | if (rtd->dai_link->ignore_suspend) |
627 | continue; | 677 | continue; |
628 | 678 | ||
629 | if (cpu_dai->driver->suspend && !cpu_dai->driver->bus_control) | 679 | if (cpu_dai->driver->suspend && !cpu_dai->driver->bus_control) |
@@ -631,19 +681,19 @@ int snd_soc_suspend(struct device *dev) | |||
631 | } | 681 | } |
632 | 682 | ||
633 | /* close any waiting streams */ | 683 | /* close any waiting streams */ |
634 | for (i = 0; i < card->num_rtd; i++) | 684 | list_for_each_entry(rtd, &card->rtd_list, list) |
635 | flush_delayed_work(&card->rtd[i].delayed_work); | 685 | flush_delayed_work(&rtd->delayed_work); |
636 | 686 | ||
637 | for (i = 0; i < card->num_rtd; i++) { | 687 | list_for_each_entry(rtd, &card->rtd_list, list) { |
638 | 688 | ||
639 | if (card->rtd[i].dai_link->ignore_suspend) | 689 | if (rtd->dai_link->ignore_suspend) |
640 | continue; | 690 | continue; |
641 | 691 | ||
642 | snd_soc_dapm_stream_event(&card->rtd[i], | 692 | snd_soc_dapm_stream_event(rtd, |
643 | SNDRV_PCM_STREAM_PLAYBACK, | 693 | SNDRV_PCM_STREAM_PLAYBACK, |
644 | SND_SOC_DAPM_STREAM_SUSPEND); | 694 | SND_SOC_DAPM_STREAM_SUSPEND); |
645 | 695 | ||
646 | snd_soc_dapm_stream_event(&card->rtd[i], | 696 | snd_soc_dapm_stream_event(rtd, |
647 | SNDRV_PCM_STREAM_CAPTURE, | 697 | SNDRV_PCM_STREAM_CAPTURE, |
648 | SND_SOC_DAPM_STREAM_SUSPEND); | 698 | SND_SOC_DAPM_STREAM_SUSPEND); |
649 | } | 699 | } |
@@ -690,10 +740,10 @@ int snd_soc_suspend(struct device *dev) | |||
690 | } | 740 | } |
691 | } | 741 | } |
692 | 742 | ||
693 | for (i = 0; i < card->num_rtd; i++) { | 743 | list_for_each_entry(rtd, &card->rtd_list, list) { |
694 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 744 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
695 | 745 | ||
696 | if (card->rtd[i].dai_link->ignore_suspend) | 746 | if (rtd->dai_link->ignore_suspend) |
697 | continue; | 747 | continue; |
698 | 748 | ||
699 | if (cpu_dai->driver->suspend && cpu_dai->driver->bus_control) | 749 | if (cpu_dai->driver->suspend && cpu_dai->driver->bus_control) |
@@ -717,8 +767,9 @@ static void soc_resume_deferred(struct work_struct *work) | |||
717 | { | 767 | { |
718 | struct snd_soc_card *card = | 768 | struct snd_soc_card *card = |
719 | container_of(work, struct snd_soc_card, deferred_resume_work); | 769 | container_of(work, struct snd_soc_card, deferred_resume_work); |
770 | struct snd_soc_pcm_runtime *rtd; | ||
720 | struct snd_soc_codec *codec; | 771 | struct snd_soc_codec *codec; |
721 | int i, j; | 772 | int i; |
722 | 773 | ||
723 | /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, | 774 | /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, |
724 | * so userspace apps are blocked from touching us | 775 | * so userspace apps are blocked from touching us |
@@ -733,10 +784,10 @@ static void soc_resume_deferred(struct work_struct *work) | |||
733 | card->resume_pre(card); | 784 | card->resume_pre(card); |
734 | 785 | ||
735 | /* resume control bus DAIs */ | 786 | /* resume control bus DAIs */ |
736 | for (i = 0; i < card->num_rtd; i++) { | 787 | list_for_each_entry(rtd, &card->rtd_list, list) { |
737 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 788 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
738 | 789 | ||
739 | if (card->rtd[i].dai_link->ignore_suspend) | 790 | if (rtd->dai_link->ignore_suspend) |
740 | continue; | 791 | continue; |
741 | 792 | ||
742 | if (cpu_dai->driver->resume && cpu_dai->driver->bus_control) | 793 | if (cpu_dai->driver->resume && cpu_dai->driver->bus_control) |
@@ -751,28 +802,28 @@ static void soc_resume_deferred(struct work_struct *work) | |||
751 | } | 802 | } |
752 | } | 803 | } |
753 | 804 | ||
754 | for (i = 0; i < card->num_rtd; i++) { | 805 | list_for_each_entry(rtd, &card->rtd_list, list) { |
755 | 806 | ||
756 | if (card->rtd[i].dai_link->ignore_suspend) | 807 | if (rtd->dai_link->ignore_suspend) |
757 | continue; | 808 | continue; |
758 | 809 | ||
759 | snd_soc_dapm_stream_event(&card->rtd[i], | 810 | snd_soc_dapm_stream_event(rtd, |
760 | SNDRV_PCM_STREAM_PLAYBACK, | 811 | SNDRV_PCM_STREAM_PLAYBACK, |
761 | SND_SOC_DAPM_STREAM_RESUME); | 812 | SND_SOC_DAPM_STREAM_RESUME); |
762 | 813 | ||
763 | snd_soc_dapm_stream_event(&card->rtd[i], | 814 | snd_soc_dapm_stream_event(rtd, |
764 | SNDRV_PCM_STREAM_CAPTURE, | 815 | SNDRV_PCM_STREAM_CAPTURE, |
765 | SND_SOC_DAPM_STREAM_RESUME); | 816 | SND_SOC_DAPM_STREAM_RESUME); |
766 | } | 817 | } |
767 | 818 | ||
768 | /* unmute any active DACs */ | 819 | /* unmute any active DACs */ |
769 | for (i = 0; i < card->num_rtd; i++) { | 820 | list_for_each_entry(rtd, &card->rtd_list, list) { |
770 | 821 | ||
771 | if (card->rtd[i].dai_link->ignore_suspend) | 822 | if (rtd->dai_link->ignore_suspend) |
772 | continue; | 823 | continue; |
773 | 824 | ||
774 | for (j = 0; j < card->rtd[i].num_codecs; j++) { | 825 | for (i = 0; i < rtd->num_codecs; i++) { |
775 | struct snd_soc_dai *dai = card->rtd[i].codec_dais[j]; | 826 | struct snd_soc_dai *dai = rtd->codec_dais[i]; |
776 | struct snd_soc_dai_driver *drv = dai->driver; | 827 | struct snd_soc_dai_driver *drv = dai->driver; |
777 | 828 | ||
778 | if (drv->ops->digital_mute && dai->playback_active) | 829 | if (drv->ops->digital_mute && dai->playback_active) |
@@ -780,10 +831,10 @@ static void soc_resume_deferred(struct work_struct *work) | |||
780 | } | 831 | } |
781 | } | 832 | } |
782 | 833 | ||
783 | for (i = 0; i < card->num_rtd; i++) { | 834 | list_for_each_entry(rtd, &card->rtd_list, list) { |
784 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 835 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
785 | 836 | ||
786 | if (card->rtd[i].dai_link->ignore_suspend) | 837 | if (rtd->dai_link->ignore_suspend) |
787 | continue; | 838 | continue; |
788 | 839 | ||
789 | if (cpu_dai->driver->resume && !cpu_dai->driver->bus_control) | 840 | if (cpu_dai->driver->resume && !cpu_dai->driver->bus_control) |
@@ -808,15 +859,14 @@ int snd_soc_resume(struct device *dev) | |||
808 | { | 859 | { |
809 | struct snd_soc_card *card = dev_get_drvdata(dev); | 860 | struct snd_soc_card *card = dev_get_drvdata(dev); |
810 | bool bus_control = false; | 861 | bool bus_control = false; |
811 | int i; | 862 | struct snd_soc_pcm_runtime *rtd; |
812 | 863 | ||
813 | /* If the card is not initialized yet there is nothing to do */ | 864 | /* If the card is not initialized yet there is nothing to do */ |
814 | if (!card->instantiated) | 865 | if (!card->instantiated) |
815 | return 0; | 866 | return 0; |
816 | 867 | ||
817 | /* activate pins from sleep state */ | 868 | /* activate pins from sleep state */ |
818 | for (i = 0; i < card->num_rtd; i++) { | 869 | list_for_each_entry(rtd, &card->rtd_list, list) { |
819 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | ||
820 | struct snd_soc_dai **codec_dais = rtd->codec_dais; | 870 | struct snd_soc_dai **codec_dais = rtd->codec_dais; |
821 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 871 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
822 | int j; | 872 | int j; |
@@ -837,8 +887,8 @@ int snd_soc_resume(struct device *dev) | |||
837 | * have that problem and may take a substantial amount of time to resume | 887 | * have that problem and may take a substantial amount of time to resume |
838 | * due to I/O costs and anti-pop so handle them out of line. | 888 | * due to I/O costs and anti-pop so handle them out of line. |
839 | */ | 889 | */ |
840 | for (i = 0; i < card->num_rtd; i++) { | 890 | list_for_each_entry(rtd, &card->rtd_list, list) { |
841 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 891 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
842 | bus_control |= cpu_dai->driver->bus_control; | 892 | bus_control |= cpu_dai->driver->bus_control; |
843 | } | 893 | } |
844 | if (bus_control) { | 894 | if (bus_control) { |
@@ -910,18 +960,41 @@ static struct snd_soc_dai *snd_soc_find_dai( | |||
910 | return NULL; | 960 | return NULL; |
911 | } | 961 | } |
912 | 962 | ||
913 | static int soc_bind_dai_link(struct snd_soc_card *card, int num) | 963 | static bool soc_is_dai_link_bound(struct snd_soc_card *card, |
964 | struct snd_soc_dai_link *dai_link) | ||
965 | { | ||
966 | struct snd_soc_pcm_runtime *rtd; | ||
967 | |||
968 | list_for_each_entry(rtd, &card->rtd_list, list) { | ||
969 | if (rtd->dai_link == dai_link) | ||
970 | return true; | ||
971 | } | ||
972 | |||
973 | return false; | ||
974 | } | ||
975 | |||
976 | static int soc_bind_dai_link(struct snd_soc_card *card, | ||
977 | struct snd_soc_dai_link *dai_link) | ||
914 | { | 978 | { |
915 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 979 | struct snd_soc_pcm_runtime *rtd; |
916 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
917 | struct snd_soc_dai_link_component *codecs = dai_link->codecs; | 980 | struct snd_soc_dai_link_component *codecs = dai_link->codecs; |
918 | struct snd_soc_dai_link_component cpu_dai_component; | 981 | struct snd_soc_dai_link_component cpu_dai_component; |
919 | struct snd_soc_dai **codec_dais = rtd->codec_dais; | 982 | struct snd_soc_dai **codec_dais; |
920 | struct snd_soc_platform *platform; | 983 | struct snd_soc_platform *platform; |
921 | const char *platform_name; | 984 | const char *platform_name; |
922 | int i; | 985 | int i; |
923 | 986 | ||
924 | dev_dbg(card->dev, "ASoC: binding %s at idx %d\n", dai_link->name, num); | 987 | dev_dbg(card->dev, "ASoC: binding %s\n", dai_link->name); |
988 | |||
989 | rtd = soc_new_pcm_runtime(card, dai_link); | ||
990 | if (!rtd) | ||
991 | return -ENOMEM; | ||
992 | |||
993 | if (soc_is_dai_link_bound(card, dai_link)) { | ||
994 | dev_dbg(card->dev, "ASoC: dai link %s already bound\n", | ||
995 | dai_link->name); | ||
996 | return 0; | ||
997 | } | ||
925 | 998 | ||
926 | cpu_dai_component.name = dai_link->cpu_name; | 999 | cpu_dai_component.name = dai_link->cpu_name; |
927 | cpu_dai_component.of_node = dai_link->cpu_of_node; | 1000 | cpu_dai_component.of_node = dai_link->cpu_of_node; |
@@ -930,18 +1003,19 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
930 | if (!rtd->cpu_dai) { | 1003 | if (!rtd->cpu_dai) { |
931 | dev_err(card->dev, "ASoC: CPU DAI %s not registered\n", | 1004 | dev_err(card->dev, "ASoC: CPU DAI %s not registered\n", |
932 | dai_link->cpu_dai_name); | 1005 | dai_link->cpu_dai_name); |
933 | return -EPROBE_DEFER; | 1006 | goto _err_defer; |
934 | } | 1007 | } |
935 | 1008 | ||
936 | rtd->num_codecs = dai_link->num_codecs; | 1009 | rtd->num_codecs = dai_link->num_codecs; |
937 | 1010 | ||
938 | /* Find CODEC from registered CODECs */ | 1011 | /* Find CODEC from registered CODECs */ |
1012 | codec_dais = rtd->codec_dais; | ||
939 | for (i = 0; i < rtd->num_codecs; i++) { | 1013 | for (i = 0; i < rtd->num_codecs; i++) { |
940 | codec_dais[i] = snd_soc_find_dai(&codecs[i]); | 1014 | codec_dais[i] = snd_soc_find_dai(&codecs[i]); |
941 | if (!codec_dais[i]) { | 1015 | if (!codec_dais[i]) { |
942 | dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", | 1016 | dev_err(card->dev, "ASoC: CODEC DAI %s not registered\n", |
943 | codecs[i].dai_name); | 1017 | codecs[i].dai_name); |
944 | return -EPROBE_DEFER; | 1018 | goto _err_defer; |
945 | } | 1019 | } |
946 | } | 1020 | } |
947 | 1021 | ||
@@ -973,9 +1047,12 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
973 | return -EPROBE_DEFER; | 1047 | return -EPROBE_DEFER; |
974 | } | 1048 | } |
975 | 1049 | ||
976 | card->num_rtd++; | 1050 | soc_add_pcm_runtime(card, rtd); |
977 | |||
978 | return 0; | 1051 | return 0; |
1052 | |||
1053 | _err_defer: | ||
1054 | soc_free_pcm_runtime(rtd); | ||
1055 | return -EPROBE_DEFER; | ||
979 | } | 1056 | } |
980 | 1057 | ||
981 | static void soc_remove_component(struct snd_soc_component *component) | 1058 | static void soc_remove_component(struct snd_soc_component *component) |
@@ -1014,9 +1091,9 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order) | |||
1014 | } | 1091 | } |
1015 | } | 1092 | } |
1016 | 1093 | ||
1017 | static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) | 1094 | static void soc_remove_link_dais(struct snd_soc_card *card, |
1095 | struct snd_soc_pcm_runtime *rtd, int order) | ||
1018 | { | 1096 | { |
1019 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
1020 | int i; | 1097 | int i; |
1021 | 1098 | ||
1022 | /* unregister the rtd device */ | 1099 | /* unregister the rtd device */ |
@@ -1032,10 +1109,9 @@ static void soc_remove_link_dais(struct snd_soc_card *card, int num, int order) | |||
1032 | soc_remove_dai(rtd->cpu_dai, order); | 1109 | soc_remove_dai(rtd->cpu_dai, order); |
1033 | } | 1110 | } |
1034 | 1111 | ||
1035 | static void soc_remove_link_components(struct snd_soc_card *card, int num, | 1112 | static void soc_remove_link_components(struct snd_soc_card *card, |
1036 | int order) | 1113 | struct snd_soc_pcm_runtime *rtd, int order) |
1037 | { | 1114 | { |
1038 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
1039 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1115 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1040 | struct snd_soc_platform *platform = rtd->platform; | 1116 | struct snd_soc_platform *platform = rtd->platform; |
1041 | struct snd_soc_component *component; | 1117 | struct snd_soc_component *component; |
@@ -1061,23 +1137,200 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num, | |||
1061 | 1137 | ||
1062 | static void soc_remove_dai_links(struct snd_soc_card *card) | 1138 | static void soc_remove_dai_links(struct snd_soc_card *card) |
1063 | { | 1139 | { |
1064 | int dai, order; | 1140 | int order; |
1141 | struct snd_soc_pcm_runtime *rtd; | ||
1142 | struct snd_soc_dai_link *link, *_link; | ||
1065 | 1143 | ||
1066 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1144 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; |
1067 | order++) { | 1145 | order++) { |
1068 | for (dai = 0; dai < card->num_rtd; dai++) | 1146 | list_for_each_entry(rtd, &card->rtd_list, list) |
1069 | soc_remove_link_dais(card, dai, order); | 1147 | soc_remove_link_dais(card, rtd, order); |
1070 | } | 1148 | } |
1071 | 1149 | ||
1072 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1150 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; |
1073 | order++) { | 1151 | order++) { |
1074 | for (dai = 0; dai < card->num_rtd; dai++) | 1152 | list_for_each_entry(rtd, &card->rtd_list, list) |
1075 | soc_remove_link_components(card, dai, order); | 1153 | soc_remove_link_components(card, rtd, order); |
1076 | } | 1154 | } |
1077 | 1155 | ||
1078 | card->num_rtd = 0; | 1156 | list_for_each_entry_safe(link, _link, &card->dai_link_list, list) { |
1157 | if (link->dobj.type == SND_SOC_DOBJ_DAI_LINK) | ||
1158 | dev_warn(card->dev, "Topology forgot to remove link %s?\n", | ||
1159 | link->name); | ||
1160 | |||
1161 | list_del(&link->list); | ||
1162 | card->num_dai_links--; | ||
1163 | } | ||
1164 | } | ||
1165 | |||
1166 | static int snd_soc_init_multicodec(struct snd_soc_card *card, | ||
1167 | struct snd_soc_dai_link *dai_link) | ||
1168 | { | ||
1169 | /* Legacy codec/codec_dai link is a single entry in multicodec */ | ||
1170 | if (dai_link->codec_name || dai_link->codec_of_node || | ||
1171 | dai_link->codec_dai_name) { | ||
1172 | dai_link->num_codecs = 1; | ||
1173 | |||
1174 | dai_link->codecs = devm_kzalloc(card->dev, | ||
1175 | sizeof(struct snd_soc_dai_link_component), | ||
1176 | GFP_KERNEL); | ||
1177 | if (!dai_link->codecs) | ||
1178 | return -ENOMEM; | ||
1179 | |||
1180 | dai_link->codecs[0].name = dai_link->codec_name; | ||
1181 | dai_link->codecs[0].of_node = dai_link->codec_of_node; | ||
1182 | dai_link->codecs[0].dai_name = dai_link->codec_dai_name; | ||
1183 | } | ||
1184 | |||
1185 | if (!dai_link->codecs) { | ||
1186 | dev_err(card->dev, "ASoC: DAI link has no CODECs\n"); | ||
1187 | return -EINVAL; | ||
1188 | } | ||
1189 | |||
1190 | return 0; | ||
1191 | } | ||
1192 | |||
1193 | static int soc_init_dai_link(struct snd_soc_card *card, | ||
1194 | struct snd_soc_dai_link *link) | ||
1195 | { | ||
1196 | int i, ret; | ||
1197 | |||
1198 | ret = snd_soc_init_multicodec(card, link); | ||
1199 | if (ret) { | ||
1200 | dev_err(card->dev, "ASoC: failed to init multicodec\n"); | ||
1201 | return ret; | ||
1202 | } | ||
1203 | |||
1204 | for (i = 0; i < link->num_codecs; i++) { | ||
1205 | /* | ||
1206 | * Codec must be specified by 1 of name or OF node, | ||
1207 | * not both or neither. | ||
1208 | */ | ||
1209 | if (!!link->codecs[i].name == | ||
1210 | !!link->codecs[i].of_node) { | ||
1211 | dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n", | ||
1212 | link->name); | ||
1213 | return -EINVAL; | ||
1214 | } | ||
1215 | /* Codec DAI name must be specified */ | ||
1216 | if (!link->codecs[i].dai_name) { | ||
1217 | dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n", | ||
1218 | link->name); | ||
1219 | return -EINVAL; | ||
1220 | } | ||
1221 | } | ||
1222 | |||
1223 | /* | ||
1224 | * Platform may be specified by either name or OF node, but | ||
1225 | * can be left unspecified, and a dummy platform will be used. | ||
1226 | */ | ||
1227 | if (link->platform_name && link->platform_of_node) { | ||
1228 | dev_err(card->dev, | ||
1229 | "ASoC: Both platform name/of_node are set for %s\n", | ||
1230 | link->name); | ||
1231 | return -EINVAL; | ||
1232 | } | ||
1233 | |||
1234 | /* | ||
1235 | * CPU device may be specified by either name or OF node, but | ||
1236 | * can be left unspecified, and will be matched based on DAI | ||
1237 | * name alone.. | ||
1238 | */ | ||
1239 | if (link->cpu_name && link->cpu_of_node) { | ||
1240 | dev_err(card->dev, | ||
1241 | "ASoC: Neither/both cpu name/of_node are set for %s\n", | ||
1242 | link->name); | ||
1243 | return -EINVAL; | ||
1244 | } | ||
1245 | /* | ||
1246 | * At least one of CPU DAI name or CPU device name/node must be | ||
1247 | * specified | ||
1248 | */ | ||
1249 | if (!link->cpu_dai_name && | ||
1250 | !(link->cpu_name || link->cpu_of_node)) { | ||
1251 | dev_err(card->dev, | ||
1252 | "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n", | ||
1253 | link->name); | ||
1254 | return -EINVAL; | ||
1255 | } | ||
1256 | |||
1257 | return 0; | ||
1079 | } | 1258 | } |
1080 | 1259 | ||
1260 | /** | ||
1261 | * snd_soc_add_dai_link - Add a DAI link dynamically | ||
1262 | * @card: The ASoC card to which the DAI link is added | ||
1263 | * @dai_link: The new DAI link to add | ||
1264 | * | ||
1265 | * This function adds a DAI link to the ASoC card's link list. | ||
1266 | * | ||
1267 | * Note: Topology can use this API to add DAI links when probing the | ||
1268 | * topology component. And machine drivers can still define static | ||
1269 | * DAI links in dai_link array. | ||
1270 | */ | ||
1271 | int snd_soc_add_dai_link(struct snd_soc_card *card, | ||
1272 | struct snd_soc_dai_link *dai_link) | ||
1273 | { | ||
1274 | if (dai_link->dobj.type | ||
1275 | && dai_link->dobj.type != SND_SOC_DOBJ_DAI_LINK) { | ||
1276 | dev_err(card->dev, "Invalid dai link type %d\n", | ||
1277 | dai_link->dobj.type); | ||
1278 | return -EINVAL; | ||
1279 | } | ||
1280 | |||
1281 | lockdep_assert_held(&client_mutex); | ||
1282 | /* Notify the machine driver for extra initialization | ||
1283 | * on the link created by topology. | ||
1284 | */ | ||
1285 | if (dai_link->dobj.type && card->add_dai_link) | ||
1286 | card->add_dai_link(card, dai_link); | ||
1287 | |||
1288 | list_add_tail(&dai_link->list, &card->dai_link_list); | ||
1289 | card->num_dai_links++; | ||
1290 | |||
1291 | return 0; | ||
1292 | } | ||
1293 | EXPORT_SYMBOL_GPL(snd_soc_add_dai_link); | ||
1294 | |||
1295 | /** | ||
1296 | * snd_soc_remove_dai_link - Remove a DAI link from the list | ||
1297 | * @card: The ASoC card that owns the link | ||
1298 | * @dai_link: The DAI link to remove | ||
1299 | * | ||
1300 | * This function removes a DAI link from the ASoC card's link list. | ||
1301 | * | ||
1302 | * For DAI links previously added by topology, topology should | ||
1303 | * remove them by using the dobj embedded in the link. | ||
1304 | */ | ||
1305 | void snd_soc_remove_dai_link(struct snd_soc_card *card, | ||
1306 | struct snd_soc_dai_link *dai_link) | ||
1307 | { | ||
1308 | struct snd_soc_dai_link *link, *_link; | ||
1309 | |||
1310 | if (dai_link->dobj.type | ||
1311 | && dai_link->dobj.type != SND_SOC_DOBJ_DAI_LINK) { | ||
1312 | dev_err(card->dev, "Invalid dai link type %d\n", | ||
1313 | dai_link->dobj.type); | ||
1314 | return; | ||
1315 | } | ||
1316 | |||
1317 | lockdep_assert_held(&client_mutex); | ||
1318 | /* Notify the machine driver for extra destruction | ||
1319 | * on the link created by topology. | ||
1320 | */ | ||
1321 | if (dai_link->dobj.type && card->remove_dai_link) | ||
1322 | card->remove_dai_link(card, dai_link); | ||
1323 | |||
1324 | list_for_each_entry_safe(link, _link, &card->dai_link_list, list) { | ||
1325 | if (link == dai_link) { | ||
1326 | list_del(&link->list); | ||
1327 | card->num_dai_links--; | ||
1328 | return; | ||
1329 | } | ||
1330 | } | ||
1331 | } | ||
1332 | EXPORT_SYMBOL_GPL(snd_soc_remove_dai_link); | ||
1333 | |||
1081 | static void soc_set_name_prefix(struct snd_soc_card *card, | 1334 | static void soc_set_name_prefix(struct snd_soc_card *card, |
1082 | struct snd_soc_component *component) | 1335 | struct snd_soc_component *component) |
1083 | { | 1336 | { |
@@ -1220,10 +1473,10 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd, | |||
1220 | return 0; | 1473 | return 0; |
1221 | } | 1474 | } |
1222 | 1475 | ||
1223 | static int soc_probe_link_components(struct snd_soc_card *card, int num, | 1476 | static int soc_probe_link_components(struct snd_soc_card *card, |
1477 | struct snd_soc_pcm_runtime *rtd, | ||
1224 | int order) | 1478 | int order) |
1225 | { | 1479 | { |
1226 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
1227 | struct snd_soc_platform *platform = rtd->platform; | 1480 | struct snd_soc_platform *platform = rtd->platform; |
1228 | struct snd_soc_component *component; | 1481 | struct snd_soc_component *component; |
1229 | int i, ret; | 1482 | int i, ret; |
@@ -1283,35 +1536,35 @@ static int soc_link_dai_widgets(struct snd_soc_card *card, | |||
1283 | { | 1536 | { |
1284 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1537 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1285 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 1538 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
1286 | struct snd_soc_dapm_widget *play_w, *capture_w; | 1539 | struct snd_soc_dapm_widget *sink, *source; |
1287 | int ret; | 1540 | int ret; |
1288 | 1541 | ||
1289 | if (rtd->num_codecs > 1) | 1542 | if (rtd->num_codecs > 1) |
1290 | dev_warn(card->dev, "ASoC: Multiple codecs not supported yet\n"); | 1543 | dev_warn(card->dev, "ASoC: Multiple codecs not supported yet\n"); |
1291 | 1544 | ||
1292 | /* link the DAI widgets */ | 1545 | /* link the DAI widgets */ |
1293 | play_w = codec_dai->playback_widget; | 1546 | sink = codec_dai->playback_widget; |
1294 | capture_w = cpu_dai->capture_widget; | 1547 | source = cpu_dai->capture_widget; |
1295 | if (play_w && capture_w) { | 1548 | if (sink && source) { |
1296 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, | 1549 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, |
1297 | dai_link->num_params, capture_w, | 1550 | dai_link->num_params, |
1298 | play_w); | 1551 | source, sink); |
1299 | if (ret != 0) { | 1552 | if (ret != 0) { |
1300 | dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n", | 1553 | dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n", |
1301 | play_w->name, capture_w->name, ret); | 1554 | sink->name, source->name, ret); |
1302 | return ret; | 1555 | return ret; |
1303 | } | 1556 | } |
1304 | } | 1557 | } |
1305 | 1558 | ||
1306 | play_w = cpu_dai->playback_widget; | 1559 | sink = cpu_dai->playback_widget; |
1307 | capture_w = codec_dai->capture_widget; | 1560 | source = codec_dai->capture_widget; |
1308 | if (play_w && capture_w) { | 1561 | if (sink && source) { |
1309 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, | 1562 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, |
1310 | dai_link->num_params, capture_w, | 1563 | dai_link->num_params, |
1311 | play_w); | 1564 | source, sink); |
1312 | if (ret != 0) { | 1565 | if (ret != 0) { |
1313 | dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n", | 1566 | dev_err(card->dev, "ASoC: Can't link %s to %s: %d\n", |
1314 | play_w->name, capture_w->name, ret); | 1567 | sink->name, source->name, ret); |
1315 | return ret; | 1568 | return ret; |
1316 | } | 1569 | } |
1317 | } | 1570 | } |
@@ -1319,15 +1572,15 @@ static int soc_link_dai_widgets(struct snd_soc_card *card, | |||
1319 | return 0; | 1572 | return 0; |
1320 | } | 1573 | } |
1321 | 1574 | ||
1322 | static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | 1575 | static int soc_probe_link_dais(struct snd_soc_card *card, |
1576 | struct snd_soc_pcm_runtime *rtd, int order) | ||
1323 | { | 1577 | { |
1324 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1578 | struct snd_soc_dai_link *dai_link = rtd->dai_link; |
1325 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | ||
1326 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 1579 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1327 | int i, ret; | 1580 | int i, ret; |
1328 | 1581 | ||
1329 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", | 1582 | dev_dbg(card->dev, "ASoC: probe %s dai link %d late %d\n", |
1330 | card->name, num, order); | 1583 | card->name, rtd->num, order); |
1331 | 1584 | ||
1332 | /* set default power off timeout */ | 1585 | /* set default power off timeout */ |
1333 | rtd->pmdown_time = pmdown_time; | 1586 | rtd->pmdown_time = pmdown_time; |
@@ -1372,7 +1625,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1372 | 1625 | ||
1373 | if (cpu_dai->driver->compress_new) { | 1626 | if (cpu_dai->driver->compress_new) { |
1374 | /*create compress_device"*/ | 1627 | /*create compress_device"*/ |
1375 | ret = cpu_dai->driver->compress_new(rtd, num); | 1628 | ret = cpu_dai->driver->compress_new(rtd, rtd->num); |
1376 | if (ret < 0) { | 1629 | if (ret < 0) { |
1377 | dev_err(card->dev, "ASoC: can't create compress %s\n", | 1630 | dev_err(card->dev, "ASoC: can't create compress %s\n", |
1378 | dai_link->stream_name); | 1631 | dai_link->stream_name); |
@@ -1382,7 +1635,7 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1382 | 1635 | ||
1383 | if (!dai_link->params) { | 1636 | if (!dai_link->params) { |
1384 | /* create the pcm */ | 1637 | /* create the pcm */ |
1385 | ret = soc_new_pcm(rtd, num); | 1638 | ret = soc_new_pcm(rtd, rtd->num); |
1386 | if (ret < 0) { | 1639 | if (ret < 0) { |
1387 | dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", | 1640 | dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", |
1388 | dai_link->stream_name, ret); | 1641 | dai_link->stream_name, ret); |
@@ -1552,6 +1805,8 @@ EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt); | |||
1552 | static int snd_soc_instantiate_card(struct snd_soc_card *card) | 1805 | static int snd_soc_instantiate_card(struct snd_soc_card *card) |
1553 | { | 1806 | { |
1554 | struct snd_soc_codec *codec; | 1807 | struct snd_soc_codec *codec; |
1808 | struct snd_soc_pcm_runtime *rtd; | ||
1809 | struct snd_soc_dai_link *dai_link; | ||
1555 | int ret, i, order; | 1810 | int ret, i, order; |
1556 | 1811 | ||
1557 | mutex_lock(&client_mutex); | 1812 | mutex_lock(&client_mutex); |
@@ -1559,7 +1814,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1559 | 1814 | ||
1560 | /* bind DAIs */ | 1815 | /* bind DAIs */ |
1561 | for (i = 0; i < card->num_links; i++) { | 1816 | for (i = 0; i < card->num_links; i++) { |
1562 | ret = soc_bind_dai_link(card, i); | 1817 | ret = soc_bind_dai_link(card, &card->dai_link[i]); |
1563 | if (ret != 0) | 1818 | if (ret != 0) |
1564 | goto base_error; | 1819 | goto base_error; |
1565 | } | 1820 | } |
@@ -1571,6 +1826,10 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1571 | goto base_error; | 1826 | goto base_error; |
1572 | } | 1827 | } |
1573 | 1828 | ||
1829 | /* add predefined DAI links to the list */ | ||
1830 | for (i = 0; i < card->num_links; i++) | ||
1831 | snd_soc_add_dai_link(card, card->dai_link+i); | ||
1832 | |||
1574 | /* initialize the register cache for each available codec */ | 1833 | /* initialize the register cache for each available codec */ |
1575 | list_for_each_entry(codec, &codec_list, list) { | 1834 | list_for_each_entry(codec, &codec_list, list) { |
1576 | if (codec->cache_init) | 1835 | if (codec->cache_init) |
@@ -1624,8 +1883,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1624 | /* probe all components used by DAI links on this card */ | 1883 | /* probe all components used by DAI links on this card */ |
1625 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1884 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; |
1626 | order++) { | 1885 | order++) { |
1627 | for (i = 0; i < card->num_links; i++) { | 1886 | list_for_each_entry(rtd, &card->rtd_list, list) { |
1628 | ret = soc_probe_link_components(card, i, order); | 1887 | ret = soc_probe_link_components(card, rtd, order); |
1629 | if (ret < 0) { | 1888 | if (ret < 0) { |
1630 | dev_err(card->dev, | 1889 | dev_err(card->dev, |
1631 | "ASoC: failed to instantiate card %d\n", | 1890 | "ASoC: failed to instantiate card %d\n", |
@@ -1635,11 +1894,26 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1635 | } | 1894 | } |
1636 | } | 1895 | } |
1637 | 1896 | ||
1897 | /* Find new DAI links added during probing components and bind them. | ||
1898 | * Components with topology may bring new DAIs and DAI links. | ||
1899 | */ | ||
1900 | list_for_each_entry(dai_link, &card->dai_link_list, list) { | ||
1901 | if (soc_is_dai_link_bound(card, dai_link)) | ||
1902 | continue; | ||
1903 | |||
1904 | ret = soc_init_dai_link(card, dai_link); | ||
1905 | if (ret) | ||
1906 | goto probe_dai_err; | ||
1907 | ret = soc_bind_dai_link(card, dai_link); | ||
1908 | if (ret) | ||
1909 | goto probe_dai_err; | ||
1910 | } | ||
1911 | |||
1638 | /* probe all DAI links on this card */ | 1912 | /* probe all DAI links on this card */ |
1639 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; | 1913 | for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST; |
1640 | order++) { | 1914 | order++) { |
1641 | for (i = 0; i < card->num_links; i++) { | 1915 | list_for_each_entry(rtd, &card->rtd_list, list) { |
1642 | ret = soc_probe_link_dais(card, i, order); | 1916 | ret = soc_probe_link_dais(card, rtd, order); |
1643 | if (ret < 0) { | 1917 | if (ret < 0) { |
1644 | dev_err(card->dev, | 1918 | dev_err(card->dev, |
1645 | "ASoC: failed to instantiate card %d\n", | 1919 | "ASoC: failed to instantiate card %d\n", |
@@ -1733,6 +2007,7 @@ card_probe_error: | |||
1733 | snd_card_free(card->snd_card); | 2007 | snd_card_free(card->snd_card); |
1734 | 2008 | ||
1735 | base_error: | 2009 | base_error: |
2010 | soc_remove_pcm_runtimes(card); | ||
1736 | mutex_unlock(&card->mutex); | 2011 | mutex_unlock(&card->mutex); |
1737 | mutex_unlock(&client_mutex); | 2012 | mutex_unlock(&client_mutex); |
1738 | 2013 | ||
@@ -1763,13 +2038,12 @@ static int soc_probe(struct platform_device *pdev) | |||
1763 | 2038 | ||
1764 | static int soc_cleanup_card_resources(struct snd_soc_card *card) | 2039 | static int soc_cleanup_card_resources(struct snd_soc_card *card) |
1765 | { | 2040 | { |
2041 | struct snd_soc_pcm_runtime *rtd; | ||
1766 | int i; | 2042 | int i; |
1767 | 2043 | ||
1768 | /* make sure any delayed work runs */ | 2044 | /* make sure any delayed work runs */ |
1769 | for (i = 0; i < card->num_rtd; i++) { | 2045 | list_for_each_entry(rtd, &card->rtd_list, list) |
1770 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | ||
1771 | flush_delayed_work(&rtd->delayed_work); | 2046 | flush_delayed_work(&rtd->delayed_work); |
1772 | } | ||
1773 | 2047 | ||
1774 | /* remove auxiliary devices */ | 2048 | /* remove auxiliary devices */ |
1775 | for (i = 0; i < card->num_aux_devs; i++) | 2049 | for (i = 0; i < card->num_aux_devs; i++) |
@@ -1777,6 +2051,7 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card) | |||
1777 | 2051 | ||
1778 | /* remove and free each DAI */ | 2052 | /* remove and free each DAI */ |
1779 | soc_remove_dai_links(card); | 2053 | soc_remove_dai_links(card); |
2054 | soc_remove_pcm_runtimes(card); | ||
1780 | 2055 | ||
1781 | soc_cleanup_card_debugfs(card); | 2056 | soc_cleanup_card_debugfs(card); |
1782 | 2057 | ||
@@ -1803,29 +2078,26 @@ static int soc_remove(struct platform_device *pdev) | |||
1803 | int snd_soc_poweroff(struct device *dev) | 2078 | int snd_soc_poweroff(struct device *dev) |
1804 | { | 2079 | { |
1805 | struct snd_soc_card *card = dev_get_drvdata(dev); | 2080 | struct snd_soc_card *card = dev_get_drvdata(dev); |
1806 | int i; | 2081 | struct snd_soc_pcm_runtime *rtd; |
1807 | 2082 | ||
1808 | if (!card->instantiated) | 2083 | if (!card->instantiated) |
1809 | return 0; | 2084 | return 0; |
1810 | 2085 | ||
1811 | /* Flush out pmdown_time work - we actually do want to run it | 2086 | /* Flush out pmdown_time work - we actually do want to run it |
1812 | * now, we're shutting down so no imminent restart. */ | 2087 | * now, we're shutting down so no imminent restart. */ |
1813 | for (i = 0; i < card->num_rtd; i++) { | 2088 | list_for_each_entry(rtd, &card->rtd_list, list) |
1814 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | ||
1815 | flush_delayed_work(&rtd->delayed_work); | 2089 | flush_delayed_work(&rtd->delayed_work); |
1816 | } | ||
1817 | 2090 | ||
1818 | snd_soc_dapm_shutdown(card); | 2091 | snd_soc_dapm_shutdown(card); |
1819 | 2092 | ||
1820 | /* deactivate pins to sleep state */ | 2093 | /* deactivate pins to sleep state */ |
1821 | for (i = 0; i < card->num_rtd; i++) { | 2094 | list_for_each_entry(rtd, &card->rtd_list, list) { |
1822 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | ||
1823 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 2095 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
1824 | int j; | 2096 | int i; |
1825 | 2097 | ||
1826 | pinctrl_pm_select_sleep_state(cpu_dai->dev); | 2098 | pinctrl_pm_select_sleep_state(cpu_dai->dev); |
1827 | for (j = 0; j < rtd->num_codecs; j++) { | 2099 | for (i = 0; i < rtd->num_codecs; i++) { |
1828 | struct snd_soc_dai *codec_dai = rtd->codec_dais[j]; | 2100 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; |
1829 | pinctrl_pm_select_sleep_state(codec_dai->dev); | 2101 | pinctrl_pm_select_sleep_state(codec_dai->dev); |
1830 | } | 2102 | } |
1831 | } | 2103 | } |
@@ -2301,33 +2573,6 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, | |||
2301 | } | 2573 | } |
2302 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | 2574 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); |
2303 | 2575 | ||
2304 | static int snd_soc_init_multicodec(struct snd_soc_card *card, | ||
2305 | struct snd_soc_dai_link *dai_link) | ||
2306 | { | ||
2307 | /* Legacy codec/codec_dai link is a single entry in multicodec */ | ||
2308 | if (dai_link->codec_name || dai_link->codec_of_node || | ||
2309 | dai_link->codec_dai_name) { | ||
2310 | dai_link->num_codecs = 1; | ||
2311 | |||
2312 | dai_link->codecs = devm_kzalloc(card->dev, | ||
2313 | sizeof(struct snd_soc_dai_link_component), | ||
2314 | GFP_KERNEL); | ||
2315 | if (!dai_link->codecs) | ||
2316 | return -ENOMEM; | ||
2317 | |||
2318 | dai_link->codecs[0].name = dai_link->codec_name; | ||
2319 | dai_link->codecs[0].of_node = dai_link->codec_of_node; | ||
2320 | dai_link->codecs[0].dai_name = dai_link->codec_dai_name; | ||
2321 | } | ||
2322 | |||
2323 | if (!dai_link->codecs) { | ||
2324 | dev_err(card->dev, "ASoC: DAI link has no CODECs\n"); | ||
2325 | return -EINVAL; | ||
2326 | } | ||
2327 | |||
2328 | return 0; | ||
2329 | } | ||
2330 | |||
2331 | /** | 2576 | /** |
2332 | * snd_soc_register_card - Register a card with the ASoC core | 2577 | * snd_soc_register_card - Register a card with the ASoC core |
2333 | * | 2578 | * |
@@ -2336,7 +2581,8 @@ static int snd_soc_init_multicodec(struct snd_soc_card *card, | |||
2336 | */ | 2581 | */ |
2337 | int snd_soc_register_card(struct snd_soc_card *card) | 2582 | int snd_soc_register_card(struct snd_soc_card *card) |
2338 | { | 2583 | { |
2339 | int i, j, ret; | 2584 | int i, ret; |
2585 | struct snd_soc_pcm_runtime *rtd; | ||
2340 | 2586 | ||
2341 | if (!card->name || !card->dev) | 2587 | if (!card->name || !card->dev) |
2342 | return -EINVAL; | 2588 | return -EINVAL; |
@@ -2344,63 +2590,11 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
2344 | for (i = 0; i < card->num_links; i++) { | 2590 | for (i = 0; i < card->num_links; i++) { |
2345 | struct snd_soc_dai_link *link = &card->dai_link[i]; | 2591 | struct snd_soc_dai_link *link = &card->dai_link[i]; |
2346 | 2592 | ||
2347 | ret = snd_soc_init_multicodec(card, link); | 2593 | ret = soc_init_dai_link(card, link); |
2348 | if (ret) { | 2594 | if (ret) { |
2349 | dev_err(card->dev, "ASoC: failed to init multicodec\n"); | 2595 | dev_err(card->dev, "ASoC: failed to init link %s\n", |
2350 | return ret; | ||
2351 | } | ||
2352 | |||
2353 | for (j = 0; j < link->num_codecs; j++) { | ||
2354 | /* | ||
2355 | * Codec must be specified by 1 of name or OF node, | ||
2356 | * not both or neither. | ||
2357 | */ | ||
2358 | if (!!link->codecs[j].name == | ||
2359 | !!link->codecs[j].of_node) { | ||
2360 | dev_err(card->dev, "ASoC: Neither/both codec name/of_node are set for %s\n", | ||
2361 | link->name); | ||
2362 | return -EINVAL; | ||
2363 | } | ||
2364 | /* Codec DAI name must be specified */ | ||
2365 | if (!link->codecs[j].dai_name) { | ||
2366 | dev_err(card->dev, "ASoC: codec_dai_name not set for %s\n", | ||
2367 | link->name); | ||
2368 | return -EINVAL; | ||
2369 | } | ||
2370 | } | ||
2371 | |||
2372 | /* | ||
2373 | * Platform may be specified by either name or OF node, but | ||
2374 | * can be left unspecified, and a dummy platform will be used. | ||
2375 | */ | ||
2376 | if (link->platform_name && link->platform_of_node) { | ||
2377 | dev_err(card->dev, | ||
2378 | "ASoC: Both platform name/of_node are set for %s\n", | ||
2379 | link->name); | ||
2380 | return -EINVAL; | ||
2381 | } | ||
2382 | |||
2383 | /* | ||
2384 | * CPU device may be specified by either name or OF node, but | ||
2385 | * can be left unspecified, and will be matched based on DAI | ||
2386 | * name alone.. | ||
2387 | */ | ||
2388 | if (link->cpu_name && link->cpu_of_node) { | ||
2389 | dev_err(card->dev, | ||
2390 | "ASoC: Neither/both cpu name/of_node are set for %s\n", | ||
2391 | link->name); | ||
2392 | return -EINVAL; | ||
2393 | } | ||
2394 | /* | ||
2395 | * At least one of CPU DAI name or CPU device name/node must be | ||
2396 | * specified | ||
2397 | */ | ||
2398 | if (!link->cpu_dai_name && | ||
2399 | !(link->cpu_name || link->cpu_of_node)) { | ||
2400 | dev_err(card->dev, | ||
2401 | "ASoC: Neither cpu_dai_name nor cpu_name/of_node are set for %s\n", | ||
2402 | link->name); | 2596 | link->name); |
2403 | return -EINVAL; | 2597 | return ret; |
2404 | } | 2598 | } |
2405 | } | 2599 | } |
2406 | 2600 | ||
@@ -2408,25 +2602,18 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
2408 | 2602 | ||
2409 | snd_soc_initialize_card_lists(card); | 2603 | snd_soc_initialize_card_lists(card); |
2410 | 2604 | ||
2411 | card->rtd = devm_kzalloc(card->dev, | 2605 | INIT_LIST_HEAD(&card->dai_link_list); |
2606 | card->num_dai_links = 0; | ||
2607 | |||
2608 | INIT_LIST_HEAD(&card->rtd_list); | ||
2609 | card->num_rtd = 0; | ||
2610 | |||
2611 | card->rtd_aux = devm_kzalloc(card->dev, | ||
2412 | sizeof(struct snd_soc_pcm_runtime) * | 2612 | sizeof(struct snd_soc_pcm_runtime) * |
2413 | (card->num_links + card->num_aux_devs), | 2613 | card->num_aux_devs, |
2414 | GFP_KERNEL); | 2614 | GFP_KERNEL); |
2415 | if (card->rtd == NULL) | 2615 | if (card->rtd_aux == NULL) |
2416 | return -ENOMEM; | 2616 | return -ENOMEM; |
2417 | card->num_rtd = 0; | ||
2418 | card->rtd_aux = &card->rtd[card->num_links]; | ||
2419 | |||
2420 | for (i = 0; i < card->num_links; i++) { | ||
2421 | card->rtd[i].card = card; | ||
2422 | card->rtd[i].dai_link = &card->dai_link[i]; | ||
2423 | card->rtd[i].codec_dais = devm_kzalloc(card->dev, | ||
2424 | sizeof(struct snd_soc_dai *) * | ||
2425 | (card->rtd[i].dai_link->num_codecs), | ||
2426 | GFP_KERNEL); | ||
2427 | if (card->rtd[i].codec_dais == NULL) | ||
2428 | return -ENOMEM; | ||
2429 | } | ||
2430 | 2617 | ||
2431 | for (i = 0; i < card->num_aux_devs; i++) | 2618 | for (i = 0; i < card->num_aux_devs; i++) |
2432 | card->rtd_aux[i].card = card; | 2619 | card->rtd_aux[i].card = card; |
@@ -2442,8 +2629,7 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
2442 | return ret; | 2629 | return ret; |
2443 | 2630 | ||
2444 | /* deactivate pins to sleep state */ | 2631 | /* deactivate pins to sleep state */ |
2445 | for (i = 0; i < card->num_rtd; i++) { | 2632 | list_for_each_entry(rtd, &card->rtd_list, list) { |
2446 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | ||
2447 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 2633 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
2448 | int j; | 2634 | int j; |
2449 | 2635 | ||