diff options
Diffstat (limited to 'Documentation/sound/alsa/soc/DPCM.txt')
-rw-r--r-- | Documentation/sound/alsa/soc/DPCM.txt | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/Documentation/sound/alsa/soc/DPCM.txt b/Documentation/sound/alsa/soc/DPCM.txt new file mode 100644 index 000000000000..0110180b7ac6 --- /dev/null +++ b/Documentation/sound/alsa/soc/DPCM.txt | |||
@@ -0,0 +1,380 @@ | |||
1 | Dynamic PCM | ||
2 | =========== | ||
3 | |||
4 | 1. Description | ||
5 | ============== | ||
6 | |||
7 | Dynamic PCM allows an ALSA PCM device to digitally route its PCM audio to | ||
8 | various digital endpoints during the PCM stream runtime. e.g. PCM0 can route | ||
9 | digital audio to I2S DAI0, I2S DAI1 or PDM DAI2. This is useful for on SoC DSP | ||
10 | drivers that expose several ALSA PCMs and can route to multiple DAIs. | ||
11 | |||
12 | The DPCM runtime routing is determined by the ALSA mixer settings in the same | ||
13 | way as the analog signal is routed in an ASoC codec driver. DPCM uses a DAPM | ||
14 | graph representing the DSP internal audio paths and uses the mixer settings to | ||
15 | determine the patch used by each ALSA PCM. | ||
16 | |||
17 | DPCM re-uses all the existing component codec, platform and DAI drivers without | ||
18 | any modifications. | ||
19 | |||
20 | |||
21 | Phone Audio System with SoC based DSP | ||
22 | ------------------------------------- | ||
23 | |||
24 | Consider the following phone audio subsystem. This will be used in this | ||
25 | document for all examples :- | ||
26 | |||
27 | | Front End PCMs | SoC DSP | Back End DAIs | Audio devices | | ||
28 | |||
29 | ************* | ||
30 | PCM0 <------------> * * <----DAI0-----> Codec Headset | ||
31 | * * | ||
32 | PCM1 <------------> * * <----DAI1-----> Codec Speakers | ||
33 | * DSP * | ||
34 | PCM2 <------------> * * <----DAI2-----> MODEM | ||
35 | * * | ||
36 | PCM3 <------------> * * <----DAI3-----> BT | ||
37 | * * | ||
38 | * * <----DAI4-----> DMIC | ||
39 | * * | ||
40 | * * <----DAI5-----> FM | ||
41 | ************* | ||
42 | |||
43 | This diagram shows a simple smart phone audio subsystem. It supports Bluetooth, | ||
44 | FM digital radio, Speakers, Headset Jack, digital microphones and cellular | ||
45 | modem. This sound card exposes 4 DSP front end (FE) ALSA PCM devices and | ||
46 | supports 6 back end (BE) DAIs. Each FE PCM can digitally route audio data to any | ||
47 | of the BE DAIs. The FE PCM devices can also route audio to more than 1 BE DAI. | ||
48 | |||
49 | |||
50 | |||
51 | Example - DPCM Switching playback from DAI0 to DAI1 | ||
52 | --------------------------------------------------- | ||
53 | |||
54 | Audio is being played to the Headset. After a while the user removes the headset | ||
55 | and audio continues playing on the speakers. | ||
56 | |||
57 | Playback on PCM0 to Headset would look like :- | ||
58 | |||
59 | ************* | ||
60 | PCM0 <============> * * <====DAI0=====> Codec Headset | ||
61 | * * | ||
62 | PCM1 <------------> * * <----DAI1-----> Codec Speakers | ||
63 | * DSP * | ||
64 | PCM2 <------------> * * <----DAI2-----> MODEM | ||
65 | * * | ||
66 | PCM3 <------------> * * <----DAI3-----> BT | ||
67 | * * | ||
68 | * * <----DAI4-----> DMIC | ||
69 | * * | ||
70 | * * <----DAI5-----> FM | ||
71 | ************* | ||
72 | |||
73 | The headset is removed from the jack by user so the speakers must now be used :- | ||
74 | |||
75 | ************* | ||
76 | PCM0 <============> * * <----DAI0-----> Codec Headset | ||
77 | * * | ||
78 | PCM1 <------------> * * <====DAI1=====> Codec Speakers | ||
79 | * DSP * | ||
80 | PCM2 <------------> * * <----DAI2-----> MODEM | ||
81 | * * | ||
82 | PCM3 <------------> * * <----DAI3-----> BT | ||
83 | * * | ||
84 | * * <----DAI4-----> DMIC | ||
85 | * * | ||
86 | * * <----DAI5-----> FM | ||
87 | ************* | ||
88 | |||
89 | The audio driver processes this as follows :- | ||
90 | |||
91 | 1) Machine driver receives Jack removal event. | ||
92 | |||
93 | 2) Machine driver OR audio HAL disables the Headset path. | ||
94 | |||
95 | 3) DPCM runs the PCM trigger(stop), hw_free(), shutdown() operations on DAI0 | ||
96 | for headset since the path is now disabled. | ||
97 | |||
98 | 4) Machine driver or audio HAL enables the speaker path. | ||
99 | |||
100 | 5) DPCM runs the PCM ops for startup(), hw_params(), prepapre() and | ||
101 | trigger(start) for DAI1 Speakers since the path is enabled. | ||
102 | |||
103 | In this example, the machine driver or userspace audio HAL can alter the routing | ||
104 | and then DPCM will take care of managing the DAI PCM operations to either bring | ||
105 | the link up or down. Audio playback does not stop during this transition. | ||
106 | |||
107 | |||
108 | |||
109 | DPCM machine driver | ||
110 | =================== | ||
111 | |||
112 | The DPCM enabled ASoC machine driver is similar to normal machine drivers | ||
113 | except that we also have to :- | ||
114 | |||
115 | 1) Define the FE and BE DAI links. | ||
116 | |||
117 | 2) Define any FE/BE PCM operations. | ||
118 | |||
119 | 3) Define widget graph connections. | ||
120 | |||
121 | |||
122 | 1 FE and BE DAI links | ||
123 | --------------------- | ||
124 | |||
125 | | Front End PCMs | SoC DSP | Back End DAIs | Audio devices | | ||
126 | |||
127 | ************* | ||
128 | PCM0 <------------> * * <----DAI0-----> Codec Headset | ||
129 | * * | ||
130 | PCM1 <------------> * * <----DAI1-----> Codec Speakers | ||
131 | * DSP * | ||
132 | PCM2 <------------> * * <----DAI2-----> MODEM | ||
133 | * * | ||
134 | PCM3 <------------> * * <----DAI3-----> BT | ||
135 | * * | ||
136 | * * <----DAI4-----> DMIC | ||
137 | * * | ||
138 | * * <----DAI5-----> FM | ||
139 | ************* | ||
140 | |||
141 | For the example above we have to define 4 FE DAI links and 6 BE DAI links. The | ||
142 | FE DAI links are defined as follows :- | ||
143 | |||
144 | static struct snd_soc_dai_link machine_dais[] = { | ||
145 | { | ||
146 | .name = "PCM0 System", | ||
147 | .stream_name = "System Playback", | ||
148 | .cpu_dai_name = "System Pin", | ||
149 | .platform_name = "dsp-audio", | ||
150 | .codec_name = "snd-soc-dummy", | ||
151 | .codec_dai_name = "snd-soc-dummy-dai", | ||
152 | .dynamic = 1, | ||
153 | .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | ||
154 | .dpcm_playback = 1, | ||
155 | }, | ||
156 | .....< other FE and BE DAI links here > | ||
157 | }; | ||
158 | |||
159 | This FE DAI link is pretty similar to a regular DAI link except that we also | ||
160 | set the DAI link to a DPCM FE with the "dynamic = 1". The supported FE stream | ||
161 | directions should also be set with the "dpcm_playback" and "dpcm_capture" | ||
162 | flags. There is also an option to specify the ordering of the trigger call for | ||
163 | each FE. This allows the ASoC core to trigger the DSP before or after the other | ||
164 | components (as some DSPs have strong requirements for the ordering DAI/DSP | ||
165 | start and stop sequences). | ||
166 | |||
167 | The FE DAI above sets the codec and code DAIs to dummy devices since the BE is | ||
168 | dynamic and will change depending on runtime config. | ||
169 | |||
170 | The BE DAIs are configured as follows :- | ||
171 | |||
172 | static struct snd_soc_dai_link machine_dais[] = { | ||
173 | .....< FE DAI links here > | ||
174 | { | ||
175 | .name = "Codec Headset", | ||
176 | .cpu_dai_name = "ssp-dai.0", | ||
177 | .platform_name = "snd-soc-dummy", | ||
178 | .no_pcm = 1, | ||
179 | .codec_name = "rt5640.0-001c", | ||
180 | .codec_dai_name = "rt5640-aif1", | ||
181 | .ignore_suspend = 1, | ||
182 | .ignore_pmdown_time = 1, | ||
183 | .be_hw_params_fixup = hswult_ssp0_fixup, | ||
184 | .ops = &haswell_ops, | ||
185 | .dpcm_playback = 1, | ||
186 | .dpcm_capture = 1, | ||
187 | }, | ||
188 | .....< other BE DAI links here > | ||
189 | }; | ||
190 | |||
191 | This BE DAI link connects DAI0 to the codec (in this case RT5460 AIF1). It sets | ||
192 | the "no_pcm" flag to mark it has a BE and sets flags for supported stream | ||
193 | directions using "dpcm_playback" and "dpcm_capture" above. | ||
194 | |||
195 | The BE has also flags set for ignoring suspend and PM down time. This allows | ||
196 | the BE to work in a hostless mode where the host CPU is not transferring data | ||
197 | like a BT phone call :- | ||
198 | |||
199 | ************* | ||
200 | PCM0 <------------> * * <----DAI0-----> Codec Headset | ||
201 | * * | ||
202 | PCM1 <------------> * * <----DAI1-----> Codec Speakers | ||
203 | * DSP * | ||
204 | PCM2 <------------> * * <====DAI2=====> MODEM | ||
205 | * * | ||
206 | PCM3 <------------> * * <====DAI3=====> BT | ||
207 | * * | ||
208 | * * <----DAI4-----> DMIC | ||
209 | * * | ||
210 | * * <----DAI5-----> FM | ||
211 | ************* | ||
212 | |||
213 | This allows the host CPU to sleep whilst the DSP, MODEM DAI and the BT DAI are | ||
214 | still in operation. | ||
215 | |||
216 | A BE DAI link can also set the codec to a dummy device if the code is a device | ||
217 | that is managed externally. | ||
218 | |||
219 | Likewise a BE DAI can also set a dummy cpu DAI if the CPU DAI is managed by the | ||
220 | DSP firmware. | ||
221 | |||
222 | |||
223 | 2 FE/BE PCM operations | ||
224 | ---------------------- | ||
225 | |||
226 | The BE above also exports some PCM operations and a "fixup" callback. The fixup | ||
227 | callback is used by the machine driver to (re)configure the DAI based upon the | ||
228 | FE hw params. i.e. the DSP may perform SRC or ASRC from the FE to BE. | ||
229 | |||
230 | e.g. DSP converts all FE hw params to run at fixed rate of 48k, 16bit, stereo for | ||
231 | DAI0. This means all FE hw_params have to be fixed in the machine driver for | ||
232 | DAI0 so that the DAI is running at desired configuration regardless of the FE | ||
233 | configuration. | ||
234 | |||
235 | static int dai0_fixup(struct snd_soc_pcm_runtime *rtd, | ||
236 | struct snd_pcm_hw_params *params) | ||
237 | { | ||
238 | struct snd_interval *rate = hw_param_interval(params, | ||
239 | SNDRV_PCM_HW_PARAM_RATE); | ||
240 | struct snd_interval *channels = hw_param_interval(params, | ||
241 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
242 | |||
243 | /* The DSP will covert the FE rate to 48k, stereo */ | ||
244 | rate->min = rate->max = 48000; | ||
245 | channels->min = channels->max = 2; | ||
246 | |||
247 | /* set DAI0 to 16 bit */ | ||
248 | snd_mask_set(¶ms->masks[SNDRV_PCM_HW_PARAM_FORMAT - | ||
249 | SNDRV_PCM_HW_PARAM_FIRST_MASK], | ||
250 | SNDRV_PCM_FORMAT_S16_LE); | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | The other PCM operation are the same as for regular DAI links. Use as necessary. | ||
255 | |||
256 | |||
257 | 3 Widget graph connections | ||
258 | -------------------------- | ||
259 | |||
260 | The BE DAI links will normally be connected to the graph at initialisation time | ||
261 | by the ASoC DAPM core. However, if the BE codec or BE DAI is a dummy then this | ||
262 | has to be set explicitly in the driver :- | ||
263 | |||
264 | /* BE for codec Headset - DAI0 is dummy and managed by DSP FW */ | ||
265 | {"DAI0 CODEC IN", NULL, "AIF1 Capture"}, | ||
266 | {"AIF1 Playback", NULL, "DAI0 CODEC OUT"}, | ||
267 | |||
268 | |||
269 | Writing a DPCM DSP driver | ||
270 | ========================= | ||
271 | |||
272 | The DPCM DSP driver looks much like a standard platform class ASoC driver | ||
273 | combined with elements from a codec class driver. A DSP platform driver must | ||
274 | implement :- | ||
275 | |||
276 | 1) Front End PCM DAIs - i.e. struct snd_soc_dai_driver. | ||
277 | |||
278 | 2) DAPM graph showing DSP audio routing from FE DAIs to BEs. | ||
279 | |||
280 | 3) DAPM widgets from DSP graph. | ||
281 | |||
282 | 4) Mixers for gains, routing, etc. | ||
283 | |||
284 | 5) DMA configuration. | ||
285 | |||
286 | 6) BE AIF widgets. | ||
287 | |||
288 | Items 6 is important for routing the audio outside of the DSP. AIF need to be | ||
289 | defined for each BE and each stream direction. e.g for BE DAI0 above we would | ||
290 | have :- | ||
291 | |||
292 | SND_SOC_DAPM_AIF_IN("DAI0 RX", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
293 | SND_SOC_DAPM_AIF_OUT("DAI0 TX", NULL, 0, SND_SOC_NOPM, 0, 0), | ||
294 | |||
295 | The BE AIF are used to connect the DSP graph to the graphs for the other | ||
296 | component drivers (e.g. codec graph). | ||
297 | |||
298 | |||
299 | Hostless PCM streams | ||
300 | ==================== | ||
301 | |||
302 | A hostless PCM stream is a stream that is not routed through the host CPU. An | ||
303 | example of this would be a phone call from handset to modem. | ||
304 | |||
305 | |||
306 | ************* | ||
307 | PCM0 <------------> * * <----DAI0-----> Codec Headset | ||
308 | * * | ||
309 | PCM1 <------------> * * <====DAI1=====> Codec Speakers/Mic | ||
310 | * DSP * | ||
311 | PCM2 <------------> * * <====DAI2=====> MODEM | ||
312 | * * | ||
313 | PCM3 <------------> * * <----DAI3-----> BT | ||
314 | * * | ||
315 | * * <----DAI4-----> DMIC | ||
316 | * * | ||
317 | * * <----DAI5-----> FM | ||
318 | ************* | ||
319 | |||
320 | In this case the PCM data is routed via the DSP. The host CPU in this use case | ||
321 | is only used for control and can sleep during the runtime of the stream. | ||
322 | |||
323 | The host can control the hostless link either by :- | ||
324 | |||
325 | 1) Configuring the link as a CODEC <-> CODEC style link. In this case the link | ||
326 | is enabled or disabled by the state of the DAPM graph. This usually means | ||
327 | there is a mixer control that can be used to connect or disconnect the path | ||
328 | between both DAIs. | ||
329 | |||
330 | 2) Hostless FE. This FE has a virtual connection to the BE DAI links on the DAPM | ||
331 | graph. Control is then carried out by the FE as regular PCM operations. | ||
332 | This method gives more control over the DAI links, but requires much more | ||
333 | userspace code to control the link. Its recommended to use CODEC<->CODEC | ||
334 | unless your HW needs more fine grained sequencing of the PCM ops. | ||
335 | |||
336 | |||
337 | CODEC <-> CODEC link | ||
338 | -------------------- | ||
339 | |||
340 | This DAI link is enabled when DAPM detects a valid path within the DAPM graph. | ||
341 | The machine driver sets some additional parameters to the DAI link i.e. | ||
342 | |||
343 | static const struct snd_soc_pcm_stream dai_params = { | ||
344 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
345 | .rate_min = 8000, | ||
346 | .rate_max = 8000, | ||
347 | .channels_min = 2, | ||
348 | .channels_max = 2, | ||
349 | }; | ||
350 | |||
351 | static struct snd_soc_dai_link dais[] = { | ||
352 | < ... more DAI links above ... > | ||
353 | { | ||
354 | .name = "MODEM", | ||
355 | .stream_name = "MODEM", | ||
356 | .cpu_dai_name = "dai2", | ||
357 | .codec_dai_name = "modem-aif1", | ||
358 | .codec_name = "modem", | ||
359 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
360 | | SND_SOC_DAIFMT_CBM_CFM, | ||
361 | .params = &dai_params, | ||
362 | } | ||
363 | < ... more DAI links here ... > | ||
364 | |||
365 | These parameters are used to configure the DAI hw_params() when DAPM detects a | ||
366 | valid path and then calls the PCM operations to start the link. DAPM will also | ||
367 | call the appropriate PCM operations to disable the DAI when the path is no | ||
368 | longer valid. | ||
369 | |||
370 | |||
371 | Hostless FE | ||
372 | ----------- | ||
373 | |||
374 | The DAI link(s) are enabled by a FE that does not read or write any PCM data. | ||
375 | This means creating a new FE that is connected with a virtual path to both | ||
376 | DAI links. The DAI links will be started when the FE PCM is started and stopped | ||
377 | when the FE PCM is stopped. Note that the FE PCM cannot read or write data in | ||
378 | this configuration. | ||
379 | |||
380 | |||