blob: 327bec05295440adc7a80ec22041d21eaadc462b [file] [log] [blame]
Kuninori Morimotob3ed4c82018-07-02 06:24:57 +00001// SPDX-License-Identifier: GPL-2.0+
2//
3// soc-compress.c -- ALSA SoC Compress
4//
5// Copyright (C) 2012 Intel Corp.
6//
7// Authors: Namarta Kohli <namartax.kohli@intel.com>
8// Ramesh Babu K V <ramesh.babu@linux.intel.com>
9// Vinod Koul <vinod.koul@linux.intel.com>
Namarta Kohli1245b702012-08-16 17:10:41 +053010
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/delay.h>
14#include <linux/slab.h>
15#include <linux/workqueue.h>
16#include <sound/core.h>
17#include <sound/compress_params.h>
18#include <sound/compress_driver.h>
19#include <sound/soc.h>
20#include <sound/initval.h>
Liam Girdwood2a99ef02014-01-17 17:03:56 +000021#include <sound/soc-dpcm.h>
Kuninori Morimoto9ab711c2020-05-25 09:57:41 +090022#include <sound/soc-link.h>
Cezary Rojewski4137f4b2019-12-17 10:58:50 +010023#include <linux/pm_runtime.h>
Namarta Kohli1245b702012-08-16 17:10:41 +053024
Charles Keepax1e57b822018-04-24 16:39:03 +010025static int soc_compr_components_open(struct snd_compr_stream *cstream,
26 struct snd_soc_component **last)
Namarta Kohli1245b702012-08-16 17:10:41 +053027{
28 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000029 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +090030 int i, ret;
Charles Keepax1e57b822018-04-24 16:39:03 +010031
Kuninori Morimoto613fb502020-01-10 11:35:21 +090032 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +090033 if (!component->driver->compress_ops ||
34 !component->driver->compress_ops->open)
35 continue;
36
37 ret = component->driver->compress_ops->open(component, cstream);
38 if (ret < 0) {
39 dev_err(component->dev,
40 "Compress ASoC: can't open platform %s: %d\n",
41 component->name, ret);
42
43 *last = component;
44 return ret;
45 }
46 }
47
Charles Keepax1e57b822018-04-24 16:39:03 +010048 *last = NULL;
49 return 0;
50}
51
52static int soc_compr_components_free(struct snd_compr_stream *cstream,
53 struct snd_soc_component *last)
54{
55 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
56 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +090057 int i;
Charles Keepax1e57b822018-04-24 16:39:03 +010058
Kuninori Morimoto613fb502020-01-10 11:35:21 +090059 for_each_rtd_components(rtd, i, component) {
Charles Keepax1e57b822018-04-24 16:39:03 +010060 if (component == last)
61 break;
62
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +090063 if (!component->driver->compress_ops ||
64 !component->driver->compress_ops->free)
65 continue;
66
67 component->driver->compress_ops->free(component, cstream);
68 }
69
Charles Keepax1e57b822018-04-24 16:39:03 +010070 return 0;
71}
72
73static int soc_compr_open(struct snd_compr_stream *cstream)
74{
75 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Rong Chen3e645a42020-04-24 08:54:37 +080076 struct snd_soc_component *component = NULL, *save = NULL;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +090077 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +090078 int ret, i;
Namarta Kohli1245b702012-08-16 17:10:41 +053079
Kuninori Morimoto613fb502020-01-10 11:35:21 +090080 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +010081 ret = pm_runtime_get_sync(component->dev);
82 if (ret < 0 && ret != -EACCES) {
83 pm_runtime_put_noidle(component->dev);
84 save = component;
85 goto pm_err;
86 }
87 }
88
Peter Ujfalusi72b745e2019-08-13 13:45:32 +030089 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +000090
Kuninori Morimotob5ae4cc2020-04-24 08:15:24 +090091 ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
92 if (ret < 0)
93 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +053094
Charles Keepax1e57b822018-04-24 16:39:03 +010095 ret = soc_compr_components_open(cstream, &component);
96 if (ret < 0)
97 goto machine_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000098
Kuninori Morimoto9ab711c2020-05-25 09:57:41 +090099 ret = snd_soc_link_compr_startup(cstream);
100 if (ret < 0)
101 goto machine_err;
Namarta Kohli1245b702012-08-16 17:10:41 +0530102
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100103 snd_soc_runtime_activate(rtd, cstream->direction);
Namarta Kohli1245b702012-08-16 17:10:41 +0530104
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300105 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax15e2e612013-01-24 09:44:29 +0000106
Namarta Kohli1245b702012-08-16 17:10:41 +0530107 return 0;
108
109machine_err:
Charles Keepax1e57b822018-04-24 16:39:03 +0100110 soc_compr_components_free(cstream, component);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000111
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900112 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530113out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300114 mutex_unlock(&rtd->card->pcm_mutex);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100115pm_err:
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900116 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100117 if (component == save)
118 break;
119 pm_runtime_mark_last_busy(component->dev);
120 pm_runtime_put_autosuspend(component->dev);
121 }
122
Namarta Kohli1245b702012-08-16 17:10:41 +0530123 return ret;
124}
125
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000126static int soc_compr_open_fe(struct snd_compr_stream *cstream)
127{
128 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700129 struct snd_pcm_substream *fe_substream =
130 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000131 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900132 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000133 struct snd_soc_dpcm *dpcm;
134 struct snd_soc_dapm_widget_list *list;
135 int stream;
Charles Keepax572e6c82018-04-24 16:39:01 +0100136 int ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000137
138 if (cstream->direction == SND_COMPRESS_PLAYBACK)
139 stream = SNDRV_PCM_STREAM_PLAYBACK;
140 else
141 stream = SNDRV_PCM_STREAM_CAPTURE;
142
143 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100144 fe->dpcm[stream].runtime = fe_substream->runtime;
145
146 ret = dpcm_path_get(fe, stream, &list);
147 if (ret < 0)
148 goto be_err;
149 else if (ret == 0)
150 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
151 fe->dai_link->name, stream ? "capture" : "playback");
152 /* calculate valid and active FE <-> BE dpcms */
153 dpcm_process_paths(fe, stream, &list, 1);
154 fe->dpcm[stream].runtime = fe_substream->runtime;
155
156 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
157
158 ret = dpcm_be_dai_startup(fe, stream);
159 if (ret < 0) {
160 /* clean up all links */
Kuninori Morimoto8d6258a2018-09-18 01:31:09 +0000161 for_each_dpcm_be(fe, stream, dpcm)
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100162 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
163
164 dpcm_be_disconnect(fe, stream);
165 fe->dpcm[stream].runtime = NULL;
166 goto out;
167 }
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000168
Kuninori Morimotob5ae4cc2020-04-24 08:15:24 +0900169 ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
170 if (ret < 0)
171 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530172
Charles Keepax1e57b822018-04-24 16:39:03 +0100173 ret = soc_compr_components_open(cstream, &component);
174 if (ret < 0)
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100175 goto open_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000176
Kuninori Morimoto9ab711c2020-05-25 09:57:41 +0900177 ret = snd_soc_link_compr_startup(cstream);
178 if (ret < 0)
179 goto machine_err;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000180
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000181 dpcm_clear_pending_state(fe, stream);
182 dpcm_path_put(&list);
183
184 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
185 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
186
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100187 snd_soc_runtime_activate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000188
189 mutex_unlock(&fe->card->mutex);
190
191 return 0;
192
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000193machine_err:
Charles Keepax1e57b822018-04-24 16:39:03 +0100194 soc_compr_components_free(cstream, component);
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100195open_err:
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900196 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000197out:
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100198 dpcm_path_put(&list);
199be_err:
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000200 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
201 mutex_unlock(&fe->card->mutex);
202 return ret;
203}
204
Namarta Kohli1245b702012-08-16 17:10:41 +0530205static int soc_compr_free(struct snd_compr_stream *cstream)
206{
207 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100208 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900209 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
210 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900211 int stream, i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530212
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300213 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000214
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100215 if (cstream->direction == SND_COMPRESS_PLAYBACK)
216 stream = SNDRV_PCM_STREAM_PLAYBACK;
217 else
218 stream = SNDRV_PCM_STREAM_CAPTURE;
219
220 snd_soc_runtime_deactivate(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530221
Mark Brownda183962013-02-06 15:44:07 +0000222 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
223
Kuninori Morimotob3dea622020-05-15 09:46:51 +0900224 if (!snd_soc_dai_active(cpu_dai))
Namarta Kohli1245b702012-08-16 17:10:41 +0530225 cpu_dai->rate = 0;
226
Kuninori Morimotob3dea622020-05-15 09:46:51 +0900227 if (!snd_soc_dai_active(codec_dai))
Namarta Kohli1245b702012-08-16 17:10:41 +0530228 codec_dai->rate = 0;
229
Kuninori Morimoto0e532c92020-05-25 09:57:45 +0900230 snd_soc_link_compr_shutdown(cstream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530231
Charles Keepax1e57b822018-04-24 16:39:03 +0100232 soc_compr_components_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000233
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900234 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Vinod Koul2e622ae2016-11-13 12:10:02 +0530235
Kuninori Morimoto3f4cf792020-01-10 11:36:23 +0900236 snd_soc_dapm_stream_stop(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530237
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300238 mutex_unlock(&rtd->card->pcm_mutex);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100239
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900240 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100241 pm_runtime_mark_last_busy(component->dev);
242 pm_runtime_put_autosuspend(component->dev);
243 }
244
Namarta Kohli1245b702012-08-16 17:10:41 +0530245 return 0;
246}
247
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000248static int soc_compr_free_fe(struct snd_compr_stream *cstream)
249{
250 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900251 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000252 struct snd_soc_dpcm *dpcm;
253 int stream, ret;
254
255 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
256
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100257 if (cstream->direction == SND_COMPRESS_PLAYBACK)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000258 stream = SNDRV_PCM_STREAM_PLAYBACK;
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100259 else
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000260 stream = SNDRV_PCM_STREAM_CAPTURE;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000261
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100262 snd_soc_runtime_deactivate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000263
264 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
265
266 ret = dpcm_be_dai_hw_free(fe, stream);
267 if (ret < 0)
Charles Keepax141dfc92018-01-26 13:08:45 +0000268 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000269
270 ret = dpcm_be_dai_shutdown(fe, stream);
271
272 /* mark FE's links ready to prune */
Kuninori Morimoto8d6258a2018-09-18 01:31:09 +0000273 for_each_dpcm_be(fe, stream, dpcm)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000274 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
275
Kuninori Morimoto1c531232020-02-21 10:25:18 +0900276 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000277
278 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
279 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
280
281 dpcm_be_disconnect(fe, stream);
282
283 fe->dpcm[stream].runtime = NULL;
284
Kuninori Morimoto0e532c92020-05-25 09:57:45 +0900285 snd_soc_link_compr_shutdown(cstream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000286
Charles Keepax1e57b822018-04-24 16:39:03 +0100287 soc_compr_components_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000288
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900289 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Vinod Koul2e622ae2016-11-13 12:10:02 +0530290
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000291 mutex_unlock(&fe->card->mutex);
292 return 0;
293}
294
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000295static int soc_compr_components_trigger(struct snd_compr_stream *cstream,
296 int cmd)
Namarta Kohli1245b702012-08-16 17:10:41 +0530297{
Namarta Kohli1245b702012-08-16 17:10:41 +0530298 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000299 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900300 int i, ret;
Charles Keepax15e2e612013-01-24 09:44:29 +0000301
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900302 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900303 if (!component->driver->compress_ops ||
304 !component->driver->compress_ops->trigger)
305 continue;
306
307 ret = component->driver->compress_ops->trigger(
308 component, cstream, cmd);
309 if (ret < 0)
310 return ret;
311 }
312
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000313 return 0;
314}
315
316static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
317{
318 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900319 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
320 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000321 int ret;
322
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300323 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000324
325 ret = soc_compr_components_trigger(cstream, cmd);
326 if (ret < 0)
327 goto out;
328
Kuninori Morimotoeb084112020-04-24 08:15:32 +0900329 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
330 if (ret < 0)
331 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530332
Mark Brownda183962013-02-06 15:44:07 +0000333 switch (cmd) {
334 case SNDRV_PCM_TRIGGER_START:
335 snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
336 break;
337 case SNDRV_PCM_TRIGGER_STOP:
338 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
339 break;
Mark Browne38b9b72013-02-06 13:52:42 +0000340 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530341
Charles Keepax15e2e612013-01-24 09:44:29 +0000342out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300343 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530344 return ret;
345}
346
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000347static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
348{
349 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900350 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000351 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000352
353 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000354 cmd == SND_COMPR_TRIGGER_DRAIN)
355 return soc_compr_components_trigger(cstream, cmd);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000356
357 if (cstream->direction == SND_COMPRESS_PLAYBACK)
358 stream = SNDRV_PCM_STREAM_PLAYBACK;
359 else
360 stream = SNDRV_PCM_STREAM_CAPTURE;
361
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000362 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
363
Kuninori Morimotoeb084112020-04-24 08:15:32 +0900364 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
365 if (ret < 0)
366 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530367
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000368 ret = soc_compr_components_trigger(cstream, cmd);
369 if (ret < 0)
370 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000371
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000372 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
373
374 ret = dpcm_be_dai_trigger(fe, stream, cmd);
375
376 switch (cmd) {
377 case SNDRV_PCM_TRIGGER_START:
378 case SNDRV_PCM_TRIGGER_RESUME:
379 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
380 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
381 break;
382 case SNDRV_PCM_TRIGGER_STOP:
383 case SNDRV_PCM_TRIGGER_SUSPEND:
384 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
385 break;
386 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
387 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
388 break;
389 }
390
391out:
392 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
393 mutex_unlock(&fe->card->mutex);
394 return ret;
395}
396
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000397static int soc_compr_components_set_params(struct snd_compr_stream *cstream,
398 struct snd_compr_params *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530399{
400 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000401 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900402 int i, ret;
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000403
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900404 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900405 if (!component->driver->compress_ops ||
406 !component->driver->compress_ops->set_params)
407 continue;
408
409 ret = component->driver->compress_ops->set_params(
410 component, cstream, params);
411 if (ret < 0)
412 return ret;
413 }
414
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000415 return 0;
416}
417
418static int soc_compr_set_params(struct snd_compr_stream *cstream,
419 struct snd_compr_params *params)
420{
421 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900422 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000423 int ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530424
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300425 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000426
Charles Keepaxef050be2018-04-24 16:39:02 +0100427 /*
428 * First we call set_params for the CPU DAI, then the component
429 * driver this should configure the SoC side. If the machine has
430 * compressed ops then we call that as well. The expectation is
431 * that these callbacks will configure everything for this compress
432 * path, like configuring a PCM port for a CODEC.
Namarta Kohli1245b702012-08-16 17:10:41 +0530433 */
Kuninori Morimoto8dfedaf2020-04-24 08:15:36 +0900434 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
435 if (ret < 0)
436 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530437
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000438 ret = soc_compr_components_set_params(cstream, params);
439 if (ret < 0)
440 goto err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000441
Namarta Kohli1245b702012-08-16 17:10:41 +0530442 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
443 ret = rtd->dai_link->compr_ops->set_params(cstream);
444 if (ret < 0)
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000445 goto err;
Namarta Kohli1245b702012-08-16 17:10:41 +0530446 }
447
Charles Keepax2c071ed2013-05-20 08:33:54 +0100448 if (cstream->direction == SND_COMPRESS_PLAYBACK)
449 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
Charles Keepax89027d92018-04-26 17:30:07 +0100450 SND_SOC_DAPM_STREAM_START);
Charles Keepax2c071ed2013-05-20 08:33:54 +0100451 else
452 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
Charles Keepax89027d92018-04-26 17:30:07 +0100453 SND_SOC_DAPM_STREAM_START);
Namarta Kohli1245b702012-08-16 17:10:41 +0530454
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000455 /* cancel any delayed stream shutdown that is pending */
456 rtd->pop_wait = 0;
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300457 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000458
459 cancel_delayed_work_sync(&rtd->delayed_work);
460
Charles Keepax52cadf12019-02-05 11:18:12 +0000461 return 0;
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000462
463err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300464 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530465 return ret;
466}
467
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000468static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100469 struct snd_compr_params *params)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000470{
471 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700472 struct snd_pcm_substream *fe_substream =
473 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900474 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000475 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000476
477 if (cstream->direction == SND_COMPRESS_PLAYBACK)
478 stream = SNDRV_PCM_STREAM_PLAYBACK;
479 else
480 stream = SNDRV_PCM_STREAM_CAPTURE;
481
482 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
483
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100484 /*
485 * Create an empty hw_params for the BE as the machine driver must
486 * fix this up to match DSP decoder and ASRC configuration.
487 * I.e. machine driver fixup for compressed BE is mandatory.
488 */
489 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
490 sizeof(struct snd_pcm_hw_params));
491
492 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
493
494 ret = dpcm_be_dai_hw_params(fe, stream);
495 if (ret < 0)
496 goto out;
497
498 ret = dpcm_be_dai_prepare(fe, stream);
499 if (ret < 0)
500 goto out;
501
Kuninori Morimoto8dfedaf2020-04-24 08:15:36 +0900502 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
503 if (ret < 0)
504 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530505
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000506 ret = soc_compr_components_set_params(cstream, params);
507 if (ret < 0)
508 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000509
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000510 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
511 ret = fe->dai_link->compr_ops->set_params(cstream);
512 if (ret < 0)
513 goto out;
514 }
515
Daniel Mack15f6b092014-10-19 09:07:35 +0200516 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000517 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
518
519out:
520 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
521 mutex_unlock(&fe->card->mutex);
522 return ret;
523}
524
Namarta Kohli1245b702012-08-16 17:10:41 +0530525static int soc_compr_get_params(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100526 struct snd_codec *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530527{
528 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000529 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900530 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900531 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530532
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300533 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000534
Kuninori Morimotoadbef5432020-04-24 08:15:40 +0900535 ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params);
536 if (ret < 0)
537 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530538
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900539 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900540 if (!component->driver->compress_ops ||
541 !component->driver->compress_ops->get_params)
542 continue;
543
544 ret = component->driver->compress_ops->get_params(
545 component, cstream, params);
546 break;
547 }
548
Vinod Koul2e622ae2016-11-13 12:10:02 +0530549err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300550 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530551 return ret;
552}
553
554static int soc_compr_get_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100555 struct snd_compr_caps *caps)
Namarta Kohli1245b702012-08-16 17:10:41 +0530556{
557 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000558 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900559 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530560
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300561 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000562
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900563 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900564 if (!component->driver->compress_ops ||
565 !component->driver->compress_ops->get_caps)
566 continue;
567
568 ret = component->driver->compress_ops->get_caps(
569 component, cstream, caps);
570 break;
571 }
572
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300573 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530574 return ret;
575}
576
577static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100578 struct snd_compr_codec_caps *codec)
Namarta Kohli1245b702012-08-16 17:10:41 +0530579{
580 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000581 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900582 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530583
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300584 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000585
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900586 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900587 if (!component->driver->compress_ops ||
588 !component->driver->compress_ops->get_codec_caps)
589 continue;
590
591 ret = component->driver->compress_ops->get_codec_caps(
592 component, cstream, codec);
593 break;
594 }
595
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300596 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530597 return ret;
598}
599
600static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
601{
602 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000603 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900604 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900605 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530606
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300607 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000608
Kuninori Morimoto53294352020-04-24 08:15:45 +0900609 ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes);
610 if (ret < 0)
611 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530612
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900613 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900614 if (!component->driver->compress_ops ||
615 !component->driver->compress_ops->ack)
616 continue;
617
618 ret = component->driver->compress_ops->ack(
619 component, cstream, bytes);
620 if (ret < 0)
621 goto err;
622 }
623
Vinod Koul2e622ae2016-11-13 12:10:02 +0530624err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300625 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530626 return ret;
627}
628
629static int soc_compr_pointer(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100630 struct snd_compr_tstamp *tstamp)
Namarta Kohli1245b702012-08-16 17:10:41 +0530631{
632 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000633 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900634 int i, ret = 0;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900635 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530636
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300637 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000638
Kuninori Morimotoed38cc52020-04-24 08:15:49 +0900639 ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp);
640 if (ret < 0)
641 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530642
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900643 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900644 if (!component->driver->compress_ops ||
645 !component->driver->compress_ops->pointer)
646 continue;
647
648 ret = component->driver->compress_ops->pointer(
649 component, cstream, tstamp);
650 break;
651 }
Kuninori Morimotoed38cc52020-04-24 08:15:49 +0900652out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300653 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax7c9190f2016-06-20 09:51:32 +0100654 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530655}
656
Charles Keepax1f88eb02013-02-05 10:41:47 +0000657static int soc_compr_copy(struct snd_compr_stream *cstream,
Charles Keepax4daf8912013-04-18 11:01:38 +0100658 char __user *buf, size_t count)
Charles Keepax1f88eb02013-02-05 10:41:47 +0000659{
660 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000661 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900662 int i, ret = 0;
Charles Keepax1f88eb02013-02-05 10:41:47 +0000663
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300664 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000665
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900666 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900667 if (!component->driver->compress_ops ||
668 !component->driver->compress_ops->copy)
669 continue;
670
671 ret = component->driver->compress_ops->copy(
672 component, cstream, buf, count);
673 break;
674 }
675
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300676 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000677 return ret;
678}
679
Vinod Koul02bd90e2013-07-28 20:06:15 +0530680static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100681 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530682{
683 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000684 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900685 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900686 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530687
Kuninori Morimoto88b3a7d2020-04-24 08:15:54 +0900688 ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata);
689 if (ret < 0)
690 return ret;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530691
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900692 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900693 if (!component->driver->compress_ops ||
694 !component->driver->compress_ops->set_metadata)
695 continue;
696
697 ret = component->driver->compress_ops->set_metadata(
698 component, cstream, metadata);
699 if (ret < 0)
700 return ret;
701 }
702
Charles Keepax52cadf12019-02-05 11:18:12 +0000703 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530704}
705
Vinod Koul02bd90e2013-07-28 20:06:15 +0530706static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100707 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530708{
709 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000710 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900711 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900712 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530713
Kuninori Morimoto94d72812020-04-24 08:15:59 +0900714 ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata);
715 if (ret < 0)
716 return ret;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530717
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900718 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900719 if (!component->driver->compress_ops ||
720 !component->driver->compress_ops->get_metadata)
721 continue;
722
723 return component->driver->compress_ops->get_metadata(
724 component, cstream, metadata);
725 }
726
Charles Keepax52cadf12019-02-05 11:18:12 +0000727 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530728}
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000729
Namarta Kohli1245b702012-08-16 17:10:41 +0530730/* ASoC Compress operations */
731static struct snd_compr_ops soc_compr_ops = {
732 .open = soc_compr_open,
733 .free = soc_compr_free,
734 .set_params = soc_compr_set_params,
Vinod Koul02bd90e2013-07-28 20:06:15 +0530735 .set_metadata = soc_compr_set_metadata,
736 .get_metadata = soc_compr_get_metadata,
Namarta Kohli1245b702012-08-16 17:10:41 +0530737 .get_params = soc_compr_get_params,
738 .trigger = soc_compr_trigger,
739 .pointer = soc_compr_pointer,
740 .ack = soc_compr_ack,
741 .get_caps = soc_compr_get_caps,
742 .get_codec_caps = soc_compr_get_codec_caps
743};
744
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000745/* ASoC Dynamic Compress operations */
746static struct snd_compr_ops soc_compr_dyn_ops = {
747 .open = soc_compr_open_fe,
748 .free = soc_compr_free_fe,
749 .set_params = soc_compr_set_params_fe,
750 .get_params = soc_compr_get_params,
751 .set_metadata = soc_compr_set_metadata,
752 .get_metadata = soc_compr_get_metadata,
753 .trigger = soc_compr_trigger_fe,
754 .pointer = soc_compr_pointer,
755 .ack = soc_compr_ack,
756 .get_caps = soc_compr_get_caps,
757 .get_codec_caps = soc_compr_get_codec_caps
758};
759
Jie Yang6f0c4222015-10-13 23:41:00 +0800760/**
761 * snd_soc_new_compress - create a new compress.
762 *
763 * @rtd: The runtime for which we will create compress
764 * @num: the device index number (zero based - shared with normal PCMs)
765 *
766 * Return: 0 for success, else error.
767 */
768int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
Namarta Kohli1245b702012-08-16 17:10:41 +0530769{
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000770 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900771 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
772 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530773 struct snd_compr *compr;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000774 struct snd_pcm *be_pcm;
Namarta Kohli1245b702012-08-16 17:10:41 +0530775 char new_name[64];
776 int ret = 0, direction = 0;
Vinod Koula1068042016-01-07 21:48:14 +0530777 int playback = 0, capture = 0;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900778 int i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530779
Bard Liao6e1276a2020-02-25 21:39:16 +0800780 if (rtd->num_cpus > 1 ||
781 rtd->num_codecs > 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000782 dev_err(rtd->card->dev,
Bard Liao6e1276a2020-02-25 21:39:16 +0800783 "Compress ASoC: Multi CPU/Codec not supported\n");
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200784 return -EINVAL;
785 }
786
Namarta Kohli1245b702012-08-16 17:10:41 +0530787 /* check client and interface hw capabilities */
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900788 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
789 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
Vinod Koula1068042016-01-07 21:48:14 +0530790 playback = 1;
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900791 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
792 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
Vinod Koula1068042016-01-07 21:48:14 +0530793 capture = 1;
794
Vinod Koula1068042016-01-07 21:48:14 +0530795 /*
796 * Compress devices are unidirectional so only one of the directions
797 * should be set, check for that (xor)
798 */
799 if (playback + capture != 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000800 dev_err(rtd->card->dev,
801 "Compress ASoC: Invalid direction for P %d, C %d\n",
802 playback, capture);
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100803 return -EINVAL;
Vinod Koula1068042016-01-07 21:48:14 +0530804 }
805
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800806 if (playback)
Vinod Koula1068042016-01-07 21:48:14 +0530807 direction = SND_COMPRESS_PLAYBACK;
808 else
809 direction = SND_COMPRESS_CAPTURE;
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100810
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200811 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200812 if (!compr)
Namarta Kohli1245b702012-08-16 17:10:41 +0530813 return -ENOMEM;
Namarta Kohli1245b702012-08-16 17:10:41 +0530814
Charles Keepax1f88eb02013-02-05 10:41:47 +0000815 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
816 GFP_KERNEL);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200817 if (!compr->ops)
818 return -ENOMEM;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000819
820 if (rtd->dai_link->dynamic) {
821 snprintf(new_name, sizeof(new_name), "(%s)",
822 rtd->dai_link->stream_name);
823
824 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
Qais Yousefd3268a42015-01-14 08:47:29 +0000825 rtd->dai_link->dpcm_playback,
826 rtd->dai_link->dpcm_capture, &be_pcm);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000827 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000828 dev_err(rtd->card->dev,
829 "Compress ASoC: can't create compressed for %s: %d\n",
830 rtd->dai_link->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200831 return ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000832 }
833
834 rtd->pcm = be_pcm;
835 rtd->fe_compr = 1;
Qais Yousefd3268a42015-01-14 08:47:29 +0000836 if (rtd->dai_link->dpcm_playback)
837 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
838 else if (rtd->dai_link->dpcm_capture)
839 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000840 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800841 } else {
842 snprintf(new_name, sizeof(new_name), "%s %s-%d",
843 rtd->dai_link->stream_name, codec_dai->name, num);
844
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000845 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800846 }
Charles Keepax1f88eb02013-02-05 10:41:47 +0000847
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900848 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900849 if (!component->driver->compress_ops ||
850 !component->driver->compress_ops->copy)
851 continue;
852
853 compr->ops->copy = soc_compr_copy;
854 break;
855 }
856
Namarta Kohli1245b702012-08-16 17:10:41 +0530857 mutex_init(&compr->lock);
Richard Fitzgeralde5241a82015-11-25 13:00:24 +0000858 ret = snd_compress_new(rtd->card->snd_card, num, direction,
859 new_name, compr);
Namarta Kohli1245b702012-08-16 17:10:41 +0530860 if (ret < 0) {
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900861 component = asoc_rtd_to_codec(rtd, 0)->component;
Charles Keepax141dfc92018-01-26 13:08:45 +0000862 dev_err(component->dev,
863 "Compress ASoC: can't create compress for codec %s: %d\n",
864 component->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200865 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530866 }
867
Charles Keepax202c8f72013-01-24 09:44:30 +0000868 /* DAPM dai link stream work */
Kuninori Morimoto83f94a22020-01-10 11:36:17 +0900869 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
Charles Keepax202c8f72013-01-24 09:44:30 +0000870
Namarta Kohli1245b702012-08-16 17:10:41 +0530871 rtd->compr = compr;
872 compr->private_data = rtd;
873
Charles Keepax141dfc92018-01-26 13:08:45 +0000874 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
875 codec_dai->name, cpu_dai->name);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000876
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200877 return 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530878}
Jie Yang6f0c4222015-10-13 23:41:00 +0800879EXPORT_SYMBOL_GPL(snd_soc_new_compress);