blob: abc00c6cc2d736aca57c6889945b5334c07b5d66 [file] [log] [blame]
Namarta Kohli1245b702012-08-16 17:10:41 +05301/*
2 * soc-compress.c -- ALSA SoC Compress
3 *
4 * Copyright (C) 2012 Intel Corp.
5 *
6 * Authors: Namarta Kohli <namartax.kohli@intel.com>
7 * Ramesh Babu K V <ramesh.babu@linux.intel.com>
8 * Vinod Koul <vinod.koul@linux.intel.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/delay.h>
20#include <linux/slab.h>
21#include <linux/workqueue.h>
22#include <sound/core.h>
23#include <sound/compress_params.h>
24#include <sound/compress_driver.h>
25#include <sound/soc.h>
26#include <sound/initval.h>
Liam Girdwood2a99ef02014-01-17 17:03:56 +000027#include <sound/soc-dpcm.h>
Namarta Kohli1245b702012-08-16 17:10:41 +053028
29static int soc_compr_open(struct snd_compr_stream *cstream)
30{
31 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000032 struct snd_soc_component *component;
33 struct snd_soc_rtdcom_list *rtdcom;
Vinod Koul2e622ae2016-11-13 12:10:02 +053034 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Charles Keepax572e6c82018-04-24 16:39:01 +010035 int ret;
Namarta Kohli1245b702012-08-16 17:10:41 +053036
Charles Keepax15e2e612013-01-24 09:44:29 +000037 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
38
Vinod Koul2e622ae2016-11-13 12:10:02 +053039 if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
40 ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
41 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +000042 dev_err(cpu_dai->dev,
43 "Compress ASoC: can't open interface %s: %d\n",
Vinod Koul2e622ae2016-11-13 12:10:02 +053044 cpu_dai->name, ret);
45 goto out;
46 }
47 }
48
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000049 for_each_rtdcom(rtd, rtdcom) {
50 component = rtdcom->component;
51
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000052 if (!component->driver->compr_ops ||
53 !component->driver->compr_ops->open)
54 continue;
55
Charles Keepax572e6c82018-04-24 16:39:01 +010056 ret = component->driver->compr_ops->open(cstream);
57 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +000058 dev_err(component->dev,
59 "Compress ASoC: can't open platform %s: %d\n",
Charles Keepax572e6c82018-04-24 16:39:01 +010060 component->name, ret);
61 goto machine_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000062 }
63 }
Charles Keepax572e6c82018-04-24 16:39:01 +010064 component = NULL;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000065
Namarta Kohli1245b702012-08-16 17:10:41 +053066 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
67 ret = rtd->dai_link->compr_ops->startup(cstream);
68 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +000069 dev_err(rtd->dev,
70 "Compress ASoC: %s startup failed: %d\n",
71 rtd->dai_link->name, ret);
Namarta Kohli1245b702012-08-16 17:10:41 +053072 goto machine_err;
73 }
74 }
75
Lars-Peter Clausen24894b72014-03-05 13:17:43 +010076 snd_soc_runtime_activate(rtd, cstream->direction);
Namarta Kohli1245b702012-08-16 17:10:41 +053077
Charles Keepax15e2e612013-01-24 09:44:29 +000078 mutex_unlock(&rtd->pcm_mutex);
79
Namarta Kohli1245b702012-08-16 17:10:41 +053080 return 0;
81
82machine_err:
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000083 for_each_rtdcom(rtd, rtdcom) {
Charles Keepax572e6c82018-04-24 16:39:01 +010084 struct snd_soc_component *err_comp = rtdcom->component;
85
86 if (err_comp == component)
87 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000088
Charles Keepax572e6c82018-04-24 16:39:01 +010089 if (!err_comp->driver->compr_ops ||
90 !err_comp->driver->compr_ops->free)
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000091 continue;
92
Charles Keepax572e6c82018-04-24 16:39:01 +010093 err_comp->driver->compr_ops->free(cstream);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +000094 }
95
Vinod Koul2e622ae2016-11-13 12:10:02 +053096 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
97 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
Namarta Kohli1245b702012-08-16 17:10:41 +053098out:
Charles Keepax15e2e612013-01-24 09:44:29 +000099 mutex_unlock(&rtd->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530100 return ret;
101}
102
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000103static int soc_compr_open_fe(struct snd_compr_stream *cstream)
104{
105 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700106 struct snd_pcm_substream *fe_substream =
107 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000108 struct snd_soc_component *component;
109 struct snd_soc_rtdcom_list *rtdcom;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530110 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000111 struct snd_soc_dpcm *dpcm;
112 struct snd_soc_dapm_widget_list *list;
113 int stream;
Charles Keepax572e6c82018-04-24 16:39:01 +0100114 int ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000115
116 if (cstream->direction == SND_COMPRESS_PLAYBACK)
117 stream = SNDRV_PCM_STREAM_PLAYBACK;
118 else
119 stream = SNDRV_PCM_STREAM_CAPTURE;
120
121 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
122
Vinod Koul2e622ae2016-11-13 12:10:02 +0530123 if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
124 ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
125 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000126 dev_err(cpu_dai->dev,
127 "Compress ASoC: can't open interface %s: %d\n",
Vinod Koul2e622ae2016-11-13 12:10:02 +0530128 cpu_dai->name, ret);
129 goto out;
130 }
131 }
132
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000133 for_each_rtdcom(fe, rtdcom) {
134 component = rtdcom->component;
135
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000136 if (!component->driver->compr_ops ||
137 !component->driver->compr_ops->open)
138 continue;
139
Charles Keepax572e6c82018-04-24 16:39:01 +0100140 ret = component->driver->compr_ops->open(cstream);
141 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000142 dev_err(component->dev,
143 "Compress ASoC: can't open platform %s: %d\n",
Charles Keepax572e6c82018-04-24 16:39:01 +0100144 component->name, ret);
145 goto machine_err;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000146 }
147 }
Charles Keepax572e6c82018-04-24 16:39:01 +0100148 component = NULL;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000149
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000150 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
151 ret = fe->dai_link->compr_ops->startup(cstream);
152 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000153 pr_err("Compress ASoC: %s startup failed: %d\n",
154 fe->dai_link->name, ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000155 goto machine_err;
156 }
157 }
158
159 fe->dpcm[stream].runtime = fe_substream->runtime;
160
Qiao Zhou8f70e512014-09-10 17:54:07 +0800161 ret = dpcm_path_get(fe, stream, &list);
Qiao Zhou2e4ec1c2014-09-12 09:41:31 +0800162 if (ret < 0)
Qiao Zhou8f70e512014-09-10 17:54:07 +0800163 goto fe_err;
Qiao Zhou2e4ec1c2014-09-12 09:41:31 +0800164 else if (ret == 0)
Charles Keepax141dfc92018-01-26 13:08:45 +0000165 dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000166 fe->dai_link->name, stream ? "capture" : "playback");
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000167
168 /* calculate valid and active FE <-> BE dpcms */
169 dpcm_process_paths(fe, stream, &list, 1);
170
171 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
172
173 ret = dpcm_be_dai_startup(fe, stream);
174 if (ret < 0) {
175 /* clean up all links */
176 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
177 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
178
179 dpcm_be_disconnect(fe, stream);
180 fe->dpcm[stream].runtime = NULL;
Charles Keepaxb0f12c62016-08-16 11:24:46 +0100181 goto path_err;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000182 }
183
184 dpcm_clear_pending_state(fe, stream);
185 dpcm_path_put(&list);
186
187 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
188 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
189
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100190 snd_soc_runtime_activate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000191
192 mutex_unlock(&fe->card->mutex);
193
194 return 0;
195
Charles Keepaxb0f12c62016-08-16 11:24:46 +0100196path_err:
197 dpcm_path_put(&list);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000198fe_err:
199 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
200 fe->dai_link->compr_ops->shutdown(cstream);
201machine_err:
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000202 for_each_rtdcom(fe, rtdcom) {
Charles Keepax572e6c82018-04-24 16:39:01 +0100203 struct snd_soc_component *err_comp = rtdcom->component;
204
205 if (err_comp == component)
206 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000207
Charles Keepax572e6c82018-04-24 16:39:01 +0100208 if (!err_comp->driver->compr_ops ||
209 !err_comp->driver->compr_ops->free)
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000210 continue;
211
Charles Keepax572e6c82018-04-24 16:39:01 +0100212 err_comp->driver->compr_ops->free(cstream);
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000213 }
214
Vinod Koul2e622ae2016-11-13 12:10:02 +0530215 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
216 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000217out:
218 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
219 mutex_unlock(&fe->card->mutex);
220 return ret;
221}
222
Charles Keepax202c8f72013-01-24 09:44:30 +0000223/*
224 * Power down the audio subsystem pmdown_time msecs after close is called.
225 * This is to ensure there are no pops or clicks in between any music tracks
226 * due to DAPM power cycling.
227 */
228static void close_delayed_work(struct work_struct *work)
229{
230 struct snd_soc_pcm_runtime *rtd =
231 container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
232 struct snd_soc_dai *codec_dai = rtd->codec_dai;
233
234 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
235
Charles Keepax141dfc92018-01-26 13:08:45 +0000236 dev_dbg(rtd->dev,
237 "Compress ASoC: pop wq checking: %s status: %s waiting: %s\n",
238 codec_dai->driver->playback.stream_name,
239 codec_dai->playback_active ? "active" : "inactive",
240 rtd->pop_wait ? "yes" : "no");
Charles Keepax202c8f72013-01-24 09:44:30 +0000241
242 /* are we waiting on this codec DAI stream */
243 if (rtd->pop_wait == 1) {
244 rtd->pop_wait = 0;
245 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
246 SND_SOC_DAPM_STREAM_STOP);
247 }
248
249 mutex_unlock(&rtd->pcm_mutex);
250}
251
Namarta Kohli1245b702012-08-16 17:10:41 +0530252static int soc_compr_free(struct snd_compr_stream *cstream)
253{
254 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000255 struct snd_soc_component *component;
256 struct snd_soc_rtdcom_list *rtdcom;
Namarta Kohli1245b702012-08-16 17:10:41 +0530257 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
258 struct snd_soc_dai *codec_dai = rtd->codec_dai;
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100259 int stream;
Namarta Kohli1245b702012-08-16 17:10:41 +0530260
Charles Keepax15e2e612013-01-24 09:44:29 +0000261 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
262
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100263 if (cstream->direction == SND_COMPRESS_PLAYBACK)
264 stream = SNDRV_PCM_STREAM_PLAYBACK;
265 else
266 stream = SNDRV_PCM_STREAM_CAPTURE;
267
268 snd_soc_runtime_deactivate(rtd, stream);
Namarta Kohli1245b702012-08-16 17:10:41 +0530269
Mark Brownda183962013-02-06 15:44:07 +0000270 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
271
Namarta Kohli1245b702012-08-16 17:10:41 +0530272 if (!cpu_dai->active)
273 cpu_dai->rate = 0;
274
275 if (!codec_dai->active)
276 codec_dai->rate = 0;
277
Namarta Kohli1245b702012-08-16 17:10:41 +0530278 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
279 rtd->dai_link->compr_ops->shutdown(cstream);
280
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000281 for_each_rtdcom(rtd, rtdcom) {
282 component = rtdcom->component;
283
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000284 if (!component->driver->compr_ops ||
285 !component->driver->compr_ops->free)
286 continue;
287
288 component->driver->compr_ops->free(cstream);
289 }
290
Vinod Koul2e622ae2016-11-13 12:10:02 +0530291 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
292 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
293
Namarta Kohli1245b702012-08-16 17:10:41 +0530294 if (cstream->direction == SND_COMPRESS_PLAYBACK) {
Lars-Peter Clausen208a1582014-03-05 13:17:42 +0100295 if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
Namarta Kohli1245b702012-08-16 17:10:41 +0530296 snd_soc_dapm_stream_event(rtd,
297 SNDRV_PCM_STREAM_PLAYBACK,
298 SND_SOC_DAPM_STREAM_STOP);
Charles Keepax8c3d2aa2013-01-24 09:44:28 +0000299 } else {
Misael Lopez Cruz9bffb1f2012-12-13 12:23:05 -0600300 rtd->pop_wait = 1;
Mark Brown3d24cfe2013-08-09 18:12:29 +0100301 queue_delayed_work(system_power_efficient_wq,
302 &rtd->delayed_work,
303 msecs_to_jiffies(rtd->pmdown_time));
Charles Keepax8c3d2aa2013-01-24 09:44:28 +0000304 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530305 } else {
306 /* capture streams can be powered down now */
307 snd_soc_dapm_stream_event(rtd,
308 SNDRV_PCM_STREAM_CAPTURE,
309 SND_SOC_DAPM_STREAM_STOP);
310 }
311
Charles Keepax15e2e612013-01-24 09:44:29 +0000312 mutex_unlock(&rtd->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530313 return 0;
314}
315
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000316static int soc_compr_free_fe(struct snd_compr_stream *cstream)
317{
318 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000319 struct snd_soc_component *component;
320 struct snd_soc_rtdcom_list *rtdcom;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530321 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000322 struct snd_soc_dpcm *dpcm;
323 int stream, ret;
324
325 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
326
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100327 if (cstream->direction == SND_COMPRESS_PLAYBACK)
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000328 stream = SNDRV_PCM_STREAM_PLAYBACK;
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100329 else
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000330 stream = SNDRV_PCM_STREAM_CAPTURE;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000331
Lars-Peter Clausen24894b72014-03-05 13:17:43 +0100332 snd_soc_runtime_deactivate(fe, stream);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000333
334 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
335
336 ret = dpcm_be_dai_hw_free(fe, stream);
337 if (ret < 0)
Charles Keepax141dfc92018-01-26 13:08:45 +0000338 dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000339
340 ret = dpcm_be_dai_shutdown(fe, stream);
341
342 /* mark FE's links ready to prune */
343 list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
344 dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
345
Daniel Mack15f6b092014-10-19 09:07:35 +0200346 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000347
348 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
349 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
350
351 dpcm_be_disconnect(fe, stream);
352
353 fe->dpcm[stream].runtime = NULL;
354
355 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
356 fe->dai_link->compr_ops->shutdown(cstream);
357
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000358 for_each_rtdcom(fe, rtdcom) {
359 component = rtdcom->component;
360
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000361 if (!component->driver->compr_ops ||
362 !component->driver->compr_ops->free)
363 continue;
364
365 component->driver->compr_ops->free(cstream);
366 }
367
Vinod Koul2e622ae2016-11-13 12:10:02 +0530368 if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
369 cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
370
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000371 mutex_unlock(&fe->card->mutex);
372 return 0;
373}
374
Namarta Kohli1245b702012-08-16 17:10:41 +0530375static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
376{
377
378 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000379 struct snd_soc_component *component;
380 struct snd_soc_rtdcom_list *rtdcom;
Namarta Kohli1245b702012-08-16 17:10:41 +0530381 struct snd_soc_dai *codec_dai = rtd->codec_dai;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530382 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000383 int ret = 0, __ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530384
Charles Keepax15e2e612013-01-24 09:44:29 +0000385 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
386
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000387 for_each_rtdcom(rtd, rtdcom) {
388 component = rtdcom->component;
389
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000390 if (!component->driver->compr_ops ||
391 !component->driver->compr_ops->trigger)
392 continue;
393
394 __ret = component->driver->compr_ops->trigger(cstream, cmd);
395 if (__ret < 0)
396 ret = __ret;
397 }
398 if (ret < 0)
399 goto out;
400
Vinod Koul2e622ae2016-11-13 12:10:02 +0530401 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
402 cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
403
Mark Brownda183962013-02-06 15:44:07 +0000404 switch (cmd) {
405 case SNDRV_PCM_TRIGGER_START:
406 snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
407 break;
408 case SNDRV_PCM_TRIGGER_STOP:
409 snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
410 break;
Mark Browne38b9b72013-02-06 13:52:42 +0000411 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530412
Charles Keepax15e2e612013-01-24 09:44:29 +0000413out:
414 mutex_unlock(&rtd->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530415 return ret;
416}
417
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000418static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
419{
420 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000421 struct snd_soc_component *component;
422 struct snd_soc_rtdcom_list *rtdcom;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530423 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000424 int ret = 0, __ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000425
426 if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
427 cmd == SND_COMPR_TRIGGER_DRAIN) {
428
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000429 for_each_rtdcom(fe, rtdcom) {
430 component = rtdcom->component;
431
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000432 if (!component->driver->compr_ops ||
433 !component->driver->compr_ops->trigger)
434 continue;
435
436 __ret = component->driver->compr_ops->trigger(cstream, cmd);
437 if (__ret < 0)
438 ret = __ret;
439 }
440 return ret;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000441 }
442
443 if (cstream->direction == SND_COMPRESS_PLAYBACK)
444 stream = SNDRV_PCM_STREAM_PLAYBACK;
445 else
446 stream = SNDRV_PCM_STREAM_CAPTURE;
447
448
449 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
450
Vinod Koul2e622ae2016-11-13 12:10:02 +0530451 if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) {
452 ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
453 if (ret < 0)
454 goto out;
455 }
456
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000457 for_each_rtdcom(fe, rtdcom) {
458 component = rtdcom->component;
459
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000460 if (!component->driver->compr_ops ||
461 !component->driver->compr_ops->trigger)
462 continue;
463
464 __ret = component->driver->compr_ops->trigger(cstream, cmd);
465 if (__ret < 0)
466 ret = __ret;
467 }
468 if (ret < 0)
469 goto out;
470
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000471 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
472
473 ret = dpcm_be_dai_trigger(fe, stream, cmd);
474
475 switch (cmd) {
476 case SNDRV_PCM_TRIGGER_START:
477 case SNDRV_PCM_TRIGGER_RESUME:
478 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
479 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
480 break;
481 case SNDRV_PCM_TRIGGER_STOP:
482 case SNDRV_PCM_TRIGGER_SUSPEND:
483 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
484 break;
485 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
486 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
487 break;
488 }
489
490out:
491 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
492 mutex_unlock(&fe->card->mutex);
493 return ret;
494}
495
Namarta Kohli1245b702012-08-16 17:10:41 +0530496static int soc_compr_set_params(struct snd_compr_stream *cstream,
497 struct snd_compr_params *params)
498{
499 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000500 struct snd_soc_component *component;
501 struct snd_soc_rtdcom_list *rtdcom;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530502 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000503 int ret = 0, __ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530504
Charles Keepax15e2e612013-01-24 09:44:29 +0000505 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
506
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
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000520 for_each_rtdcom(rtd, rtdcom) {
521 component = rtdcom->component;
522
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000523 if (!component->driver->compr_ops ||
524 !component->driver->compr_ops->set_params)
525 continue;
526
527 __ret = component->driver->compr_ops->set_params(cstream, params);
528 if (__ret < 0)
529 ret = __ret;
530 }
531 if (ret < 0)
532 goto err;
533
Namarta Kohli1245b702012-08-16 17:10:41 +0530534 if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
535 ret = rtd->dai_link->compr_ops->set_params(cstream);
536 if (ret < 0)
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000537 goto err;
Namarta Kohli1245b702012-08-16 17:10:41 +0530538 }
539
Charles Keepax2c071ed2013-05-20 08:33:54 +0100540 if (cstream->direction == SND_COMPRESS_PLAYBACK)
541 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
542 SND_SOC_DAPM_STREAM_START);
543 else
544 snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
545 SND_SOC_DAPM_STREAM_START);
Namarta Kohli1245b702012-08-16 17:10:41 +0530546
Charles Keepaxfa40ef22013-03-27 16:39:01 +0000547 /* cancel any delayed stream shutdown that is pending */
548 rtd->pop_wait = 0;
549 mutex_unlock(&rtd->pcm_mutex);
550
551 cancel_delayed_work_sync(&rtd->delayed_work);
552
553 return ret;
554
555err:
Charles Keepax15e2e612013-01-24 09:44:29 +0000556 mutex_unlock(&rtd->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530557 return ret;
558}
559
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000560static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
561 struct snd_compr_params *params)
562{
563 struct snd_soc_pcm_runtime *fe = cstream->private_data;
Satish Babu Patakokila01b8ced2017-06-16 17:33:40 -0700564 struct snd_pcm_substream *fe_substream =
565 fe->pcm->streams[cstream->direction].substream;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000566 struct snd_soc_component *component;
567 struct snd_soc_rtdcom_list *rtdcom;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530568 struct snd_soc_dai *cpu_dai = fe->cpu_dai;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000569 int ret = 0, __ret, stream;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000570
571 if (cstream->direction == SND_COMPRESS_PLAYBACK)
572 stream = SNDRV_PCM_STREAM_PLAYBACK;
573 else
574 stream = SNDRV_PCM_STREAM_CAPTURE;
575
576 mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
577
Vinod Koul2e622ae2016-11-13 12:10:02 +0530578 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
579 ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
580 if (ret < 0)
581 goto out;
582 }
583
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000584 for_each_rtdcom(fe, rtdcom) {
585 component = rtdcom->component;
586
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000587 if (!component->driver->compr_ops ||
588 !component->driver->compr_ops->set_params)
589 continue;
590
591 __ret = component->driver->compr_ops->set_params(cstream, params);
592 if (__ret < 0)
593 ret = __ret;
594 }
595 if (ret < 0)
596 goto out;
597
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000598 if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
599 ret = fe->dai_link->compr_ops->set_params(cstream);
600 if (ret < 0)
601 goto out;
602 }
603
604 /*
605 * Create an empty hw_params for the BE as the machine driver must
606 * fix this up to match DSP decoder and ASRC configuration.
607 * I.e. machine driver fixup for compressed BE is mandatory.
608 */
609 memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
610 sizeof(struct snd_pcm_hw_params));
611
612 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
613
614 ret = dpcm_be_dai_hw_params(fe, stream);
615 if (ret < 0)
616 goto out;
617
618 ret = dpcm_be_dai_prepare(fe, stream);
619 if (ret < 0)
620 goto out;
621
Daniel Mack15f6b092014-10-19 09:07:35 +0200622 dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000623 fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
624
625out:
626 fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
627 mutex_unlock(&fe->card->mutex);
628 return ret;
629}
630
Namarta Kohli1245b702012-08-16 17:10:41 +0530631static int soc_compr_get_params(struct snd_compr_stream *cstream,
632 struct snd_codec *params)
633{
634 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000635 struct snd_soc_component *component;
636 struct snd_soc_rtdcom_list *rtdcom;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530637 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000638 int ret = 0, __ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530639
Charles Keepax15e2e612013-01-24 09:44:29 +0000640 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
641
Vinod Koul2e622ae2016-11-13 12:10:02 +0530642 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
643 ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
644 if (ret < 0)
645 goto err;
646 }
647
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000648 for_each_rtdcom(rtd, rtdcom) {
649 component = rtdcom->component;
650
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000651 if (!component->driver->compr_ops ||
652 !component->driver->compr_ops->get_params)
653 continue;
654
655 __ret = component->driver->compr_ops->get_params(cstream, params);
656 if (__ret < 0)
657 ret = __ret;
658 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530659
Vinod Koul2e622ae2016-11-13 12:10:02 +0530660err:
Charles Keepax15e2e612013-01-24 09:44:29 +0000661 mutex_unlock(&rtd->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530662 return ret;
663}
664
665static int soc_compr_get_caps(struct snd_compr_stream *cstream,
666 struct snd_compr_caps *caps)
667{
668 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000669 struct snd_soc_component *component;
670 struct snd_soc_rtdcom_list *rtdcom;
671 int ret = 0, __ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530672
Charles Keepax15e2e612013-01-24 09:44:29 +0000673 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
674
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000675 for_each_rtdcom(rtd, rtdcom) {
676 component = rtdcom->component;
677
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000678 if (!component->driver->compr_ops ||
679 !component->driver->compr_ops->get_caps)
680 continue;
681
682 __ret = component->driver->compr_ops->get_caps(cstream, caps);
683 if (__ret < 0)
684 ret = __ret;
685 }
686
Charles Keepax15e2e612013-01-24 09:44:29 +0000687 mutex_unlock(&rtd->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530688 return ret;
689}
690
691static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
692 struct snd_compr_codec_caps *codec)
693{
694 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000695 struct snd_soc_component *component;
696 struct snd_soc_rtdcom_list *rtdcom;
697 int ret = 0, __ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530698
Charles Keepax15e2e612013-01-24 09:44:29 +0000699 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
700
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000701 for_each_rtdcom(rtd, rtdcom) {
702 component = rtdcom->component;
703
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000704 if (!component->driver->compr_ops ||
705 !component->driver->compr_ops->get_codec_caps)
706 continue;
707
708 __ret = component->driver->compr_ops->get_codec_caps(cstream, codec);
709 if (__ret < 0)
710 ret = __ret;
711 }
712
Charles Keepax15e2e612013-01-24 09:44:29 +0000713 mutex_unlock(&rtd->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;
721 struct snd_soc_rtdcom_list *rtdcom;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530722 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000723 int ret = 0, __ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530724
Charles Keepax15e2e612013-01-24 09:44:29 +0000725 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
726
Vinod Koul2e622ae2016-11-13 12:10:02 +0530727 if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
728 ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
729 if (ret < 0)
730 goto err;
731 }
732
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000733 for_each_rtdcom(rtd, rtdcom) {
734 component = rtdcom->component;
735
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000736 if (!component->driver->compr_ops ||
737 !component->driver->compr_ops->ack)
738 continue;
739
740 __ret = component->driver->compr_ops->ack(cstream, bytes);
741 if (__ret < 0)
742 ret = __ret;
743 }
Namarta Kohli1245b702012-08-16 17:10:41 +0530744
Vinod Koul2e622ae2016-11-13 12:10:02 +0530745err:
Charles Keepax15e2e612013-01-24 09:44:29 +0000746 mutex_unlock(&rtd->pcm_mutex);
Namarta Kohli1245b702012-08-16 17:10:41 +0530747 return ret;
748}
749
750static int soc_compr_pointer(struct snd_compr_stream *cstream,
751 struct snd_compr_tstamp *tstamp)
752{
753 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000754 struct snd_soc_component *component;
755 struct snd_soc_rtdcom_list *rtdcom;
756 int ret = 0, __ret;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530757 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Namarta Kohli1245b702012-08-16 17:10:41 +0530758
Charles Keepax15e2e612013-01-24 09:44:29 +0000759 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
760
Vinod Koul2e622ae2016-11-13 12:10:02 +0530761 if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
762 cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
763
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000764 for_each_rtdcom(rtd, rtdcom) {
765 component = rtdcom->component;
766
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000767 if (!component->driver->compr_ops ||
768 !component->driver->compr_ops->pointer)
769 continue;
770
771 __ret = component->driver->compr_ops->pointer(cstream, tstamp);
772 if (__ret < 0)
773 ret = __ret;
774 }
775
Charles Keepax15e2e612013-01-24 09:44:29 +0000776 mutex_unlock(&rtd->pcm_mutex);
Charles Keepax7c9190f2016-06-20 09:51:32 +0100777 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +0530778}
779
Charles Keepax1f88eb02013-02-05 10:41:47 +0000780static int soc_compr_copy(struct snd_compr_stream *cstream,
Charles Keepax4daf8912013-04-18 11:01:38 +0100781 char __user *buf, size_t count)
Charles Keepax1f88eb02013-02-05 10:41:47 +0000782{
783 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000784 struct snd_soc_component *component;
785 struct snd_soc_rtdcom_list *rtdcom;
Charles Keepax290df4d32018-01-26 13:08:43 +0000786 int ret = 0;
Charles Keepax1f88eb02013-02-05 10:41:47 +0000787
788 mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
789
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000790 for_each_rtdcom(rtd, rtdcom) {
791 component = rtdcom->component;
792
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000793 if (!component->driver->compr_ops ||
794 !component->driver->compr_ops->copy)
795 continue;
796
Charles Keepax290df4d32018-01-26 13:08:43 +0000797 ret = component->driver->compr_ops->copy(cstream, buf, count);
798 break;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000799 }
Charles Keepax290df4d32018-01-26 13:08:43 +0000800
Charles Keepax1f88eb02013-02-05 10:41:47 +0000801 mutex_unlock(&rtd->pcm_mutex);
802 return ret;
803}
804
Vinod Koul02bd90e2013-07-28 20:06:15 +0530805static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
Jeeja KP36953d92013-03-26 21:22:28 +0530806 struct snd_compr_metadata *metadata)
807{
808 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000809 struct snd_soc_component *component;
810 struct snd_soc_rtdcom_list *rtdcom;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530811 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000812 int ret = 0, __ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530813
Vinod Koul2e622ae2016-11-13 12:10:02 +0530814 if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
815 ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
816 if (ret < 0)
817 return ret;
818 }
819
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000820 for_each_rtdcom(rtd, rtdcom) {
821 component = rtdcom->component;
822
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000823 if (!component->driver->compr_ops ||
824 !component->driver->compr_ops->set_metadata)
825 continue;
826
827 __ret = component->driver->compr_ops->set_metadata(cstream, metadata);
828 if (__ret < 0)
829 ret = __ret;
830 }
Jeeja KP36953d92013-03-26 21:22:28 +0530831
832 return ret;
833}
834
Vinod Koul02bd90e2013-07-28 20:06:15 +0530835static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
Jeeja KP36953d92013-03-26 21:22:28 +0530836 struct snd_compr_metadata *metadata)
837{
838 struct snd_soc_pcm_runtime *rtd = cstream->private_data;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000839 struct snd_soc_component *component;
840 struct snd_soc_rtdcom_list *rtdcom;
Vinod Koul2e622ae2016-11-13 12:10:02 +0530841 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000842 int ret = 0, __ret;
Jeeja KP36953d92013-03-26 21:22:28 +0530843
Vinod Koul2e622ae2016-11-13 12:10:02 +0530844 if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
845 ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
846 if (ret < 0)
847 return ret;
848 }
849
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000850 for_each_rtdcom(rtd, rtdcom) {
851 component = rtdcom->component;
852
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000853 if (!component->driver->compr_ops ||
854 !component->driver->compr_ops->get_metadata)
855 continue;
856
857 __ret = component->driver->compr_ops->get_metadata(cstream, metadata);
858 if (__ret < 0)
859 ret = __ret;
860 }
Jeeja KP36953d92013-03-26 21:22:28 +0530861
862 return ret;
863}
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000864
Namarta Kohli1245b702012-08-16 17:10:41 +0530865/* ASoC Compress operations */
866static struct snd_compr_ops soc_compr_ops = {
867 .open = soc_compr_open,
868 .free = soc_compr_free,
869 .set_params = soc_compr_set_params,
Vinod Koul02bd90e2013-07-28 20:06:15 +0530870 .set_metadata = soc_compr_set_metadata,
871 .get_metadata = soc_compr_get_metadata,
Namarta Kohli1245b702012-08-16 17:10:41 +0530872 .get_params = soc_compr_get_params,
873 .trigger = soc_compr_trigger,
874 .pointer = soc_compr_pointer,
875 .ack = soc_compr_ack,
876 .get_caps = soc_compr_get_caps,
877 .get_codec_caps = soc_compr_get_codec_caps
878};
879
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000880/* ASoC Dynamic Compress operations */
881static struct snd_compr_ops soc_compr_dyn_ops = {
882 .open = soc_compr_open_fe,
883 .free = soc_compr_free_fe,
884 .set_params = soc_compr_set_params_fe,
885 .get_params = soc_compr_get_params,
886 .set_metadata = soc_compr_set_metadata,
887 .get_metadata = soc_compr_get_metadata,
888 .trigger = soc_compr_trigger_fe,
889 .pointer = soc_compr_pointer,
890 .ack = soc_compr_ack,
891 .get_caps = soc_compr_get_caps,
892 .get_codec_caps = soc_compr_get_codec_caps
893};
894
Jie Yang6f0c4222015-10-13 23:41:00 +0800895/**
896 * snd_soc_new_compress - create a new compress.
897 *
898 * @rtd: The runtime for which we will create compress
899 * @num: the device index number (zero based - shared with normal PCMs)
900 *
901 * Return: 0 for success, else error.
902 */
903int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
Namarta Kohli1245b702012-08-16 17:10:41 +0530904{
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000905 struct snd_soc_component *component;
906 struct snd_soc_rtdcom_list *rtdcom;
Namarta Kohli1245b702012-08-16 17:10:41 +0530907 struct snd_soc_dai *codec_dai = rtd->codec_dai;
908 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
909 struct snd_compr *compr;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000910 struct snd_pcm *be_pcm;
Namarta Kohli1245b702012-08-16 17:10:41 +0530911 char new_name[64];
912 int ret = 0, direction = 0;
Vinod Koula1068042016-01-07 21:48:14 +0530913 int playback = 0, capture = 0;
Namarta Kohli1245b702012-08-16 17:10:41 +0530914
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200915 if (rtd->num_codecs > 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000916 dev_err(rtd->card->dev,
917 "Compress ASoC: Multicodec not supported\n");
Benoit Cousson8151d5e2014-07-08 23:19:37 +0200918 return -EINVAL;
919 }
920
Namarta Kohli1245b702012-08-16 17:10:41 +0530921 /* check client and interface hw capabilities */
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100922 if (codec_dai->driver->playback.channels_min)
Vinod Koula1068042016-01-07 21:48:14 +0530923 playback = 1;
924 if (codec_dai->driver->capture.channels_min)
925 capture = 1;
926
927 capture = capture && cpu_dai->driver->capture.channels_min;
928 playback = playback && cpu_dai->driver->playback.channels_min;
929
930 /*
931 * Compress devices are unidirectional so only one of the directions
932 * should be set, check for that (xor)
933 */
934 if (playback + capture != 1) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000935 dev_err(rtd->card->dev,
936 "Compress ASoC: Invalid direction for P %d, C %d\n",
937 playback, capture);
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100938 return -EINVAL;
Vinod Koula1068042016-01-07 21:48:14 +0530939 }
940
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800941 if (playback)
Vinod Koula1068042016-01-07 21:48:14 +0530942 direction = SND_COMPRESS_PLAYBACK;
943 else
944 direction = SND_COMPRESS_CAPTURE;
Charles Keepaxdaa2db52013-04-18 11:02:38 +0100945
Namarta Kohli1245b702012-08-16 17:10:41 +0530946 compr = kzalloc(sizeof(*compr), GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200947 if (!compr)
Namarta Kohli1245b702012-08-16 17:10:41 +0530948 return -ENOMEM;
Namarta Kohli1245b702012-08-16 17:10:41 +0530949
Charles Keepax1f88eb02013-02-05 10:41:47 +0000950 compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
951 GFP_KERNEL);
Markus Elfring7a0cf422017-08-10 16:21:34 +0200952 if (!compr->ops) {
Charles Keepax1f88eb02013-02-05 10:41:47 +0000953 ret = -ENOMEM;
954 goto compr_err;
955 }
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000956
957 if (rtd->dai_link->dynamic) {
958 snprintf(new_name, sizeof(new_name), "(%s)",
959 rtd->dai_link->stream_name);
960
961 ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
Qais Yousefd3268a42015-01-14 08:47:29 +0000962 rtd->dai_link->dpcm_playback,
963 rtd->dai_link->dpcm_capture, &be_pcm);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000964 if (ret < 0) {
Charles Keepax141dfc92018-01-26 13:08:45 +0000965 dev_err(rtd->card->dev,
966 "Compress ASoC: can't create compressed for %s: %d\n",
967 rtd->dai_link->name, ret);
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000968 goto compr_err;
969 }
970
971 rtd->pcm = be_pcm;
972 rtd->fe_compr = 1;
Qais Yousefd3268a42015-01-14 08:47:29 +0000973 if (rtd->dai_link->dpcm_playback)
974 be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
975 else if (rtd->dai_link->dpcm_capture)
976 be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000977 memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800978 } else {
979 snprintf(new_name, sizeof(new_name), "%s %s-%d",
980 rtd->dai_link->stream_name, codec_dai->name, num);
981
Liam Girdwood2a99ef02014-01-17 17:03:56 +0000982 memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
Peng Donglinaeb6fa02017-08-16 22:47:53 +0800983 }
Charles Keepax1f88eb02013-02-05 10:41:47 +0000984
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000985 for_each_rtdcom(rtd, rtdcom) {
986 component = rtdcom->component;
987
Kuninori Morimoto9e7e3732017-10-11 01:37:45 +0000988 if (!component->driver->compr_ops ||
989 !component->driver->compr_ops->copy)
990 continue;
991
992 compr->ops->copy = soc_compr_copy;
993 }
994
995
Namarta Kohli1245b702012-08-16 17:10:41 +0530996 mutex_init(&compr->lock);
Richard Fitzgeralde5241a82015-11-25 13:00:24 +0000997 ret = snd_compress_new(rtd->card->snd_card, num, direction,
998 new_name, compr);
Namarta Kohli1245b702012-08-16 17:10:41 +0530999 if (ret < 0) {
Kuninori Morimotoe5acfc72017-12-05 04:23:05 +00001000 component = rtd->codec_dai->component;
Charles Keepax141dfc92018-01-26 13:08:45 +00001001 dev_err(component->dev,
1002 "Compress ASoC: can't create compress for codec %s: %d\n",
1003 component->name, ret);
Charles Keepax1f88eb02013-02-05 10:41:47 +00001004 goto compr_err;
Namarta Kohli1245b702012-08-16 17:10:41 +05301005 }
1006
Charles Keepax202c8f72013-01-24 09:44:30 +00001007 /* DAPM dai link stream work */
1008 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
1009
Namarta Kohli1245b702012-08-16 17:10:41 +05301010 rtd->compr = compr;
1011 compr->private_data = rtd;
1012
Charles Keepax141dfc92018-01-26 13:08:45 +00001013 dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
1014 codec_dai->name, cpu_dai->name);
Namarta Kohli1245b702012-08-16 17:10:41 +05301015 return ret;
Charles Keepax1f88eb02013-02-05 10:41:47 +00001016
1017compr_err:
1018 kfree(compr);
1019 return ret;
Namarta Kohli1245b702012-08-16 17:10:41 +05301020}
Jie Yang6f0c4222015-10-13 23:41:00 +08001021EXPORT_SYMBOL_GPL(snd_soc_new_compress);