blob: 343de969179eada92aea184c86084078732e9eb0 [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
47 /* remvoe me */
48 for_each_rtd_components(rtd, i, component) {
Charles Keepax1e57b822018-04-24 16:39:03 +010049 if (!component->driver->compr_ops ||
50 !component->driver->compr_ops->open)
51 continue;
52
53 ret = component->driver->compr_ops->open(cstream);
54 if (ret < 0) {
55 dev_err(component->dev,
56 "Compress ASoC: can't open platform %s: %d\n",
57 component->name, ret);
58
59 *last = component;
60 return ret;
61 }
62 }
63
64 *last = NULL;
65 return 0;
66}
67
68static int soc_compr_components_free(struct snd_compr_stream *cstream,
69 struct snd_soc_component *last)
70{
71 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
72 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +090073 int i;
Charles Keepax1e57b822018-04-24 16:39:03 +010074
Kuninori Morimoto613fb502020-01-10 11:35:21 +090075 for_each_rtd_components(rtd, i, component) {
Charles Keepax1e57b822018-04-24 16:39:03 +010076 if (component == last)
77 break;
78
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +090079 if (!component->driver->compress_ops ||
80 !component->driver->compress_ops->free)
81 continue;
82
83 component->driver->compress_ops->free(component, cstream);
84 }
85
86 /* remove me */
87 for_each_rtd_components(rtd, i, component) {
88 if (component == last)
89 break;
90
Charles Keepax1e57b822018-04-24 16:39:03 +010091 if (!component->driver->compr_ops ||
92 !component->driver->compr_ops->free)
93 continue;
94
95 component->driver->compr_ops->free(cstream);
96 }
97
98 return 0;
99}
100
101static int soc_compr_open(struct snd_compr_stream *cstream)
102{
103 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100104 struct snd_soc_component *component, *save = NULL;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900105 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900106 int ret, i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530107
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900108 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100109 ret = pm_runtime_get_sync(component->dev);
110 if (ret < 0 && ret != -EACCES) {
111 pm_runtime_put_noidle(component->dev);
112 save = component;
113 goto pm_err;
114 }
115 }
116
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300117 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000118
Vinod Koul2e622ae2016-11-13 12:10:02 +0530119 if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
120 ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
121 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000122 dev_err(cpu_dai->dev,
123 "Compress ASoC: can't open interface %s: %d\n",
Vinod Koul2e622ae2016-11-13 12:10:02 +0530124 cpu_dai->name, ret);
125 goto out;
126 }
127 }
128
Charles Keepax1e57b822018-04-24 16:39:03 +0100129 ret = soc_compr_components_open(cstream, &component);
130 if (ret < 0)
131 goto machine_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000132
Namarta Kohli1245b702012-08-16 17:10:41 +0530133 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
134 ret = rtd->dai_link->compr_ops->startup(cstream);
135 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000136 dev_err(rtd->dev,
137 "Compress ASoC: %s startup failed: %d\n",
138 rtd->dai_link->name, ret);
Namarta Kohli1245b702012-08-16 17:10:41 +0530139 goto machine_err;
140 }
141 }
142
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100143 snd_soc_runtime_activate(rtd, cstream->direction);
Namarta Kohli1245b702012-08-16 17:10:41 +0530144
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300145 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax15e2e612013-01-24 09:44:29 +0000146
Namarta Kohli1245b702012-08-16 17:10:41 +0530147 return 0;
148
149machine_err:
Charles Keepax1e57b822018-04-24 16:39:03 +0100150 soc_compr_components_free(cstream, component);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000151
Vinod Koul2e622ae2016-11-13 12:10:02 +0530152 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
153 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
Namarta Kohli1245b702012-08-16 17:10:41 +0530154out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300155 mutex_unlock(&rtd->card->pcm_mutex);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100156pm_err:
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900157 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100158 if (component == save)
159 break;
160 pm_runtime_mark_last_busy(component->dev);
161 pm_runtime_put_autosuspend(component->dev);
162 }
163
Namarta Kohli1245b702012-08-16 17:10:41 +0530164 return ret;
165}
166
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000167static int soc_compr_open_fe(struct snd_compr_stream *cstream)
168{
169 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700170 struct snd_pcm_substream *fe_substream =
171 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000172 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900173 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000174 struct snd_soc_dpcm *dpcm;
175 struct snd_soc_dapm_widget_list *list;
176 int stream;
Charles Keepax572e6c82018-04-24 16:39:01 +0100177 int ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000178
179 if (cstream->direction == SND_COMPRESS_PLAYBACK)
180 stream = SNDRV_PCM_STREAM_PLAYBACK;
181 else
182 stream = SNDRV_PCM_STREAM_CAPTURE;
183
184 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100185 fe->dpcm[stream].runtime = fe_substream->runtime;
186
187 ret = dpcm_path_get(fe, stream, &list);
188 if (ret < 0)
189 goto be_err;
190 else if (ret == 0)
191 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
192 fe->dai_link->name, stream ? "capture" : "playback");
193 /* calculate valid and active FE <-> BE dpcms */
194 dpcm_process_paths(fe, stream, &list, 1);
195 fe->dpcm[stream].runtime = fe_substream->runtime;
196
197 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
198
199 ret = dpcm_be_dai_startup(fe, stream);
200 if (ret < 0) {
201 /* clean up all links */
Kuninori Morimoto8d6258a2018-09-18 01:31:09 +0000202 for_each_dpcm_be(fe, stream, dpcm)
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100203 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
204
205 dpcm_be_disconnect(fe, stream);
206 fe->dpcm[stream].runtime = NULL;
207 goto out;
208 }
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000209
Vinod Koul2e622ae2016-11-13 12:10:02 +0530210 if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
211 ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
212 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000213 dev_err(cpu_dai->dev,
214 "Compress ASoC: can't open interface %s: %d\n",
Vinod Koul2e622ae2016-11-13 12:10:02 +0530215 cpu_dai->name, ret);
216 goto out;
217 }
218 }
219
Charles Keepax1e57b822018-04-24 16:39:03 +0100220 ret = soc_compr_components_open(cstream, &component);
221 if (ret < 0)
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100222 goto open_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000223
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000224 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
225 ret = fe->dai_link->compr_ops->startup(cstream);
226 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000227 pr_err("Compress ASoC: %s startup failed: %d\n",
228 fe->dai_link->name, ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000229 goto machine_err;
230 }
231 }
232
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000233 dpcm_clear_pending_state(fe, stream);
234 dpcm_path_put(&list);
235
236 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
237 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
238
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100239 snd_soc_runtime_activate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000240
241 mutex_unlock(&fe->card->mutex);
242
243 return 0;
244
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000245machine_err:
Charles Keepax1e57b822018-04-24 16:39:03 +0100246 soc_compr_components_free(cstream, component);
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100247open_err:
Vinod Koul2e622ae2016-11-13 12:10:02 +0530248 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
249 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000250out:
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100251 dpcm_path_put(&list);
252be_err:
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000253 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
254 mutex_unlock(&fe->card->mutex);
255 return ret;
256}
257
Namarta Kohli1245b702012-08-16 17:10:41 +0530258static int soc_compr_free(struct snd_compr_stream *cstream)
259{
260 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100261 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900262 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
263 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900264 int stream, i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530265
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300266 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000267
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100268 if (cstream->direction == SND_COMPRESS_PLAYBACK)
269 stream = SNDRV_PCM_STREAM_PLAYBACK;
270 else
271 stream = SNDRV_PCM_STREAM_CAPTURE;
272
273 snd_soc_runtime_deactivate(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530274
Mark Brownda183962013-02-06 15:44:07 +0000275 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
276
Namarta Kohli1245b702012-08-16 17:10:41 +0530277 if (!cpu_dai->active)
278 cpu_dai->rate = 0;
279
280 if (!codec_dai->active)
281 codec_dai->rate = 0;
282
Namarta Kohli1245b702012-08-16 17:10:41 +0530283 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
284 rtd->dai_link->compr_ops->shutdown(cstream);
285
Charles Keepax1e57b822018-04-24 16:39:03 +0100286 soc_compr_components_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000287
Vinod Koul2e622ae2016-11-13 12:10:02 +0530288 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
289 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
290
Kuninori Morimoto3f4cf792020-01-10 11:36:23 +0900291 snd_soc_dapm_stream_stop(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530292
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300293 mutex_unlock(&rtd->card->pcm_mutex);
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100294
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900295 for_each_rtd_components(rtd, i, component) {
Cezary Rojewski4137f4b2019-12-17 10:58:50 +0100296 pm_runtime_mark_last_busy(component->dev);
297 pm_runtime_put_autosuspend(component->dev);
298 }
299
Namarta Kohli1245b702012-08-16 17:10:41 +0530300 return 0;
301}
302
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000303static int soc_compr_free_fe(struct snd_compr_stream *cstream)
304{
305 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900306 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000307 struct snd_soc_dpcm *dpcm;
308 int stream, ret;
309
310 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
311
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100312 if (cstream->direction == SND_COMPRESS_PLAYBACK)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000313 stream = SNDRV_PCM_STREAM_PLAYBACK;
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100314 else
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000315 stream = SNDRV_PCM_STREAM_CAPTURE;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000316
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100317 snd_soc_runtime_deactivate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000318
319 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
320
321 ret = dpcm_be_dai_hw_free(fe, stream);
322 if (ret < 0)
Charles Keepax141dfc92018-01-26 13:08:45 +0000323 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000324
325 ret = dpcm_be_dai_shutdown(fe, stream);
326
327 /* mark FE's links ready to prune */
Kuninori Morimoto8d6258a2018-09-18 01:31:09 +0000328 for_each_dpcm_be(fe, stream, dpcm)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000329 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
330
Kuninori Morimoto1c531232020-02-21 10:25:18 +0900331 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000332
333 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
334 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
335
336 dpcm_be_disconnect(fe, stream);
337
338 fe->dpcm[stream].runtime = NULL;
339
340 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
341 fe->dai_link->compr_ops->shutdown(cstream);
342
Charles Keepax1e57b822018-04-24 16:39:03 +0100343 soc_compr_components_free(cstream, NULL);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000344
Vinod Koul2e622ae2016-11-13 12:10:02 +0530345 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
346 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
347
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000348 mutex_unlock(&fe->card->mutex);
349 return 0;
350}
351
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000352static int soc_compr_components_trigger(struct snd_compr_stream *cstream,
353 int cmd)
Namarta Kohli1245b702012-08-16 17:10:41 +0530354{
Namarta Kohli1245b702012-08-16 17:10:41 +0530355 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000356 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900357 int i, ret;
Charles Keepax15e2e612013-01-24 09:44:29 +0000358
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900359 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900360 if (!component->driver->compress_ops ||
361 !component->driver->compress_ops->trigger)
362 continue;
363
364 ret = component->driver->compress_ops->trigger(
365 component, cstream, cmd);
366 if (ret < 0)
367 return ret;
368 }
369
370 /* remove me */
371 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000372 if (!component->driver->compr_ops ||
373 !component->driver->compr_ops->trigger)
374 continue;
375
Charles Keepax52cadf12019-02-05 11:18:12 +0000376 ret = component->driver->compr_ops->trigger(cstream, cmd);
377 if (ret < 0)
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000378 return ret;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000379 }
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000380
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000381 return 0;
382}
383
384static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
385{
386 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900387 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
388 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000389 int ret;
390
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300391 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000392
393 ret = soc_compr_components_trigger(cstream, cmd);
394 if (ret < 0)
395 goto out;
396
Vinod Koul2e622ae2016-11-13 12:10:02 +0530397 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
398 cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
399
Mark Brownda183962013-02-06 15:44:07 +0000400 switch (cmd) {
401 case SNDRV_PCM_TRIGGER_START:
402 snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
403 break;
404 case SNDRV_PCM_TRIGGER_STOP:
405 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
406 break;
Mark Browne38b9b72013-02-06 13:52:42 +0000407 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530408
Charles Keepax15e2e612013-01-24 09:44:29 +0000409out:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300410 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530411 return ret;
412}
413
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000414static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
415{
416 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900417 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000418 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000419
420 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000421 cmd == SND_COMPR_TRIGGER_DRAIN)
422 return soc_compr_components_trigger(cstream, cmd);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000423
424 if (cstream->direction == SND_COMPRESS_PLAYBACK)
425 stream = SNDRV_PCM_STREAM_PLAYBACK;
426 else
427 stream = SNDRV_PCM_STREAM_CAPTURE;
428
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000429 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
430
Vinod Koul2e622ae2016-11-13 12:10:02 +0530431 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) {
432 ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
433 if (ret < 0)
434 goto out;
435 }
436
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000437 ret = soc_compr_components_trigger(cstream, cmd);
438 if (ret < 0)
439 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000440
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000441 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
442
443 ret = dpcm_be_dai_trigger(fe, stream, cmd);
444
445 switch (cmd) {
446 case SNDRV_PCM_TRIGGER_START:
447 case SNDRV_PCM_TRIGGER_RESUME:
448 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
449 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
450 break;
451 case SNDRV_PCM_TRIGGER_STOP:
452 case SNDRV_PCM_TRIGGER_SUSPEND:
453 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
454 break;
455 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
456 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
457 break;
458 }
459
460out:
461 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
462 mutex_unlock(&fe->card->mutex);
463 return ret;
464}
465
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000466static int soc_compr_components_set_params(struct snd_compr_stream *cstream,
467 struct snd_compr_params *params)
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;
Charles Keepax4ef0ecb2019-02-05 11:18:13 +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->set_params)
476 continue;
477
478 ret = component->driver->compress_ops->set_params(
479 component, cstream, params);
480 if (ret < 0)
481 return ret;
482 }
483
484 /* remove me */
485 for_each_rtd_components(rtd, i, component) {
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000486 if (!component->driver->compr_ops ||
487 !component->driver->compr_ops->set_params)
488 continue;
489
490 ret = component->driver->compr_ops->set_params(cstream, params);
491 if (ret < 0)
492 return ret;
493 }
494
495 return 0;
496}
497
498static int soc_compr_set_params(struct snd_compr_stream *cstream,
499 struct snd_compr_params *params)
500{
501 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900502 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000503 int ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530504
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300505 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000506
Charles Keepaxef050be2018-04-24 16:39:02 +0100507 /*
508 * First we call set_params for the CPU DAI, then the component
509 * driver this should configure the SoC side. If the machine has
510 * compressed ops then we call that as well. The expectation is
511 * that these callbacks will configure everything for this compress
512 * path, like configuring a PCM port for a CODEC.
Namarta Kohli1245b702012-08-16 17:10:41 +0530513 */
Vinod Koul2e622ae2016-11-13 12:10:02 +0530514 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
515 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
516 if (ret < 0)
517 goto err;
518 }
519
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000520 ret = soc_compr_components_set_params(cstream, params);
521 if (ret < 0)
522 goto err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000523
Namarta Kohli1245b702012-08-16 17:10:41 +0530524 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
525 ret = rtd->dai_link->compr_ops->set_params(cstream);
526 if (ret < 0)
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000527 goto err;
Namarta Kohli1245b702012-08-16 17:10:41 +0530528 }
529
Charles Keepax2c071ed2013-05-20 08:33:54 +0100530 if (cstream->direction == SND_COMPRESS_PLAYBACK)
531 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
Charles Keepax89027d92018-04-26 17:30:07 +0100532 SND_SOC_DAPM_STREAM_START);
Charles Keepax2c071ed2013-05-20 08:33:54 +0100533 else
534 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
Charles Keepax89027d92018-04-26 17:30:07 +0100535 SND_SOC_DAPM_STREAM_START);
Namarta Kohli1245b702012-08-16 17:10:41 +0530536
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000537 /* cancel any delayed stream shutdown that is pending */
538 rtd->pop_wait = 0;
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300539 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000540
541 cancel_delayed_work_sync(&rtd->delayed_work);
542
Charles Keepax52cadf12019-02-05 11:18:12 +0000543 return 0;
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000544
545err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300546 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530547 return ret;
548}
549
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000550static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100551 struct snd_compr_params *params)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000552{
553 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700554 struct snd_pcm_substream *fe_substream =
555 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900556 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0);
Charles Keepax52cadf12019-02-05 11:18:12 +0000557 int ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000558
559 if (cstream->direction == SND_COMPRESS_PLAYBACK)
560 stream = SNDRV_PCM_STREAM_PLAYBACK;
561 else
562 stream = SNDRV_PCM_STREAM_CAPTURE;
563
564 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
565
Srinivas Kandagatla0b0722e2018-08-03 13:30:03 +0100566 /*
567 * Create an empty hw_params for the BE as the machine driver must
568 * fix this up to match DSP decoder and ASRC configuration.
569 * I.e. machine driver fixup for compressed BE is mandatory.
570 */
571 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
572 sizeof(struct snd_pcm_hw_params));
573
574 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
575
576 ret = dpcm_be_dai_hw_params(fe, stream);
577 if (ret < 0)
578 goto out;
579
580 ret = dpcm_be_dai_prepare(fe, stream);
581 if (ret < 0)
582 goto out;
583
Vinod Koul2e622ae2016-11-13 12:10:02 +0530584 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
585 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
586 if (ret < 0)
587 goto out;
588 }
589
Charles Keepax4ef0ecb2019-02-05 11:18:13 +0000590 ret = soc_compr_components_set_params(cstream, params);
591 if (ret < 0)
592 goto out;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000593
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000594 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
595 ret = fe->dai_link->compr_ops->set_params(cstream);
596 if (ret < 0)
597 goto out;
598 }
599
Daniel Mack15f6b092014-10-19 09:07:35 +0200600 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000601 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
602
603out:
604 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
605 mutex_unlock(&fe->card->mutex);
606 return ret;
607}
608
Namarta Kohli1245b702012-08-16 17:10:41 +0530609static int soc_compr_get_params(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100610 struct snd_codec *params)
Namarta Kohli1245b702012-08-16 17:10:41 +0530611{
612 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000613 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900614 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900615 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530616
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300617 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000618
Vinod Koul2e622ae2016-11-13 12:10:02 +0530619 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
620 ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
621 if (ret < 0)
622 goto err;
623 }
624
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900625 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900626 if (!component->driver->compress_ops ||
627 !component->driver->compress_ops->get_params)
628 continue;
629
630 ret = component->driver->compress_ops->get_params(
631 component, cstream, params);
632 break;
633 }
634
635 /* remove me */
636 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000637 if (!component->driver->compr_ops ||
638 !component->driver->compr_ops->get_params)
639 continue;
640
Charles Keepax52cadf12019-02-05 11:18:12 +0000641 ret = component->driver->compr_ops->get_params(cstream, params);
642 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000643 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530644
Vinod Koul2e622ae2016-11-13 12:10:02 +0530645err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300646 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530647 return ret;
648}
649
650static int soc_compr_get_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100651 struct snd_compr_caps *caps)
Namarta Kohli1245b702012-08-16 17:10:41 +0530652{
653 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000654 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900655 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530656
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300657 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000658
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900659 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900660 if (!component->driver->compress_ops ||
661 !component->driver->compress_ops->get_caps)
662 continue;
663
664 ret = component->driver->compress_ops->get_caps(
665 component, cstream, caps);
666 break;
667 }
668
669 /* remove me */
670 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000671 if (!component->driver->compr_ops ||
672 !component->driver->compr_ops->get_caps)
673 continue;
674
Charles Keepax52cadf12019-02-05 11:18:12 +0000675 ret = component->driver->compr_ops->get_caps(cstream, caps);
676 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000677 }
678
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300679 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530680 return ret;
681}
682
683static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100684 struct snd_compr_codec_caps *codec)
Namarta Kohli1245b702012-08-16 17:10:41 +0530685{
686 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000687 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900688 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530689
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300690 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000691
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900692 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900693 if (!component->driver->compress_ops ||
694 !component->driver->compress_ops->get_codec_caps)
695 continue;
696
697 ret = component->driver->compress_ops->get_codec_caps(
698 component, cstream, codec);
699 break;
700 }
701
702 /* remove me */
703 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000704 if (!component->driver->compr_ops ||
705 !component->driver->compr_ops->get_codec_caps)
706 continue;
707
Charles Keepax52cadf12019-02-05 11:18:12 +0000708 ret = component->driver->compr_ops->get_codec_caps(cstream,
709 codec);
710 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000711 }
712
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300713 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530714 return ret;
715}
716
717static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
718{
719 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000720 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900721 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900722 int i, ret = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530723
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300724 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000725
Vinod Koul2e622ae2016-11-13 12:10:02 +0530726 if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
727 ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
728 if (ret < 0)
729 goto err;
730 }
731
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900732 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900733 if (!component->driver->compress_ops ||
734 !component->driver->compress_ops->ack)
735 continue;
736
737 ret = component->driver->compress_ops->ack(
738 component, cstream, bytes);
739 if (ret < 0)
740 goto err;
741 }
742
743 /* remove me */
744 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000745 if (!component->driver->compr_ops ||
746 !component->driver->compr_ops->ack)
747 continue;
748
Charles Keepax52cadf12019-02-05 11:18:12 +0000749 ret = component->driver->compr_ops->ack(cstream, bytes);
750 if (ret < 0)
751 goto err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000752 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530753
Vinod Koul2e622ae2016-11-13 12:10:02 +0530754err:
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300755 mutex_unlock(&rtd->card->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530756 return ret;
757}
758
759static int soc_compr_pointer(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100760 struct snd_compr_tstamp *tstamp)
Namarta Kohli1245b702012-08-16 17:10:41 +0530761{
762 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000763 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900764 int i, ret = 0;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900765 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530766
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300767 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax15e2e612013-01-24 09:44:29 +0000768
Vinod Koul2e622ae2016-11-13 12:10:02 +0530769 if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
770 cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
771
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900772 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900773 if (!component->driver->compress_ops ||
774 !component->driver->compress_ops->pointer)
775 continue;
776
777 ret = component->driver->compress_ops->pointer(
778 component, cstream, tstamp);
779 break;
780 }
781
782 /* remove me */
783 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000784 if (!component->driver->compr_ops ||
785 !component->driver->compr_ops->pointer)
786 continue;
787
Charles Keepax52cadf12019-02-05 11:18:12 +0000788 ret = component->driver->compr_ops->pointer(cstream, tstamp);
789 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000790 }
791
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300792 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax7c9190f2016-06-20 09:51:32 +0100793 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530794}
795
Charles Keepax1f88eb02013-02-05 10:41:47 +0000796static int soc_compr_copy(struct snd_compr_stream *cstream,
Charles Keepax4daf8912013-04-18 11:01:38 +0100797 char __user *buf, size_t count)
Charles Keepax1f88eb02013-02-05 10:41:47 +0000798{
799 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000800 struct snd_soc_component *component;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900801 int i, ret = 0;
Charles Keepax1f88eb02013-02-05 10:41:47 +0000802
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300803 mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000804
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900805 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900806 if (!component->driver->compress_ops ||
807 !component->driver->compress_ops->copy)
808 continue;
809
810 ret = component->driver->compress_ops->copy(
811 component, cstream, buf, count);
812 break;
813 }
814
815 /* remove me */
816 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000817 if (!component->driver->compr_ops ||
818 !component->driver->compr_ops->copy)
819 continue;
820
Charles Keepax290df4d32018-01-26 13:08:43 +0000821 ret = component->driver->compr_ops->copy(cstream, buf, count);
822 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000823 }
Charles Keepax290df4d32018-01-26 13:08:43 +0000824
Peter Ujfalusi72b745e2019-08-13 13:45:32 +0300825 mutex_unlock(&rtd->card->pcm_mutex);
Charles Keepax1f88eb02013-02-05 10:41:47 +0000826 return ret;
827}
828
Vinod Koul02bd90e2013-07-28 20:06:15 +0530829static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100830 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530831{
832 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000833 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900834 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900835 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530836
Vinod Koul2e622ae2016-11-13 12:10:02 +0530837 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
838 ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
839 if (ret < 0)
840 return ret;
841 }
842
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900843 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900844 if (!component->driver->compress_ops ||
845 !component->driver->compress_ops->set_metadata)
846 continue;
847
848 ret = component->driver->compress_ops->set_metadata(
849 component, cstream, metadata);
850 if (ret < 0)
851 return ret;
852 }
853
854 /* remove me */
855 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000856 if (!component->driver->compr_ops ||
857 !component->driver->compr_ops->set_metadata)
858 continue;
859
Charles Keepax52cadf12019-02-05 11:18:12 +0000860 ret = component->driver->compr_ops->set_metadata(cstream,
861 metadata);
862 if (ret < 0)
863 return ret;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000864 }
Jeeja KP36953d92013-03-26 21:22:28 +0530865
Charles Keepax52cadf12019-02-05 11:18:12 +0000866 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530867}
868
Vinod Koul02bd90e2013-07-28 20:06:15 +0530869static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
Charles Keepax89027d92018-04-26 17:30:07 +0100870 struct snd_compr_metadata *metadata)
Jeeja KP36953d92013-03-26 21:22:28 +0530871{
872 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000873 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900874 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900875 int i, ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530876
Vinod Koul2e622ae2016-11-13 12:10:02 +0530877 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
878 ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
879 if (ret < 0)
880 return ret;
881 }
882
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900883 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +0900884 if (!component->driver->compress_ops ||
885 !component->driver->compress_ops->get_metadata)
886 continue;
887
888 return component->driver->compress_ops->get_metadata(
889 component, cstream, metadata);
890 }
891
892 /* remove me */
893 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000894 if (!component->driver->compr_ops ||
895 !component->driver->compr_ops->get_metadata)
896 continue;
897
Charles Keepax52cadf12019-02-05 11:18:12 +0000898 return component->driver->compr_ops->get_metadata(cstream,
899 metadata);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000900 }
Jeeja KP36953d92013-03-26 21:22:28 +0530901
Charles Keepax52cadf12019-02-05 11:18:12 +0000902 return 0;
Jeeja KP36953d92013-03-26 21:22:28 +0530903}
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000904
Namarta Kohli1245b702012-08-16 17:10:41 +0530905/* ASoC Compress operations */
906static struct snd_compr_ops soc_compr_ops = {
907 .open = soc_compr_open,
908 .free = soc_compr_free,
909 .set_params = soc_compr_set_params,
Vinod Koul02bd90e2013-07-28 20:06:15 +0530910 .set_metadata = soc_compr_set_metadata,
911 .get_metadata = soc_compr_get_metadata,
Namarta Kohli1245b702012-08-16 17:10:41 +0530912 .get_params = soc_compr_get_params,
913 .trigger = soc_compr_trigger,
914 .pointer = soc_compr_pointer,
915 .ack = soc_compr_ack,
916 .get_caps = soc_compr_get_caps,
917 .get_codec_caps = soc_compr_get_codec_caps
918};
919
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000920/* ASoC Dynamic Compress operations */
921static struct snd_compr_ops soc_compr_dyn_ops = {
922 .open = soc_compr_open_fe,
923 .free = soc_compr_free_fe,
924 .set_params = soc_compr_set_params_fe,
925 .get_params = soc_compr_get_params,
926 .set_metadata = soc_compr_set_metadata,
927 .get_metadata = soc_compr_get_metadata,
928 .trigger = soc_compr_trigger_fe,
929 .pointer = soc_compr_pointer,
930 .ack = soc_compr_ack,
931 .get_caps = soc_compr_get_caps,
932 .get_codec_caps = soc_compr_get_codec_caps
933};
934
Jie Yang6f0c4222015-10-13 23:41:00 +0800935/**
936 * snd_soc_new_compress - create a new compress.
937 *
938 * @rtd: The runtime for which we will create compress
939 * @num: the device index number (zero based - shared with normal PCMs)
940 *
941 * Return: 0 for success, else error.
942 */
943int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
Namarta Kohli1245b702012-08-16 17:10:41 +0530944{
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000945 struct snd_soc_component *component;
Kuninori Morimotoc2233a22020-03-30 10:47:37 +0900946 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
947 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
Namarta Kohli1245b702012-08-16 17:10:41 +0530948 struct snd_compr *compr;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000949 struct snd_pcm *be_pcm;
Namarta Kohli1245b702012-08-16 17:10:41 +0530950 char new_name[64];
951 int ret = 0, direction = 0;
Vinod Koula1068042016-01-07 21:48:14 +0530952 int playback = 0, capture = 0;
Kuninori Morimoto613fb502020-01-10 11:35:21 +0900953 int i;
Namarta Kohli1245b702012-08-16 17:10:41 +0530954
Bard Liao6e1276a2020-02-25 21:39:16 +0800955 if (rtd->num_cpus > 1 ||
956 rtd->num_codecs > 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000957 dev_err(rtd->card->dev,
Bard Liao6e1276a2020-02-25 21:39:16 +0800958 "Compress ASoC: Multi CPU/Codec not supported\n");
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200959 return -EINVAL;
960 }
961
Namarta Kohli1245b702012-08-16 17:10:41 +0530962 /* check client and interface hw capabilities */
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900963 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
964 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_PLAYBACK))
Vinod Koula1068042016-01-07 21:48:14 +0530965 playback = 1;
Kuninori Morimoto467fece2019-07-22 10:36:16 +0900966 if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
967 snd_soc_dai_stream_valid(cpu_dai, SNDRV_PCM_STREAM_CAPTURE))
Vinod Koula1068042016-01-07 21:48:14 +0530968 capture = 1;
969
Vinod Koula1068042016-01-07 21:48:14 +0530970 /*
971 * Compress devices are unidirectional so only one of the directions
972 * should be set, check for that (xor)
973 */
974 if (playback + capture != 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000975 dev_err(rtd->card->dev,
976 "Compress ASoC: Invalid direction for P %d, C %d\n",
977 playback, capture);
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100978 return -EINVAL;
Vinod Koula1068042016-01-07 21:48:14 +0530979 }
980
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800981 if (playback)
Vinod Koula1068042016-01-07 21:48:14 +0530982 direction = SND_COMPRESS_PLAYBACK;
983 else
984 direction = SND_COMPRESS_CAPTURE;
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100985
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200986 compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200987 if (!compr)
Namarta Kohli1245b702012-08-16 17:10:41 +0530988 return -ENOMEM;
Namarta Kohli1245b702012-08-16 17:10:41 +0530989
Charles Keepax1f88eb02013-02-05 10:41:47 +0000990 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
991 GFP_KERNEL);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +0200992 if (!compr->ops)
993 return -ENOMEM;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000994
995 if (rtd->dai_link->dynamic) {
996 snprintf(new_name, sizeof(new_name), "(%s)",
997 rtd->dai_link->stream_name);
998
999 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
Qais Yousefd3268a42015-01-14 08:47:29 +00001000 rtd->dai_link->dpcm_playback,
1001 rtd->dai_link->dpcm_capture, &be_pcm);
Liam Girdwood2a99ef02014-01-17 17:03:56 +00001002 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +00001003 dev_err(rtd->card->dev,
1004 "Compress ASoC: can't create compressed for %s: %d\n",
1005 rtd->dai_link->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +02001006 return ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +00001007 }
1008
1009 rtd->pcm = be_pcm;
1010 rtd->fe_compr = 1;
Qais Yousefd3268a42015-01-14 08:47:29 +00001011 if (rtd->dai_link->dpcm_playback)
1012 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
1013 else if (rtd->dai_link->dpcm_capture)
1014 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
Liam Girdwood2a99ef02014-01-17 17:03:56 +00001015 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +08001016 } else {
1017 snprintf(new_name, sizeof(new_name), "%s %s-%d",
1018 rtd->dai_link->stream_name, codec_dai->name, num);
1019
Liam Girdwood2a99ef02014-01-17 17:03:56 +00001020 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +08001021 }
Charles Keepax1f88eb02013-02-05 10:41:47 +00001022
Kuninori Morimoto613fb502020-01-10 11:35:21 +09001023 for_each_rtd_components(rtd, i, component) {
Kuninori Morimotoc6cb5222020-04-20 16:07:50 +09001024 if (!component->driver->compress_ops ||
1025 !component->driver->compress_ops->copy)
1026 continue;
1027
1028 compr->ops->copy = soc_compr_copy;
1029 break;
1030 }
1031
1032 /* remove me */
1033 for_each_rtd_components(rtd, i, component) {
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +00001034 if (!component->driver->compr_ops ||
1035 !component->driver->compr_ops->copy)
1036 continue;
1037
1038 compr->ops->copy = soc_compr_copy;
Charles Keepaxca76db62018-04-26 17:30:04 +01001039 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +00001040 }
1041
Namarta Kohli1245b702012-08-16 17:10:41 +05301042 mutex_init(&compr->lock);
Richard Fitzgeralde5241a82015-11-25 13:00:24 +00001043 ret = snd_compress_new(rtd->card->snd_card, num, direction,
1044 new_name, compr);
Namarta Kohli1245b702012-08-16 17:10:41 +05301045 if (ret < 0) {
Kuninori Morimotoc2233a22020-03-30 10:47:37 +09001046 component = asoc_rtd_to_codec(rtd, 0)->component;
Charles Keepax141dfc92018-01-26 13:08:45 +00001047 dev_err(component->dev,
1048 "Compress ASoC: can't create compress for codec %s: %d\n",
1049 component->name, ret);
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +02001050 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +05301051 }
1052
Charles Keepax202c8f72013-01-24 09:44:30 +00001053 /* DAPM dai link stream work */
Kuninori Morimoto83f94a22020-01-10 11:36:17 +09001054 rtd->close_delayed_work_func = snd_soc_close_delayed_work;
Charles Keepax202c8f72013-01-24 09:44:30 +00001055
Namarta Kohli1245b702012-08-16 17:10:41 +05301056 rtd->compr = compr;
1057 compr->private_data = rtd;
1058
Charles Keepax141dfc92018-01-26 13:08:45 +00001059 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
1060 codec_dai->name, cpu_dai->name);
Charles Keepax1f88eb02013-02-05 10:41:47 +00001061
Amadeusz Sławiński09f448a2019-06-17 13:36:36 +02001062 return 0;
Namarta Kohli1245b702012-08-16 17:10:41 +05301063}
Jie Yang6f0c4222015-10-13 23:41:00 +08001064EXPORT_SYMBOL_GPL(snd_soc_new_compress);