blob: ddc6c6f69d2f30827ca97e66151de81b520220ca [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
Namarta Kohli1245b702012-08-16 17:10:41 +0530230 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
231 rtd->dai_link->compr_ops->shutdown(cstream);
232
Charles Keepax1e57b822018-04-24 16:39:03 +0100233 soc_compr_components_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000234
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900235 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Vinod Koul2e622ae2016-11-13 12:10:02 +0530236
Kuninori Morimoto3f4cf792020-01-10 11:36:23 +0900237 snd_soc_dapm_stream_stop(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530238
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300239 mutex_unlock(&rtd->card->pcm_mutex);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100240
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900241 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100242 pm_runtime_mark_last_busy(component->dev);
243 pm_runtime_put_autosuspend(component->dev);
244 }
245
Namarta Kohli1245b702012-08-16 17:10:41 +0530246 return 0;
247}
248
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000249static int soc_compr_free_fe(struct snd_compr_stream *cstream)
250{
251 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900252 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000253 struct snd_soc_dpcm *dpcm;
254 int stream, ret;
255
256 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
257
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100258 if (cstream->direction == SND_COMPRESS_PLAYBACK)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000259 stream = SNDRV_PCM_STREAM_PLAYBACK;
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100260 else
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000261 stream = SNDRV_PCM_STREAM_CAPTURE;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000262
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100263 snd_soc_runtime_deactivate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000264
265 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
266
267 ret = dpcm_be_dai_hw_free(fe, stream);
268 if (ret < 0)
Charles Keepax141dfc92018-01-26 13:08:45 +0000269 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000270
271 ret = dpcm_be_dai_shutdown(fe, stream);
272
273 /* mark FE's links ready to prune */
Kuninori Morimoto8d6258a2018-09-18 01:31:09 +0000274 for_each_dpcm_be(fe, stream, dpcm)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000275 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
276
Kuninori Morimoto1c531232020-02-21 10:25:18 +0900277 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000278
279 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
280 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
281
282 dpcm_be_disconnect(fe, stream);
283
284 fe->dpcm[stream].runtime = NULL;
285
286 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
287 fe->dai_link->compr_ops->shutdown(cstream);
288
Charles Keepax1e57b822018-04-24 16:39:03 +0100289 soc_compr_components_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000290
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900291 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Vinod Koul2e622ae2016-11-13 12:10:02 +0530292
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000293 mutex_unlock(&fe->card->mutex);
294 return 0;
295}
296
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000297static int soc_compr_components_trigger(struct snd_compr_stream *cstream,
298 int cmd)
Namarta Kohli1245b702012-08-16 17:10:41 +0530299{
Namarta Kohli1245b702012-08-16 17:10:41 +0530300 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000301 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900302 int i, ret;
Charles Keepax15e2e612013-01-24 09:44:29 +0000303
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900304 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900305 if (!component->driver->compress_ops ||
306 !component->driver->compress_ops->trigger)
307 continue;
308
309 ret = component->driver->compress_ops->trigger(
310 component, cstream, cmd);
311 if (ret < 0)
312 return ret;
313 }
314
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000315 return 0;
316}
317
318static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
319{
320 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900321 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
322 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000323 int ret;
324
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300325 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000326
327 ret = soc_compr_components_trigger(cstream, cmd);
328 if (ret < 0)
329 goto out;
330
Kuninori Morimotoeb084112020-04-24 08:15:32 +0900331 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
332 if (ret < 0)
333 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530334
Mark Brownda183962013-02-06 15:44:07 +0000335 switch (cmd) {
336 case SNDRV_PCM_TRIGGER_START:
337 snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
338 break;
339 case SNDRV_PCM_TRIGGER_STOP:
340 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
341 break;
Mark Browne38b9b72013-02-06 13:52:42 +0000342 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530343
Charles Keepax15e2e612013-01-24 09:44:29 +0000344out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300345 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530346 return ret;
347}
348
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000349static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
350{
351 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900352 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000353 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000354
355 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000356 cmd == SND_COMPR_TRIGGER_DRAIN)
357 return soc_compr_components_trigger(cstream, cmd);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000358
359 if (cstream->direction == SND_COMPRESS_PLAYBACK)
360 stream = SNDRV_PCM_STREAM_PLAYBACK;
361 else
362 stream = SNDRV_PCM_STREAM_CAPTURE;
363
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000364 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
365
Kuninori Morimotoeb084112020-04-24 08:15:32 +0900366 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
367 if (ret < 0)
368 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530369
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000370 ret = soc_compr_components_trigger(cstream, cmd);
371 if (ret < 0)
372 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000373
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000374 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
375
376 ret = dpcm_be_dai_trigger(fe, stream, cmd);
377
378 switch (cmd) {
379 case SNDRV_PCM_TRIGGER_START:
380 case SNDRV_PCM_TRIGGER_RESUME:
381 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
382 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
383 break;
384 case SNDRV_PCM_TRIGGER_STOP:
385 case SNDRV_PCM_TRIGGER_SUSPEND:
386 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
387 break;
388 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
389 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
390 break;
391 }
392
393out:
394 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
395 mutex_unlock(&fe->card->mutex);
396 return ret;
397}
398
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000399static int soc_compr_components_set_params(struct snd_compr_stream *cstream,
400 struct snd_compr_params *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530401{
402 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000403 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900404 int i, ret;
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000405
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900406 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900407 if (!component->driver->compress_ops ||
408 !component->driver->compress_ops->set_params)
409 continue;
410
411 ret = component->driver->compress_ops->set_params(
412 component, cstream, params);
413 if (ret < 0)
414 return ret;
415 }
416
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000417 return 0;
418}
419
420static int soc_compr_set_params(struct snd_compr_stream *cstream,
421 struct snd_compr_params *params)
422{
423 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900424 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000425 int ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530426
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300427 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000428
Charles Keepaxef050be2018-04-24 16:39:02 +0100429 /*
430 * First we call set_params for the CPU DAI, then the component
431 * driver this should configure the SoC side. If the machine has
432 * compressed ops then we call that as well. The expectation is
433 * that these callbacks will configure everything for this compress
434 * path, like configuring a PCM port for a CODEC.
Namarta Kohli1245b702012-08-16 17:10:41 +0530435 */
Kuninori Morimoto8dfedaf2020-04-24 08:15:36 +0900436 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
437 if (ret < 0)
438 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530439
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000440 ret = soc_compr_components_set_params(cstream, params);
441 if (ret < 0)
442 goto err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000443
Namarta Kohli1245b702012-08-16 17:10:41 +0530444 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
445 ret = rtd->dai_link->compr_ops->set_params(cstream);
446 if (ret < 0)
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000447 goto err;
Namarta Kohli1245b702012-08-16 17:10:41 +0530448 }
449
Charles Keepax2c071ed2013-05-20 08:33:54 +0100450 if (cstream->direction == SND_COMPRESS_PLAYBACK)
451 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
Charles Keepax89027d92018-04-26 17:30:07 +0100452 SND_SOC_DAPM_STREAM_START);
Charles Keepax2c071ed2013-05-20 08:33:54 +0100453 else
454 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
Charles Keepax89027d92018-04-26 17:30:07 +0100455 SND_SOC_DAPM_STREAM_START);
Namarta Kohli1245b702012-08-16 17:10:41 +0530456
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000457 /* cancel any delayed stream shutdown that is pending */
458 rtd->pop_wait = 0;
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300459 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000460
461 cancel_delayed_work_sync(&rtd->delayed_work);
462
Charles Keepax52cadf12019-02-05 11:18:12 +0000463 return 0;
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000464
465err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300466 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530467 return ret;
468}
469
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000470static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100471 struct snd_compr_params *params)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000472{
473 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700474 struct snd_pcm_substream *fe_substream =
475 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900476 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000477 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000478
479 if (cstream->direction == SND_COMPRESS_PLAYBACK)
480 stream = SNDRV_PCM_STREAM_PLAYBACK;
481 else
482 stream = SNDRV_PCM_STREAM_CAPTURE;
483
484 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
485
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100486 /*
487 * Create an empty hw_params for the BE as the machine driver must
488 * fix this up to match DSP decoder and ASRC configuration.
489 * I.e. machine driver fixup for compressed BE is mandatory.
490 */
491 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
492 sizeof(struct snd_pcm_hw_params));
493
494 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
495
496 ret = dpcm_be_dai_hw_params(fe, stream);
497 if (ret < 0)
498 goto out;
499
500 ret = dpcm_be_dai_prepare(fe, stream);
501 if (ret < 0)
502 goto out;
503
Kuninori Morimoto8dfedaf2020-04-24 08:15:36 +0900504 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
505 if (ret < 0)
506 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530507
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000508 ret = soc_compr_components_set_params(cstream, params);
509 if (ret < 0)
510 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000511
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000512 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
513 ret = fe->dai_link->compr_ops->set_params(cstream);
514 if (ret < 0)
515 goto out;
516 }
517
Daniel Mack15f6b092014-10-19 09:07:35 +0200518 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000519 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
520
521out:
522 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
523 mutex_unlock(&fe->card->mutex);
524 return ret;
525}
526
Namarta Kohli1245b702012-08-16 17:10:41 +0530527static int soc_compr_get_params(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100528 struct snd_codec *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530529{
530 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000531 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900532 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900533 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530534
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300535 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000536
Kuninori Morimotoadbef5432020-04-24 08:15:40 +0900537 ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params);
538 if (ret < 0)
539 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530540
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900541 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900542 if (!component->driver->compress_ops ||
543 !component->driver->compress_ops->get_params)
544 continue;
545
546 ret = component->driver->compress_ops->get_params(
547 component, cstream, params);
548 break;
549 }
550
Vinod Koul2e622ae2016-11-13 12:10:02 +0530551err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300552 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530553 return ret;
554}
555
556static int soc_compr_get_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100557 struct snd_compr_caps *caps)
Namarta Kohli1245b702012-08-16 17:10:41 +0530558{
559 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000560 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900561 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530562
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300563 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000564
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900565 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900566 if (!component->driver->compress_ops ||
567 !component->driver->compress_ops->get_caps)
568 continue;
569
570 ret = component->driver->compress_ops->get_caps(
571 component, cstream, caps);
572 break;
573 }
574
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300575 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530576 return ret;
577}
578
579static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100580 struct snd_compr_codec_caps *codec)
Namarta Kohli1245b702012-08-16 17:10:41 +0530581{
582 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000583 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900584 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530585
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300586 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000587
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900588 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900589 if (!component->driver->compress_ops ||
590 !component->driver->compress_ops->get_codec_caps)
591 continue;
592
593 ret = component->driver->compress_ops->get_codec_caps(
594 component, cstream, codec);
595 break;
596 }
597
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300598 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530599 return ret;
600}
601
602static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
603{
604 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000605 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900606 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900607 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530608
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300609 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000610
Kuninori Morimoto53294352020-04-24 08:15:45 +0900611 ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes);
612 if (ret < 0)
613 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530614
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900615 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900616 if (!component->driver->compress_ops ||
617 !component->driver->compress_ops->ack)
618 continue;
619
620 ret = component->driver->compress_ops->ack(
621 component, cstream, bytes);
622 if (ret < 0)
623 goto err;
624 }
625
Vinod Koul2e622ae2016-11-13 12:10:02 +0530626err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300627 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530628 return ret;
629}
630
631static int soc_compr_pointer(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100632 struct snd_compr_tstamp *tstamp)
Namarta Kohli1245b702012-08-16 17:10:41 +0530633{
634 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000635 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900636 int i, ret = 0;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900637 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530638
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300639 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000640
Kuninori Morimotoed38cc52020-04-24 08:15:49 +0900641 ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp);
642 if (ret < 0)
643 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530644
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900645 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900646 if (!component->driver->compress_ops ||
647 !component->driver->compress_ops->pointer)
648 continue;
649
650 ret = component->driver->compress_ops->pointer(
651 component, cstream, tstamp);
652 break;
653 }
Kuninori Morimotoed38cc52020-04-24 08:15:49 +0900654out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300655 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax7c9190f2016-06-20 09:51:32 +0100656 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530657}
658
Charles Keepax1f88eb02013-02-05 10:41:47 +0000659static int soc_compr_copy(struct snd_compr_stream *cstream,
Charles Keepax4daf8912013-04-18 11:01:38 +0100660 char __user *buf, size_t count)
Charles Keepax1f88eb02013-02-05 10:41:47 +0000661{
662 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000663 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900664 int i, ret = 0;
Charles Keepax1f88eb02013-02-05 10:41:47 +0000665
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300666 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000667
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900668 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900669 if (!component->driver->compress_ops ||
670 !component->driver->compress_ops->copy)
671 continue;
672
673 ret = component->driver->compress_ops->copy(
674 component, cstream, buf, count);
675 break;
676 }
677
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300678 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000679 return ret;
680}
681
Vinod Koul02bd90e2013-07-28 20:06:15 +0530682static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100683 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530684{
685 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000686 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900687 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900688 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530689
Kuninori Morimoto88b3a7d2020-04-24 08:15:54 +0900690 ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata);
691 if (ret < 0)
692 return ret;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530693
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900694 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900695 if (!component->driver->compress_ops ||
696 !component->driver->compress_ops->set_metadata)
697 continue;
698
699 ret = component->driver->compress_ops->set_metadata(
700 component, cstream, metadata);
701 if (ret < 0)
702 return ret;
703 }
704
Charles Keepax52cadf12019-02-05 11:18:12 +0000705 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530706}
707
Vinod Koul02bd90e2013-07-28 20:06:15 +0530708static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100709 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530710{
711 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000712 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900713 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900714 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530715
Kuninori Morimoto94d72812020-04-24 08:15:59 +0900716 ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata);
717 if (ret < 0)
718 return ret;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530719
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900720 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900721 if (!component->driver->compress_ops ||
722 !component->driver->compress_ops->get_metadata)
723 continue;
724
725 return component->driver->compress_ops->get_metadata(
726 component, cstream, metadata);
727 }
728
Charles Keepax52cadf12019-02-05 11:18:12 +0000729 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530730}
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000731
Namarta Kohli1245b702012-08-16 17:10:41 +0530732/* ASoC Compress operations */
733static struct snd_compr_ops soc_compr_ops = {
734 .open = soc_compr_open,
735 .free = soc_compr_free,
736 .set_params = soc_compr_set_params,
Vinod Koul02bd90e2013-07-28 20:06:15 +0530737 .set_metadata = soc_compr_set_metadata,
738 .get_metadata = soc_compr_get_metadata,
Namarta Kohli1245b702012-08-16 17:10:41 +0530739 .get_params = soc_compr_get_params,
740 .trigger = soc_compr_trigger,
741 .pointer = soc_compr_pointer,
742 .ack = soc_compr_ack,
743 .get_caps = soc_compr_get_caps,
744 .get_codec_caps = soc_compr_get_codec_caps
745};
746
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000747/* ASoC Dynamic Compress operations */
748static struct snd_compr_ops soc_compr_dyn_ops = {
749 .open = soc_compr_open_fe,
750 .free = soc_compr_free_fe,
751 .set_params = soc_compr_set_params_fe,
752 .get_params = soc_compr_get_params,
753 .set_metadata = soc_compr_set_metadata,
754 .get_metadata = soc_compr_get_metadata,
755 .trigger = soc_compr_trigger_fe,
756 .pointer = soc_compr_pointer,
757 .ack = soc_compr_ack,
758 .get_caps = soc_compr_get_caps,
759 .get_codec_caps = soc_compr_get_codec_caps
760};
761
Jie Yang6f0c4222015-10-13 23:41:00 +0800762/**
763 * snd_soc_new_compress - create a new compress.
764 *
765 * @rtd: The runtime for which we will create compress
766 * @num: the device index number (zero based - shared with normal PCMs)
767 *
768 * Return: 0 for success, else error.
769 */
770int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
Namarta Kohli1245b702012-08-16 17:10:41 +0530771{
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000772 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900773 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
774 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530775 struct snd_compr *compr;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000776 struct snd_pcm *be_pcm;
Namarta Kohli1245b702012-08-16 17:10:41 +0530777 char new_name[64];
778 int ret = 0, direction = 0;
Vinod Koula1068042016-01-07 21:48:14 +0530779 int playback = 0, capture = 0;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900780 int i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530781
Bard Liao6e1276a2020-02-25 21:39:16 +0800782 if (rtd->num_cpus > 1 ||
783 rtd->num_codecs > 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000784 dev_err(rtd->card->dev,
Bard Liao6e1276a2020-02-25 21:39:16 +0800785 "Compress ASoC: Multi CPU/Codec not supported\n");
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200786 return -EINVAL;
787 }
788
Namarta Kohli1245b702012-08-16 17:10:41 +0530789 /* check client and interface hw capabilities */
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900790 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
791 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
Vinod Koula1068042016-01-07 21:48:14 +0530792 playback = 1;
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900793 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
794 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
Vinod Koula1068042016-01-07 21:48:14 +0530795 capture = 1;
796
Vinod Koula1068042016-01-07 21:48:14 +0530797 /*
798 * Compress devices are unidirectional so only one of the directions
799 * should be set, check for that (xor)
800 */
801 if (playback + capture != 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000802 dev_err(rtd->card->dev,
803 "Compress ASoC: Invalid direction for P %d, C %d\n",
804 playback, capture);
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100805 return -EINVAL;
Vinod Koula1068042016-01-07 21:48:14 +0530806 }
807
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800808 if (playback)
Vinod Koula1068042016-01-07 21:48:14 +0530809 direction = SND_COMPRESS_PLAYBACK;
810 else
811 direction = SND_COMPRESS_CAPTURE;
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100812
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200813 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200814 if (!compr)
Namarta Kohli1245b702012-08-16 17:10:41 +0530815 return -ENOMEM;
Namarta Kohli1245b702012-08-16 17:10:41 +0530816
Charles Keepax1f88eb02013-02-05 10:41:47 +0000817 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
818 GFP_KERNEL);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200819 if (!compr->ops)
820 return -ENOMEM;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000821
822 if (rtd->dai_link->dynamic) {
823 snprintf(new_name, sizeof(new_name), "(%s)",
824 rtd->dai_link->stream_name);
825
826 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
Qais Yousefd3268a42015-01-14 08:47:29 +0000827 rtd->dai_link->dpcm_playback,
828 rtd->dai_link->dpcm_capture, &be_pcm);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000829 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000830 dev_err(rtd->card->dev,
831 "Compress ASoC: can't create compressed for %s: %d\n",
832 rtd->dai_link->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200833 return ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000834 }
835
836 rtd->pcm = be_pcm;
837 rtd->fe_compr = 1;
Qais Yousefd3268a42015-01-14 08:47:29 +0000838 if (rtd->dai_link->dpcm_playback)
839 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
840 else if (rtd->dai_link->dpcm_capture)
841 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000842 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800843 } else {
844 snprintf(new_name, sizeof(new_name), "%s %s-%d",
845 rtd->dai_link->stream_name, codec_dai->name, num);
846
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000847 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800848 }
Charles Keepax1f88eb02013-02-05 10:41:47 +0000849
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900850 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900851 if (!component->driver->compress_ops ||
852 !component->driver->compress_ops->copy)
853 continue;
854
855 compr->ops->copy = soc_compr_copy;
856 break;
857 }
858
Namarta Kohli1245b702012-08-16 17:10:41 +0530859 mutex_init(&compr->lock);
Richard Fitzgeralde5241a82015-11-25 13:00:24 +0000860 ret = snd_compress_new(rtd->card->snd_card, num, direction,
861 new_name, compr);
Namarta Kohli1245b702012-08-16 17:10:41 +0530862 if (ret < 0) {
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900863 component = asoc_rtd_to_codec(rtd, 0)->component;
Charles Keepax141dfc92018-01-26 13:08:45 +0000864 dev_err(component->dev,
865 "Compress ASoC: can't create compress for codec %s: %d\n",
866 component->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200867 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530868 }
869
Charles Keepax202c8f72013-01-24 09:44:30 +0000870 /* DAPM dai link stream work */
Kuninori Morimoto83f94a22020-01-10 11:36:17 +0900871 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
Charles Keepax202c8f72013-01-24 09:44:30 +0000872
Namarta Kohli1245b702012-08-16 17:10:41 +0530873 rtd->compr = compr;
874 compr->private_data = rtd;
875
Charles Keepax141dfc92018-01-26 13:08:45 +0000876 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
877 codec_dai->name, cpu_dai->name);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000878
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200879 return 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530880}
Jie Yang6f0c4222015-10-13 23:41:00 +0800881EXPORT_SYMBOL_GPL(snd_soc_new_compress);