blob: af74fb7959b94ce8ba9e8f7abfc3d598bd2e94a4 [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
Vinod Koul2e622ae2016-11-13 12:10:02 +0530341 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
342 cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
343
Mark Brownda183962013-02-06 15:44:07 +0000344 switch (cmd) {
345 case SNDRV_PCM_TRIGGER_START:
346 snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
347 break;
348 case SNDRV_PCM_TRIGGER_STOP:
349 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
350 break;
Mark Browne38b9b72013-02-06 13:52:42 +0000351 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530352
Charles Keepax15e2e612013-01-24 09:44:29 +0000353out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300354 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530355 return ret;
356}
357
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000358static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
359{
360 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900361 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000362 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000363
364 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000365 cmd == SND_COMPR_TRIGGER_DRAIN)
366 return soc_compr_components_trigger(cstream, cmd);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000367
368 if (cstream->direction == SND_COMPRESS_PLAYBACK)
369 stream = SNDRV_PCM_STREAM_PLAYBACK;
370 else
371 stream = SNDRV_PCM_STREAM_CAPTURE;
372
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000373 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
374
Vinod Koul2e622ae2016-11-13 12:10:02 +0530375 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) {
376 ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
377 if (ret < 0)
378 goto out;
379 }
380
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000381 ret = soc_compr_components_trigger(cstream, cmd);
382 if (ret < 0)
383 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000384
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000385 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
386
387 ret = dpcm_be_dai_trigger(fe, stream, cmd);
388
389 switch (cmd) {
390 case SNDRV_PCM_TRIGGER_START:
391 case SNDRV_PCM_TRIGGER_RESUME:
392 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
393 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
394 break;
395 case SNDRV_PCM_TRIGGER_STOP:
396 case SNDRV_PCM_TRIGGER_SUSPEND:
397 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
398 break;
399 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
400 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
401 break;
402 }
403
404out:
405 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
406 mutex_unlock(&fe->card->mutex);
407 return ret;
408}
409
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000410static int soc_compr_components_set_params(struct snd_compr_stream *cstream,
411 struct snd_compr_params *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530412{
413 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000414 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900415 int i, ret;
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000416
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900417 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900418 if (!component->driver->compress_ops ||
419 !component->driver->compress_ops->set_params)
420 continue;
421
422 ret = component->driver->compress_ops->set_params(
423 component, cstream, params);
424 if (ret < 0)
425 return ret;
426 }
427
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000428 return 0;
429}
430
431static int soc_compr_set_params(struct snd_compr_stream *cstream,
432 struct snd_compr_params *params)
433{
434 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900435 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000436 int ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530437
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300438 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000439
Charles Keepaxef050be2018-04-24 16:39:02 +0100440 /*
441 * First we call set_params for the CPU DAI, then the component
442 * driver this should configure the SoC side. If the machine has
443 * compressed ops then we call that as well. The expectation is
444 * that these callbacks will configure everything for this compress
445 * path, like configuring a PCM port for a CODEC.
Namarta Kohli1245b702012-08-16 17:10:41 +0530446 */
Vinod Koul2e622ae2016-11-13 12:10:02 +0530447 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
448 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
449 if (ret < 0)
450 goto err;
451 }
452
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000453 ret = soc_compr_components_set_params(cstream, params);
454 if (ret < 0)
455 goto err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000456
Namarta Kohli1245b702012-08-16 17:10:41 +0530457 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
458 ret = rtd->dai_link->compr_ops->set_params(cstream);
459 if (ret < 0)
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000460 goto err;
Namarta Kohli1245b702012-08-16 17:10:41 +0530461 }
462
Charles Keepax2c071ed2013-05-20 08:33:54 +0100463 if (cstream->direction == SND_COMPRESS_PLAYBACK)
464 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
Charles Keepax89027d92018-04-26 17:30:07 +0100465 SND_SOC_DAPM_STREAM_START);
Charles Keepax2c071ed2013-05-20 08:33:54 +0100466 else
467 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
Charles Keepax89027d92018-04-26 17:30:07 +0100468 SND_SOC_DAPM_STREAM_START);
Namarta Kohli1245b702012-08-16 17:10:41 +0530469
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000470 /* cancel any delayed stream shutdown that is pending */
471 rtd->pop_wait = 0;
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300472 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000473
474 cancel_delayed_work_sync(&rtd->delayed_work);
475
Charles Keepax52cadf12019-02-05 11:18:12 +0000476 return 0;
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000477
478err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300479 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530480 return ret;
481}
482
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000483static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100484 struct snd_compr_params *params)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000485{
486 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700487 struct snd_pcm_substream *fe_substream =
488 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900489 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000490 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000491
492 if (cstream->direction == SND_COMPRESS_PLAYBACK)
493 stream = SNDRV_PCM_STREAM_PLAYBACK;
494 else
495 stream = SNDRV_PCM_STREAM_CAPTURE;
496
497 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
498
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100499 /*
500 * Create an empty hw_params for the BE as the machine driver must
501 * fix this up to match DSP decoder and ASRC configuration.
502 * I.e. machine driver fixup for compressed BE is mandatory.
503 */
504 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
505 sizeof(struct snd_pcm_hw_params));
506
507 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
508
509 ret = dpcm_be_dai_hw_params(fe, stream);
510 if (ret < 0)
511 goto out;
512
513 ret = dpcm_be_dai_prepare(fe, stream);
514 if (ret < 0)
515 goto out;
516
Vinod Koul2e622ae2016-11-13 12:10:02 +0530517 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
518 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
519 if (ret < 0)
520 goto out;
521 }
522
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000523 ret = soc_compr_components_set_params(cstream, params);
524 if (ret < 0)
525 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000526
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000527 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
528 ret = fe->dai_link->compr_ops->set_params(cstream);
529 if (ret < 0)
530 goto out;
531 }
532
Daniel Mack15f6b092014-10-19 09:07:35 +0200533 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000534 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
535
536out:
537 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
538 mutex_unlock(&fe->card->mutex);
539 return ret;
540}
541
Namarta Kohli1245b702012-08-16 17:10:41 +0530542static int soc_compr_get_params(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100543 struct snd_codec *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530544{
545 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000546 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900547 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900548 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530549
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300550 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000551
Vinod Koul2e622ae2016-11-13 12:10:02 +0530552 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
553 ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
554 if (ret < 0)
555 goto err;
556 }
557
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900558 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900559 if (!component->driver->compress_ops ||
560 !component->driver->compress_ops->get_params)
561 continue;
562
563 ret = component->driver->compress_ops->get_params(
564 component, cstream, params);
565 break;
566 }
567
Vinod Koul2e622ae2016-11-13 12:10:02 +0530568err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300569 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530570 return ret;
571}
572
573static int soc_compr_get_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100574 struct snd_compr_caps *caps)
Namarta Kohli1245b702012-08-16 17:10:41 +0530575{
576 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000577 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900578 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530579
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300580 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000581
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900582 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900583 if (!component->driver->compress_ops ||
584 !component->driver->compress_ops->get_caps)
585 continue;
586
587 ret = component->driver->compress_ops->get_caps(
588 component, cstream, caps);
589 break;
590 }
591
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300592 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530593 return ret;
594}
595
596static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100597 struct snd_compr_codec_caps *codec)
Namarta Kohli1245b702012-08-16 17:10:41 +0530598{
599 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000600 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900601 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530602
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300603 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000604
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900605 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900606 if (!component->driver->compress_ops ||
607 !component->driver->compress_ops->get_codec_caps)
608 continue;
609
610 ret = component->driver->compress_ops->get_codec_caps(
611 component, cstream, codec);
612 break;
613 }
614
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300615 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530616 return ret;
617}
618
619static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
620{
621 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000622 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900623 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900624 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530625
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300626 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000627
Vinod Koul2e622ae2016-11-13 12:10:02 +0530628 if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
629 ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
630 if (ret < 0)
631 goto err;
632 }
633
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900634 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900635 if (!component->driver->compress_ops ||
636 !component->driver->compress_ops->ack)
637 continue;
638
639 ret = component->driver->compress_ops->ack(
640 component, cstream, bytes);
641 if (ret < 0)
642 goto err;
643 }
644
Vinod Koul2e622ae2016-11-13 12:10:02 +0530645err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300646 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530647 return ret;
648}
649
650static int soc_compr_pointer(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100651 struct snd_compr_tstamp *tstamp)
Namarta Kohli1245b702012-08-16 17:10:41 +0530652{
653 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000654 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900655 int i, ret = 0;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900656 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530657
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300658 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000659
Vinod Koul2e622ae2016-11-13 12:10:02 +0530660 if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
661 cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
662
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900663 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900664 if (!component->driver->compress_ops ||
665 !component->driver->compress_ops->pointer)
666 continue;
667
668 ret = component->driver->compress_ops->pointer(
669 component, cstream, tstamp);
670 break;
671 }
672
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300673 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax7c9190f2016-06-20 09:51:32 +0100674 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530675}
676
Charles Keepax1f88eb02013-02-05 10:41:47 +0000677static int soc_compr_copy(struct snd_compr_stream *cstream,
Charles Keepax4daf8912013-04-18 11:01:38 +0100678 char __user *buf, size_t count)
Charles Keepax1f88eb02013-02-05 10:41:47 +0000679{
680 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000681 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900682 int i, ret = 0;
Charles Keepax1f88eb02013-02-05 10:41:47 +0000683
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300684 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000685
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900686 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900687 if (!component->driver->compress_ops ||
688 !component->driver->compress_ops->copy)
689 continue;
690
691 ret = component->driver->compress_ops->copy(
692 component, cstream, buf, count);
693 break;
694 }
695
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300696 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000697 return ret;
698}
699
Vinod Koul02bd90e2013-07-28 20:06:15 +0530700static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100701 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530702{
703 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000704 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900705 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900706 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530707
Vinod Koul2e622ae2016-11-13 12:10:02 +0530708 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
709 ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
710 if (ret < 0)
711 return ret;
712 }
713
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900714 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900715 if (!component->driver->compress_ops ||
716 !component->driver->compress_ops->set_metadata)
717 continue;
718
719 ret = component->driver->compress_ops->set_metadata(
720 component, cstream, metadata);
721 if (ret < 0)
722 return ret;
723 }
724
Charles Keepax52cadf12019-02-05 11:18:12 +0000725 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530726}
727
Vinod Koul02bd90e2013-07-28 20:06:15 +0530728static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100729 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530730{
731 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000732 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900733 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900734 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530735
Vinod Koul2e622ae2016-11-13 12:10:02 +0530736 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
737 ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
738 if (ret < 0)
739 return ret;
740 }
741
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900742 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900743 if (!component->driver->compress_ops ||
744 !component->driver->compress_ops->get_metadata)
745 continue;
746
747 return component->driver->compress_ops->get_metadata(
748 component, cstream, metadata);
749 }
750
Charles Keepax52cadf12019-02-05 11:18:12 +0000751 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530752}
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000753
Namarta Kohli1245b702012-08-16 17:10:41 +0530754/* ASoC Compress operations */
755static struct snd_compr_ops soc_compr_ops = {
756 .open = soc_compr_open,
757 .free = soc_compr_free,
758 .set_params = soc_compr_set_params,
Vinod Koul02bd90e2013-07-28 20:06:15 +0530759 .set_metadata = soc_compr_set_metadata,
760 .get_metadata = soc_compr_get_metadata,
Namarta Kohli1245b702012-08-16 17:10:41 +0530761 .get_params = soc_compr_get_params,
762 .trigger = soc_compr_trigger,
763 .pointer = soc_compr_pointer,
764 .ack = soc_compr_ack,
765 .get_caps = soc_compr_get_caps,
766 .get_codec_caps = soc_compr_get_codec_caps
767};
768
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000769/* ASoC Dynamic Compress operations */
770static struct snd_compr_ops soc_compr_dyn_ops = {
771 .open = soc_compr_open_fe,
772 .free = soc_compr_free_fe,
773 .set_params = soc_compr_set_params_fe,
774 .get_params = soc_compr_get_params,
775 .set_metadata = soc_compr_set_metadata,
776 .get_metadata = soc_compr_get_metadata,
777 .trigger = soc_compr_trigger_fe,
778 .pointer = soc_compr_pointer,
779 .ack = soc_compr_ack,
780 .get_caps = soc_compr_get_caps,
781 .get_codec_caps = soc_compr_get_codec_caps
782};
783
Jie Yang6f0c4222015-10-13 23:41:00 +0800784/**
785 * snd_soc_new_compress - create a new compress.
786 *
787 * @rtd: The runtime for which we will create compress
788 * @num: the device index number (zero based - shared with normal PCMs)
789 *
790 * Return: 0 for success, else error.
791 */
792int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
Namarta Kohli1245b702012-08-16 17:10:41 +0530793{
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000794 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900795 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
796 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530797 struct snd_compr *compr;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000798 struct snd_pcm *be_pcm;
Namarta Kohli1245b702012-08-16 17:10:41 +0530799 char new_name[64];
800 int ret = 0, direction = 0;
Vinod Koula1068042016-01-07 21:48:14 +0530801 int playback = 0, capture = 0;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900802 int i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530803
Bard Liao6e1276a2020-02-25 21:39:16 +0800804 if (rtd->num_cpus > 1 ||
805 rtd->num_codecs > 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000806 dev_err(rtd->card->dev,
Bard Liao6e1276a2020-02-25 21:39:16 +0800807 "Compress ASoC: Multi CPU/Codec not supported\n");
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200808 return -EINVAL;
809 }
810
Namarta Kohli1245b702012-08-16 17:10:41 +0530811 /* check client and interface hw capabilities */
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900812 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
813 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
Vinod Koula1068042016-01-07 21:48:14 +0530814 playback = 1;
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900815 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
816 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
Vinod Koula1068042016-01-07 21:48:14 +0530817 capture = 1;
818
Vinod Koula1068042016-01-07 21:48:14 +0530819 /*
820 * Compress devices are unidirectional so only one of the directions
821 * should be set, check for that (xor)
822 */
823 if (playback + capture != 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000824 dev_err(rtd->card->dev,
825 "Compress ASoC: Invalid direction for P %d, C %d\n",
826 playback, capture);
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100827 return -EINVAL;
Vinod Koula1068042016-01-07 21:48:14 +0530828 }
829
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800830 if (playback)
Vinod Koula1068042016-01-07 21:48:14 +0530831 direction = SND_COMPRESS_PLAYBACK;
832 else
833 direction = SND_COMPRESS_CAPTURE;
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100834
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200835 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200836 if (!compr)
Namarta Kohli1245b702012-08-16 17:10:41 +0530837 return -ENOMEM;
Namarta Kohli1245b702012-08-16 17:10:41 +0530838
Charles Keepax1f88eb02013-02-05 10:41:47 +0000839 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
840 GFP_KERNEL);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200841 if (!compr->ops)
842 return -ENOMEM;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000843
844 if (rtd->dai_link->dynamic) {
845 snprintf(new_name, sizeof(new_name), "(%s)",
846 rtd->dai_link->stream_name);
847
848 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
Qais Yousefd3268a42015-01-14 08:47:29 +0000849 rtd->dai_link->dpcm_playback,
850 rtd->dai_link->dpcm_capture, &be_pcm);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000851 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000852 dev_err(rtd->card->dev,
853 "Compress ASoC: can't create compressed for %s: %d\n",
854 rtd->dai_link->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200855 return ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000856 }
857
858 rtd->pcm = be_pcm;
859 rtd->fe_compr = 1;
Qais Yousefd3268a42015-01-14 08:47:29 +0000860 if (rtd->dai_link->dpcm_playback)
861 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
862 else if (rtd->dai_link->dpcm_capture)
863 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000864 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800865 } else {
866 snprintf(new_name, sizeof(new_name), "%s %s-%d",
867 rtd->dai_link->stream_name, codec_dai->name, num);
868
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000869 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800870 }
Charles Keepax1f88eb02013-02-05 10:41:47 +0000871
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900872 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900873 if (!component->driver->compress_ops ||
874 !component->driver->compress_ops->copy)
875 continue;
876
877 compr->ops->copy = soc_compr_copy;
878 break;
879 }
880
Namarta Kohli1245b702012-08-16 17:10:41 +0530881 mutex_init(&compr->lock);
Richard Fitzgeralde5241a82015-11-25 13:00:24 +0000882 ret = snd_compress_new(rtd->card->snd_card, num, direction,
883 new_name, compr);
Namarta Kohli1245b702012-08-16 17:10:41 +0530884 if (ret < 0) {
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900885 component = asoc_rtd_to_codec(rtd, 0)->component;
Charles Keepax141dfc92018-01-26 13:08:45 +0000886 dev_err(component->dev,
887 "Compress ASoC: can't create compress for codec %s: %d\n",
888 component->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200889 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530890 }
891
Charles Keepax202c8f72013-01-24 09:44:30 +0000892 /* DAPM dai link stream work */
Kuninori Morimoto83f94a22020-01-10 11:36:17 +0900893 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
Charles Keepax202c8f72013-01-24 09:44:30 +0000894
Namarta Kohli1245b702012-08-16 17:10:41 +0530895 rtd->compr = compr;
896 compr->private_data = rtd;
897
Charles Keepax141dfc92018-01-26 13:08:45 +0000898 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
899 codec_dai->name, cpu_dai->name);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000900
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200901 return 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530902}
Jie Yang6f0c4222015-10-13 23:41:00 +0800903EXPORT_SYMBOL_GPL(snd_soc_new_compress);