blob: 4517baf0e62c78027557825b5ed3e84f66b4a2ee [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_components_trigger(struct snd_compr_stream *cstream,
221 int cmd)
Namarta Kohli1245b702012-08-16 17:10:41 +0530222{
Namarta Kohli1245b702012-08-16 17:10:41 +0530223 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000224 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900225 int i, ret;
Charles Keepax15e2e612013-01-24 09:44:29 +0000226
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900227 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900228 if (!component->driver->compress_ops ||
229 !component->driver->compress_ops->trigger)
230 continue;
231
232 ret = component->driver->compress_ops->trigger(
233 component, cstream, cmd);
234 if (ret < 0)
235 return ret;
236 }
237
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000238 return 0;
239}
240
241static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
242{
243 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900244 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
245 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900246 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000247 int ret;
248
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300249 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000250
251 ret = soc_compr_components_trigger(cstream, cmd);
252 if (ret < 0)
253 goto out;
254
Kuninori Morimotoeb084112020-04-24 08:15:32 +0900255 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
256 if (ret < 0)
257 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530258
Mark Brownda183962013-02-06 15:44:07 +0000259 switch (cmd) {
260 case SNDRV_PCM_TRIGGER_START:
Kuninori Morimotoeb849592020-10-30 10:01:15 +0900261 snd_soc_dai_digital_mute(codec_dai, 0, stream);
Mark Brownda183962013-02-06 15:44:07 +0000262 break;
263 case SNDRV_PCM_TRIGGER_STOP:
Kuninori Morimotoeb849592020-10-30 10:01:15 +0900264 snd_soc_dai_digital_mute(codec_dai, 1, stream);
Mark Brownda183962013-02-06 15:44:07 +0000265 break;
Mark Browne38b9b72013-02-06 13:52:42 +0000266 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530267
Charles Keepax15e2e612013-01-24 09:44:29 +0000268out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300269 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530270 return ret;
271}
272
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000273static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
274{
275 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900276 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900277 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
278 int ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000279
280 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000281 cmd == SND_COMPR_TRIGGER_DRAIN)
282 return soc_compr_components_trigger(cstream, cmd);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000283
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000284 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
285
Kuninori Morimotoeb084112020-04-24 08:15:32 +0900286 ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
287 if (ret < 0)
288 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530289
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000290 ret = soc_compr_components_trigger(cstream, cmd);
291 if (ret < 0)
292 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000293
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000294 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
295
296 ret = dpcm_be_dai_trigger(fe, stream, cmd);
297
298 switch (cmd) {
299 case SNDRV_PCM_TRIGGER_START:
300 case SNDRV_PCM_TRIGGER_RESUME:
301 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
302 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
303 break;
304 case SNDRV_PCM_TRIGGER_STOP:
305 case SNDRV_PCM_TRIGGER_SUSPEND:
306 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
307 break;
308 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
309 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
310 break;
311 }
312
313out:
314 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
315 mutex_unlock(&fe->card->mutex);
316 return ret;
317}
318
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000319static int soc_compr_components_set_params(struct snd_compr_stream *cstream,
320 struct snd_compr_params *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530321{
322 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000323 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900324 int i, ret;
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000325
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900326 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900327 if (!component->driver->compress_ops ||
328 !component->driver->compress_ops->set_params)
329 continue;
330
331 ret = component->driver->compress_ops->set_params(
332 component, cstream, params);
333 if (ret < 0)
334 return ret;
335 }
336
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000337 return 0;
338}
339
340static int soc_compr_set_params(struct snd_compr_stream *cstream,
341 struct snd_compr_params *params)
342{
343 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900344 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900345 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
Charles Keepax52cadf12019-02-05 11:18:12 +0000346 int ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530347
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300348 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000349
Charles Keepaxef050be2018-04-24 16:39:02 +0100350 /*
351 * First we call set_params for the CPU DAI, then the component
352 * driver this should configure the SoC side. If the machine has
353 * compressed ops then we call that as well. The expectation is
354 * that these callbacks will configure everything for this compress
355 * path, like configuring a PCM port for a CODEC.
Namarta Kohli1245b702012-08-16 17:10:41 +0530356 */
Kuninori Morimoto8dfedaf2020-04-24 08:15:36 +0900357 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
358 if (ret < 0)
359 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530360
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000361 ret = soc_compr_components_set_params(cstream, params);
362 if (ret < 0)
363 goto err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000364
Kuninori Morimotoeab810f2020-05-25 09:57:50 +0900365 ret = snd_soc_link_compr_set_params(cstream);
366 if (ret < 0)
367 goto err;
Namarta Kohli1245b702012-08-16 17:10:41 +0530368
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900369 snd_soc_dapm_stream_event(rtd, stream, SND_SOC_DAPM_STREAM_START);
Namarta Kohli1245b702012-08-16 17:10:41 +0530370
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000371 /* cancel any delayed stream shutdown that is pending */
372 rtd->pop_wait = 0;
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300373 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000374
375 cancel_delayed_work_sync(&rtd->delayed_work);
376
Charles Keepax52cadf12019-02-05 11:18:12 +0000377 return 0;
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000378
379err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300380 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530381 return ret;
382}
383
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000384static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100385 struct snd_compr_params *params)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000386{
387 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700388 struct snd_pcm_substream *fe_substream =
389 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900390 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900391 int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
392 int ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000393
394 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
395
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100396 /*
397 * Create an empty hw_params for the BE as the machine driver must
398 * fix this up to match DSP decoder and ASRC configuration.
399 * I.e. machine driver fixup for compressed BE is mandatory.
400 */
401 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
402 sizeof(struct snd_pcm_hw_params));
403
404 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
405
406 ret = dpcm_be_dai_hw_params(fe, stream);
407 if (ret < 0)
408 goto out;
409
410 ret = dpcm_be_dai_prepare(fe, stream);
411 if (ret < 0)
412 goto out;
413
Kuninori Morimoto8dfedaf2020-04-24 08:15:36 +0900414 ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
415 if (ret < 0)
416 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530417
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000418 ret = soc_compr_components_set_params(cstream, params);
419 if (ret < 0)
420 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000421
Kuninori Morimotoeab810f2020-05-25 09:57:50 +0900422 ret = snd_soc_link_compr_set_params(cstream);
423 if (ret < 0)
424 goto out;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000425
Daniel Mack15f6b092014-10-19 09:07:35 +0200426 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000427 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
428
429out:
430 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
431 mutex_unlock(&fe->card->mutex);
432 return ret;
433}
434
Namarta Kohli1245b702012-08-16 17:10:41 +0530435static int soc_compr_get_params(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100436 struct snd_codec *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530437{
438 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000439 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900440 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900441 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530442
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300443 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000444
Kuninori Morimotoadbef5432020-04-24 08:15:40 +0900445 ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params);
446 if (ret < 0)
447 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530448
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900449 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900450 if (!component->driver->compress_ops ||
451 !component->driver->compress_ops->get_params)
452 continue;
453
454 ret = component->driver->compress_ops->get_params(
455 component, cstream, params);
456 break;
457 }
458
Vinod Koul2e622ae2016-11-13 12:10:02 +0530459err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300460 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530461 return ret;
462}
463
464static int soc_compr_get_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100465 struct snd_compr_caps *caps)
Namarta Kohli1245b702012-08-16 17:10:41 +0530466{
467 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000468 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900469 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530470
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300471 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000472
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900473 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900474 if (!component->driver->compress_ops ||
475 !component->driver->compress_ops->get_caps)
476 continue;
477
478 ret = component->driver->compress_ops->get_caps(
479 component, cstream, caps);
480 break;
481 }
482
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300483 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530484 return ret;
485}
486
487static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100488 struct snd_compr_codec_caps *codec)
Namarta Kohli1245b702012-08-16 17:10:41 +0530489{
490 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000491 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900492 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530493
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300494 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000495
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900496 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900497 if (!component->driver->compress_ops ||
498 !component->driver->compress_ops->get_codec_caps)
499 continue;
500
501 ret = component->driver->compress_ops->get_codec_caps(
502 component, cstream, codec);
503 break;
504 }
505
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300506 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530507 return ret;
508}
509
510static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
511{
512 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000513 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900514 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900515 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530516
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300517 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000518
Kuninori Morimoto53294352020-04-24 08:15:45 +0900519 ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes);
520 if (ret < 0)
521 goto err;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530522
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900523 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900524 if (!component->driver->compress_ops ||
525 !component->driver->compress_ops->ack)
526 continue;
527
528 ret = component->driver->compress_ops->ack(
529 component, cstream, bytes);
530 if (ret < 0)
531 goto err;
532 }
533
Vinod Koul2e622ae2016-11-13 12:10:02 +0530534err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300535 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530536 return ret;
537}
538
539static int soc_compr_pointer(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100540 struct snd_compr_tstamp *tstamp)
Namarta Kohli1245b702012-08-16 17:10:41 +0530541{
542 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000543 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900544 int i, ret = 0;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900545 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530546
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300547 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000548
Kuninori Morimotoed38cc52020-04-24 08:15:49 +0900549 ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp);
550 if (ret < 0)
551 goto out;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530552
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900553 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900554 if (!component->driver->compress_ops ||
555 !component->driver->compress_ops->pointer)
556 continue;
557
558 ret = component->driver->compress_ops->pointer(
559 component, cstream, tstamp);
560 break;
561 }
Kuninori Morimotoed38cc52020-04-24 08:15:49 +0900562out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300563 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax7c9190f2016-06-20 09:51:32 +0100564 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530565}
566
Charles Keepax1f88eb02013-02-05 10:41:47 +0000567static int soc_compr_copy(struct snd_compr_stream *cstream,
Charles Keepax4daf8912013-04-18 11:01:38 +0100568 char __user *buf, size_t count)
Charles Keepax1f88eb02013-02-05 10:41:47 +0000569{
570 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000571 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900572 int i, ret = 0;
Charles Keepax1f88eb02013-02-05 10:41:47 +0000573
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300574 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000575
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900576 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900577 if (!component->driver->compress_ops ||
578 !component->driver->compress_ops->copy)
579 continue;
580
581 ret = component->driver->compress_ops->copy(
582 component, cstream, buf, count);
583 break;
584 }
585
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300586 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000587 return ret;
588}
589
Vinod Koul02bd90e2013-07-28 20:06:15 +0530590static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100591 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530592{
593 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000594 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900595 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900596 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530597
Kuninori Morimoto88b3a7d2020-04-24 08:15:54 +0900598 ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata);
599 if (ret < 0)
600 return ret;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530601
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900602 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900603 if (!component->driver->compress_ops ||
604 !component->driver->compress_ops->set_metadata)
605 continue;
606
607 ret = component->driver->compress_ops->set_metadata(
608 component, cstream, metadata);
609 if (ret < 0)
610 return ret;
611 }
612
Charles Keepax52cadf12019-02-05 11:18:12 +0000613 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530614}
615
Vinod Koul02bd90e2013-07-28 20:06:15 +0530616static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100617 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530618{
619 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000620 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900621 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900622 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530623
Kuninori Morimoto94d72812020-04-24 08:15:59 +0900624 ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata);
625 if (ret < 0)
626 return ret;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530627
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900628 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900629 if (!component->driver->compress_ops ||
630 !component->driver->compress_ops->get_metadata)
631 continue;
632
633 return component->driver->compress_ops->get_metadata(
634 component, cstream, metadata);
635 }
636
Charles Keepax52cadf12019-02-05 11:18:12 +0000637 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530638}
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000639
Namarta Kohli1245b702012-08-16 17:10:41 +0530640/* ASoC Compress operations */
641static struct snd_compr_ops soc_compr_ops = {
642 .open = soc_compr_open,
643 .free = soc_compr_free,
644 .set_params = soc_compr_set_params,
Vinod Koul02bd90e2013-07-28 20:06:15 +0530645 .set_metadata = soc_compr_set_metadata,
646 .get_metadata = soc_compr_get_metadata,
Namarta Kohli1245b702012-08-16 17:10:41 +0530647 .get_params = soc_compr_get_params,
648 .trigger = soc_compr_trigger,
649 .pointer = soc_compr_pointer,
650 .ack = soc_compr_ack,
651 .get_caps = soc_compr_get_caps,
652 .get_codec_caps = soc_compr_get_codec_caps
653};
654
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000655/* ASoC Dynamic Compress operations */
656static struct snd_compr_ops soc_compr_dyn_ops = {
657 .open = soc_compr_open_fe,
658 .free = soc_compr_free_fe,
659 .set_params = soc_compr_set_params_fe,
660 .get_params = soc_compr_get_params,
661 .set_metadata = soc_compr_set_metadata,
662 .get_metadata = soc_compr_get_metadata,
663 .trigger = soc_compr_trigger_fe,
664 .pointer = soc_compr_pointer,
665 .ack = soc_compr_ack,
666 .get_caps = soc_compr_get_caps,
667 .get_codec_caps = soc_compr_get_codec_caps
668};
669
Jie Yang6f0c4222015-10-13 23:41:00 +0800670/**
671 * snd_soc_new_compress - create a new compress.
672 *
673 * @rtd: The runtime for which we will create compress
674 * @num: the device index number (zero based - shared with normal PCMs)
675 *
676 * Return: 0 for success, else error.
677 */
678int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
Namarta Kohli1245b702012-08-16 17:10:41 +0530679{
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000680 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900681 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
682 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530683 struct snd_compr *compr;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000684 struct snd_pcm *be_pcm;
Namarta Kohli1245b702012-08-16 17:10:41 +0530685 char new_name[64];
686 int ret = 0, direction = 0;
Vinod Koula1068042016-01-07 21:48:14 +0530687 int playback = 0, capture = 0;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900688 int i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530689
Kuninori Morimoto7428d8c2020-10-30 10:01:22 +0900690 /*
691 * make sure these are same value,
692 * and then use these as equally
693 */
694 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK);
695 BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE != (int)SND_COMPRESS_CAPTURE);
696
Bard Liao6e1276a2020-02-25 21:39:16 +0800697 if (rtd->num_cpus > 1 ||
698 rtd->num_codecs > 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000699 dev_err(rtd->card->dev,
Bard Liao6e1276a2020-02-25 21:39:16 +0800700 "Compress ASoC: Multi CPU/Codec not supported\n");
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200701 return -EINVAL;
702 }
703
Namarta Kohli1245b702012-08-16 17:10:41 +0530704 /* check client and interface hw capabilities */
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900705 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
706 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
Vinod Koula1068042016-01-07 21:48:14 +0530707 playback = 1;
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900708 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
709 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
Vinod Koula1068042016-01-07 21:48:14 +0530710 capture = 1;
711
Vinod Koula1068042016-01-07 21:48:14 +0530712 /*
713 * Compress devices are unidirectional so only one of the directions
714 * should be set, check for that (xor)
715 */
716 if (playback + capture != 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000717 dev_err(rtd->card->dev,
718 "Compress ASoC: Invalid direction for P %d, C %d\n",
719 playback, capture);
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100720 return -EINVAL;
Vinod Koula1068042016-01-07 21:48:14 +0530721 }
722
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800723 if (playback)
Vinod Koula1068042016-01-07 21:48:14 +0530724 direction = SND_COMPRESS_PLAYBACK;
725 else
726 direction = SND_COMPRESS_CAPTURE;
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100727
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200728 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200729 if (!compr)
Namarta Kohli1245b702012-08-16 17:10:41 +0530730 return -ENOMEM;
Namarta Kohli1245b702012-08-16 17:10:41 +0530731
Charles Keepax1f88eb02013-02-05 10:41:47 +0000732 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
733 GFP_KERNEL);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200734 if (!compr->ops)
735 return -ENOMEM;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000736
737 if (rtd->dai_link->dynamic) {
738 snprintf(new_name, sizeof(new_name), "(%s)",
739 rtd->dai_link->stream_name);
740
741 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
Qais Yousefd3268a42015-01-14 08:47:29 +0000742 rtd->dai_link->dpcm_playback,
743 rtd->dai_link->dpcm_capture, &be_pcm);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000744 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000745 dev_err(rtd->card->dev,
746 "Compress ASoC: can't create compressed for %s: %d\n",
747 rtd->dai_link->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200748 return ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000749 }
750
751 rtd->pcm = be_pcm;
752 rtd->fe_compr = 1;
Qais Yousefd3268a42015-01-14 08:47:29 +0000753 if (rtd->dai_link->dpcm_playback)
754 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
755 else if (rtd->dai_link->dpcm_capture)
756 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000757 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800758 } else {
759 snprintf(new_name, sizeof(new_name), "%s %s-%d",
760 rtd->dai_link->stream_name, codec_dai->name, num);
761
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000762 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800763 }
Charles Keepax1f88eb02013-02-05 10:41:47 +0000764
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900765 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900766 if (!component->driver->compress_ops ||
767 !component->driver->compress_ops->copy)
768 continue;
769
770 compr->ops->copy = soc_compr_copy;
771 break;
772 }
773
Namarta Kohli1245b702012-08-16 17:10:41 +0530774 mutex_init(&compr->lock);
Richard Fitzgeralde5241a82015-11-25 13:00:24 +0000775 ret = snd_compress_new(rtd->card->snd_card, num, direction,
776 new_name, compr);
Namarta Kohli1245b702012-08-16 17:10:41 +0530777 if (ret < 0) {
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900778 component = asoc_rtd_to_codec(rtd, 0)->component;
Charles Keepax141dfc92018-01-26 13:08:45 +0000779 dev_err(component->dev,
780 "Compress ASoC: can't create compress for codec %s: %d\n",
781 component->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200782 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530783 }
784
Charles Keepax202c8f72013-01-24 09:44:30 +0000785 /* DAPM dai link stream work */
Kuninori Morimoto83f94a22020-01-10 11:36:17 +0900786 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
Charles Keepax202c8f72013-01-24 09:44:30 +0000787
Namarta Kohli1245b702012-08-16 17:10:41 +0530788 rtd->compr = compr;
789 compr->private_data = rtd;
790
Pierre-Louis Bossart1d5cd522020-06-12 15:40:50 -0500791 dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
792 codec_dai->name, cpu_dai->name);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000793
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200794 return 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530795}
Jie Yang6f0c4222015-10-13 23:41:00 +0800796EXPORT_SYMBOL_GPL(snd_soc_new_compress);