blob: d85bd1d1c11984037212448e5d5660ee413f77e7 [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>
Kuninori Morimoto9ab711c2020-05-25 09:57:41 +090022#include <sound/soc-link.h>
Cezary Rojewski4137f4b2019-12-17 10:58:50 +010023#include <linux/pm_runtime.h>
Namarta Kohli1245b702012-08-16 17:10:41 +053024
Charles Keepax1e57b822018-04-24 16:39:03 +010025static int soc_compr_open(struct snd_compr_stream *cstream)
26{
27 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto939a5cf2020-09-28 09:01:17 +090028 struct snd_soc_component *component = NULL;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +090029 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +090030 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
Kuninori Morimoto939a5cf2020-09-28 09:01:17 +090031 int ret;
Namarta Kohli1245b702012-08-16 17:10:41 +053032
Kuninori Morimoto939a5cf2020-09-28 09:01:17 +090033 ret = snd_soc_pcm_component_pm_runtime_get(rtd, cstream);
34 if (ret < 0)
35 goto pm_err;
Cezary Rojewski4137f4b2019-12-17 10:58:50 +010036
Peter Ujfalusi72b745e2019-08-13 13:45:32 +030037 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +000038
Kuninori Morimotob5ae4cc2020-04-24 08:15:24 +090039 ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
40 if (ret < 0)
41 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +053042
Kuninori Morimotoa4e427c2020-11-13 13:15:20 +090043 ret = snd_soc_component_compr_open(cstream, &component);
Charles Keepax1e57b822018-04-24 16:39:03 +010044 if (ret < 0)
45 goto machine_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000046
Kuninori Morimoto9ab711c2020-05-25 09:57:41 +090047 ret = snd_soc_link_compr_startup(cstream);
48 if (ret < 0)
49 goto machine_err;
Namarta Kohli1245b702012-08-16 17:10:41 +053050
Kuninori Morimotoeb849592020-10-30 10:01:15 +090051 snd_soc_runtime_activate(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +053052
Peter Ujfalusi72b745e2019-08-13 13:45:32 +030053 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax15e2e612013-01-24 09:44:29 +000054
Namarta Kohli1245b702012-08-16 17:10:41 +053055 return 0;
56
57machine_err:
Kuninori Morimotodbde5e212020-11-13 13:15:26 +090058 snd_soc_component_compr_free(cstream, component);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000059
Kuninori Morimoto2b25f812020-04-24 08:15:28 +090060 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Namarta Kohli1245b702012-08-16 17:10:41 +053061out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +030062 mutex_unlock(&rtd->card->pcm_mutex);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +010063pm_err:
Kuninori Morimoto939a5cf2020-09-28 09:01:17 +090064 snd_soc_pcm_component_pm_runtime_put(rtd, cstream, 1);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +010065
Namarta Kohli1245b702012-08-16 17:10:41 +053066 return ret;
67}
68
Liam Girdwood2a99ef02014-01-17 17:03:56 +000069static int soc_compr_open_fe(struct snd_compr_stream *cstream)
70{
71 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -070072 struct snd_pcm_substream *fe_substream =
73 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000074 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +090075 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Liam Girdwood2a99ef02014-01-17 17:03:56 +000076 struct snd_soc_dpcm *dpcm;
77 struct snd_soc_dapm_widget_list *list;
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +090078 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
Charles Keepax572e6c82018-04-24 16:39:01 +010079 int ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +000080
Liam Girdwood2a99ef02014-01-17 17:03:56 +000081 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +010082 fe->dpcm[stream].runtime = fe_substream->runtime;
83
84 ret = dpcm_path_get(fe, stream, &list);
85 if (ret < 0)
86 goto be_err;
87 else if (ret == 0)
88 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
89 fe->dai_link->name, stream ? "capture" : "playback");
90 /* calculate valid and active FE <-> BE dpcms */
91 dpcm_process_paths(fe, stream, &list, 1);
92 fe->dpcm[stream].runtime = fe_substream->runtime;
93
94 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
95
96 ret = dpcm_be_dai_startup(fe, stream);
97 if (ret < 0) {
98 /* clean up all links */
Kuninori Morimoto8d6258a2018-09-18 01:31:09 +000099 for_each_dpcm_be(fe, stream, dpcm)
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100100 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
101
102 dpcm_be_disconnect(fe, stream);
103 fe->dpcm[stream].runtime = NULL;
104 goto out;
105 }
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000106
Kuninori Morimotob5ae4cc2020-04-24 08:15:24 +0900107 ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
108 if (ret < 0)
109 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530110
Kuninori Morimotoa4e427c2020-11-13 13:15:20 +0900111 ret = snd_soc_component_compr_open(cstream, &component);
Charles Keepax1e57b822018-04-24 16:39:03 +0100112 if (ret < 0)
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100113 goto open_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000114
Kuninori Morimoto9ab711c2020-05-25 09:57:41 +0900115 ret = snd_soc_link_compr_startup(cstream);
116 if (ret < 0)
117 goto machine_err;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000118
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000119 dpcm_clear_pending_state(fe, stream);
120 dpcm_path_put(&list);
121
122 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
123 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
124
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100125 snd_soc_runtime_activate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000126
127 mutex_unlock(&fe->card->mutex);
128
129 return 0;
130
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000131machine_err:
Kuninori Morimotodbde5e212020-11-13 13:15:26 +0900132 snd_soc_component_compr_free(cstream, component);
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100133open_err:
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900134 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000135out:
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100136 dpcm_path_put(&list);
137be_err:
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000138 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
139 mutex_unlock(&fe->card->mutex);
140 return ret;
141}
142
Namarta Kohli1245b702012-08-16 17:10:41 +0530143static int soc_compr_free(struct snd_compr_stream *cstream)
144{
145 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900146 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
147 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900148 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
Namarta Kohli1245b702012-08-16 17:10:41 +0530149
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300150 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000151
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100152 snd_soc_runtime_deactivate(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530153
Kuninori Morimotoeb849592020-10-30 10:01:15 +0900154 snd_soc_dai_digital_mute(codec_dai, 1, stream);
Mark Brownda183962013-02-06 15:44:07 +0000155
Kuninori Morimotob3dea622020-05-15 09:46:51 +0900156 if (!snd_soc_dai_active(cpu_dai))
Namarta Kohli1245b702012-08-16 17:10:41 +0530157 cpu_dai->rate = 0;
158
Kuninori Morimotob3dea622020-05-15 09:46:51 +0900159 if (!snd_soc_dai_active(codec_dai))
Namarta Kohli1245b702012-08-16 17:10:41 +0530160 codec_dai->rate = 0;
161
Kuninori Morimoto0e532c92020-05-25 09:57:45 +0900162 snd_soc_link_compr_shutdown(cstream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530163
Kuninori Morimotodbde5e212020-11-13 13:15:26 +0900164 snd_soc_component_compr_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000165
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900166 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Vinod Koul2e622ae2016-11-13 12:10:02 +0530167
Kuninori Morimoto3f4cf792020-01-10 11:36:23 +0900168 snd_soc_dapm_stream_stop(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530169
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300170 mutex_unlock(&rtd->card->pcm_mutex);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100171
Kuninori Morimoto939a5cf2020-09-28 09:01:17 +0900172 snd_soc_pcm_component_pm_runtime_put(rtd, cstream, 0);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100173
Namarta Kohli1245b702012-08-16 17:10:41 +0530174 return 0;
175}
176
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000177static int soc_compr_free_fe(struct snd_compr_stream *cstream)
178{
179 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900180 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000181 struct snd_soc_dpcm *dpcm;
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900182 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
183 int ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000184
185 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
186
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100187 snd_soc_runtime_deactivate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000188
189 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
190
191 ret = dpcm_be_dai_hw_free(fe, stream);
192 if (ret < 0)
Charles Keepax141dfc92018-01-26 13:08:45 +0000193 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000194
195 ret = dpcm_be_dai_shutdown(fe, stream);
196
197 /* mark FE's links ready to prune */
Kuninori Morimoto8d6258a2018-09-18 01:31:09 +0000198 for_each_dpcm_be(fe, stream, dpcm)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000199 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
200
Kuninori Morimoto1c531232020-02-21 10:25:18 +0900201 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000202
203 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
204 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
205
206 dpcm_be_disconnect(fe, stream);
207
208 fe->dpcm[stream].runtime = NULL;
209
Kuninori Morimoto0e532c92020-05-25 09:57:45 +0900210 snd_soc_link_compr_shutdown(cstream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000211
Kuninori Morimotodbde5e212020-11-13 13:15:26 +0900212 snd_soc_component_compr_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000213
Kuninori Morimoto2b25f812020-04-24 08:15:28 +0900214 snd_soc_dai_compr_shutdown(cpu_dai, cstream);
Vinod Koul2e622ae2016-11-13 12:10:02 +0530215
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000216 mutex_unlock(&fe->card->mutex);
217 return 0;
218}
219
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000220static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
221{
222 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900223 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
224 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900225 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000226 int ret;
227
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300228 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000229
Kuninori Morimoto08aee252020-11-13 13:15:33 +0900230 ret = snd_soc_component_compr_trigger(cstream, cmd);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000231 if (ret < 0)
232 goto out;
233
Kuninori Morimotoeb084112020-04-24 08:15:32 +0900234 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
235 if (ret < 0)
236 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530237
Mark Brownda183962013-02-06 15:44:07 +0000238 switch (cmd) {
239 case SNDRV_PCM_TRIGGER_START:
Kuninori Morimotoeb849592020-10-30 10:01:15 +0900240 snd_soc_dai_digital_mute(codec_dai, 0, stream);
Mark Brownda183962013-02-06 15:44:07 +0000241 break;
242 case SNDRV_PCM_TRIGGER_STOP:
Kuninori Morimotoeb849592020-10-30 10:01:15 +0900243 snd_soc_dai_digital_mute(codec_dai, 1, stream);
Mark Brownda183962013-02-06 15:44:07 +0000244 break;
Mark Browne38b9b72013-02-06 13:52:42 +0000245 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530246
Charles Keepax15e2e612013-01-24 09:44:29 +0000247out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300248 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530249 return ret;
250}
251
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000252static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
253{
254 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900255 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900256 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
257 int ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000258
259 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000260 cmd == SND_COMPR_TRIGGER_DRAIN)
Kuninori Morimoto08aee252020-11-13 13:15:33 +0900261 return snd_soc_component_compr_trigger(cstream, cmd);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000262
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000263 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
264
Kuninori Morimotoeb084112020-04-24 08:15:32 +0900265 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
266 if (ret < 0)
267 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530268
Kuninori Morimoto08aee252020-11-13 13:15:33 +0900269 ret = snd_soc_component_compr_trigger(cstream, cmd);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000270 if (ret < 0)
271 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000272
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000273 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
274
275 ret = dpcm_be_dai_trigger(fe, stream, cmd);
276
277 switch (cmd) {
278 case SNDRV_PCM_TRIGGER_START:
279 case SNDRV_PCM_TRIGGER_RESUME:
280 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
281 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
282 break;
283 case SNDRV_PCM_TRIGGER_STOP:
284 case SNDRV_PCM_TRIGGER_SUSPEND:
285 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
286 break;
287 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
288 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
289 break;
290 }
291
292out:
293 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
294 mutex_unlock(&fe->card->mutex);
295 return ret;
296}
297
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000298static int soc_compr_components_set_params(struct snd_compr_stream *cstream,
299 struct snd_compr_params *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530300{
301 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000302 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900303 int i, ret;
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000304
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900305 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900306 if (!component->driver->compress_ops ||
307 !component->driver->compress_ops->set_params)
308 continue;
309
310 ret = component->driver->compress_ops->set_params(
311 component, cstream, params);
312 if (ret < 0)
313 return ret;
314 }
315
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000316 return 0;
317}
318
319static int soc_compr_set_params(struct snd_compr_stream *cstream,
320 struct snd_compr_params *params)
321{
322 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900323 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900324 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
Charles Keepax52cadf12019-02-05 11:18:12 +0000325 int ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530326
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300327 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000328
Charles Keepaxef050be2018-04-24 16:39:02 +0100329 /*
330 * First we call set_params for the CPU DAI, then the component
331 * driver this should configure the SoC side. If the machine has
332 * compressed ops then we call that as well. The expectation is
333 * that these callbacks will configure everything for this compress
334 * path, like configuring a PCM port for a CODEC.
Namarta Kohli1245b702012-08-16 17:10:41 +0530335 */
Kuninori Morimoto8dfedaf2020-04-24 08:15:36 +0900336 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
337 if (ret < 0)
338 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530339
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000340 ret = soc_compr_components_set_params(cstream, params);
341 if (ret < 0)
342 goto err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000343
Kuninori Morimotoeab810f2020-05-25 09:57:50 +0900344 ret = snd_soc_link_compr_set_params(cstream);
345 if (ret < 0)
346 goto err;
Namarta Kohli1245b702012-08-16 17:10:41 +0530347
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900348 snd_soc_dapm_stream_event(rtd, stream, SND_SOC_DAPM_STREAM_START);
Namarta Kohli1245b702012-08-16 17:10:41 +0530349
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000350 /* cancel any delayed stream shutdown that is pending */
351 rtd->pop_wait = 0;
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300352 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000353
354 cancel_delayed_work_sync(&rtd->delayed_work);
355
Charles Keepax52cadf12019-02-05 11:18:12 +0000356 return 0;
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000357
358err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300359 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530360 return ret;
361}
362
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000363static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100364 struct snd_compr_params *params)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000365{
366 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700367 struct snd_pcm_substream *fe_substream =
368 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900369 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900370 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
371 int ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000372
373 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
374
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100375 /*
376 * Create an empty hw_params for the BE as the machine driver must
377 * fix this up to match DSP decoder and ASRC configuration.
378 * I.e. machine driver fixup for compressed BE is mandatory.
379 */
380 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
381 sizeof(struct snd_pcm_hw_params));
382
383 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
384
385 ret = dpcm_be_dai_hw_params(fe, stream);
386 if (ret < 0)
387 goto out;
388
389 ret = dpcm_be_dai_prepare(fe, stream);
390 if (ret < 0)
391 goto out;
392
Kuninori Morimoto8dfedaf2020-04-24 08:15:36 +0900393 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
394 if (ret < 0)
395 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530396
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000397 ret = soc_compr_components_set_params(cstream, params);
398 if (ret < 0)
399 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000400
Kuninori Morimotoeab810f2020-05-25 09:57:50 +0900401 ret = snd_soc_link_compr_set_params(cstream);
402 if (ret < 0)
403 goto out;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000404
Daniel Mack15f6b092014-10-19 09:07:35 +0200405 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000406 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
407
408out:
409 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
410 mutex_unlock(&fe->card->mutex);
411 return ret;
412}
413
Namarta Kohli1245b702012-08-16 17:10:41 +0530414static int soc_compr_get_params(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100415 struct snd_codec *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530416{
417 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000418 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900419 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900420 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530421
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300422 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000423
Kuninori Morimotoadbef5432020-04-24 08:15:40 +0900424 ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params);
425 if (ret < 0)
426 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530427
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900428 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900429 if (!component->driver->compress_ops ||
430 !component->driver->compress_ops->get_params)
431 continue;
432
433 ret = component->driver->compress_ops->get_params(
434 component, cstream, params);
435 break;
436 }
437
Vinod Koul2e622ae2016-11-13 12:10:02 +0530438err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300439 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530440 return ret;
441}
442
443static int soc_compr_get_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100444 struct snd_compr_caps *caps)
Namarta Kohli1245b702012-08-16 17:10:41 +0530445{
446 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000447 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900448 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530449
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300450 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000451
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900452 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900453 if (!component->driver->compress_ops ||
454 !component->driver->compress_ops->get_caps)
455 continue;
456
457 ret = component->driver->compress_ops->get_caps(
458 component, cstream, caps);
459 break;
460 }
461
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300462 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530463 return ret;
464}
465
466static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100467 struct snd_compr_codec_caps *codec)
Namarta Kohli1245b702012-08-16 17:10:41 +0530468{
469 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000470 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900471 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530472
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300473 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000474
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900475 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900476 if (!component->driver->compress_ops ||
477 !component->driver->compress_ops->get_codec_caps)
478 continue;
479
480 ret = component->driver->compress_ops->get_codec_caps(
481 component, cstream, codec);
482 break;
483 }
484
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300485 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530486 return ret;
487}
488
489static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
490{
491 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000492 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900493 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900494 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530495
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300496 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000497
Kuninori Morimoto53294352020-04-24 08:15:45 +0900498 ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes);
499 if (ret < 0)
500 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530501
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900502 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900503 if (!component->driver->compress_ops ||
504 !component->driver->compress_ops->ack)
505 continue;
506
507 ret = component->driver->compress_ops->ack(
508 component, cstream, bytes);
509 if (ret < 0)
510 goto err;
511 }
512
Vinod Koul2e622ae2016-11-13 12:10:02 +0530513err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300514 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530515 return ret;
516}
517
518static int soc_compr_pointer(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100519 struct snd_compr_tstamp *tstamp)
Namarta Kohli1245b702012-08-16 17:10:41 +0530520{
521 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000522 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900523 int i, ret = 0;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900524 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530525
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300526 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000527
Kuninori Morimotoed38cc52020-04-24 08:15:49 +0900528 ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp);
529 if (ret < 0)
530 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530531
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900532 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900533 if (!component->driver->compress_ops ||
534 !component->driver->compress_ops->pointer)
535 continue;
536
537 ret = component->driver->compress_ops->pointer(
538 component, cstream, tstamp);
539 break;
540 }
Kuninori Morimotoed38cc52020-04-24 08:15:49 +0900541out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300542 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax7c9190f2016-06-20 09:51:32 +0100543 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530544}
545
Charles Keepax1f88eb02013-02-05 10:41:47 +0000546static int soc_compr_copy(struct snd_compr_stream *cstream,
Charles Keepax4daf8912013-04-18 11:01:38 +0100547 char __user *buf, size_t count)
Charles Keepax1f88eb02013-02-05 10:41:47 +0000548{
549 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000550 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900551 int i, ret = 0;
Charles Keepax1f88eb02013-02-05 10:41:47 +0000552
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300553 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000554
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900555 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900556 if (!component->driver->compress_ops ||
557 !component->driver->compress_ops->copy)
558 continue;
559
560 ret = component->driver->compress_ops->copy(
561 component, cstream, buf, count);
562 break;
563 }
564
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300565 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000566 return ret;
567}
568
Vinod Koul02bd90e2013-07-28 20:06:15 +0530569static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100570 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530571{
572 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000573 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900574 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900575 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530576
Kuninori Morimoto88b3a7d2020-04-24 08:15:54 +0900577 ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata);
578 if (ret < 0)
579 return ret;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530580
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->set_metadata)
584 continue;
585
586 ret = component->driver->compress_ops->set_metadata(
587 component, cstream, metadata);
588 if (ret < 0)
589 return ret;
590 }
591
Charles Keepax52cadf12019-02-05 11:18:12 +0000592 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530593}
594
Vinod Koul02bd90e2013-07-28 20:06:15 +0530595static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100596 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +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 Morimotoc2233a22020-03-30 10:47:37 +0900600 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900601 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530602
Kuninori Morimoto94d72812020-04-24 08:15:59 +0900603 ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata);
604 if (ret < 0)
605 return ret;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530606
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900607 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900608 if (!component->driver->compress_ops ||
609 !component->driver->compress_ops->get_metadata)
610 continue;
611
612 return component->driver->compress_ops->get_metadata(
613 component, cstream, metadata);
614 }
615
Charles Keepax52cadf12019-02-05 11:18:12 +0000616 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530617}
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000618
Namarta Kohli1245b702012-08-16 17:10:41 +0530619/* ASoC Compress operations */
620static struct snd_compr_ops soc_compr_ops = {
621 .open = soc_compr_open,
622 .free = soc_compr_free,
623 .set_params = soc_compr_set_params,
Vinod Koul02bd90e2013-07-28 20:06:15 +0530624 .set_metadata = soc_compr_set_metadata,
625 .get_metadata = soc_compr_get_metadata,
Namarta Kohli1245b702012-08-16 17:10:41 +0530626 .get_params = soc_compr_get_params,
627 .trigger = soc_compr_trigger,
628 .pointer = soc_compr_pointer,
629 .ack = soc_compr_ack,
630 .get_caps = soc_compr_get_caps,
631 .get_codec_caps = soc_compr_get_codec_caps
632};
633
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000634/* ASoC Dynamic Compress operations */
635static struct snd_compr_ops soc_compr_dyn_ops = {
636 .open = soc_compr_open_fe,
637 .free = soc_compr_free_fe,
638 .set_params = soc_compr_set_params_fe,
639 .get_params = soc_compr_get_params,
640 .set_metadata = soc_compr_set_metadata,
641 .get_metadata = soc_compr_get_metadata,
642 .trigger = soc_compr_trigger_fe,
643 .pointer = soc_compr_pointer,
644 .ack = soc_compr_ack,
645 .get_caps = soc_compr_get_caps,
646 .get_codec_caps = soc_compr_get_codec_caps
647};
648
Jie Yang6f0c4222015-10-13 23:41:00 +0800649/**
650 * snd_soc_new_compress - create a new compress.
651 *
652 * @rtd: The runtime for which we will create compress
653 * @num: the device index number (zero based - shared with normal PCMs)
654 *
655 * Return: 0 for success, else error.
656 */
657int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
Namarta Kohli1245b702012-08-16 17:10:41 +0530658{
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000659 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900660 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
661 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530662 struct snd_compr *compr;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000663 struct snd_pcm *be_pcm;
Namarta Kohli1245b702012-08-16 17:10:41 +0530664 char new_name[64];
665 int ret = 0, direction = 0;
Vinod Koula1068042016-01-07 21:48:14 +0530666 int playback = 0, capture = 0;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900667 int i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530668
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900669 /*
670 * make sure these are same value,
671 * and then use these as equally
672 */
673 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK);
674 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE != (int)SND_COMPRESS_CAPTURE);
675
Bard Liao6e1276a2020-02-25 21:39:16 +0800676 if (rtd->num_cpus > 1 ||
677 rtd->num_codecs > 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000678 dev_err(rtd->card->dev,
Bard Liao6e1276a2020-02-25 21:39:16 +0800679 "Compress ASoC: Multi CPU/Codec not supported\n");
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200680 return -EINVAL;
681 }
682
Namarta Kohli1245b702012-08-16 17:10:41 +0530683 /* check client and interface hw capabilities */
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900684 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
685 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
Vinod Koula1068042016-01-07 21:48:14 +0530686 playback = 1;
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900687 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
688 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
Vinod Koula1068042016-01-07 21:48:14 +0530689 capture = 1;
690
Vinod Koula1068042016-01-07 21:48:14 +0530691 /*
692 * Compress devices are unidirectional so only one of the directions
693 * should be set, check for that (xor)
694 */
695 if (playback + capture != 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000696 dev_err(rtd->card->dev,
697 "Compress ASoC: Invalid direction for P %d, C %d\n",
698 playback, capture);
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100699 return -EINVAL;
Vinod Koula1068042016-01-07 21:48:14 +0530700 }
701
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800702 if (playback)
Vinod Koula1068042016-01-07 21:48:14 +0530703 direction = SND_COMPRESS_PLAYBACK;
704 else
705 direction = SND_COMPRESS_CAPTURE;
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100706
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200707 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200708 if (!compr)
Namarta Kohli1245b702012-08-16 17:10:41 +0530709 return -ENOMEM;
Namarta Kohli1245b702012-08-16 17:10:41 +0530710
Charles Keepax1f88eb02013-02-05 10:41:47 +0000711 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
712 GFP_KERNEL);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200713 if (!compr->ops)
714 return -ENOMEM;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000715
716 if (rtd->dai_link->dynamic) {
717 snprintf(new_name, sizeof(new_name), "(%s)",
718 rtd->dai_link->stream_name);
719
720 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
Qais Yousefd3268a42015-01-14 08:47:29 +0000721 rtd->dai_link->dpcm_playback,
722 rtd->dai_link->dpcm_capture, &be_pcm);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000723 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000724 dev_err(rtd->card->dev,
725 "Compress ASoC: can't create compressed for %s: %d\n",
726 rtd->dai_link->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200727 return ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000728 }
729
730 rtd->pcm = be_pcm;
731 rtd->fe_compr = 1;
Qais Yousefd3268a42015-01-14 08:47:29 +0000732 if (rtd->dai_link->dpcm_playback)
733 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
734 else if (rtd->dai_link->dpcm_capture)
735 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000736 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800737 } else {
738 snprintf(new_name, sizeof(new_name), "%s %s-%d",
739 rtd->dai_link->stream_name, codec_dai->name, num);
740
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000741 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800742 }
Charles Keepax1f88eb02013-02-05 10:41:47 +0000743
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900744 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900745 if (!component->driver->compress_ops ||
746 !component->driver->compress_ops->copy)
747 continue;
748
749 compr->ops->copy = soc_compr_copy;
750 break;
751 }
752
Namarta Kohli1245b702012-08-16 17:10:41 +0530753 mutex_init(&compr->lock);
Richard Fitzgeralde5241a82015-11-25 13:00:24 +0000754 ret = snd_compress_new(rtd->card->snd_card, num, direction,
755 new_name, compr);
Namarta Kohli1245b702012-08-16 17:10:41 +0530756 if (ret < 0) {
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900757 component = asoc_rtd_to_codec(rtd, 0)->component;
Charles Keepax141dfc92018-01-26 13:08:45 +0000758 dev_err(component->dev,
759 "Compress ASoC: can't create compress for codec %s: %d\n",
760 component->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200761 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530762 }
763
Charles Keepax202c8f72013-01-24 09:44:30 +0000764 /* DAPM dai link stream work */
Kuninori Morimoto83f94a22020-01-10 11:36:17 +0900765 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
Charles Keepax202c8f72013-01-24 09:44:30 +0000766
Namarta Kohli1245b702012-08-16 17:10:41 +0530767 rtd->compr = compr;
768 compr->private_data = rtd;
769
Pierre-Louis Bossart1d5cd522020-06-12 15:40:50 -0500770 dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
771 codec_dai->name, cpu_dai->name);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000772
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200773 return 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530774}
Jie Yang6f0c4222015-10-13 23:41:00 +0800775EXPORT_SYMBOL_GPL(snd_soc_new_compress);