blob: def3ae78b4a7de817991a8a8b967da6ae0c6b39e [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) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +090032 if (!component->driver->compress_ops ||
33 !component->driver->compress_ops->open)
34 continue;
35
36 ret = component->driver->compress_ops->open(component, 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
Charles Keepax1e57b822018-04-24 16:39:03 +010047 *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
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +090062 if (!component->driver->compress_ops ||
63 !component->driver->compress_ops->free)
64 continue;
65
66 component->driver->compress_ops->free(component, cstream);
67 }
68
Charles Keepax1e57b822018-04-24 16:39:03 +010069 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;
Rong Chen3e645a42020-04-24 08:54:37 +080075 struct snd_soc_component *component = NULL, *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
Kuninori Morimotob5ae4cc2020-04-24 08:15:24 +090090 ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
91 if (ret < 0)
92 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +053093
Charles Keepax1e57b822018-04-24 16:39:03 +010094 ret = soc_compr_components_open(cstream, &component);
95 if (ret < 0)
96 goto machine_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000097
Namarta Kohli1245b702012-08-16 17:10:41 +053098 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
99 ret = rtd->dai_link->compr_ops->startup(cstream);
100 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000101 dev_err(rtd->dev,
102 "Compress ASoC: %s startup failed: %d\n",
103 rtd->dai_link->name, ret);
Namarta Kohli1245b702012-08-16 17:10:41 +0530104 goto machine_err;
105 }
106 }
107
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100108 snd_soc_runtime_activate(rtd, cstream->direction);
Namarta Kohli1245b702012-08-16 17:10:41 +0530109
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300110 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax15e2e612013-01-24 09:44:29 +0000111
Namarta Kohli1245b702012-08-16 17:10:41 +0530112 return 0;
113
114machine_err:
Charles Keepax1e57b822018-04-24 16:39:03 +0100115 soc_compr_components_free(cstream, component);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000116
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900117 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530118out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300119 mutex_unlock(&rtd->card->pcm_mutex);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100120pm_err:
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900121 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100122 if (component == save)
123 break;
124 pm_runtime_mark_last_busy(component->dev);
125 pm_runtime_put_autosuspend(component->dev);
126 }
127
Namarta Kohli1245b702012-08-16 17:10:41 +0530128 return ret;
129}
130
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000131static int soc_compr_open_fe(struct snd_compr_stream *cstream)
132{
133 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700134 struct snd_pcm_substream *fe_substream =
135 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000136 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900137 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000138 struct snd_soc_dpcm *dpcm;
139 struct snd_soc_dapm_widget_list *list;
140 int stream;
Charles Keepax572e6c82018-04-24 16:39:01 +0100141 int ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000142
143 if (cstream->direction == SND_COMPRESS_PLAYBACK)
144 stream = SNDRV_PCM_STREAM_PLAYBACK;
145 else
146 stream = SNDRV_PCM_STREAM_CAPTURE;
147
148 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100149 fe->dpcm[stream].runtime = fe_substream->runtime;
150
151 ret = dpcm_path_get(fe, stream, &list);
152 if (ret < 0)
153 goto be_err;
154 else if (ret == 0)
155 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
156 fe->dai_link->name, stream ? "capture" : "playback");
157 /* calculate valid and active FE <-> BE dpcms */
158 dpcm_process_paths(fe, stream, &list, 1);
159 fe->dpcm[stream].runtime = fe_substream->runtime;
160
161 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
162
163 ret = dpcm_be_dai_startup(fe, stream);
164 if (ret < 0) {
165 /* clean up all links */
Kuninori Morimoto8d6258a2018-09-18 01:31:09 +0000166 for_each_dpcm_be(fe, stream, dpcm)
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100167 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
168
169 dpcm_be_disconnect(fe, stream);
170 fe->dpcm[stream].runtime = NULL;
171 goto out;
172 }
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000173
Kuninori Morimotob5ae4cc2020-04-24 08:15:24 +0900174 ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
175 if (ret < 0)
176 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530177
Charles Keepax1e57b822018-04-24 16:39:03 +0100178 ret = soc_compr_components_open(cstream, &component);
179 if (ret < 0)
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100180 goto open_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000181
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000182 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
183 ret = fe->dai_link->compr_ops->startup(cstream);
184 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000185 pr_err("Compress ASoC: %s startup failed: %d\n",
186 fe->dai_link->name, ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000187 goto machine_err;
188 }
189 }
190
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000191 dpcm_clear_pending_state(fe, stream);
192 dpcm_path_put(&list);
193
194 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
195 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
196
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100197 snd_soc_runtime_activate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000198
199 mutex_unlock(&fe->card->mutex);
200
201 return 0;
202
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000203machine_err:
Charles Keepax1e57b822018-04-24 16:39:03 +0100204 soc_compr_components_free(cstream, component);
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100205open_err:
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900206 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000207out:
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100208 dpcm_path_put(&list);
209be_err:
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000210 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
211 mutex_unlock(&fe->card->mutex);
212 return ret;
213}
214
Namarta Kohli1245b702012-08-16 17:10:41 +0530215static int soc_compr_free(struct snd_compr_stream *cstream)
216{
217 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100218 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900219 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
220 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900221 int stream, i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530222
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300223 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000224
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100225 if (cstream->direction == SND_COMPRESS_PLAYBACK)
226 stream = SNDRV_PCM_STREAM_PLAYBACK;
227 else
228 stream = SNDRV_PCM_STREAM_CAPTURE;
229
230 snd_soc_runtime_deactivate(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530231
Mark Brownda183962013-02-06 15:44:07 +0000232 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
233
Namarta Kohli1245b702012-08-16 17:10:41 +0530234 if (!cpu_dai->active)
235 cpu_dai->rate = 0;
236
237 if (!codec_dai->active)
238 codec_dai->rate = 0;
239
Namarta Kohli1245b702012-08-16 17:10:41 +0530240 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
241 rtd->dai_link->compr_ops->shutdown(cstream);
242
Charles Keepax1e57b822018-04-24 16:39:03 +0100243 soc_compr_components_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000244
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900245 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Vinod Koul2e622ae2016-11-13 12:10:02 +0530246
Kuninori Morimoto3f4cf792020-01-10 11:36:23 +0900247 snd_soc_dapm_stream_stop(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530248
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300249 mutex_unlock(&rtd->card->pcm_mutex);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100250
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900251 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100252 pm_runtime_mark_last_busy(component->dev);
253 pm_runtime_put_autosuspend(component->dev);
254 }
255
Namarta Kohli1245b702012-08-16 17:10:41 +0530256 return 0;
257}
258
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000259static int soc_compr_free_fe(struct snd_compr_stream *cstream)
260{
261 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900262 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000263 struct snd_soc_dpcm *dpcm;
264 int stream, ret;
265
266 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
267
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100268 if (cstream->direction == SND_COMPRESS_PLAYBACK)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000269 stream = SNDRV_PCM_STREAM_PLAYBACK;
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100270 else
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000271 stream = SNDRV_PCM_STREAM_CAPTURE;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000272
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100273 snd_soc_runtime_deactivate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000274
275 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
276
277 ret = dpcm_be_dai_hw_free(fe, stream);
278 if (ret < 0)
Charles Keepax141dfc92018-01-26 13:08:45 +0000279 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000280
281 ret = dpcm_be_dai_shutdown(fe, stream);
282
283 /* mark FE's links ready to prune */
Kuninori Morimoto8d6258a2018-09-18 01:31:09 +0000284 for_each_dpcm_be(fe, stream, dpcm)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000285 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
286
Kuninori Morimoto1c531232020-02-21 10:25:18 +0900287 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000288
289 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
290 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
291
292 dpcm_be_disconnect(fe, stream);
293
294 fe->dpcm[stream].runtime = NULL;
295
296 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
297 fe->dai_link->compr_ops->shutdown(cstream);
298
Charles Keepax1e57b822018-04-24 16:39:03 +0100299 soc_compr_components_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000300
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900301 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Vinod Koul2e622ae2016-11-13 12:10:02 +0530302
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000303 mutex_unlock(&fe->card->mutex);
304 return 0;
305}
306
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000307static int soc_compr_components_trigger(struct snd_compr_stream *cstream,
308 int cmd)
Namarta Kohli1245b702012-08-16 17:10:41 +0530309{
Namarta Kohli1245b702012-08-16 17:10:41 +0530310 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000311 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900312 int i, ret;
Charles Keepax15e2e612013-01-24 09:44:29 +0000313
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900314 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900315 if (!component->driver->compress_ops ||
316 !component->driver->compress_ops->trigger)
317 continue;
318
319 ret = component->driver->compress_ops->trigger(
320 component, cstream, cmd);
321 if (ret < 0)
322 return ret;
323 }
324
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000325 return 0;
326}
327
328static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
329{
330 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900331 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
332 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000333 int ret;
334
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300335 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000336
337 ret = soc_compr_components_trigger(cstream, cmd);
338 if (ret < 0)
339 goto out;
340
Kuninori Morimotoeb084112020-04-24 08:15:32 +0900341 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
342 if (ret < 0)
343 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530344
Mark Brownda183962013-02-06 15:44:07 +0000345 switch (cmd) {
346 case SNDRV_PCM_TRIGGER_START:
347 snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
348 break;
349 case SNDRV_PCM_TRIGGER_STOP:
350 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
351 break;
Mark Browne38b9b72013-02-06 13:52:42 +0000352 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530353
Charles Keepax15e2e612013-01-24 09:44:29 +0000354out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300355 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530356 return ret;
357}
358
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000359static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
360{
361 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900362 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000363 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000364
365 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000366 cmd == SND_COMPR_TRIGGER_DRAIN)
367 return soc_compr_components_trigger(cstream, cmd);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000368
369 if (cstream->direction == SND_COMPRESS_PLAYBACK)
370 stream = SNDRV_PCM_STREAM_PLAYBACK;
371 else
372 stream = SNDRV_PCM_STREAM_CAPTURE;
373
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000374 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
375
Kuninori Morimotoeb084112020-04-24 08:15:32 +0900376 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
377 if (ret < 0)
378 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530379
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000380 ret = soc_compr_components_trigger(cstream, cmd);
381 if (ret < 0)
382 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000383
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000384 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
385
386 ret = dpcm_be_dai_trigger(fe, stream, cmd);
387
388 switch (cmd) {
389 case SNDRV_PCM_TRIGGER_START:
390 case SNDRV_PCM_TRIGGER_RESUME:
391 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
392 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
393 break;
394 case SNDRV_PCM_TRIGGER_STOP:
395 case SNDRV_PCM_TRIGGER_SUSPEND:
396 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
397 break;
398 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
399 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
400 break;
401 }
402
403out:
404 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
405 mutex_unlock(&fe->card->mutex);
406 return ret;
407}
408
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000409static int soc_compr_components_set_params(struct snd_compr_stream *cstream,
410 struct snd_compr_params *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530411{
412 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000413 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900414 int i, ret;
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000415
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900416 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900417 if (!component->driver->compress_ops ||
418 !component->driver->compress_ops->set_params)
419 continue;
420
421 ret = component->driver->compress_ops->set_params(
422 component, cstream, params);
423 if (ret < 0)
424 return ret;
425 }
426
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000427 return 0;
428}
429
430static int soc_compr_set_params(struct snd_compr_stream *cstream,
431 struct snd_compr_params *params)
432{
433 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900434 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000435 int ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530436
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300437 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000438
Charles Keepaxef050be2018-04-24 16:39:02 +0100439 /*
440 * First we call set_params for the CPU DAI, then the component
441 * driver this should configure the SoC side. If the machine has
442 * compressed ops then we call that as well. The expectation is
443 * that these callbacks will configure everything for this compress
444 * path, like configuring a PCM port for a CODEC.
Namarta Kohli1245b702012-08-16 17:10:41 +0530445 */
Kuninori Morimoto8dfedaf2020-04-24 08:15:36 +0900446 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
447 if (ret < 0)
448 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530449
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000450 ret = soc_compr_components_set_params(cstream, params);
451 if (ret < 0)
452 goto err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000453
Namarta Kohli1245b702012-08-16 17:10:41 +0530454 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
455 ret = rtd->dai_link->compr_ops->set_params(cstream);
456 if (ret < 0)
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000457 goto err;
Namarta Kohli1245b702012-08-16 17:10:41 +0530458 }
459
Charles Keepax2c071ed2013-05-20 08:33:54 +0100460 if (cstream->direction == SND_COMPRESS_PLAYBACK)
461 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
Charles Keepax89027d92018-04-26 17:30:07 +0100462 SND_SOC_DAPM_STREAM_START);
Charles Keepax2c071ed2013-05-20 08:33:54 +0100463 else
464 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
Charles Keepax89027d92018-04-26 17:30:07 +0100465 SND_SOC_DAPM_STREAM_START);
Namarta Kohli1245b702012-08-16 17:10:41 +0530466
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000467 /* cancel any delayed stream shutdown that is pending */
468 rtd->pop_wait = 0;
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300469 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000470
471 cancel_delayed_work_sync(&rtd->delayed_work);
472
Charles Keepax52cadf12019-02-05 11:18:12 +0000473 return 0;
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000474
475err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300476 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530477 return ret;
478}
479
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000480static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100481 struct snd_compr_params *params)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000482{
483 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700484 struct snd_pcm_substream *fe_substream =
485 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900486 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000487 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000488
489 if (cstream->direction == SND_COMPRESS_PLAYBACK)
490 stream = SNDRV_PCM_STREAM_PLAYBACK;
491 else
492 stream = SNDRV_PCM_STREAM_CAPTURE;
493
494 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
495
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100496 /*
497 * Create an empty hw_params for the BE as the machine driver must
498 * fix this up to match DSP decoder and ASRC configuration.
499 * I.e. machine driver fixup for compressed BE is mandatory.
500 */
501 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
502 sizeof(struct snd_pcm_hw_params));
503
504 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
505
506 ret = dpcm_be_dai_hw_params(fe, stream);
507 if (ret < 0)
508 goto out;
509
510 ret = dpcm_be_dai_prepare(fe, stream);
511 if (ret < 0)
512 goto out;
513
Kuninori Morimoto8dfedaf2020-04-24 08:15:36 +0900514 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
515 if (ret < 0)
516 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530517
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000518 ret = soc_compr_components_set_params(cstream, params);
519 if (ret < 0)
520 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000521
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000522 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
523 ret = fe->dai_link->compr_ops->set_params(cstream);
524 if (ret < 0)
525 goto out;
526 }
527
Daniel Mack15f6b092014-10-19 09:07:35 +0200528 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000529 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
530
531out:
532 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
533 mutex_unlock(&fe->card->mutex);
534 return ret;
535}
536
Namarta Kohli1245b702012-08-16 17:10:41 +0530537static int soc_compr_get_params(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100538 struct snd_codec *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530539{
540 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000541 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900542 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900543 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530544
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300545 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000546
Kuninori Morimotoadbef5432020-04-24 08:15:40 +0900547 ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params);
548 if (ret < 0)
549 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530550
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900551 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900552 if (!component->driver->compress_ops ||
553 !component->driver->compress_ops->get_params)
554 continue;
555
556 ret = component->driver->compress_ops->get_params(
557 component, cstream, params);
558 break;
559 }
560
Vinod Koul2e622ae2016-11-13 12:10:02 +0530561err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300562 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530563 return ret;
564}
565
566static int soc_compr_get_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100567 struct snd_compr_caps *caps)
Namarta Kohli1245b702012-08-16 17:10:41 +0530568{
569 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000570 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900571 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530572
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300573 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000574
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900575 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900576 if (!component->driver->compress_ops ||
577 !component->driver->compress_ops->get_caps)
578 continue;
579
580 ret = component->driver->compress_ops->get_caps(
581 component, cstream, caps);
582 break;
583 }
584
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300585 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530586 return ret;
587}
588
589static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100590 struct snd_compr_codec_caps *codec)
Namarta Kohli1245b702012-08-16 17:10:41 +0530591{
592 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000593 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900594 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530595
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300596 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000597
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900598 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900599 if (!component->driver->compress_ops ||
600 !component->driver->compress_ops->get_codec_caps)
601 continue;
602
603 ret = component->driver->compress_ops->get_codec_caps(
604 component, cstream, codec);
605 break;
606 }
607
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300608 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530609 return ret;
610}
611
612static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
613{
614 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000615 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900616 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900617 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530618
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300619 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000620
Kuninori Morimoto53294352020-04-24 08:15:45 +0900621 ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes);
622 if (ret < 0)
623 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530624
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900625 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900626 if (!component->driver->compress_ops ||
627 !component->driver->compress_ops->ack)
628 continue;
629
630 ret = component->driver->compress_ops->ack(
631 component, cstream, bytes);
632 if (ret < 0)
633 goto err;
634 }
635
Vinod Koul2e622ae2016-11-13 12:10:02 +0530636err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300637 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530638 return ret;
639}
640
641static int soc_compr_pointer(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100642 struct snd_compr_tstamp *tstamp)
Namarta Kohli1245b702012-08-16 17:10:41 +0530643{
644 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000645 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900646 int i, ret = 0;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900647 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530648
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300649 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000650
Kuninori Morimotoed38cc52020-04-24 08:15:49 +0900651 ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp);
652 if (ret < 0)
653 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530654
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900655 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900656 if (!component->driver->compress_ops ||
657 !component->driver->compress_ops->pointer)
658 continue;
659
660 ret = component->driver->compress_ops->pointer(
661 component, cstream, tstamp);
662 break;
663 }
Kuninori Morimotoed38cc52020-04-24 08:15:49 +0900664out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300665 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax7c9190f2016-06-20 09:51:32 +0100666 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530667}
668
Charles Keepax1f88eb02013-02-05 10:41:47 +0000669static int soc_compr_copy(struct snd_compr_stream *cstream,
Charles Keepax4daf8912013-04-18 11:01:38 +0100670 char __user *buf, size_t count)
Charles Keepax1f88eb02013-02-05 10:41:47 +0000671{
672 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000673 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900674 int i, ret = 0;
Charles Keepax1f88eb02013-02-05 10:41:47 +0000675
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300676 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000677
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900678 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900679 if (!component->driver->compress_ops ||
680 !component->driver->compress_ops->copy)
681 continue;
682
683 ret = component->driver->compress_ops->copy(
684 component, cstream, buf, count);
685 break;
686 }
687
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300688 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000689 return ret;
690}
691
Vinod Koul02bd90e2013-07-28 20:06:15 +0530692static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100693 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530694{
695 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000696 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900697 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900698 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530699
Kuninori Morimoto88b3a7d2020-04-24 08:15:54 +0900700 ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata);
701 if (ret < 0)
702 return ret;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530703
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900704 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900705 if (!component->driver->compress_ops ||
706 !component->driver->compress_ops->set_metadata)
707 continue;
708
709 ret = component->driver->compress_ops->set_metadata(
710 component, cstream, metadata);
711 if (ret < 0)
712 return ret;
713 }
714
Charles Keepax52cadf12019-02-05 11:18:12 +0000715 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530716}
717
Vinod Koul02bd90e2013-07-28 20:06:15 +0530718static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100719 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530720{
721 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000722 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900723 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900724 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530725
Kuninori Morimoto94d72812020-04-24 08:15:59 +0900726 ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata);
727 if (ret < 0)
728 return ret;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530729
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900730 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900731 if (!component->driver->compress_ops ||
732 !component->driver->compress_ops->get_metadata)
733 continue;
734
735 return component->driver->compress_ops->get_metadata(
736 component, cstream, metadata);
737 }
738
Charles Keepax52cadf12019-02-05 11:18:12 +0000739 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530740}
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000741
Namarta Kohli1245b702012-08-16 17:10:41 +0530742/* ASoC Compress operations */
743static struct snd_compr_ops soc_compr_ops = {
744 .open = soc_compr_open,
745 .free = soc_compr_free,
746 .set_params = soc_compr_set_params,
Vinod Koul02bd90e2013-07-28 20:06:15 +0530747 .set_metadata = soc_compr_set_metadata,
748 .get_metadata = soc_compr_get_metadata,
Namarta Kohli1245b702012-08-16 17:10:41 +0530749 .get_params = soc_compr_get_params,
750 .trigger = soc_compr_trigger,
751 .pointer = soc_compr_pointer,
752 .ack = soc_compr_ack,
753 .get_caps = soc_compr_get_caps,
754 .get_codec_caps = soc_compr_get_codec_caps
755};
756
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000757/* ASoC Dynamic Compress operations */
758static struct snd_compr_ops soc_compr_dyn_ops = {
759 .open = soc_compr_open_fe,
760 .free = soc_compr_free_fe,
761 .set_params = soc_compr_set_params_fe,
762 .get_params = soc_compr_get_params,
763 .set_metadata = soc_compr_set_metadata,
764 .get_metadata = soc_compr_get_metadata,
765 .trigger = soc_compr_trigger_fe,
766 .pointer = soc_compr_pointer,
767 .ack = soc_compr_ack,
768 .get_caps = soc_compr_get_caps,
769 .get_codec_caps = soc_compr_get_codec_caps
770};
771
Jie Yang6f0c4222015-10-13 23:41:00 +0800772/**
773 * snd_soc_new_compress - create a new compress.
774 *
775 * @rtd: The runtime for which we will create compress
776 * @num: the device index number (zero based - shared with normal PCMs)
777 *
778 * Return: 0 for success, else error.
779 */
780int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
Namarta Kohli1245b702012-08-16 17:10:41 +0530781{
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000782 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900783 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
784 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530785 struct snd_compr *compr;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000786 struct snd_pcm *be_pcm;
Namarta Kohli1245b702012-08-16 17:10:41 +0530787 char new_name[64];
788 int ret = 0, direction = 0;
Vinod Koula1068042016-01-07 21:48:14 +0530789 int playback = 0, capture = 0;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900790 int i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530791
Bard Liao6e1276a2020-02-25 21:39:16 +0800792 if (rtd->num_cpus > 1 ||
793 rtd->num_codecs > 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000794 dev_err(rtd->card->dev,
Bard Liao6e1276a2020-02-25 21:39:16 +0800795 "Compress ASoC: Multi CPU/Codec not supported\n");
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200796 return -EINVAL;
797 }
798
Namarta Kohli1245b702012-08-16 17:10:41 +0530799 /* check client and interface hw capabilities */
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900800 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
801 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
Vinod Koula1068042016-01-07 21:48:14 +0530802 playback = 1;
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900803 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
804 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
Vinod Koula1068042016-01-07 21:48:14 +0530805 capture = 1;
806
Vinod Koula1068042016-01-07 21:48:14 +0530807 /*
808 * Compress devices are unidirectional so only one of the directions
809 * should be set, check for that (xor)
810 */
811 if (playback + capture != 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000812 dev_err(rtd->card->dev,
813 "Compress ASoC: Invalid direction for P %d, C %d\n",
814 playback, capture);
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100815 return -EINVAL;
Vinod Koula1068042016-01-07 21:48:14 +0530816 }
817
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800818 if (playback)
Vinod Koula1068042016-01-07 21:48:14 +0530819 direction = SND_COMPRESS_PLAYBACK;
820 else
821 direction = SND_COMPRESS_CAPTURE;
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100822
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200823 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200824 if (!compr)
Namarta Kohli1245b702012-08-16 17:10:41 +0530825 return -ENOMEM;
Namarta Kohli1245b702012-08-16 17:10:41 +0530826
Charles Keepax1f88eb02013-02-05 10:41:47 +0000827 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
828 GFP_KERNEL);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200829 if (!compr->ops)
830 return -ENOMEM;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000831
832 if (rtd->dai_link->dynamic) {
833 snprintf(new_name, sizeof(new_name), "(%s)",
834 rtd->dai_link->stream_name);
835
836 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
Qais Yousefd3268a42015-01-14 08:47:29 +0000837 rtd->dai_link->dpcm_playback,
838 rtd->dai_link->dpcm_capture, &be_pcm);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000839 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000840 dev_err(rtd->card->dev,
841 "Compress ASoC: can't create compressed for %s: %d\n",
842 rtd->dai_link->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200843 return ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000844 }
845
846 rtd->pcm = be_pcm;
847 rtd->fe_compr = 1;
Qais Yousefd3268a42015-01-14 08:47:29 +0000848 if (rtd->dai_link->dpcm_playback)
849 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
850 else if (rtd->dai_link->dpcm_capture)
851 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000852 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800853 } else {
854 snprintf(new_name, sizeof(new_name), "%s %s-%d",
855 rtd->dai_link->stream_name, codec_dai->name, num);
856
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000857 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800858 }
Charles Keepax1f88eb02013-02-05 10:41:47 +0000859
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900860 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900861 if (!component->driver->compress_ops ||
862 !component->driver->compress_ops->copy)
863 continue;
864
865 compr->ops->copy = soc_compr_copy;
866 break;
867 }
868
Namarta Kohli1245b702012-08-16 17:10:41 +0530869 mutex_init(&compr->lock);
Richard Fitzgeralde5241a82015-11-25 13:00:24 +0000870 ret = snd_compress_new(rtd->card->snd_card, num, direction,
871 new_name, compr);
Namarta Kohli1245b702012-08-16 17:10:41 +0530872 if (ret < 0) {
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900873 component = asoc_rtd_to_codec(rtd, 0)->component;
Charles Keepax141dfc92018-01-26 13:08:45 +0000874 dev_err(component->dev,
875 "Compress ASoC: can't create compress for codec %s: %d\n",
876 component->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200877 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530878 }
879
Charles Keepax202c8f72013-01-24 09:44:30 +0000880 /* DAPM dai link stream work */
Kuninori Morimoto83f94a22020-01-10 11:36:17 +0900881 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
Charles Keepax202c8f72013-01-24 09:44:30 +0000882
Namarta Kohli1245b702012-08-16 17:10:41 +0530883 rtd->compr = compr;
884 compr->private_data = rtd;
885
Charles Keepax141dfc92018-01-26 13:08:45 +0000886 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
887 codec_dai->name, cpu_dai->name);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000888
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200889 return 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530890}
Jie Yang6f0c4222015-10-13 23:41:00 +0800891EXPORT_SYMBOL_GPL(snd_soc_new_compress);