blob: 3f77c0208e09bc302a6ac3f095277909729f2643 [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>
Cezary Rojewski4137f4b2019-12-17 10:58:50 +010022#include <linux/pm_runtime.h>
Namarta Kohli1245b702012-08-16 17:10:41 +053023
Charles Keepax1e57b822018-04-24 16:39:03 +010024static int soc_compr_components_open(struct snd_compr_stream *cstream,
25 struct snd_soc_component **last)
Namarta Kohli1245b702012-08-16 17:10:41 +053026{
27 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000028 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +090029 int i, ret;
Charles Keepax1e57b822018-04-24 16:39:03 +010030
Kuninori Morimoto613fb502020-01-10 11:35:21 +090031 for_each_rtd_components(rtd, i, component) {
Charles Keepax1e57b822018-04-24 16:39:03 +010032 if (!component->driver->compr_ops ||
33 !component->driver->compr_ops->open)
34 continue;
35
36 ret = component->driver->compr_ops->open(cstream);
37 if (ret < 0) {
38 dev_err(component->dev,
39 "Compress ASoC: can't open platform %s: %d\n",
40 component->name, ret);
41
42 *last = component;
43 return ret;
44 }
45 }
46
47 *last = NULL;
48 return 0;
49}
50
51static int soc_compr_components_free(struct snd_compr_stream *cstream,
52 struct snd_soc_component *last)
53{
54 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
55 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +090056 int i;
Charles Keepax1e57b822018-04-24 16:39:03 +010057
Kuninori Morimoto613fb502020-01-10 11:35:21 +090058 for_each_rtd_components(rtd, i, component) {
Charles Keepax1e57b822018-04-24 16:39:03 +010059 if (component == last)
60 break;
61
62 if (!component->driver->compr_ops ||
63 !component->driver->compr_ops->free)
64 continue;
65
66 component->driver->compr_ops->free(cstream);
67 }
68
69 return 0;
70}
71
72static int soc_compr_open(struct snd_compr_stream *cstream)
73{
74 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Cezary Rojewski4137f4b2019-12-17 10:58:50 +010075 struct snd_soc_component *component, *save = NULL;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +090076 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +090077 int ret, i;
Namarta Kohli1245b702012-08-16 17:10:41 +053078
Kuninori Morimoto613fb502020-01-10 11:35:21 +090079 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +010080 ret = pm_runtime_get_sync(component->dev);
81 if (ret < 0 && ret != -EACCES) {
82 pm_runtime_put_noidle(component->dev);
83 save = component;
84 goto pm_err;
85 }
86 }
87
Peter Ujfalusi72b745e2019-08-13 13:45:32 +030088 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +000089
Vinod Koul2e622ae2016-11-13 12:10:02 +053090 if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
91 ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
92 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +000093 dev_err(cpu_dai->dev,
94 "Compress ASoC: can't open interface %s: %d\n",
Vinod Koul2e622ae2016-11-13 12:10:02 +053095 cpu_dai->name, ret);
96 goto out;
97 }
98 }
99
Charles Keepax1e57b822018-04-24 16:39:03 +0100100 ret = soc_compr_components_open(cstream, &component);
101 if (ret < 0)
102 goto machine_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000103
Namarta Kohli1245b702012-08-16 17:10:41 +0530104 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
105 ret = rtd->dai_link->compr_ops->startup(cstream);
106 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000107 dev_err(rtd->dev,
108 "Compress ASoC: %s startup failed: %d\n",
109 rtd->dai_link->name, ret);
Namarta Kohli1245b702012-08-16 17:10:41 +0530110 goto machine_err;
111 }
112 }
113
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100114 snd_soc_runtime_activate(rtd, cstream->direction);
Namarta Kohli1245b702012-08-16 17:10:41 +0530115
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300116 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax15e2e612013-01-24 09:44:29 +0000117
Namarta Kohli1245b702012-08-16 17:10:41 +0530118 return 0;
119
120machine_err:
Charles Keepax1e57b822018-04-24 16:39:03 +0100121 soc_compr_components_free(cstream, component);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000122
Vinod Koul2e622ae2016-11-13 12:10:02 +0530123 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
124 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
Namarta Kohli1245b702012-08-16 17:10:41 +0530125out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300126 mutex_unlock(&rtd->card->pcm_mutex);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100127pm_err:
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900128 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100129 if (component == save)
130 break;
131 pm_runtime_mark_last_busy(component->dev);
132 pm_runtime_put_autosuspend(component->dev);
133 }
134
Namarta Kohli1245b702012-08-16 17:10:41 +0530135 return ret;
136}
137
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000138static int soc_compr_open_fe(struct snd_compr_stream *cstream)
139{
140 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700141 struct snd_pcm_substream *fe_substream =
142 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000143 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900144 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000145 struct snd_soc_dpcm *dpcm;
146 struct snd_soc_dapm_widget_list *list;
147 int stream;
Charles Keepax572e6c82018-04-24 16:39:01 +0100148 int ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000149
150 if (cstream->direction == SND_COMPRESS_PLAYBACK)
151 stream = SNDRV_PCM_STREAM_PLAYBACK;
152 else
153 stream = SNDRV_PCM_STREAM_CAPTURE;
154
155 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100156 fe->dpcm[stream].runtime = fe_substream->runtime;
157
158 ret = dpcm_path_get(fe, stream, &list);
159 if (ret < 0)
160 goto be_err;
161 else if (ret == 0)
162 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
163 fe->dai_link->name, stream ? "capture" : "playback");
164 /* calculate valid and active FE <-> BE dpcms */
165 dpcm_process_paths(fe, stream, &list, 1);
166 fe->dpcm[stream].runtime = fe_substream->runtime;
167
168 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
169
170 ret = dpcm_be_dai_startup(fe, stream);
171 if (ret < 0) {
172 /* clean up all links */
Kuninori Morimoto8d6258a2018-09-18 01:31:09 +0000173 for_each_dpcm_be(fe, stream, dpcm)
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100174 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
175
176 dpcm_be_disconnect(fe, stream);
177 fe->dpcm[stream].runtime = NULL;
178 goto out;
179 }
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000180
Vinod Koul2e622ae2016-11-13 12:10:02 +0530181 if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
182 ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
183 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000184 dev_err(cpu_dai->dev,
185 "Compress ASoC: can't open interface %s: %d\n",
Vinod Koul2e622ae2016-11-13 12:10:02 +0530186 cpu_dai->name, ret);
187 goto out;
188 }
189 }
190
Charles Keepax1e57b822018-04-24 16:39:03 +0100191 ret = soc_compr_components_open(cstream, &component);
192 if (ret < 0)
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100193 goto open_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000194
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000195 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
196 ret = fe->dai_link->compr_ops->startup(cstream);
197 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000198 pr_err("Compress ASoC: %s startup failed: %d\n",
199 fe->dai_link->name, ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000200 goto machine_err;
201 }
202 }
203
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000204 dpcm_clear_pending_state(fe, stream);
205 dpcm_path_put(&list);
206
207 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
208 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
209
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100210 snd_soc_runtime_activate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000211
212 mutex_unlock(&fe->card->mutex);
213
214 return 0;
215
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000216machine_err:
Charles Keepax1e57b822018-04-24 16:39:03 +0100217 soc_compr_components_free(cstream, component);
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100218open_err:
Vinod Koul2e622ae2016-11-13 12:10:02 +0530219 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
220 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000221out:
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100222 dpcm_path_put(&list);
223be_err:
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000224 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
225 mutex_unlock(&fe->card->mutex);
226 return ret;
227}
228
Namarta Kohli1245b702012-08-16 17:10:41 +0530229static int soc_compr_free(struct snd_compr_stream *cstream)
230{
231 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100232 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900233 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
234 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900235 int stream, i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530236
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300237 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000238
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100239 if (cstream->direction == SND_COMPRESS_PLAYBACK)
240 stream = SNDRV_PCM_STREAM_PLAYBACK;
241 else
242 stream = SNDRV_PCM_STREAM_CAPTURE;
243
244 snd_soc_runtime_deactivate(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530245
Mark Brownda183962013-02-06 15:44:07 +0000246 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
247
Namarta Kohli1245b702012-08-16 17:10:41 +0530248 if (!cpu_dai->active)
249 cpu_dai->rate = 0;
250
251 if (!codec_dai->active)
252 codec_dai->rate = 0;
253
Namarta Kohli1245b702012-08-16 17:10:41 +0530254 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
255 rtd->dai_link->compr_ops->shutdown(cstream);
256
Charles Keepax1e57b822018-04-24 16:39:03 +0100257 soc_compr_components_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000258
Vinod Koul2e622ae2016-11-13 12:10:02 +0530259 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
260 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
261
Kuninori Morimoto3f4cf792020-01-10 11:36:23 +0900262 snd_soc_dapm_stream_stop(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530263
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300264 mutex_unlock(&rtd->card->pcm_mutex);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100265
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900266 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100267 pm_runtime_mark_last_busy(component->dev);
268 pm_runtime_put_autosuspend(component->dev);
269 }
270
Namarta Kohli1245b702012-08-16 17:10:41 +0530271 return 0;
272}
273
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000274static int soc_compr_free_fe(struct snd_compr_stream *cstream)
275{
276 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900277 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000278 struct snd_soc_dpcm *dpcm;
279 int stream, ret;
280
281 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
282
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100283 if (cstream->direction == SND_COMPRESS_PLAYBACK)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000284 stream = SNDRV_PCM_STREAM_PLAYBACK;
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100285 else
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000286 stream = SNDRV_PCM_STREAM_CAPTURE;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000287
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100288 snd_soc_runtime_deactivate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000289
290 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
291
292 ret = dpcm_be_dai_hw_free(fe, stream);
293 if (ret < 0)
Charles Keepax141dfc92018-01-26 13:08:45 +0000294 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000295
296 ret = dpcm_be_dai_shutdown(fe, stream);
297
298 /* mark FE's links ready to prune */
Kuninori Morimoto8d6258a2018-09-18 01:31:09 +0000299 for_each_dpcm_be(fe, stream, dpcm)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000300 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
301
Kuninori Morimoto1c531232020-02-21 10:25:18 +0900302 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000303
304 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
305 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
306
307 dpcm_be_disconnect(fe, stream);
308
309 fe->dpcm[stream].runtime = NULL;
310
311 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
312 fe->dai_link->compr_ops->shutdown(cstream);
313
Charles Keepax1e57b822018-04-24 16:39:03 +0100314 soc_compr_components_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000315
Vinod Koul2e622ae2016-11-13 12:10:02 +0530316 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
317 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
318
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000319 mutex_unlock(&fe->card->mutex);
320 return 0;
321}
322
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000323static int soc_compr_components_trigger(struct snd_compr_stream *cstream,
324 int cmd)
Namarta Kohli1245b702012-08-16 17:10:41 +0530325{
Namarta Kohli1245b702012-08-16 17:10:41 +0530326 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000327 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900328 int i, ret;
Charles Keepax15e2e612013-01-24 09:44:29 +0000329
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900330 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000331 if (!component->driver->compr_ops ||
332 !component->driver->compr_ops->trigger)
333 continue;
334
Charles Keepax52cadf12019-02-05 11:18:12 +0000335 ret = component->driver->compr_ops->trigger(cstream, cmd);
336 if (ret < 0)
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000337 return ret;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000338 }
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000339
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000340 return 0;
341}
342
343static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
344{
345 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900346 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
347 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000348 int ret;
349
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300350 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000351
352 ret = soc_compr_components_trigger(cstream, cmd);
353 if (ret < 0)
354 goto out;
355
Vinod Koul2e622ae2016-11-13 12:10:02 +0530356 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
357 cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
358
Mark Brownda183962013-02-06 15:44:07 +0000359 switch (cmd) {
360 case SNDRV_PCM_TRIGGER_START:
361 snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
362 break;
363 case SNDRV_PCM_TRIGGER_STOP:
364 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
365 break;
Mark Browne38b9b72013-02-06 13:52:42 +0000366 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530367
Charles Keepax15e2e612013-01-24 09:44:29 +0000368out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300369 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530370 return ret;
371}
372
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000373static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
374{
375 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900376 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000377 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000378
379 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000380 cmd == SND_COMPR_TRIGGER_DRAIN)
381 return soc_compr_components_trigger(cstream, cmd);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000382
383 if (cstream->direction == SND_COMPRESS_PLAYBACK)
384 stream = SNDRV_PCM_STREAM_PLAYBACK;
385 else
386 stream = SNDRV_PCM_STREAM_CAPTURE;
387
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000388 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
389
Vinod Koul2e622ae2016-11-13 12:10:02 +0530390 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) {
391 ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
392 if (ret < 0)
393 goto out;
394 }
395
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000396 ret = soc_compr_components_trigger(cstream, cmd);
397 if (ret < 0)
398 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000399
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000400 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
401
402 ret = dpcm_be_dai_trigger(fe, stream, cmd);
403
404 switch (cmd) {
405 case SNDRV_PCM_TRIGGER_START:
406 case SNDRV_PCM_TRIGGER_RESUME:
407 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
408 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
409 break;
410 case SNDRV_PCM_TRIGGER_STOP:
411 case SNDRV_PCM_TRIGGER_SUSPEND:
412 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
413 break;
414 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
415 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
416 break;
417 }
418
419out:
420 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
421 mutex_unlock(&fe->card->mutex);
422 return ret;
423}
424
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000425static int soc_compr_components_set_params(struct snd_compr_stream *cstream,
426 struct snd_compr_params *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530427{
428 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000429 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900430 int i, ret;
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000431
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900432 for_each_rtd_components(rtd, i, component) {
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000433 if (!component->driver->compr_ops ||
434 !component->driver->compr_ops->set_params)
435 continue;
436
437 ret = component->driver->compr_ops->set_params(cstream, params);
438 if (ret < 0)
439 return ret;
440 }
441
442 return 0;
443}
444
445static int soc_compr_set_params(struct snd_compr_stream *cstream,
446 struct snd_compr_params *params)
447{
448 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900449 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000450 int ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530451
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300452 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000453
Charles Keepaxef050be2018-04-24 16:39:02 +0100454 /*
455 * First we call set_params for the CPU DAI, then the component
456 * driver this should configure the SoC side. If the machine has
457 * compressed ops then we call that as well. The expectation is
458 * that these callbacks will configure everything for this compress
459 * path, like configuring a PCM port for a CODEC.
Namarta Kohli1245b702012-08-16 17:10:41 +0530460 */
Vinod Koul2e622ae2016-11-13 12:10:02 +0530461 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
462 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
463 if (ret < 0)
464 goto err;
465 }
466
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000467 ret = soc_compr_components_set_params(cstream, params);
468 if (ret < 0)
469 goto err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000470
Namarta Kohli1245b702012-08-16 17:10:41 +0530471 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
472 ret = rtd->dai_link->compr_ops->set_params(cstream);
473 if (ret < 0)
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000474 goto err;
Namarta Kohli1245b702012-08-16 17:10:41 +0530475 }
476
Charles Keepax2c071ed2013-05-20 08:33:54 +0100477 if (cstream->direction == SND_COMPRESS_PLAYBACK)
478 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
Charles Keepax89027d92018-04-26 17:30:07 +0100479 SND_SOC_DAPM_STREAM_START);
Charles Keepax2c071ed2013-05-20 08:33:54 +0100480 else
481 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
Charles Keepax89027d92018-04-26 17:30:07 +0100482 SND_SOC_DAPM_STREAM_START);
Namarta Kohli1245b702012-08-16 17:10:41 +0530483
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000484 /* cancel any delayed stream shutdown that is pending */
485 rtd->pop_wait = 0;
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300486 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000487
488 cancel_delayed_work_sync(&rtd->delayed_work);
489
Charles Keepax52cadf12019-02-05 11:18:12 +0000490 return 0;
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000491
492err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300493 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530494 return ret;
495}
496
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000497static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100498 struct snd_compr_params *params)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000499{
500 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700501 struct snd_pcm_substream *fe_substream =
502 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900503 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000504 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000505
506 if (cstream->direction == SND_COMPRESS_PLAYBACK)
507 stream = SNDRV_PCM_STREAM_PLAYBACK;
508 else
509 stream = SNDRV_PCM_STREAM_CAPTURE;
510
511 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
512
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100513 /*
514 * Create an empty hw_params for the BE as the machine driver must
515 * fix this up to match DSP decoder and ASRC configuration.
516 * I.e. machine driver fixup for compressed BE is mandatory.
517 */
518 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
519 sizeof(struct snd_pcm_hw_params));
520
521 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
522
523 ret = dpcm_be_dai_hw_params(fe, stream);
524 if (ret < 0)
525 goto out;
526
527 ret = dpcm_be_dai_prepare(fe, stream);
528 if (ret < 0)
529 goto out;
530
Vinod Koul2e622ae2016-11-13 12:10:02 +0530531 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
532 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
533 if (ret < 0)
534 goto out;
535 }
536
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000537 ret = soc_compr_components_set_params(cstream, params);
538 if (ret < 0)
539 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000540
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000541 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
542 ret = fe->dai_link->compr_ops->set_params(cstream);
543 if (ret < 0)
544 goto out;
545 }
546
Daniel Mack15f6b092014-10-19 09:07:35 +0200547 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000548 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
549
550out:
551 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
552 mutex_unlock(&fe->card->mutex);
553 return ret;
554}
555
Namarta Kohli1245b702012-08-16 17:10:41 +0530556static int soc_compr_get_params(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100557 struct snd_codec *params)
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 Morimotoc2233a22020-03-30 10:47:37 +0900561 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900562 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530563
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300564 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000565
Vinod Koul2e622ae2016-11-13 12:10:02 +0530566 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
567 ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
568 if (ret < 0)
569 goto err;
570 }
571
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900572 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000573 if (!component->driver->compr_ops ||
574 !component->driver->compr_ops->get_params)
575 continue;
576
Charles Keepax52cadf12019-02-05 11:18:12 +0000577 ret = component->driver->compr_ops->get_params(cstream, params);
578 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000579 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530580
Vinod Koul2e622ae2016-11-13 12:10:02 +0530581err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300582 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530583 return ret;
584}
585
586static int soc_compr_get_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100587 struct snd_compr_caps *caps)
Namarta Kohli1245b702012-08-16 17:10:41 +0530588{
589 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000590 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900591 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530592
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300593 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000594
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900595 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000596 if (!component->driver->compr_ops ||
597 !component->driver->compr_ops->get_caps)
598 continue;
599
Charles Keepax52cadf12019-02-05 11:18:12 +0000600 ret = component->driver->compr_ops->get_caps(cstream, caps);
601 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000602 }
603
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300604 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530605 return ret;
606}
607
608static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100609 struct snd_compr_codec_caps *codec)
Namarta Kohli1245b702012-08-16 17:10:41 +0530610{
611 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000612 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900613 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530614
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300615 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000616
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900617 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000618 if (!component->driver->compr_ops ||
619 !component->driver->compr_ops->get_codec_caps)
620 continue;
621
Charles Keepax52cadf12019-02-05 11:18:12 +0000622 ret = component->driver->compr_ops->get_codec_caps(cstream,
623 codec);
624 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000625 }
626
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_ack(struct snd_compr_stream *cstream, size_t bytes)
632{
633 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000634 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900635 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900636 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530637
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300638 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000639
Vinod Koul2e622ae2016-11-13 12:10:02 +0530640 if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
641 ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
642 if (ret < 0)
643 goto err;
644 }
645
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900646 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000647 if (!component->driver->compr_ops ||
648 !component->driver->compr_ops->ack)
649 continue;
650
Charles Keepax52cadf12019-02-05 11:18:12 +0000651 ret = component->driver->compr_ops->ack(cstream, bytes);
652 if (ret < 0)
653 goto err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000654 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530655
Vinod Koul2e622ae2016-11-13 12:10:02 +0530656err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300657 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530658 return ret;
659}
660
661static int soc_compr_pointer(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100662 struct snd_compr_tstamp *tstamp)
Namarta Kohli1245b702012-08-16 17:10:41 +0530663{
664 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000665 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900666 int i, ret = 0;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900667 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530668
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300669 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000670
Vinod Koul2e622ae2016-11-13 12:10:02 +0530671 if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
672 cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
673
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900674 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000675 if (!component->driver->compr_ops ||
676 !component->driver->compr_ops->pointer)
677 continue;
678
Charles Keepax52cadf12019-02-05 11:18:12 +0000679 ret = component->driver->compr_ops->pointer(cstream, tstamp);
680 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000681 }
682
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300683 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax7c9190f2016-06-20 09:51:32 +0100684 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530685}
686
Charles Keepax1f88eb02013-02-05 10:41:47 +0000687static int soc_compr_copy(struct snd_compr_stream *cstream,
Charles Keepax4daf8912013-04-18 11:01:38 +0100688 char __user *buf, size_t count)
Charles Keepax1f88eb02013-02-05 10:41:47 +0000689{
690 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000691 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900692 int i, ret = 0;
Charles Keepax1f88eb02013-02-05 10:41:47 +0000693
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300694 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000695
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900696 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000697 if (!component->driver->compr_ops ||
698 !component->driver->compr_ops->copy)
699 continue;
700
Charles Keepax290df4d32018-01-26 13:08:43 +0000701 ret = component->driver->compr_ops->copy(cstream, buf, count);
702 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000703 }
Charles Keepax290df4d32018-01-26 13:08:43 +0000704
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300705 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000706 return ret;
707}
708
Vinod Koul02bd90e2013-07-28 20:06:15 +0530709static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100710 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530711{
712 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000713 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900714 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900715 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530716
Vinod Koul2e622ae2016-11-13 12:10:02 +0530717 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
718 ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
719 if (ret < 0)
720 return ret;
721 }
722
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900723 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000724 if (!component->driver->compr_ops ||
725 !component->driver->compr_ops->set_metadata)
726 continue;
727
Charles Keepax52cadf12019-02-05 11:18:12 +0000728 ret = component->driver->compr_ops->set_metadata(cstream,
729 metadata);
730 if (ret < 0)
731 return ret;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000732 }
Jeeja KP36953d92013-03-26 21:22:28 +0530733
Charles Keepax52cadf12019-02-05 11:18:12 +0000734 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530735}
736
Vinod Koul02bd90e2013-07-28 20:06:15 +0530737static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100738 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530739{
740 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000741 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900742 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900743 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530744
Vinod Koul2e622ae2016-11-13 12:10:02 +0530745 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
746 ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
747 if (ret < 0)
748 return ret;
749 }
750
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900751 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000752 if (!component->driver->compr_ops ||
753 !component->driver->compr_ops->get_metadata)
754 continue;
755
Charles Keepax52cadf12019-02-05 11:18:12 +0000756 return component->driver->compr_ops->get_metadata(cstream,
757 metadata);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000758 }
Jeeja KP36953d92013-03-26 21:22:28 +0530759
Charles Keepax52cadf12019-02-05 11:18:12 +0000760 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530761}
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000762
Namarta Kohli1245b702012-08-16 17:10:41 +0530763/* ASoC Compress operations */
764static struct snd_compr_ops soc_compr_ops = {
765 .open = soc_compr_open,
766 .free = soc_compr_free,
767 .set_params = soc_compr_set_params,
Vinod Koul02bd90e2013-07-28 20:06:15 +0530768 .set_metadata = soc_compr_set_metadata,
769 .get_metadata = soc_compr_get_metadata,
Namarta Kohli1245b702012-08-16 17:10:41 +0530770 .get_params = soc_compr_get_params,
771 .trigger = soc_compr_trigger,
772 .pointer = soc_compr_pointer,
773 .ack = soc_compr_ack,
774 .get_caps = soc_compr_get_caps,
775 .get_codec_caps = soc_compr_get_codec_caps
776};
777
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000778/* ASoC Dynamic Compress operations */
779static struct snd_compr_ops soc_compr_dyn_ops = {
780 .open = soc_compr_open_fe,
781 .free = soc_compr_free_fe,
782 .set_params = soc_compr_set_params_fe,
783 .get_params = soc_compr_get_params,
784 .set_metadata = soc_compr_set_metadata,
785 .get_metadata = soc_compr_get_metadata,
786 .trigger = soc_compr_trigger_fe,
787 .pointer = soc_compr_pointer,
788 .ack = soc_compr_ack,
789 .get_caps = soc_compr_get_caps,
790 .get_codec_caps = soc_compr_get_codec_caps
791};
792
Jie Yang6f0c4222015-10-13 23:41:00 +0800793/**
794 * snd_soc_new_compress - create a new compress.
795 *
796 * @rtd: The runtime for which we will create compress
797 * @num: the device index number (zero based - shared with normal PCMs)
798 *
799 * Return: 0 for success, else error.
800 */
801int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
Namarta Kohli1245b702012-08-16 17:10:41 +0530802{
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000803 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900804 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
805 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530806 struct snd_compr *compr;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000807 struct snd_pcm *be_pcm;
Namarta Kohli1245b702012-08-16 17:10:41 +0530808 char new_name[64];
809 int ret = 0, direction = 0;
Vinod Koula1068042016-01-07 21:48:14 +0530810 int playback = 0, capture = 0;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900811 int i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530812
Bard Liao6e1276a2020-02-25 21:39:16 +0800813 if (rtd->num_cpus > 1 ||
814 rtd->num_codecs > 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000815 dev_err(rtd->card->dev,
Bard Liao6e1276a2020-02-25 21:39:16 +0800816 "Compress ASoC: Multi CPU/Codec not supported\n");
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200817 return -EINVAL;
818 }
819
Namarta Kohli1245b702012-08-16 17:10:41 +0530820 /* check client and interface hw capabilities */
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900821 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
822 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
Vinod Koula1068042016-01-07 21:48:14 +0530823 playback = 1;
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900824 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
825 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
Vinod Koula1068042016-01-07 21:48:14 +0530826 capture = 1;
827
Vinod Koula1068042016-01-07 21:48:14 +0530828 /*
829 * Compress devices are unidirectional so only one of the directions
830 * should be set, check for that (xor)
831 */
832 if (playback + capture != 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000833 dev_err(rtd->card->dev,
834 "Compress ASoC: Invalid direction for P %d, C %d\n",
835 playback, capture);
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100836 return -EINVAL;
Vinod Koula1068042016-01-07 21:48:14 +0530837 }
838
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800839 if (playback)
Vinod Koula1068042016-01-07 21:48:14 +0530840 direction = SND_COMPRESS_PLAYBACK;
841 else
842 direction = SND_COMPRESS_CAPTURE;
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100843
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200844 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200845 if (!compr)
Namarta Kohli1245b702012-08-16 17:10:41 +0530846 return -ENOMEM;
Namarta Kohli1245b702012-08-16 17:10:41 +0530847
Charles Keepax1f88eb02013-02-05 10:41:47 +0000848 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
849 GFP_KERNEL);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200850 if (!compr->ops)
851 return -ENOMEM;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000852
853 if (rtd->dai_link->dynamic) {
854 snprintf(new_name, sizeof(new_name), "(%s)",
855 rtd->dai_link->stream_name);
856
857 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
Qais Yousefd3268a42015-01-14 08:47:29 +0000858 rtd->dai_link->dpcm_playback,
859 rtd->dai_link->dpcm_capture, &be_pcm);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000860 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000861 dev_err(rtd->card->dev,
862 "Compress ASoC: can't create compressed for %s: %d\n",
863 rtd->dai_link->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200864 return ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000865 }
866
867 rtd->pcm = be_pcm;
868 rtd->fe_compr = 1;
Qais Yousefd3268a42015-01-14 08:47:29 +0000869 if (rtd->dai_link->dpcm_playback)
870 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
871 else if (rtd->dai_link->dpcm_capture)
872 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000873 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800874 } else {
875 snprintf(new_name, sizeof(new_name), "%s %s-%d",
876 rtd->dai_link->stream_name, codec_dai->name, num);
877
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000878 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800879 }
Charles Keepax1f88eb02013-02-05 10:41:47 +0000880
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900881 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000882 if (!component->driver->compr_ops ||
883 !component->driver->compr_ops->copy)
884 continue;
885
886 compr->ops->copy = soc_compr_copy;
Charles Keepaxca76db62018-04-26 17:30:04 +0100887 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000888 }
889
Namarta Kohli1245b702012-08-16 17:10:41 +0530890 mutex_init(&compr->lock);
Richard Fitzgeralde5241a82015-11-25 13:00:24 +0000891 ret = snd_compress_new(rtd->card->snd_card, num, direction,
892 new_name, compr);
Namarta Kohli1245b702012-08-16 17:10:41 +0530893 if (ret < 0) {
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900894 component = asoc_rtd_to_codec(rtd, 0)->component;
Charles Keepax141dfc92018-01-26 13:08:45 +0000895 dev_err(component->dev,
896 "Compress ASoC: can't create compress for codec %s: %d\n",
897 component->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200898 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530899 }
900
Charles Keepax202c8f72013-01-24 09:44:30 +0000901 /* DAPM dai link stream work */
Kuninori Morimoto83f94a22020-01-10 11:36:17 +0900902 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
Charles Keepax202c8f72013-01-24 09:44:30 +0000903
Namarta Kohli1245b702012-08-16 17:10:41 +0530904 rtd->compr = compr;
905 compr->private_data = rtd;
906
Charles Keepax141dfc92018-01-26 13:08:45 +0000907 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
908 codec_dai->name, cpu_dai->name);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000909
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200910 return 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530911}
Jie Yang6f0c4222015-10-13 23:41:00 +0800912EXPORT_SYMBOL_GPL(snd_soc_new_compress);