blob: 48e39c35ef08b48e55f395320e3c13c452e7cd1f [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
Vinod Koul2e622ae2016-11-13 12:10:02 +0530621 if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
622 ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
623 if (ret < 0)
624 goto err;
625 }
626
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900627 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900628 if (!component->driver->compress_ops ||
629 !component->driver->compress_ops->ack)
630 continue;
631
632 ret = component->driver->compress_ops->ack(
633 component, cstream, bytes);
634 if (ret < 0)
635 goto err;
636 }
637
Vinod Koul2e622ae2016-11-13 12:10:02 +0530638err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300639 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530640 return ret;
641}
642
643static int soc_compr_pointer(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100644 struct snd_compr_tstamp *tstamp)
Namarta Kohli1245b702012-08-16 17:10:41 +0530645{
646 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000647 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900648 int i, ret = 0;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900649 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530650
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300651 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000652
Vinod Koul2e622ae2016-11-13 12:10:02 +0530653 if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
654 cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
655
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900656 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900657 if (!component->driver->compress_ops ||
658 !component->driver->compress_ops->pointer)
659 continue;
660
661 ret = component->driver->compress_ops->pointer(
662 component, cstream, tstamp);
663 break;
664 }
665
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300666 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax7c9190f2016-06-20 09:51:32 +0100667 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530668}
669
Charles Keepax1f88eb02013-02-05 10:41:47 +0000670static int soc_compr_copy(struct snd_compr_stream *cstream,
Charles Keepax4daf8912013-04-18 11:01:38 +0100671 char __user *buf, size_t count)
Charles Keepax1f88eb02013-02-05 10:41:47 +0000672{
673 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000674 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900675 int i, ret = 0;
Charles Keepax1f88eb02013-02-05 10:41:47 +0000676
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300677 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000678
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900679 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900680 if (!component->driver->compress_ops ||
681 !component->driver->compress_ops->copy)
682 continue;
683
684 ret = component->driver->compress_ops->copy(
685 component, cstream, buf, count);
686 break;
687 }
688
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300689 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000690 return ret;
691}
692
Vinod Koul02bd90e2013-07-28 20:06:15 +0530693static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100694 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530695{
696 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000697 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900698 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900699 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530700
Vinod Koul2e622ae2016-11-13 12:10:02 +0530701 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
702 ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
703 if (ret < 0)
704 return ret;
705 }
706
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900707 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900708 if (!component->driver->compress_ops ||
709 !component->driver->compress_ops->set_metadata)
710 continue;
711
712 ret = component->driver->compress_ops->set_metadata(
713 component, cstream, metadata);
714 if (ret < 0)
715 return ret;
716 }
717
Charles Keepax52cadf12019-02-05 11:18:12 +0000718 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530719}
720
Vinod Koul02bd90e2013-07-28 20:06:15 +0530721static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100722 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530723{
724 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000725 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900726 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900727 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530728
Vinod Koul2e622ae2016-11-13 12:10:02 +0530729 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
730 ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
731 if (ret < 0)
732 return ret;
733 }
734
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900735 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900736 if (!component->driver->compress_ops ||
737 !component->driver->compress_ops->get_metadata)
738 continue;
739
740 return component->driver->compress_ops->get_metadata(
741 component, cstream, metadata);
742 }
743
Charles Keepax52cadf12019-02-05 11:18:12 +0000744 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530745}
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000746
Namarta Kohli1245b702012-08-16 17:10:41 +0530747/* ASoC Compress operations */
748static struct snd_compr_ops soc_compr_ops = {
749 .open = soc_compr_open,
750 .free = soc_compr_free,
751 .set_params = soc_compr_set_params,
Vinod Koul02bd90e2013-07-28 20:06:15 +0530752 .set_metadata = soc_compr_set_metadata,
753 .get_metadata = soc_compr_get_metadata,
Namarta Kohli1245b702012-08-16 17:10:41 +0530754 .get_params = soc_compr_get_params,
755 .trigger = soc_compr_trigger,
756 .pointer = soc_compr_pointer,
757 .ack = soc_compr_ack,
758 .get_caps = soc_compr_get_caps,
759 .get_codec_caps = soc_compr_get_codec_caps
760};
761
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000762/* ASoC Dynamic Compress operations */
763static struct snd_compr_ops soc_compr_dyn_ops = {
764 .open = soc_compr_open_fe,
765 .free = soc_compr_free_fe,
766 .set_params = soc_compr_set_params_fe,
767 .get_params = soc_compr_get_params,
768 .set_metadata = soc_compr_set_metadata,
769 .get_metadata = soc_compr_get_metadata,
770 .trigger = soc_compr_trigger_fe,
771 .pointer = soc_compr_pointer,
772 .ack = soc_compr_ack,
773 .get_caps = soc_compr_get_caps,
774 .get_codec_caps = soc_compr_get_codec_caps
775};
776
Jie Yang6f0c4222015-10-13 23:41:00 +0800777/**
778 * snd_soc_new_compress - create a new compress.
779 *
780 * @rtd: The runtime for which we will create compress
781 * @num: the device index number (zero based - shared with normal PCMs)
782 *
783 * Return: 0 for success, else error.
784 */
785int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
Namarta Kohli1245b702012-08-16 17:10:41 +0530786{
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000787 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900788 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
789 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530790 struct snd_compr *compr;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000791 struct snd_pcm *be_pcm;
Namarta Kohli1245b702012-08-16 17:10:41 +0530792 char new_name[64];
793 int ret = 0, direction = 0;
Vinod Koula1068042016-01-07 21:48:14 +0530794 int playback = 0, capture = 0;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900795 int i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530796
Bard Liao6e1276a2020-02-25 21:39:16 +0800797 if (rtd->num_cpus > 1 ||
798 rtd->num_codecs > 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000799 dev_err(rtd->card->dev,
Bard Liao6e1276a2020-02-25 21:39:16 +0800800 "Compress ASoC: Multi CPU/Codec not supported\n");
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200801 return -EINVAL;
802 }
803
Namarta Kohli1245b702012-08-16 17:10:41 +0530804 /* check client and interface hw capabilities */
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900805 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
806 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
Vinod Koula1068042016-01-07 21:48:14 +0530807 playback = 1;
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900808 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
809 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
Vinod Koula1068042016-01-07 21:48:14 +0530810 capture = 1;
811
Vinod Koula1068042016-01-07 21:48:14 +0530812 /*
813 * Compress devices are unidirectional so only one of the directions
814 * should be set, check for that (xor)
815 */
816 if (playback + capture != 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000817 dev_err(rtd->card->dev,
818 "Compress ASoC: Invalid direction for P %d, C %d\n",
819 playback, capture);
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100820 return -EINVAL;
Vinod Koula1068042016-01-07 21:48:14 +0530821 }
822
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800823 if (playback)
Vinod Koula1068042016-01-07 21:48:14 +0530824 direction = SND_COMPRESS_PLAYBACK;
825 else
826 direction = SND_COMPRESS_CAPTURE;
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100827
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200828 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200829 if (!compr)
Namarta Kohli1245b702012-08-16 17:10:41 +0530830 return -ENOMEM;
Namarta Kohli1245b702012-08-16 17:10:41 +0530831
Charles Keepax1f88eb02013-02-05 10:41:47 +0000832 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
833 GFP_KERNEL);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200834 if (!compr->ops)
835 return -ENOMEM;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000836
837 if (rtd->dai_link->dynamic) {
838 snprintf(new_name, sizeof(new_name), "(%s)",
839 rtd->dai_link->stream_name);
840
841 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
Qais Yousefd3268a42015-01-14 08:47:29 +0000842 rtd->dai_link->dpcm_playback,
843 rtd->dai_link->dpcm_capture, &be_pcm);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000844 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000845 dev_err(rtd->card->dev,
846 "Compress ASoC: can't create compressed for %s: %d\n",
847 rtd->dai_link->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200848 return ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000849 }
850
851 rtd->pcm = be_pcm;
852 rtd->fe_compr = 1;
Qais Yousefd3268a42015-01-14 08:47:29 +0000853 if (rtd->dai_link->dpcm_playback)
854 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
855 else if (rtd->dai_link->dpcm_capture)
856 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000857 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800858 } else {
859 snprintf(new_name, sizeof(new_name), "%s %s-%d",
860 rtd->dai_link->stream_name, codec_dai->name, num);
861
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000862 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800863 }
Charles Keepax1f88eb02013-02-05 10:41:47 +0000864
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900865 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900866 if (!component->driver->compress_ops ||
867 !component->driver->compress_ops->copy)
868 continue;
869
870 compr->ops->copy = soc_compr_copy;
871 break;
872 }
873
Namarta Kohli1245b702012-08-16 17:10:41 +0530874 mutex_init(&compr->lock);
Richard Fitzgeralde5241a82015-11-25 13:00:24 +0000875 ret = snd_compress_new(rtd->card->snd_card, num, direction,
876 new_name, compr);
Namarta Kohli1245b702012-08-16 17:10:41 +0530877 if (ret < 0) {
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900878 component = asoc_rtd_to_codec(rtd, 0)->component;
Charles Keepax141dfc92018-01-26 13:08:45 +0000879 dev_err(component->dev,
880 "Compress ASoC: can't create compress for codec %s: %d\n",
881 component->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200882 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530883 }
884
Charles Keepax202c8f72013-01-24 09:44:30 +0000885 /* DAPM dai link stream work */
Kuninori Morimoto83f94a22020-01-10 11:36:17 +0900886 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
Charles Keepax202c8f72013-01-24 09:44:30 +0000887
Namarta Kohli1245b702012-08-16 17:10:41 +0530888 rtd->compr = compr;
889 compr->private_data = rtd;
890
Charles Keepax141dfc92018-01-26 13:08:45 +0000891 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
892 codec_dai->name, cpu_dai->name);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000893
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200894 return 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530895}
Jie Yang6f0c4222015-10-13 23:41:00 +0800896EXPORT_SYMBOL_GPL(snd_soc_new_compress);