aboutsummaryrefslogtreecommitdiffstats
path: root/include/sound
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 /include/sound
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 'include/sound')
-rw-r--r--include/sound/soc-dpcm.h132
-rw-r--r--include/sound/soc.h17
2 files changed, 149 insertions, 0 deletions
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h
new file mode 100644
index 000000000000..cd72c1090586
--- /dev/null
+++ b/include/sound/soc-dpcm.h
@@ -0,0 +1,132 @@
1/*
2 * linux/sound/soc-dpcm.h -- ALSA SoC Dynamic PCM Support
3 *
4 * Author: Liam Girdwood <lrg@ti.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef __LINUX_SND_SOC_DPCM_H
12#define __LINUX_SND_SOC_DPCM_H
13
14#include <linux/list.h>
15#include <sound/pcm.h>
16
17struct snd_soc_pcm_runtime;
18
19/*
20 * Types of runtime_update to perform. e.g. originated from FE PCM ops
21 * or audio route changes triggered by muxes/mixers.
22 */
23enum snd_soc_dpcm_update {
24 SND_SOC_DPCM_UPDATE_NO = 0,
25 SND_SOC_DPCM_UPDATE_BE,
26 SND_SOC_DPCM_UPDATE_FE,
27};
28
29/*
30 * Dynamic PCM Frontend -> Backend link management states.
31 */
32enum snd_soc_dpcm_link_state {
33 SND_SOC_DPCM_LINK_STATE_NEW = 0, /* newly created link */
34 SND_SOC_DPCM_LINK_STATE_FREE, /* link to be dismantled */
35};
36
37/*
38 * Dynamic PCM Frontend -> Backend link PCM states.
39 */
40enum snd_soc_dpcm_state {
41 SND_SOC_DPCM_STATE_NEW = 0,
42 SND_SOC_DPCM_STATE_OPEN,
43 SND_SOC_DPCM_STATE_HW_PARAMS,
44 SND_SOC_DPCM_STATE_PREPARE,
45 SND_SOC_DPCM_STATE_START,
46 SND_SOC_DPCM_STATE_STOP,
47 SND_SOC_DPCM_STATE_PAUSED,
48 SND_SOC_DPCM_STATE_SUSPEND,
49 SND_SOC_DPCM_STATE_HW_FREE,
50 SND_SOC_DPCM_STATE_CLOSE,
51};
52
53/*
54 * Dynamic PCM trigger ordering. Triggering flexibility is required as some
55 * DSPs require triggering before/after their CPU platform and DAIs.
56 *
57 * i.e. some clients may want to manually order this call in their PCM
58 * trigger() whilst others will just use the regular core ordering.
59 */
60enum snd_soc_dpcm_trigger {
61 SND_SOC_DPCM_TRIGGER_PRE = 0,
62 SND_SOC_DPCM_TRIGGER_POST,
63};
64
65/*
66 * Dynamic PCM link
67 * This links together a FE and BE DAI at runtime and stores the link
68 * state information and the hw_params configuration.
69 */
70struct snd_soc_dpcm {
71 /* FE and BE DAIs*/
72 struct snd_soc_pcm_runtime *be;
73 struct snd_soc_pcm_runtime *fe;
74
75 /* link state */
76 enum snd_soc_dpcm_link_state state;
77
78 /* list of BE and FE for this DPCM link */
79 struct list_head list_be;
80 struct list_head list_fe;
81
82 /* hw params for this link - may be different for each link */
83 struct snd_pcm_hw_params hw_params;
84};
85
86/*
87 * Dynamic PCM runtime data.
88 */
89struct snd_soc_dpcm_runtime {
90 struct list_head be_clients;
91 struct list_head fe_clients;
92
93 int users;
94 struct snd_pcm_runtime *runtime;
95 struct snd_pcm_hw_params hw_params;
96
97 /* state and update */
98 enum snd_soc_dpcm_update runtime_update;
99 enum snd_soc_dpcm_state state;
100};
101
102/* can this BE stop and free */
103int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
104 struct snd_soc_pcm_runtime *be, int stream);
105
106/* can this BE perform a hw_params() */
107int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
108 struct snd_soc_pcm_runtime *be, int stream);
109
110/* is the current PCM operation for this FE ? */
111int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
112
113/* is the current PCM operation for this BE ? */
114int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
115 struct snd_soc_pcm_runtime *be, int stream);
116
117/* get the substream for this BE */
118struct snd_pcm_substream *
119 snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream);
120
121/* get the BE runtime state */
122enum snd_soc_dpcm_state
123 snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream);
124
125/* set the BE runtime state */
126void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
127 enum snd_soc_dpcm_state state);
128
129/* internal use only */
130int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
131
132#endif
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 1f38aa1653c8..78aec854b6a1 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -287,6 +287,7 @@ struct snd_soc_jack_zone;
287struct snd_soc_jack_pin; 287struct snd_soc_jack_pin;
288struct snd_soc_cache_ops; 288struct snd_soc_cache_ops;
289#include <sound/soc-dapm.h> 289#include <sound/soc-dapm.h>
290#include <sound/soc-dpcm.h>
290 291
291#ifdef CONFIG_GPIOLIB 292#ifdef CONFIG_GPIOLIB
292struct snd_soc_jack_gpio; 293struct snd_soc_jack_gpio;
@@ -782,23 +783,36 @@ struct snd_soc_dai_link {
782 const char *cpu_dai_name; 783 const char *cpu_dai_name;
783 const struct device_node *cpu_dai_of_node; 784 const struct device_node *cpu_dai_of_node;
784 const char *codec_dai_name; 785 const char *codec_dai_name;
786 int be_id; /* optional ID for machine driver BE identification */
785 787
786 const struct snd_soc_pcm_stream *params; 788 const struct snd_soc_pcm_stream *params;
787 789
788 unsigned int dai_fmt; /* format to set on init */ 790 unsigned int dai_fmt; /* format to set on init */
789 791
792 enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */
793
790 /* Keep DAI active over suspend */ 794 /* Keep DAI active over suspend */
791 unsigned int ignore_suspend:1; 795 unsigned int ignore_suspend:1;
792 796
793 /* Symmetry requirements */ 797 /* Symmetry requirements */
794 unsigned int symmetric_rates:1; 798 unsigned int symmetric_rates:1;
795 799
800 /* Do not create a PCM for this DAI link (Backend link) */
801 unsigned int no_pcm:1;
802
803 /* This DAI link can route to other DAI links at runtime (Frontend)*/
804 unsigned int dynamic:1;
805
796 /* pmdown_time is ignored at stop */ 806 /* pmdown_time is ignored at stop */
797 unsigned int ignore_pmdown_time:1; 807 unsigned int ignore_pmdown_time:1;
798 808
799 /* codec/machine specific init - e.g. add machine controls */ 809 /* codec/machine specific init - e.g. add machine controls */
800 int (*init)(struct snd_soc_pcm_runtime *rtd); 810 int (*init)(struct snd_soc_pcm_runtime *rtd);
801 811
812 /* optional hw_params re-writing for BE and FE sync */
813 int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd,
814 struct snd_pcm_hw_params *params);
815
802 /* machine stream operations */ 816 /* machine stream operations */
803 struct snd_soc_ops *ops; 817 struct snd_soc_ops *ops;
804}; 818};
@@ -930,6 +944,9 @@ struct snd_soc_pcm_runtime {
930 944
931 unsigned int dev_registered:1; 945 unsigned int dev_registered:1;
932 946
947 /* Dynamic PCM BE runtime data */
948 struct snd_soc_dpcm_runtime dpcm[2];
949
933 long pmdown_time; 950 long pmdown_time;
934 951
935 /* runtime devices */ 952 /* runtime devices */