blob: b05305a4d86ceb50e2d98fe80e3eacb1571f4787 [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 */
Vinod Koul2e622ae2016-11-13 12:10:02 +0530446 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
447 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
448 if (ret < 0)
449 goto err;
450 }
451
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000452 ret = soc_compr_components_set_params(cstream, params);
453 if (ret < 0)
454 goto err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000455
Namarta Kohli1245b702012-08-16 17:10:41 +0530456 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
457 ret = rtd->dai_link->compr_ops->set_params(cstream);
458 if (ret < 0)
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000459 goto err;
Namarta Kohli1245b702012-08-16 17:10:41 +0530460 }
461
Charles Keepax2c071ed2013-05-20 08:33:54 +0100462 if (cstream->direction == SND_COMPRESS_PLAYBACK)
463 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
Charles Keepax89027d92018-04-26 17:30:07 +0100464 SND_SOC_DAPM_STREAM_START);
Charles Keepax2c071ed2013-05-20 08:33:54 +0100465 else
466 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
Charles Keepax89027d92018-04-26 17:30:07 +0100467 SND_SOC_DAPM_STREAM_START);
Namarta Kohli1245b702012-08-16 17:10:41 +0530468
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000469 /* cancel any delayed stream shutdown that is pending */
470 rtd->pop_wait = 0;
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300471 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000472
473 cancel_delayed_work_sync(&rtd->delayed_work);
474
Charles Keepax52cadf12019-02-05 11:18:12 +0000475 return 0;
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000476
477err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300478 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530479 return ret;
480}
481
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000482static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100483 struct snd_compr_params *params)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000484{
485 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700486 struct snd_pcm_substream *fe_substream =
487 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900488 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000489 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000490
491 if (cstream->direction == SND_COMPRESS_PLAYBACK)
492 stream = SNDRV_PCM_STREAM_PLAYBACK;
493 else
494 stream = SNDRV_PCM_STREAM_CAPTURE;
495
496 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
497
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100498 /*
499 * Create an empty hw_params for the BE as the machine driver must
500 * fix this up to match DSP decoder and ASRC configuration.
501 * I.e. machine driver fixup for compressed BE is mandatory.
502 */
503 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
504 sizeof(struct snd_pcm_hw_params));
505
506 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
507
508 ret = dpcm_be_dai_hw_params(fe, stream);
509 if (ret < 0)
510 goto out;
511
512 ret = dpcm_be_dai_prepare(fe, stream);
513 if (ret < 0)
514 goto out;
515
Vinod Koul2e622ae2016-11-13 12:10:02 +0530516 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
517 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
518 if (ret < 0)
519 goto out;
520 }
521
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000522 ret = soc_compr_components_set_params(cstream, params);
523 if (ret < 0)
524 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000525
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000526 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
527 ret = fe->dai_link->compr_ops->set_params(cstream);
528 if (ret < 0)
529 goto out;
530 }
531
Daniel Mack15f6b092014-10-19 09:07:35 +0200532 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000533 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
534
535out:
536 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
537 mutex_unlock(&fe->card->mutex);
538 return ret;
539}
540
Namarta Kohli1245b702012-08-16 17:10:41 +0530541static int soc_compr_get_params(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100542 struct snd_codec *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530543{
544 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000545 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900546 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900547 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530548
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300549 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000550
Vinod Koul2e622ae2016-11-13 12:10:02 +0530551 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
552 ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
553 if (ret < 0)
554 goto err;
555 }
556
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900557 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900558 if (!component->driver->compress_ops ||
559 !component->driver->compress_ops->get_params)
560 continue;
561
562 ret = component->driver->compress_ops->get_params(
563 component, cstream, params);
564 break;
565 }
566
Vinod Koul2e622ae2016-11-13 12:10:02 +0530567err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300568 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530569 return ret;
570}
571
572static int soc_compr_get_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100573 struct snd_compr_caps *caps)
Namarta Kohli1245b702012-08-16 17:10:41 +0530574{
575 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000576 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900577 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530578
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300579 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000580
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900581 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900582 if (!component->driver->compress_ops ||
583 !component->driver->compress_ops->get_caps)
584 continue;
585
586 ret = component->driver->compress_ops->get_caps(
587 component, cstream, caps);
588 break;
589 }
590
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300591 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530592 return ret;
593}
594
595static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100596 struct snd_compr_codec_caps *codec)
Namarta Kohli1245b702012-08-16 17:10:41 +0530597{
598 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000599 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900600 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530601
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300602 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000603
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900604 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900605 if (!component->driver->compress_ops ||
606 !component->driver->compress_ops->get_codec_caps)
607 continue;
608
609 ret = component->driver->compress_ops->get_codec_caps(
610 component, cstream, codec);
611 break;
612 }
613
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300614 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530615 return ret;
616}
617
618static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
619{
620 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000621 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900622 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900623 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530624
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300625 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000626
Vinod Koul2e622ae2016-11-13 12:10:02 +0530627 if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
628 ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
629 if (ret < 0)
630 goto err;
631 }
632
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900633 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900634 if (!component->driver->compress_ops ||
635 !component->driver->compress_ops->ack)
636 continue;
637
638 ret = component->driver->compress_ops->ack(
639 component, cstream, bytes);
640 if (ret < 0)
641 goto err;
642 }
643
Vinod Koul2e622ae2016-11-13 12:10:02 +0530644err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300645 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530646 return ret;
647}
648
649static int soc_compr_pointer(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100650 struct snd_compr_tstamp *tstamp)
Namarta Kohli1245b702012-08-16 17:10:41 +0530651{
652 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000653 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900654 int i, ret = 0;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900655 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530656
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300657 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000658
Vinod Koul2e622ae2016-11-13 12:10:02 +0530659 if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
660 cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
661
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900662 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900663 if (!component->driver->compress_ops ||
664 !component->driver->compress_ops->pointer)
665 continue;
666
667 ret = component->driver->compress_ops->pointer(
668 component, cstream, tstamp);
669 break;
670 }
671
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300672 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax7c9190f2016-06-20 09:51:32 +0100673 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530674}
675
Charles Keepax1f88eb02013-02-05 10:41:47 +0000676static int soc_compr_copy(struct snd_compr_stream *cstream,
Charles Keepax4daf8912013-04-18 11:01:38 +0100677 char __user *buf, size_t count)
Charles Keepax1f88eb02013-02-05 10:41:47 +0000678{
679 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000680 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900681 int i, ret = 0;
Charles Keepax1f88eb02013-02-05 10:41:47 +0000682
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300683 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000684
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900685 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900686 if (!component->driver->compress_ops ||
687 !component->driver->compress_ops->copy)
688 continue;
689
690 ret = component->driver->compress_ops->copy(
691 component, cstream, buf, count);
692 break;
693 }
694
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300695 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000696 return ret;
697}
698
Vinod Koul02bd90e2013-07-28 20:06:15 +0530699static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100700 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530701{
702 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000703 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900704 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900705 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530706
Vinod Koul2e622ae2016-11-13 12:10:02 +0530707 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
708 ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
709 if (ret < 0)
710 return ret;
711 }
712
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900713 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900714 if (!component->driver->compress_ops ||
715 !component->driver->compress_ops->set_metadata)
716 continue;
717
718 ret = component->driver->compress_ops->set_metadata(
719 component, cstream, metadata);
720 if (ret < 0)
721 return ret;
722 }
723
Charles Keepax52cadf12019-02-05 11:18:12 +0000724 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530725}
726
Vinod Koul02bd90e2013-07-28 20:06:15 +0530727static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100728 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530729{
730 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000731 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900732 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900733 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530734
Vinod Koul2e622ae2016-11-13 12:10:02 +0530735 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
736 ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
737 if (ret < 0)
738 return ret;
739 }
740
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900741 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900742 if (!component->driver->compress_ops ||
743 !component->driver->compress_ops->get_metadata)
744 continue;
745
746 return component->driver->compress_ops->get_metadata(
747 component, cstream, metadata);
748 }
749
Charles Keepax52cadf12019-02-05 11:18:12 +0000750 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530751}
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000752
Namarta Kohli1245b702012-08-16 17:10:41 +0530753/* ASoC Compress operations */
754static struct snd_compr_ops soc_compr_ops = {
755 .open = soc_compr_open,
756 .free = soc_compr_free,
757 .set_params = soc_compr_set_params,
Vinod Koul02bd90e2013-07-28 20:06:15 +0530758 .set_metadata = soc_compr_set_metadata,
759 .get_metadata = soc_compr_get_metadata,
Namarta Kohli1245b702012-08-16 17:10:41 +0530760 .get_params = soc_compr_get_params,
761 .trigger = soc_compr_trigger,
762 .pointer = soc_compr_pointer,
763 .ack = soc_compr_ack,
764 .get_caps = soc_compr_get_caps,
765 .get_codec_caps = soc_compr_get_codec_caps
766};
767
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000768/* ASoC Dynamic Compress operations */
769static struct snd_compr_ops soc_compr_dyn_ops = {
770 .open = soc_compr_open_fe,
771 .free = soc_compr_free_fe,
772 .set_params = soc_compr_set_params_fe,
773 .get_params = soc_compr_get_params,
774 .set_metadata = soc_compr_set_metadata,
775 .get_metadata = soc_compr_get_metadata,
776 .trigger = soc_compr_trigger_fe,
777 .pointer = soc_compr_pointer,
778 .ack = soc_compr_ack,
779 .get_caps = soc_compr_get_caps,
780 .get_codec_caps = soc_compr_get_codec_caps
781};
782
Jie Yang6f0c4222015-10-13 23:41:00 +0800783/**
784 * snd_soc_new_compress - create a new compress.
785 *
786 * @rtd: The runtime for which we will create compress
787 * @num: the device index number (zero based - shared with normal PCMs)
788 *
789 * Return: 0 for success, else error.
790 */
791int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
Namarta Kohli1245b702012-08-16 17:10:41 +0530792{
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000793 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900794 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
795 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530796 struct snd_compr *compr;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000797 struct snd_pcm *be_pcm;
Namarta Kohli1245b702012-08-16 17:10:41 +0530798 char new_name[64];
799 int ret = 0, direction = 0;
Vinod Koula1068042016-01-07 21:48:14 +0530800 int playback = 0, capture = 0;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900801 int i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530802
Bard Liao6e1276a2020-02-25 21:39:16 +0800803 if (rtd->num_cpus > 1 ||
804 rtd->num_codecs > 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000805 dev_err(rtd->card->dev,
Bard Liao6e1276a2020-02-25 21:39:16 +0800806 "Compress ASoC: Multi CPU/Codec not supported\n");
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200807 return -EINVAL;
808 }
809
Namarta Kohli1245b702012-08-16 17:10:41 +0530810 /* check client and interface hw capabilities */
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900811 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
812 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
Vinod Koula1068042016-01-07 21:48:14 +0530813 playback = 1;
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900814 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
815 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
Vinod Koula1068042016-01-07 21:48:14 +0530816 capture = 1;
817
Vinod Koula1068042016-01-07 21:48:14 +0530818 /*
819 * Compress devices are unidirectional so only one of the directions
820 * should be set, check for that (xor)
821 */
822 if (playback + capture != 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000823 dev_err(rtd->card->dev,
824 "Compress ASoC: Invalid direction for P %d, C %d\n",
825 playback, capture);
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100826 return -EINVAL;
Vinod Koula1068042016-01-07 21:48:14 +0530827 }
828
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800829 if (playback)
Vinod Koula1068042016-01-07 21:48:14 +0530830 direction = SND_COMPRESS_PLAYBACK;
831 else
832 direction = SND_COMPRESS_CAPTURE;
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100833
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200834 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200835 if (!compr)
Namarta Kohli1245b702012-08-16 17:10:41 +0530836 return -ENOMEM;
Namarta Kohli1245b702012-08-16 17:10:41 +0530837
Charles Keepax1f88eb02013-02-05 10:41:47 +0000838 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
839 GFP_KERNEL);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200840 if (!compr->ops)
841 return -ENOMEM;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000842
843 if (rtd->dai_link->dynamic) {
844 snprintf(new_name, sizeof(new_name), "(%s)",
845 rtd->dai_link->stream_name);
846
847 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
Qais Yousefd3268a42015-01-14 08:47:29 +0000848 rtd->dai_link->dpcm_playback,
849 rtd->dai_link->dpcm_capture, &be_pcm);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000850 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000851 dev_err(rtd->card->dev,
852 "Compress ASoC: can't create compressed for %s: %d\n",
853 rtd->dai_link->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200854 return ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000855 }
856
857 rtd->pcm = be_pcm;
858 rtd->fe_compr = 1;
Qais Yousefd3268a42015-01-14 08:47:29 +0000859 if (rtd->dai_link->dpcm_playback)
860 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
861 else if (rtd->dai_link->dpcm_capture)
862 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000863 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800864 } else {
865 snprintf(new_name, sizeof(new_name), "%s %s-%d",
866 rtd->dai_link->stream_name, codec_dai->name, num);
867
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000868 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800869 }
Charles Keepax1f88eb02013-02-05 10:41:47 +0000870
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900871 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900872 if (!component->driver->compress_ops ||
873 !component->driver->compress_ops->copy)
874 continue;
875
876 compr->ops->copy = soc_compr_copy;
877 break;
878 }
879
Namarta Kohli1245b702012-08-16 17:10:41 +0530880 mutex_init(&compr->lock);
Richard Fitzgeralde5241a82015-11-25 13:00:24 +0000881 ret = snd_compress_new(rtd->card->snd_card, num, direction,
882 new_name, compr);
Namarta Kohli1245b702012-08-16 17:10:41 +0530883 if (ret < 0) {
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900884 component = asoc_rtd_to_codec(rtd, 0)->component;
Charles Keepax141dfc92018-01-26 13:08:45 +0000885 dev_err(component->dev,
886 "Compress ASoC: can't create compress for codec %s: %d\n",
887 component->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200888 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530889 }
890
Charles Keepax202c8f72013-01-24 09:44:30 +0000891 /* DAPM dai link stream work */
Kuninori Morimoto83f94a22020-01-10 11:36:17 +0900892 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
Charles Keepax202c8f72013-01-24 09:44:30 +0000893
Namarta Kohli1245b702012-08-16 17:10:41 +0530894 rtd->compr = compr;
895 compr->private_data = rtd;
896
Charles Keepax141dfc92018-01-26 13:08:45 +0000897 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
898 codec_dai->name, cpu_dai->name);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000899
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200900 return 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530901}
Jie Yang6f0c4222015-10-13 23:41:00 +0800902EXPORT_SYMBOL_GPL(snd_soc_new_compress);