aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-pcm.c
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@ti.com>2012-04-25 07:12:49 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-26 12:48:19 -0400
commit01d7584cd2e5a93a2b959c9dddaa0d93ec205404 (patch)
tree1ed8fe39b490723195812dd562536e362b8027b0 /sound/soc/soc-pcm.c
parentf20c2cb9995eb8c5cd7084e11af7b54522ef0ab9 (diff)
ASoC: dpcm: Add Dynamic PCM core operations.
The Dynamic PCM core allows digital audio data to be dynamically routed between different ALSA PCMs and DAI links on SoC CPUs with on chip DSP devices. e.g. audio data could be played on pcm:0,0 and routed to any (or all) SoC DAI links. Dynamic PCM introduces the concept of Front End (FE) PCMs and Back End (BE) PCMs. The FE PCMs are normal ALSA PCM devices except that they can dynamically route digital audio data to any supported BE PCM. A BE PCM has no ALSA device, but represents a DAI link and it's substream and audio HW parameters. e.g. pcm:0,0 routing digital data to 2 external codecs. FE pcm:0,0 ----> BE (McBSP.0) ----> CODEC 0 +--> BE (McPDM.0) ----> CODEC 1 e.g. pcm:0,0 and pcm:0,1 routing digital data to 1 external codec. FE pcm:0,0 --- +--> BE (McBSP.0) ----> CODEC FE pcm:0,1 --- The digital audio routing is controlled by the usual ALSA method of mixer kcontrols. Dynamic PCM uses a DAPM graph to work out the routing based upon the mixer settings and configures the BE PCMs based on routing and the FE HW params. DPCM is designed so that most ASoC component drivers will need no modification at all. It's intended that existing CODEC, DAI and platform drivers can be used in DPCM based audio devices without any changes. However, there will be some cases where minor changes are required (e.g. for very tightly coupled HW) and there are helpers to support this too. Somethimes the HW params of a FE and BE do not match or are incompatible, so in these cases the machine driver can reconfigure any hw_params and make any DSP perform sample rate / format conversion. This patch adds the core DPCM code and contains :- o The FE and BE PCM operations. o FE and BE DAI link support. o FE and BE PCM creation. o BE support API. o BE and FE link management. Signed-off-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-pcm.c')
-rw-r--r--sound/soc/soc-pcm.c1246
1 files changed, 1216 insertions, 30 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 26a60b4061cf..458f116aa570 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -22,12 +22,37 @@
22#include <linux/pm_runtime.h> 22#include <linux/pm_runtime.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/workqueue.h> 24#include <linux/workqueue.h>
25#include <linux/export.h>
25#include <sound/core.h> 26#include <sound/core.h>
26#include <sound/pcm.h> 27#include <sound/pcm.h>
27#include <sound/pcm_params.h> 28#include <sound/pcm_params.h>
28#include <sound/soc.h> 29#include <sound/soc.h>
30#include <sound/soc-dpcm.h>
29#include <sound/initval.h> 31#include <sound/initval.h>
30 32
33#define DPCM_MAX_BE_USERS 8
34
35/* DPCM stream event, send event to FE and all active BEs. */
36static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir,
37 int event)
38{
39 struct snd_soc_dpcm *dpcm;
40
41 list_for_each_entry(dpcm, &fe->dpcm[dir].be_clients, list_be) {
42
43 struct snd_soc_pcm_runtime *be = dpcm->be;
44
45 dev_dbg(be->dev, "pm: BE %s event %d dir %d\n",
46 be->dai_link->name, event, dir);
47
48 snd_soc_dapm_stream_event(be, dir, event);
49 }
50
51 snd_soc_dapm_stream_event(fe, dir, event);
52
53 return 0;
54}
55
31static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, 56static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
32 struct snd_soc_dai *soc_dai) 57 struct snd_soc_dai *soc_dai)
33{ 58{
@@ -156,6 +181,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
156 } 181 }
157 } 182 }
158 183
184 /* Dynamic PCM DAI links compat checks use dynamic capabilities */
185 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm)
186 goto dynamic;
187
159 /* Check that the codec and cpu DAIs are compatible */ 188 /* Check that the codec and cpu DAIs are compatible */
160 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 189 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
161 runtime->hw.rate_min = 190 runtime->hw.rate_min =
@@ -248,6 +277,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
248 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, 277 pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
249 runtime->hw.rate_max); 278 runtime->hw.rate_max);
250 279
280dynamic:
251 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 281 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
252 cpu_dai->playback_active++; 282 cpu_dai->playback_active++;
253 codec_dai->playback_active++; 283 codec_dai->playback_active++;
@@ -633,6 +663,1025 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
633 return offset; 663 return offset;
634} 664}
635 665
666/* connect a FE and BE */
667static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
668 struct snd_soc_pcm_runtime *be, int stream)
669{
670 struct snd_soc_dpcm *dpcm;
671
672 /* only add new dpcms */
673 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
674 if (dpcm->be == be && dpcm->fe == fe)
675 return 0;
676 }
677
678 dpcm = kzalloc(sizeof(struct snd_soc_dpcm), GFP_KERNEL);
679 if (!dpcm)
680 return -ENOMEM;
681
682 dpcm->be = be;
683 dpcm->fe = fe;
684 be->dpcm[stream].runtime = fe->dpcm[stream].runtime;
685 dpcm->state = SND_SOC_DPCM_LINK_STATE_NEW;
686 list_add(&dpcm->list_be, &fe->dpcm[stream].be_clients);
687 list_add(&dpcm->list_fe, &be->dpcm[stream].fe_clients);
688
689 dev_dbg(fe->dev, " connected new DPCM %s path %s %s %s\n",
690 stream ? "capture" : "playback", fe->dai_link->name,
691 stream ? "<-" : "->", be->dai_link->name);
692
693 return 1;
694}
695
696/* reparent a BE onto another FE */
697static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe,
698 struct snd_soc_pcm_runtime *be, int stream)
699{
700 struct snd_soc_dpcm *dpcm;
701 struct snd_pcm_substream *fe_substream, *be_substream;
702
703 /* reparent if BE is connected to other FEs */
704 if (!be->dpcm[stream].users)
705 return;
706
707 be_substream = snd_soc_dpcm_get_substream(be, stream);
708
709 list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) {
710 if (dpcm->fe == fe)
711 continue;
712
713 dev_dbg(fe->dev, " reparent %s path %s %s %s\n",
714 stream ? "capture" : "playback",
715 dpcm->fe->dai_link->name,
716 stream ? "<-" : "->", dpcm->be->dai_link->name);
717
718 fe_substream = snd_soc_dpcm_get_substream(dpcm->fe, stream);
719 be_substream->runtime = fe_substream->runtime;
720 break;
721 }
722}
723
724/* disconnect a BE and FE */
725static void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream)
726{
727 struct snd_soc_dpcm *dpcm, *d;
728
729 list_for_each_entry_safe(dpcm, d, &fe->dpcm[stream].be_clients, list_be) {
730 dev_dbg(fe->dev, "BE %s disconnect check for %s\n",
731 stream ? "capture" : "playback",
732 dpcm->be->dai_link->name);
733
734 if (dpcm->state != SND_SOC_DPCM_LINK_STATE_FREE)
735 continue;
736
737 dev_dbg(fe->dev, " freed DSP %s path %s %s %s\n",
738 stream ? "capture" : "playback", fe->dai_link->name,
739 stream ? "<-" : "->", dpcm->be->dai_link->name);
740
741 /* BEs still alive need new FE */
742 dpcm_be_reparent(fe, dpcm->be, stream);
743
744 list_del(&dpcm->list_be);
745 list_del(&dpcm->list_fe);
746 kfree(dpcm);
747 }
748}
749
750/* get BE for DAI widget and stream */
751static struct snd_soc_pcm_runtime *dpcm_get_be(struct snd_soc_card *card,
752 struct snd_soc_dapm_widget *widget, int stream)
753{
754 struct snd_soc_pcm_runtime *be;
755 int i;
756
757 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
758 for (i = 0; i < card->num_links; i++) {
759 be = &card->rtd[i];
760
761 if (be->cpu_dai->playback_widget == widget ||
762 be->codec_dai->playback_widget == widget)
763 return be;
764 }
765 } else {
766
767 for (i = 0; i < card->num_links; i++) {
768 be = &card->rtd[i];
769
770 if (be->cpu_dai->capture_widget == widget ||
771 be->codec_dai->capture_widget == widget)
772 return be;
773 }
774 }
775
776 dev_err(card->dev, "can't get %s BE for %s\n",
777 stream ? "capture" : "playback", widget->name);
778 return NULL;
779}
780
781static inline struct snd_soc_dapm_widget *
782 rtd_get_cpu_widget(struct snd_soc_pcm_runtime *rtd, int stream)
783{
784 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
785 return rtd->cpu_dai->playback_widget;
786 else
787 return rtd->cpu_dai->capture_widget;
788}
789
790static inline struct snd_soc_dapm_widget *
791 rtd_get_codec_widget(struct snd_soc_pcm_runtime *rtd, int stream)
792{
793 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
794 return rtd->codec_dai->playback_widget;
795 else
796 return rtd->codec_dai->capture_widget;
797}
798
799static int widget_in_list(struct snd_soc_dapm_widget_list *list,
800 struct snd_soc_dapm_widget *widget)
801{
802 int i;
803
804 for (i = 0; i < list->num_widgets; i++) {
805 if (widget == list->widgets[i])
806 return 1;
807 }
808
809 return 0;
810}
811
812static int dpcm_path_get(struct snd_soc_pcm_runtime *fe,
813 int stream, struct snd_soc_dapm_widget_list **list_)
814{
815 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
816 struct snd_soc_dapm_widget_list *list;
817 int paths;
818
819 list = kzalloc(sizeof(struct snd_soc_dapm_widget_list) +
820 sizeof(struct snd_soc_dapm_widget *), GFP_KERNEL);
821 if (list == NULL)
822 return -ENOMEM;
823
824 /* get number of valid DAI paths and their widgets */
825 paths = snd_soc_dapm_dai_get_connected_widgets(cpu_dai, stream, &list);
826
827 dev_dbg(fe->dev, "found %d audio %s paths\n", paths,
828 stream ? "capture" : "playback");
829
830 *list_ = list;
831 return paths;
832}
833
834static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
835{
836 kfree(*list);
837}
838
839static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream,
840 struct snd_soc_dapm_widget_list **list_)
841{
842 struct snd_soc_dpcm *dpcm;
843 struct snd_soc_dapm_widget_list *list = *list_;
844 struct snd_soc_dapm_widget *widget;
845 int prune = 0;
846
847 /* Destroy any old FE <--> BE connections */
848 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
849
850 /* is there a valid CPU DAI widget for this BE */
851 widget = rtd_get_cpu_widget(dpcm->be, stream);
852
853 /* prune the BE if it's no longer in our active list */
854 if (widget && widget_in_list(list, widget))
855 continue;
856
857 /* is there a valid CODEC DAI widget for this BE */
858 widget = rtd_get_codec_widget(dpcm->be, stream);
859
860 /* prune the BE if it's no longer in our active list */
861 if (widget && widget_in_list(list, widget))
862 continue;
863
864 dev_dbg(fe->dev, "pruning %s BE %s for %s\n",
865 stream ? "capture" : "playback",
866 dpcm->be->dai_link->name, fe->dai_link->name);
867 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
868 dpcm->be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
869 prune++;
870 }
871
872 dev_dbg(fe->dev, "found %d old BE paths for pruning\n", prune);
873 return prune;
874}
875
876static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream,
877 struct snd_soc_dapm_widget_list **list_)
878{
879 struct snd_soc_card *card = fe->card;
880 struct snd_soc_dapm_widget_list *list = *list_;
881 struct snd_soc_pcm_runtime *be;
882 int i, new = 0, err;
883
884 /* Create any new FE <--> BE connections */
885 for (i = 0; i < list->num_widgets; i++) {
886
887 if (list->widgets[i]->id != snd_soc_dapm_dai)
888 continue;
889
890 /* is there a valid BE rtd for this widget */
891 be = dpcm_get_be(card, list->widgets[i], stream);
892 if (!be) {
893 dev_err(fe->dev, "no BE found for %s\n",
894 list->widgets[i]->name);
895 continue;
896 }
897
898 /* make sure BE is a real BE */
899 if (!be->dai_link->no_pcm)
900 continue;
901
902 /* don't connect if FE is not running */
903 if (!fe->dpcm[stream].runtime)
904 continue;
905
906 /* newly connected FE and BE */
907 err = dpcm_be_connect(fe, be, stream);
908 if (err < 0) {
909 dev_err(fe->dev, "can't connect %s\n",
910 list->widgets[i]->name);
911 break;
912 } else if (err == 0) /* already connected */
913 continue;
914
915 /* new */
916 be->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_BE;
917 new++;
918 }
919
920 dev_dbg(fe->dev, "found %d new BE paths\n", new);
921 return new;
922}
923
924/*
925 * Find the corresponding BE DAIs that source or sink audio to this
926 * FE substream.
927 */
928static int dpcm_process_paths(struct snd_soc_pcm_runtime *fe,
929 int stream, struct snd_soc_dapm_widget_list **list, int new)
930{
931 if (new)
932 return dpcm_add_paths(fe, stream, list);
933 else
934 return dpcm_prune_paths(fe, stream, list);
935}
936
937static void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream)
938{
939 struct snd_soc_dpcm *dpcm;
940
941 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
942 dpcm->be->dpcm[stream].runtime_update =
943 SND_SOC_DPCM_UPDATE_NO;
944}
945
946static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe,
947 int stream)
948{
949 struct snd_soc_dpcm *dpcm;
950
951 /* disable any enabled and non active backends */
952 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
953
954 struct snd_soc_pcm_runtime *be = dpcm->be;
955 struct snd_pcm_substream *be_substream =
956 snd_soc_dpcm_get_substream(be, stream);
957
958 if (be->dpcm[stream].users == 0)
959 dev_err(be->dev, "no users %s at close - state %d\n",
960 stream ? "capture" : "playback",
961 be->dpcm[stream].state);
962
963 if (--be->dpcm[stream].users != 0)
964 continue;
965
966 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
967 continue;
968
969 soc_pcm_close(be_substream);
970 be_substream->runtime = NULL;
971 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
972 }
973}
974
975static int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream)
976{
977 struct snd_soc_dpcm *dpcm;
978 int err, count = 0;
979
980 /* only startup BE DAIs that are either sinks or sources to this FE DAI */
981 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
982
983 struct snd_soc_pcm_runtime *be = dpcm->be;
984 struct snd_pcm_substream *be_substream =
985 snd_soc_dpcm_get_substream(be, stream);
986
987 /* is this op for this BE ? */
988 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
989 continue;
990
991 /* first time the dpcm is open ? */
992 if (be->dpcm[stream].users == DPCM_MAX_BE_USERS)
993 dev_err(be->dev, "too many users %s at open %d\n",
994 stream ? "capture" : "playback",
995 be->dpcm[stream].state);
996
997 if (be->dpcm[stream].users++ != 0)
998 continue;
999
1000 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) &&
1001 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE))
1002 continue;
1003
1004 dev_dbg(be->dev, "dpcm: open BE %s\n", be->dai_link->name);
1005
1006 be_substream->runtime = be->dpcm[stream].runtime;
1007 err = soc_pcm_open(be_substream);
1008 if (err < 0) {
1009 dev_err(be->dev, "BE open failed %d\n", err);
1010 be->dpcm[stream].users--;
1011 if (be->dpcm[stream].users < 0)
1012 dev_err(be->dev, "no users %s at unwind %d\n",
1013 stream ? "capture" : "playback",
1014 be->dpcm[stream].state);
1015
1016 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1017 goto unwind;
1018 }
1019
1020 be->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1021 count++;
1022 }
1023
1024 return count;
1025
1026unwind:
1027 /* disable any enabled and non active backends */
1028 list_for_each_entry_continue_reverse(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1029 struct snd_soc_pcm_runtime *be = dpcm->be;
1030 struct snd_pcm_substream *be_substream =
1031 snd_soc_dpcm_get_substream(be, stream);
1032
1033 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1034 continue;
1035
1036 if (be->dpcm[stream].users == 0)
1037 dev_err(be->dev, "no users %s at close %d\n",
1038 stream ? "capture" : "playback",
1039 be->dpcm[stream].state);
1040
1041 if (--be->dpcm[stream].users != 0)
1042 continue;
1043
1044 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)
1045 continue;
1046
1047 soc_pcm_close(be_substream);
1048 be_substream->runtime = NULL;
1049 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1050 }
1051
1052 return err;
1053}
1054
1055void dpcm_set_fe_runtime(struct snd_pcm_substream *substream)
1056{
1057 struct snd_pcm_runtime *runtime = substream->runtime;
1058 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1059 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1060 struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
1061
1062 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1063 runtime->hw.rate_min = cpu_dai_drv->playback.rate_min;
1064 runtime->hw.rate_max = cpu_dai_drv->playback.rate_max;
1065 runtime->hw.channels_min = cpu_dai_drv->playback.channels_min;
1066 runtime->hw.channels_max = cpu_dai_drv->playback.channels_max;
1067 runtime->hw.formats &= cpu_dai_drv->playback.formats;
1068 runtime->hw.rates = cpu_dai_drv->playback.rates;
1069 } else {
1070 runtime->hw.rate_min = cpu_dai_drv->capture.rate_min;
1071 runtime->hw.rate_max = cpu_dai_drv->capture.rate_max;
1072 runtime->hw.channels_min = cpu_dai_drv->capture.channels_min;
1073 runtime->hw.channels_max = cpu_dai_drv->capture.channels_max;
1074 runtime->hw.formats &= cpu_dai_drv->capture.formats;
1075 runtime->hw.rates = cpu_dai_drv->capture.rates;
1076 }
1077}
1078
1079static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream)
1080{
1081 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
1082 struct snd_pcm_runtime *runtime = fe_substream->runtime;
1083 int stream = fe_substream->stream, ret = 0;
1084
1085 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1086
1087 ret = dpcm_be_dai_startup(fe, fe_substream->stream);
1088 if (ret < 0) {
1089 dev_err(fe->dev,"dpcm: failed to start some BEs %d\n", ret);
1090 goto be_err;
1091 }
1092
1093 dev_dbg(fe->dev, "dpcm: open FE %s\n", fe->dai_link->name);
1094
1095 /* start the DAI frontend */
1096 ret = soc_pcm_open(fe_substream);
1097 if (ret < 0) {
1098 dev_err(fe->dev,"dpcm: failed to start FE %d\n", ret);
1099 goto unwind;
1100 }
1101
1102 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1103
1104 dpcm_set_fe_runtime(fe_substream);
1105 snd_pcm_limit_hw_rates(runtime);
1106
1107 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1108 return 0;
1109
1110unwind:
1111 dpcm_be_dai_startup_unwind(fe, fe_substream->stream);
1112be_err:
1113 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1114 return ret;
1115}
1116
1117static int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream)
1118{
1119 struct snd_soc_dpcm *dpcm;
1120
1121 /* only shutdown BEs that are either sinks or sources to this FE DAI */
1122 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1123
1124 struct snd_soc_pcm_runtime *be = dpcm->be;
1125 struct snd_pcm_substream *be_substream =
1126 snd_soc_dpcm_get_substream(be, stream);
1127
1128 /* is this op for this BE ? */
1129 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1130 continue;
1131
1132 if (be->dpcm[stream].users == 0)
1133 dev_err(be->dev, "no users %s at close - state %d\n",
1134 stream ? "capture" : "playback",
1135 be->dpcm[stream].state);
1136
1137 if (--be->dpcm[stream].users != 0)
1138 continue;
1139
1140 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1141 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN))
1142 continue;
1143
1144 dev_dbg(be->dev, "dpcm: close BE %s\n",
1145 dpcm->fe->dai_link->name);
1146
1147 soc_pcm_close(be_substream);
1148 be_substream->runtime = NULL;
1149
1150 be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1151 }
1152 return 0;
1153}
1154
1155static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream)
1156{
1157 struct snd_soc_pcm_runtime *fe = substream->private_data;
1158 int stream = substream->stream;
1159
1160 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1161
1162 /* shutdown the BEs */
1163 dpcm_be_dai_shutdown(fe, substream->stream);
1164
1165 dev_dbg(fe->dev, "dpcm: close FE %s\n", fe->dai_link->name);
1166
1167 /* now shutdown the frontend */
1168 soc_pcm_close(substream);
1169
1170 /* run the stream event for each BE */
1171 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
1172
1173 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
1174 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1175 return 0;
1176}
1177
1178static int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
1179{
1180 struct snd_soc_dpcm *dpcm;
1181
1182 /* only hw_params backends that are either sinks or sources
1183 * to this frontend DAI */
1184 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1185
1186 struct snd_soc_pcm_runtime *be = dpcm->be;
1187 struct snd_pcm_substream *be_substream =
1188 snd_soc_dpcm_get_substream(be, stream);
1189
1190 /* is this op for this BE ? */
1191 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1192 continue;
1193
1194 /* only free hw when no longer used - check all FEs */
1195 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1196 continue;
1197
1198 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1199 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
1200 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1201 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1202 continue;
1203
1204 dev_dbg(be->dev, "dpcm: hw_free BE %s\n",
1205 dpcm->fe->dai_link->name);
1206
1207 soc_pcm_hw_free(be_substream);
1208
1209 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1210 }
1211
1212 return 0;
1213}
1214
1215int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream)
1216{
1217 struct snd_soc_pcm_runtime *fe = substream->private_data;
1218 int err, stream = substream->stream;
1219
1220 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
1221 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1222
1223 dev_dbg(fe->dev, "dpcm: hw_free FE %s\n", fe->dai_link->name);
1224
1225 /* call hw_free on the frontend */
1226 err = soc_pcm_hw_free(substream);
1227 if (err < 0)
1228 dev_err(fe->dev,"dpcm: hw_free FE %s failed\n",
1229 fe->dai_link->name);
1230
1231 /* only hw_params backends that are either sinks or sources
1232 * to this frontend DAI */
1233 err = dpcm_be_dai_hw_free(fe, stream);
1234
1235 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE;
1236 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1237
1238 mutex_unlock(&fe->card->mutex);
1239 return 0;
1240}
1241
1242static int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream)
1243{
1244 struct snd_soc_dpcm *dpcm;
1245 int ret;
1246
1247 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1248
1249 struct snd_soc_pcm_runtime *be = dpcm->be;
1250 struct snd_pcm_substream *be_substream =
1251 snd_soc_dpcm_get_substream(be, stream);
1252
1253 /* is this op for this BE ? */
1254 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1255 continue;
1256
1257 /* only allow hw_params() if no connected FEs are running */
1258 if (!snd_soc_dpcm_can_be_params(fe, be, stream))
1259 continue;
1260
1261 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
1262 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1263 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE))
1264 continue;
1265
1266 dev_dbg(be->dev, "dpcm: hw_params BE %s\n",
1267 dpcm->fe->dai_link->name);
1268
1269 /* copy params for each dpcm */
1270 memcpy(&dpcm->hw_params, &fe->dpcm[stream].hw_params,
1271 sizeof(struct snd_pcm_hw_params));
1272
1273 /* perform any hw_params fixups */
1274 if (be->dai_link->be_hw_params_fixup) {
1275 ret = be->dai_link->be_hw_params_fixup(be,
1276 &dpcm->hw_params);
1277 if (ret < 0) {
1278 dev_err(be->dev,
1279 "dpcm: hw_params BE fixup failed %d\n",
1280 ret);
1281 goto unwind;
1282 }
1283 }
1284
1285 ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params);
1286 if (ret < 0) {
1287 dev_err(dpcm->be->dev,
1288 "dpcm: hw_params BE failed %d\n", ret);
1289 goto unwind;
1290 }
1291
1292 be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
1293 }
1294 return 0;
1295
1296unwind:
1297 /* disable any enabled and non active backends */
1298 list_for_each_entry_continue_reverse(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1299 struct snd_soc_pcm_runtime *be = dpcm->be;
1300 struct snd_pcm_substream *be_substream =
1301 snd_soc_dpcm_get_substream(be, stream);
1302
1303 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1304 continue;
1305
1306 /* only allow hw_free() if no connected FEs are running */
1307 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1308 continue;
1309
1310 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) &&
1311 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1312 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
1313 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1314 continue;
1315
1316 soc_pcm_hw_free(be_substream);
1317 }
1318
1319 return ret;
1320}
1321
1322int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream,
1323 struct snd_pcm_hw_params *params)
1324{
1325 struct snd_soc_pcm_runtime *fe = substream->private_data;
1326 int ret, stream = substream->stream;
1327
1328 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
1329 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1330
1331 memcpy(&fe->dpcm[substream->stream].hw_params, params,
1332 sizeof(struct snd_pcm_hw_params));
1333 ret = dpcm_be_dai_hw_params(fe, substream->stream);
1334 if (ret < 0) {
1335 dev_err(fe->dev,"dpcm: hw_params BE failed %d\n", ret);
1336 goto out;
1337 }
1338
1339 dev_dbg(fe->dev, "dpcm: hw_params FE %s rate %d chan %x fmt %d\n",
1340 fe->dai_link->name, params_rate(params),
1341 params_channels(params), params_format(params));
1342
1343 /* call hw_params on the frontend */
1344 ret = soc_pcm_hw_params(substream, params);
1345 if (ret < 0) {
1346 dev_err(fe->dev,"dpcm: hw_params FE failed %d\n", ret);
1347 dpcm_be_dai_hw_free(fe, stream);
1348 } else
1349 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS;
1350
1351out:
1352 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1353 mutex_unlock(&fe->card->mutex);
1354 return ret;
1355}
1356
1357static int dpcm_do_trigger(struct snd_soc_dpcm *dpcm,
1358 struct snd_pcm_substream *substream, int cmd)
1359{
1360 int ret;
1361
1362 dev_dbg(dpcm->be->dev, "dpcm: trigger BE %s cmd %d\n",
1363 dpcm->fe->dai_link->name, cmd);
1364
1365 ret = soc_pcm_trigger(substream, cmd);
1366 if (ret < 0)
1367 dev_err(dpcm->be->dev,"dpcm: trigger BE failed %d\n", ret);
1368
1369 return ret;
1370}
1371
1372int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd)
1373{
1374 struct snd_soc_dpcm *dpcm;
1375 int ret = 0;
1376
1377 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1378
1379 struct snd_soc_pcm_runtime *be = dpcm->be;
1380 struct snd_pcm_substream *be_substream =
1381 snd_soc_dpcm_get_substream(be, stream);
1382
1383 /* is this op for this BE ? */
1384 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1385 continue;
1386
1387 switch (cmd) {
1388 case SNDRV_PCM_TRIGGER_START:
1389 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
1390 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1391 continue;
1392
1393 ret = dpcm_do_trigger(dpcm, be_substream, cmd);
1394 if (ret)
1395 return ret;
1396
1397 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1398 break;
1399 case SNDRV_PCM_TRIGGER_RESUME:
1400 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
1401 continue;
1402
1403 ret = dpcm_do_trigger(dpcm, be_substream, cmd);
1404 if (ret)
1405 return ret;
1406
1407 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1408 break;
1409 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1410 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED))
1411 continue;
1412
1413 ret = dpcm_do_trigger(dpcm, be_substream, cmd);
1414 if (ret)
1415 return ret;
1416
1417 be->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1418 break;
1419 case SNDRV_PCM_TRIGGER_STOP:
1420 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1421 continue;
1422
1423 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1424 continue;
1425
1426 ret = dpcm_do_trigger(dpcm, be_substream, cmd);
1427 if (ret)
1428 return ret;
1429
1430 be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
1431 break;
1432 case SNDRV_PCM_TRIGGER_SUSPEND:
1433 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)
1434 continue;
1435
1436 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1437 continue;
1438
1439 ret = dpcm_do_trigger(dpcm, be_substream, cmd);
1440 if (ret)
1441 return ret;
1442
1443 be->dpcm[stream].state = SND_SOC_DPCM_STATE_SUSPEND;
1444 break;
1445 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1446 if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_START)
1447 continue;
1448
1449 if (!snd_soc_dpcm_can_be_free_stop(fe, be, stream))
1450 continue;
1451
1452 ret = dpcm_do_trigger(dpcm, be_substream, cmd);
1453 if (ret)
1454 return ret;
1455
1456 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
1457 break;
1458 }
1459 }
1460
1461 return ret;
1462}
1463EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger);
1464
1465int dpcm_fe_dai_trigger(struct snd_pcm_substream *substream, int cmd)
1466{
1467 struct snd_soc_pcm_runtime *fe = substream->private_data;
1468 int stream = substream->stream, ret;
1469 enum snd_soc_dpcm_trigger trigger = fe->dai_link->trigger[stream];
1470
1471 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1472
1473 switch (trigger) {
1474 case SND_SOC_DPCM_TRIGGER_PRE:
1475 /* call trigger on the frontend before the backend. */
1476
1477 dev_dbg(fe->dev, "dpcm: pre trigger FE %s cmd %d\n",
1478 fe->dai_link->name, cmd);
1479
1480 ret = soc_pcm_trigger(substream, cmd);
1481 if (ret < 0) {
1482 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1483 goto out;
1484 }
1485
1486 ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
1487 break;
1488 case SND_SOC_DPCM_TRIGGER_POST:
1489 /* call trigger on the frontend after the backend. */
1490
1491 ret = dpcm_be_dai_trigger(fe, substream->stream, cmd);
1492 if (ret < 0) {
1493 dev_err(fe->dev,"dpcm: trigger FE failed %d\n", ret);
1494 goto out;
1495 }
1496
1497 dev_dbg(fe->dev, "dpcm: post trigger FE %s cmd %d\n",
1498 fe->dai_link->name, cmd);
1499
1500 ret = soc_pcm_trigger(substream, cmd);
1501 break;
1502 default:
1503 dev_err(fe->dev, "dpcm: invalid trigger cmd %d for %s\n", cmd,
1504 fe->dai_link->name);
1505 ret = -EINVAL;
1506 goto out;
1507 }
1508
1509 switch (cmd) {
1510 case SNDRV_PCM_TRIGGER_START:
1511 case SNDRV_PCM_TRIGGER_RESUME:
1512 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1513 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
1514 break;
1515 case SNDRV_PCM_TRIGGER_STOP:
1516 case SNDRV_PCM_TRIGGER_SUSPEND:
1517 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1518 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
1519 break;
1520 }
1521
1522out:
1523 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1524 return ret;
1525}
1526
1527static int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
1528{
1529 struct snd_soc_dpcm *dpcm;
1530 int ret = 0;
1531
1532 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be) {
1533
1534 struct snd_soc_pcm_runtime *be = dpcm->be;
1535 struct snd_pcm_substream *be_substream =
1536 snd_soc_dpcm_get_substream(be, stream);
1537
1538 /* is this op for this BE ? */
1539 if (!snd_soc_dpcm_be_can_update(fe, be, stream))
1540 continue;
1541
1542 if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
1543 (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
1544 continue;
1545
1546 dev_dbg(be->dev, "dpcm: prepare BE %s\n",
1547 dpcm->fe->dai_link->name);
1548
1549 ret = soc_pcm_prepare(be_substream);
1550 if (ret < 0) {
1551 dev_err(be->dev, "dpcm: backend prepare failed %d\n",
1552 ret);
1553 break;
1554 }
1555
1556 be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
1557 }
1558 return ret;
1559}
1560
1561int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream)
1562{
1563 struct snd_soc_pcm_runtime *fe = substream->private_data;
1564 int stream = substream->stream, ret = 0;
1565
1566 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
1567
1568 dev_dbg(fe->dev, "dpcm: prepare FE %s\n", fe->dai_link->name);
1569
1570 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1571
1572 /* there is no point preparing this FE if there are no BEs */
1573 if (list_empty(&fe->dpcm[stream].be_clients)) {
1574 dev_err(fe->dev, "dpcm: no backend DAIs enabled for %s\n",
1575 fe->dai_link->name);
1576 ret = -EINVAL;
1577 goto out;
1578 }
1579
1580 ret = dpcm_be_dai_prepare(fe, substream->stream);
1581 if (ret < 0)
1582 goto out;
1583
1584 /* call prepare on the frontend */
1585 ret = soc_pcm_prepare(substream);
1586 if (ret < 0) {
1587 dev_err(fe->dev,"dpcm: prepare FE %s failed\n",
1588 fe->dai_link->name);
1589 goto out;
1590 }
1591
1592 /* run the stream event for each BE */
1593 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
1594 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
1595
1596out:
1597 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1598 mutex_unlock(&fe->card->mutex);
1599
1600 return ret;
1601}
1602
1603
1604int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute)
1605{
1606 struct snd_soc_dpcm *dpcm;
1607 struct list_head *clients =
1608 &fe->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients;
1609
1610 list_for_each_entry(dpcm, clients, list_be) {
1611
1612 struct snd_soc_pcm_runtime *be = dpcm->be;
1613 struct snd_soc_dai *dai = be->codec_dai;
1614 struct snd_soc_dai_driver *drv = dai->driver;
1615
1616 if (be->dai_link->ignore_suspend)
1617 continue;
1618
1619 dev_dbg(be->dev, "BE digital mute %s\n", be->dai_link->name);
1620
1621 if (drv->ops->digital_mute && dai->playback_active)
1622 drv->ops->digital_mute(dai, mute);
1623 }
1624
1625 return 0;
1626}
1627
1628int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream)
1629{
1630 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
1631 struct snd_soc_dpcm *dpcm;
1632 struct snd_soc_dapm_widget_list *list;
1633 int ret;
1634 int stream = fe_substream->stream;
1635
1636 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
1637 fe->dpcm[stream].runtime = fe_substream->runtime;
1638
1639 if (dpcm_path_get(fe, stream, &list) <= 0) {
1640 dev_warn(fe->dev, "asoc: %s no valid %s route\n",
1641 fe->dai_link->name, stream ? "capture" : "playback");
1642 mutex_unlock(&fe->card->mutex);
1643 return -EINVAL;
1644 }
1645
1646 /* calculate valid and active FE <-> BE dpcms */
1647 dpcm_process_paths(fe, stream, &list, 1);
1648
1649 ret = dpcm_fe_dai_startup(fe_substream);
1650 if (ret < 0) {
1651 /* clean up all links */
1652 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
1653 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
1654
1655 dpcm_be_disconnect(fe, stream);
1656 fe->dpcm[stream].runtime = NULL;
1657 }
1658
1659 dpcm_clear_pending_state(fe, stream);
1660 dpcm_path_put(&list);
1661 mutex_unlock(&fe->card->mutex);
1662 return ret;
1663}
1664
1665int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream)
1666{
1667 struct snd_soc_pcm_runtime *fe = fe_substream->private_data;
1668 struct snd_soc_dpcm *dpcm;
1669 int stream = fe_substream->stream, ret;
1670
1671 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
1672 ret = dpcm_fe_dai_shutdown(fe_substream);
1673
1674 /* mark FE's links ready to prune */
1675 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
1676 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
1677
1678 dpcm_be_disconnect(fe, stream);
1679
1680 fe->dpcm[stream].runtime = NULL;
1681 mutex_unlock(&fe->card->mutex);
1682 return ret;
1683}
1684
636/* create a new pcm */ 1685/* create a new pcm */
637int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) 1686int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
638{ 1687{
@@ -640,56 +1689,92 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
640 struct snd_soc_platform *platform = rtd->platform; 1689 struct snd_soc_platform *platform = rtd->platform;
641 struct snd_soc_dai *codec_dai = rtd->codec_dai; 1690 struct snd_soc_dai *codec_dai = rtd->codec_dai;
642 struct snd_soc_dai *cpu_dai = rtd->cpu_dai; 1691 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
643 struct snd_pcm_ops *soc_pcm_ops = &rtd->ops;
644 struct snd_pcm *pcm; 1692 struct snd_pcm *pcm;
645 char new_name[64]; 1693 char new_name[64];
646 int ret = 0, playback = 0, capture = 0; 1694 int ret = 0, playback = 0, capture = 0;
647 1695
648 soc_pcm_ops->open = soc_pcm_open; 1696 if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) {
649 soc_pcm_ops->close = soc_pcm_close; 1697 if (cpu_dai->driver->playback.channels_min)
650 soc_pcm_ops->hw_params = soc_pcm_hw_params; 1698 playback = 1;
651 soc_pcm_ops->hw_free = soc_pcm_hw_free; 1699 if (cpu_dai->driver->capture.channels_min)
652 soc_pcm_ops->prepare = soc_pcm_prepare; 1700 capture = 1;
653 soc_pcm_ops->trigger = soc_pcm_trigger; 1701 } else {
654 soc_pcm_ops->pointer = soc_pcm_pointer; 1702 if (codec_dai->driver->playback.channels_min)
655 1703 playback = 1;
656 /* check client and interface hw capabilities */ 1704 if (codec_dai->driver->capture.channels_min)
657 snprintf(new_name, sizeof(new_name), "%s %s-%d", 1705 capture = 1;
658 rtd->dai_link->stream_name, codec_dai->name, num); 1706 }
659 1707
660 if (codec_dai->driver->playback.channels_min) 1708 /* create the PCM */
661 playback = 1; 1709 if (rtd->dai_link->no_pcm) {
662 if (codec_dai->driver->capture.channels_min) 1710 snprintf(new_name, sizeof(new_name), "(%s)",
663 capture = 1; 1711 rtd->dai_link->stream_name);
664 1712
665 dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name); 1713 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
666 ret = snd_pcm_new(rtd->card->snd_card, new_name, 1714 playback, capture, &pcm);
667 num, playback, capture, &pcm); 1715 } else {
1716 if (rtd->dai_link->dynamic)
1717 snprintf(new_name, sizeof(new_name), "%s (*)",
1718 rtd->dai_link->stream_name);
1719 else
1720 snprintf(new_name, sizeof(new_name), "%s %s-%d",
1721 rtd->dai_link->stream_name, codec_dai->name, num);
1722
1723 ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback,
1724 capture, &pcm);
1725 }
668 if (ret < 0) { 1726 if (ret < 0) {
669 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name); 1727 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
670 return ret; 1728 return ret;
671 } 1729 }
1730 dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num, new_name);
672 1731
673 /* DAPM dai link stream work */ 1732 /* DAPM dai link stream work */
674 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); 1733 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
675 1734
676 rtd->pcm = pcm; 1735 rtd->pcm = pcm;
677 pcm->private_data = rtd; 1736 pcm->private_data = rtd;
1737
1738 if (rtd->dai_link->no_pcm) {
1739 if (playback)
1740 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
1741 if (capture)
1742 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
1743 goto out;
1744 }
1745
1746 /* ASoC PCM operations */
1747 if (rtd->dai_link->dynamic) {
1748 rtd->ops.open = dpcm_fe_dai_open;
1749 rtd->ops.hw_params = dpcm_fe_dai_hw_params;
1750 rtd->ops.prepare = dpcm_fe_dai_prepare;
1751 rtd->ops.trigger = dpcm_fe_dai_trigger;
1752 rtd->ops.hw_free = dpcm_fe_dai_hw_free;
1753 rtd->ops.close = dpcm_fe_dai_close;
1754 rtd->ops.pointer = soc_pcm_pointer;
1755 } else {
1756 rtd->ops.open = soc_pcm_open;
1757 rtd->ops.hw_params = soc_pcm_hw_params;
1758 rtd->ops.prepare = soc_pcm_prepare;
1759 rtd->ops.trigger = soc_pcm_trigger;
1760 rtd->ops.hw_free = soc_pcm_hw_free;
1761 rtd->ops.close = soc_pcm_close;
1762 rtd->ops.pointer = soc_pcm_pointer;
1763 }
1764
678 if (platform->driver->ops) { 1765 if (platform->driver->ops) {
679 soc_pcm_ops->mmap = platform->driver->ops->mmap; 1766 rtd->ops.ack = platform->driver->ops->ack;
680 soc_pcm_ops->pointer = platform->driver->ops->pointer; 1767 rtd->ops.copy = platform->driver->ops->copy;
681 soc_pcm_ops->ioctl = platform->driver->ops->ioctl; 1768 rtd->ops.silence = platform->driver->ops->silence;
682 soc_pcm_ops->copy = platform->driver->ops->copy; 1769 rtd->ops.page = platform->driver->ops->page;
683 soc_pcm_ops->silence = platform->driver->ops->silence; 1770 rtd->ops.mmap = platform->driver->ops->mmap;
684 soc_pcm_ops->ack = platform->driver->ops->ack;
685 soc_pcm_ops->page = platform->driver->ops->page;
686 } 1771 }
687 1772
688 if (playback) 1773 if (playback)
689 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, soc_pcm_ops); 1774 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &rtd->ops);
690 1775
691 if (capture) 1776 if (capture)
692 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, soc_pcm_ops); 1777 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops);
693 1778
694 if (platform->driver->pcm_new) { 1779 if (platform->driver->pcm_new) {
695 ret = platform->driver->pcm_new(rtd); 1780 ret = platform->driver->pcm_new(rtd);
@@ -700,7 +1785,108 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
700 } 1785 }
701 1786
702 pcm->private_free = platform->driver->pcm_free; 1787 pcm->private_free = platform->driver->pcm_free;
1788out:
703 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, 1789 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
704 cpu_dai->name); 1790 cpu_dai->name);
705 return ret; 1791 return ret;
706} 1792}
1793
1794/* is the current PCM operation for this FE ? */
1795int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream)
1796{
1797 if (fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_FE)
1798 return 1;
1799 return 0;
1800}
1801EXPORT_SYMBOL_GPL(snd_soc_dpcm_fe_can_update);
1802
1803/* is the current PCM operation for this BE ? */
1804int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
1805 struct snd_soc_pcm_runtime *be, int stream)
1806{
1807 if ((fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_FE) ||
1808 ((fe->dpcm[stream].runtime_update == SND_SOC_DPCM_UPDATE_BE) &&
1809 be->dpcm[stream].runtime_update))
1810 return 1;
1811 return 0;
1812}
1813EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_can_update);
1814
1815/* get the substream for this BE */
1816struct snd_pcm_substream *
1817 snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream)
1818{
1819 return be->pcm->streams[stream].substream;
1820}
1821EXPORT_SYMBOL_GPL(snd_soc_dpcm_get_substream);
1822
1823/* get the BE runtime state */
1824enum snd_soc_dpcm_state
1825 snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream)
1826{
1827 return be->dpcm[stream].state;
1828}
1829EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_get_state);
1830
1831/* set the BE runtime state */
1832void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be,
1833 int stream, enum snd_soc_dpcm_state state)
1834{
1835 be->dpcm[stream].state = state;
1836}
1837EXPORT_SYMBOL_GPL(snd_soc_dpcm_be_set_state);
1838
1839/*
1840 * We can only hw_free, stop, pause or suspend a BE DAI if any of it's FE
1841 * are not running, paused or suspended for the specified stream direction.
1842 */
1843int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
1844 struct snd_soc_pcm_runtime *be, int stream)
1845{
1846 struct snd_soc_dpcm *dpcm;
1847 int state;
1848
1849 list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) {
1850
1851 if (dpcm->fe == fe)
1852 continue;
1853
1854 state = dpcm->fe->dpcm[stream].state;
1855 if (state == SND_SOC_DPCM_STATE_START ||
1856 state == SND_SOC_DPCM_STATE_PAUSED ||
1857 state == SND_SOC_DPCM_STATE_SUSPEND)
1858 return 0;
1859 }
1860
1861 /* it's safe to free/stop this BE DAI */
1862 return 1;
1863}
1864EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_free_stop);
1865
1866/*
1867 * We can only change hw params a BE DAI if any of it's FE are not prepared,
1868 * running, paused or suspended for the specified stream direction.
1869 */
1870int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
1871 struct snd_soc_pcm_runtime *be, int stream)
1872{
1873 struct snd_soc_dpcm *dpcm;
1874 int state;
1875
1876 list_for_each_entry(dpcm, &be->dpcm[stream].fe_clients, list_fe) {
1877
1878 if (dpcm->fe == fe)
1879 continue;
1880
1881 state = dpcm->fe->dpcm[stream].state;
1882 if (state == SND_SOC_DPCM_STATE_START ||
1883 state == SND_SOC_DPCM_STATE_PAUSED ||
1884 state == SND_SOC_DPCM_STATE_SUSPEND ||
1885 state == SND_SOC_DPCM_STATE_PREPARE)
1886 return 0;
1887 }
1888
1889 /* it's safe to change hw_params */
1890 return 1;
1891}
1892EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);