Linux Audio

Check our new training course

Loading...
v6.9.4
  1// 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>
 
 
 
 
 
 
 10
 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>
 21#include <sound/soc-dpcm.h>
 22#include <sound/soc-link.h>
 23
 24static int snd_soc_compr_components_open(struct snd_compr_stream *cstream)
 25{
 26	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 
 27	struct snd_soc_component *component;
 28	int ret = 0;
 29	int i;
 
 30
 31	for_each_rtd_components(rtd, i, component) {
 32		ret = snd_soc_component_module_get_when_open(component, cstream);
 33		if (ret < 0)
 34			break;
 35
 36		ret = snd_soc_component_compr_open(component, cstream);
 37		if (ret < 0)
 38			break;
 
 
 
 
 
 39	}
 40
 41	return ret;
 42}
 43
 44static void snd_soc_compr_components_free(struct snd_compr_stream *cstream,
 45					  int rollback)
 46{
 47	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 48	struct snd_soc_component *component;
 49	int i;
 50
 51	for_each_rtd_components(rtd, i, component) {
 52		snd_soc_component_compr_free(component, cstream, rollback);
 53		snd_soc_component_module_put_when_close(component, cstream, rollback);
 54	}
 55}
 56
 57static int soc_compr_clean(struct snd_compr_stream *cstream, int rollback)
 58{
 59	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 60	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
 61	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
 62	int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
 63
 64	snd_soc_dpcm_mutex_lock(rtd);
 
 
 65
 66	if (!rollback)
 67		snd_soc_runtime_deactivate(rtd, stream);
 
 68
 69	snd_soc_dai_digital_mute(codec_dai, 1, stream);
 
 
 
 
 
 
 
 
 
 70
 71	if (!snd_soc_dai_active(cpu_dai))
 72		cpu_dai->rate = 0;
 
 
 
 
 
 
 
 73
 74	if (!snd_soc_dai_active(codec_dai))
 75		codec_dai->rate = 0;
 76
 77	snd_soc_link_compr_shutdown(cstream, rollback);
 78
 79	snd_soc_compr_components_free(cstream, rollback);
 80
 81	snd_soc_dai_compr_shutdown(cpu_dai, cstream, rollback);
 
 
 82
 83	if (!rollback)
 84		snd_soc_dapm_stream_stop(rtd, stream);
 
 85
 86	snd_soc_dpcm_mutex_unlock(rtd);
 
 
 87
 88	snd_soc_pcm_component_pm_runtime_put(rtd, cstream, rollback);
 
 89
 90	return 0;
 
 
 
 
 
 
 
 91}
 92
 93static int soc_compr_free(struct snd_compr_stream *cstream)
 94{
 95	return soc_compr_clean(cstream, 0);
 96}
 
 
 
 
 
 
 
 
 
 97
 98static int soc_compr_open(struct snd_compr_stream *cstream)
 99{
100	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
101	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
102	int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
103	int ret;
104
105	ret = snd_soc_pcm_component_pm_runtime_get(rtd, cstream);
106	if (ret < 0)
107		goto err_no_lock;
108
109	snd_soc_dpcm_mutex_lock(rtd);
 
 
 
 
 
 
 
 
110
111	ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
112	if (ret < 0)
113		goto err;
 
 
 
 
 
 
114
115	ret = snd_soc_compr_components_open(cstream);
116	if (ret < 0)
117		goto err;
118
119	ret = snd_soc_link_compr_startup(cstream);
120	if (ret < 0)
121		goto err;
122
123	snd_soc_runtime_activate(rtd, stream);
124err:
125	snd_soc_dpcm_mutex_unlock(rtd);
126err_no_lock:
127	if (ret < 0)
128		soc_compr_clean(cstream, 1);
129
130	return ret;
131}
 
 
 
 
 
 
 
 
132
133static int soc_compr_open_fe(struct snd_compr_stream *cstream)
134{
135	struct snd_soc_pcm_runtime *fe = cstream->private_data;
136	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(fe, 0);
137	struct snd_soc_dpcm *dpcm;
138	struct snd_soc_dapm_widget_list *list;
139	int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
140	int ret;
141
142	snd_soc_card_mutex_lock(fe->card);
143
144	ret = dpcm_path_get(fe, stream, &list);
145	if (ret < 0)
146		goto be_err;
147
148	snd_soc_dpcm_mutex_lock(fe);
 
149
150	/* calculate valid and active FE <-> BE dpcms */
151	dpcm_process_paths(fe, stream, &list, 1);
152
153	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
154
155	ret = dpcm_be_dai_startup(fe, stream);
156	if (ret < 0) {
157		/* clean up all links */
158		for_each_dpcm_be(fe, stream, dpcm)
159			dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
160
161		dpcm_be_disconnect(fe, stream);
162		goto out;
 
163	}
164
165	ret = snd_soc_dai_compr_startup(cpu_dai, cstream);
166	if (ret < 0)
167		goto out;
168
169	ret = snd_soc_compr_components_open(cstream);
170	if (ret < 0)
171		goto open_err;
172
173	ret = snd_soc_link_compr_startup(cstream);
174	if (ret < 0)
175		goto machine_err;
176
177	dpcm_clear_pending_state(fe, stream);
178	dpcm_path_put(&list);
179
180	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
181	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
182
183	snd_soc_runtime_activate(fe, stream);
184	snd_soc_dpcm_mutex_unlock(fe);
185
186	snd_soc_card_mutex_unlock(fe->card);
187
188	return 0;
189
 
 
 
 
 
190machine_err:
191	snd_soc_compr_components_free(cstream, 1);
192open_err:
193	snd_soc_dai_compr_shutdown(cpu_dai, cstream, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194out:
195	dpcm_path_put(&list);
196	snd_soc_dpcm_mutex_unlock(fe);
197be_err:
198	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
199	snd_soc_card_mutex_unlock(fe->card);
200	return ret;
201}
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203static int soc_compr_free_fe(struct snd_compr_stream *cstream)
204{
205	struct snd_soc_pcm_runtime *fe = cstream->private_data;
206	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(fe, 0);
 
 
 
207	struct snd_soc_dpcm *dpcm;
208	int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
 
 
209
210	snd_soc_card_mutex_lock(fe->card);
 
 
 
211
212	snd_soc_dpcm_mutex_lock(fe);
213	snd_soc_runtime_deactivate(fe, stream);
214
215	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
216
217	dpcm_be_dai_hw_free(fe, stream);
 
 
218
219	dpcm_be_dai_shutdown(fe, stream);
220
221	/* mark FE's links ready to prune */
222	for_each_dpcm_be(fe, stream, dpcm)
223		dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
224
225	dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
226
227	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
228	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
229
230	dpcm_be_disconnect(fe, stream);
231
232	snd_soc_dpcm_mutex_unlock(fe);
 
 
 
 
 
 
 
 
 
 
 
 
 
233
234	snd_soc_link_compr_shutdown(cstream, 0);
 
 
235
236	snd_soc_compr_components_free(cstream, 0);
 
237
238	snd_soc_dai_compr_shutdown(cpu_dai, cstream, 0);
 
239
240	snd_soc_card_mutex_unlock(fe->card);
241	return 0;
242}
243
244static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
245{
 
246	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
247	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
248	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
249	int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
250	int ret;
 
 
251
252	snd_soc_dpcm_mutex_lock(rtd);
253
254	ret = snd_soc_component_compr_trigger(cstream, cmd);
255	if (ret < 0)
256		goto out;
 
 
 
 
 
257
258	ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
 
 
 
 
 
 
 
 
 
 
 
259	if (ret < 0)
260		goto out;
261
 
 
 
262	switch (cmd) {
263	case SNDRV_PCM_TRIGGER_START:
264		snd_soc_dai_digital_mute(codec_dai, 0, stream);
265		break;
266	case SNDRV_PCM_TRIGGER_STOP:
267		snd_soc_dai_digital_mute(codec_dai, 1, stream);
268		break;
269	}
270
271out:
272	snd_soc_dpcm_mutex_unlock(rtd);
273	return ret;
274}
275
276static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
277{
278	struct snd_soc_pcm_runtime *fe = cstream->private_data;
279	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(fe, 0);
280	int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
281	int ret;
 
 
282
283	if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
284	    cmd == SND_COMPR_TRIGGER_DRAIN)
285		return snd_soc_component_compr_trigger(cstream, cmd);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
287	snd_soc_card_mutex_lock(fe->card);
288
289	ret = snd_soc_dai_compr_trigger(cpu_dai, cstream, cmd);
290	if (ret < 0)
291		goto out;
292
293	ret = snd_soc_component_compr_trigger(cstream, cmd);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294	if (ret < 0)
295		goto out;
296
297	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
298
299	ret = dpcm_be_dai_trigger(fe, stream, cmd);
300
301	switch (cmd) {
302	case SNDRV_PCM_TRIGGER_START:
303	case SNDRV_PCM_TRIGGER_RESUME:
304	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
305		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
306		break;
307	case SNDRV_PCM_TRIGGER_STOP:
308	case SNDRV_PCM_TRIGGER_SUSPEND:
309		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
310		break;
311	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
312		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
313		break;
314	}
315
316out:
317	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
318	snd_soc_card_mutex_unlock(fe->card);
319	return ret;
320}
321
322static int soc_compr_set_params(struct snd_compr_stream *cstream,
323				struct snd_compr_params *params)
324{
325	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
326	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
327	int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
328	int ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
330	snd_soc_dpcm_mutex_lock(rtd);
 
 
 
 
331
332	/*
333	 * First we call set_params for the CPU DAI, then the component
334	 * driver this should configure the SoC side. If the machine has
335	 * compressed ops then we call that as well. The expectation is
336	 * that these callbacks will configure everything for this compress
337	 * path, like configuring a PCM port for a CODEC.
338	 */
339	ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
340	if (ret < 0)
341		goto err;
342
343	ret = snd_soc_component_compr_set_params(cstream, params);
344	if (ret < 0)
345		goto err;
346
347	ret = snd_soc_link_compr_set_params(cstream);
 
 
 
 
 
 
 
348	if (ret < 0)
349		goto err;
350
351	snd_soc_dapm_stream_event(rtd, stream, SND_SOC_DAPM_STREAM_START);
 
 
 
 
 
 
 
 
 
 
 
352
353	/* cancel any delayed stream shutdown that is pending */
354	rtd->pop_wait = 0;
355	snd_soc_dpcm_mutex_unlock(rtd);
356
357	cancel_delayed_work_sync(&rtd->delayed_work);
358
359	return 0;
360
361err:
362	snd_soc_dpcm_mutex_unlock(rtd);
363	return ret;
364}
365
366static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
367				   struct snd_compr_params *params)
368{
369	struct snd_soc_pcm_runtime *fe = cstream->private_data;
370	struct snd_pcm_substream *fe_substream =
371		 fe->pcm->streams[cstream->direction].substream;
372	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(fe, 0);
373	int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */
374	int ret;
 
 
 
 
 
 
 
 
 
375
376	snd_soc_card_mutex_lock(fe->card);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377
378	/*
379	 * Create an empty hw_params for the BE as the machine driver must
380	 * fix this up to match DSP decoder and ASRC configuration.
381	 * I.e. machine driver fixup for compressed BE is mandatory.
382	 */
383	memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
384		sizeof(struct snd_pcm_hw_params));
385
386	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
387
388	snd_soc_dpcm_mutex_lock(fe);
389	ret = dpcm_be_dai_hw_params(fe, stream);
390	snd_soc_dpcm_mutex_unlock(fe);
391	if (ret < 0)
392		goto out;
393
394	snd_soc_dpcm_mutex_lock(fe);
395	ret = dpcm_be_dai_prepare(fe, stream);
396	snd_soc_dpcm_mutex_unlock(fe);
397	if (ret < 0)
398		goto out;
399
400	ret = snd_soc_dai_compr_set_params(cpu_dai, cstream, params);
401	if (ret < 0)
402		goto out;
403
404	ret = snd_soc_component_compr_set_params(cstream, params);
405	if (ret < 0)
406		goto out;
407
408	ret = snd_soc_link_compr_set_params(cstream);
409	if (ret < 0)
410		goto out;
411	snd_soc_dpcm_mutex_lock(fe);
412	dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
413	snd_soc_dpcm_mutex_unlock(fe);
414	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
415
416out:
417	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
418	snd_soc_card_mutex_unlock(fe->card);
419	return ret;
420}
421
422static int soc_compr_get_params(struct snd_compr_stream *cstream,
423				struct snd_codec *params)
424{
425	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
426	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
427	int ret = 0;
 
 
 
428
429	snd_soc_dpcm_mutex_lock(rtd);
430
431	ret = snd_soc_dai_compr_get_params(cpu_dai, cstream, params);
432	if (ret < 0)
433		goto err;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
435	ret = snd_soc_component_compr_get_params(cstream, params);
436err:
437	snd_soc_dpcm_mutex_unlock(rtd);
438	return ret;
439}
440
441static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
442{
443	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
444	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
445	int ret;
 
 
 
446
447	snd_soc_dpcm_mutex_lock(rtd);
448
449	ret = snd_soc_dai_compr_ack(cpu_dai, cstream, bytes);
450	if (ret < 0)
451		goto err;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452
453	ret = snd_soc_component_compr_ack(cstream, bytes);
454err:
455	snd_soc_dpcm_mutex_unlock(rtd);
456	return ret;
457}
458
459static int soc_compr_pointer(struct snd_compr_stream *cstream,
460			     struct snd_compr_tstamp *tstamp)
461{
462	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
463	int ret;
464	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
 
 
 
465
466	snd_soc_dpcm_mutex_lock(rtd);
467
468	ret = snd_soc_dai_compr_pointer(cpu_dai, cstream, tstamp);
469	if (ret < 0)
470		goto out;
471
472	ret = snd_soc_component_compr_pointer(cstream, tstamp);
473out:
474	snd_soc_dpcm_mutex_unlock(rtd);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475	return ret;
476}
477
478static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
479				  struct snd_compr_metadata *metadata)
480{
481	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
482	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
483	int ret;
 
 
 
484
485	ret = snd_soc_dai_compr_set_metadata(cpu_dai, cstream, metadata);
486	if (ret < 0)
487		return ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
488
489	return snd_soc_component_compr_set_metadata(cstream, metadata);
 
 
 
 
 
490}
491
492static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
493				  struct snd_compr_metadata *metadata)
494{
495	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
496	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
497	int ret;
 
 
 
498
499	ret = snd_soc_dai_compr_get_metadata(cpu_dai, cstream, metadata);
500	if (ret < 0)
501		return ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
502
503	return snd_soc_component_compr_get_metadata(cstream, metadata);
 
 
 
 
 
504}
505
506/* ASoC Compress operations */
507static struct snd_compr_ops soc_compr_ops = {
508	.open		= soc_compr_open,
509	.free		= soc_compr_free,
510	.set_params	= soc_compr_set_params,
511	.set_metadata   = soc_compr_set_metadata,
512	.get_metadata	= soc_compr_get_metadata,
513	.get_params	= soc_compr_get_params,
514	.trigger	= soc_compr_trigger,
515	.pointer	= soc_compr_pointer,
516	.ack		= soc_compr_ack,
517	.get_caps	= snd_soc_component_compr_get_caps,
518	.get_codec_caps = snd_soc_component_compr_get_codec_caps,
519};
520
521/* ASoC Dynamic Compress operations */
522static struct snd_compr_ops soc_compr_dyn_ops = {
523	.open		= soc_compr_open_fe,
524	.free		= soc_compr_free_fe,
525	.set_params	= soc_compr_set_params_fe,
526	.get_params	= soc_compr_get_params,
527	.set_metadata   = soc_compr_set_metadata,
528	.get_metadata	= soc_compr_get_metadata,
529	.trigger	= soc_compr_trigger_fe,
530	.pointer	= soc_compr_pointer,
531	.ack		= soc_compr_ack,
532	.get_caps	= snd_soc_component_compr_get_caps,
533	.get_codec_caps = snd_soc_component_compr_get_codec_caps,
534};
535
536/**
537 * snd_soc_new_compress - create a new compress.
538 *
539 * @rtd: The runtime for which we will create compress
540 * @num: the device index number (zero based - shared with normal PCMs)
541 *
542 * Return: 0 for success, else error.
543 */
544int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
545{
 
546	struct snd_soc_component *component;
547	struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
548	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
 
549	struct snd_compr *compr;
550	struct snd_pcm *be_pcm;
551	char new_name[64];
552	int ret = 0, direction = 0;
553	int playback = 0, capture = 0;
554	int i;
555
556	/*
557	 * make sure these are same value,
558	 * and then use these as equally
559	 */
560	BUILD_BUG_ON((int)SNDRV_PCM_STREAM_PLAYBACK != (int)SND_COMPRESS_PLAYBACK);
561	BUILD_BUG_ON((int)SNDRV_PCM_STREAM_CAPTURE  != (int)SND_COMPRESS_CAPTURE);
562
563	if (rtd->dai_link->num_cpus > 1 ||
564	    rtd->dai_link->num_codecs > 1) {
565		dev_err(rtd->card->dev,
566			"Compress ASoC: Multi CPU/Codec not supported\n");
567		return -EINVAL;
568	}
569
570	if (!codec_dai) {
571		dev_err(rtd->card->dev, "Missing codec\n");
572		return -EINVAL;
573	}
574
575	/* check client and interface hw capabilities */
576	if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
577	    snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_PLAYBACK))
578		playback = 1;
579	if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
580	    snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_CAPTURE))
581		capture = 1;
582
 
 
 
583	/*
584	 * Compress devices are unidirectional so only one of the directions
585	 * should be set, check for that (xor)
586	 */
587	if (playback + capture != 1) {
588		dev_err(rtd->card->dev,
589			"Compress ASoC: Invalid direction for P %d, C %d\n",
590			playback, capture);
591		return -EINVAL;
592	}
593
594	if (playback)
595		direction = SND_COMPRESS_PLAYBACK;
596	else
597		direction = SND_COMPRESS_CAPTURE;
598
599	compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
600	if (!compr)
601		return -ENOMEM;
602
603	compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
604				  GFP_KERNEL);
605	if (!compr->ops)
606		return -ENOMEM;
 
 
607
608	if (rtd->dai_link->dynamic) {
609		snprintf(new_name, sizeof(new_name), "(%s)",
610			rtd->dai_link->stream_name);
611
612		ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
613				rtd->dai_link->dpcm_playback,
614				rtd->dai_link->dpcm_capture, &be_pcm);
615		if (ret < 0) {
616			dev_err(rtd->card->dev,
617				"Compress ASoC: can't create compressed for %s: %d\n",
618				rtd->dai_link->name, ret);
619			return ret;
620		}
621
622		/* inherit atomicity from DAI link */
623		be_pcm->nonatomic = rtd->dai_link->nonatomic;
624
625		rtd->pcm = be_pcm;
626		rtd->fe_compr = 1;
627		if (rtd->dai_link->dpcm_playback)
628			be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
629		if (rtd->dai_link->dpcm_capture)
630			be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
631		memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
632	} else {
633		snprintf(new_name, sizeof(new_name), "%s %s-%d",
634			rtd->dai_link->stream_name, codec_dai->name, num);
635
636		memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
637	}
638
639	for_each_rtd_components(rtd, i, component) {
640		if (!component->driver->compress_ops ||
641		    !component->driver->compress_ops->copy)
 
 
 
 
 
 
 
642			continue;
643
644		compr->ops->copy = snd_soc_component_compr_copy;
645		break;
 
 
 
646	}
647
 
 
648	ret = snd_compress_new(rtd->card->snd_card, num, direction,
649				new_name, compr);
650	if (ret < 0) {
651		component = snd_soc_rtd_to_codec(rtd, 0)->component;
652		dev_err(component->dev,
653			"Compress ASoC: can't create compress for codec %s: %d\n",
654			component->name, ret);
655		return ret;
656	}
657
658	/* DAPM dai link stream work */
659	rtd->close_delayed_work_func = snd_soc_close_delayed_work;
660
661	rtd->compr = compr;
662	compr->private_data = rtd;
663
664	dev_dbg(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
665		codec_dai->name, cpu_dai->name);
 
666
667	return 0;
 
 
668}
669EXPORT_SYMBOL_GPL(snd_soc_new_compress);
v4.17
   1/*
   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>
  27#include <sound/soc-dpcm.h>
 
  28
  29static int soc_compr_open(struct snd_compr_stream *cstream)
  30{
  31	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
  32	struct snd_soc_platform *platform = rtd->platform;
  33	struct snd_soc_component *component;
  34	struct snd_soc_rtdcom_list *rtdcom;
  35	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
  36	int ret = 0, __ret;
  37
  38	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
 
 
  39
  40	if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
  41		ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
  42		if (ret < 0) {
  43			dev_err(cpu_dai->dev,
  44				"Compress ASoC: can't open interface %s: %d\n",
  45				cpu_dai->name, ret);
  46			goto out;
  47		}
  48	}
  49
  50	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->open) {
  51		ret = platform->driver->compr_ops->open(cstream);
  52		if (ret < 0) {
  53			dev_err(platform->dev,
  54				"Compress ASoC: can't open platform %s: %d\n",
  55				platform->component.name, ret);
  56			goto plat_err;
  57		}
 
 
 
 
 
  58	}
 
  59
  60	for_each_rtdcom(rtd, rtdcom) {
  61		component = rtdcom->component;
 
 
 
 
  62
  63		/* ignore duplication for now */
  64		if (platform && (component == &platform->component))
  65			continue;
  66
  67		if (!component->driver->compr_ops ||
  68		    !component->driver->compr_ops->open)
  69			continue;
  70
  71		__ret = component->driver->compr_ops->open(cstream);
  72		if (__ret < 0) {
  73			dev_err(component->dev,
  74				"Compress ASoC: can't open platform %s: %d\n",
  75				component->name, __ret);
  76			ret = __ret;
  77		}
  78	}
  79	if (ret < 0)
  80		goto machine_err;
  81
  82	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
  83		ret = rtd->dai_link->compr_ops->startup(cstream);
  84		if (ret < 0) {
  85			dev_err(rtd->dev,
  86				"Compress ASoC: %s startup failed: %d\n",
  87				rtd->dai_link->name, ret);
  88			goto machine_err;
  89		}
  90	}
  91
  92	snd_soc_runtime_activate(rtd, cstream->direction);
 
  93
  94	mutex_unlock(&rtd->pcm_mutex);
  95
  96	return 0;
  97
  98machine_err:
  99	for_each_rtdcom(rtd, rtdcom) {
 100		component = rtdcom->component;
 101
 102		/* ignore duplication for now */
 103		if (platform && (component == &platform->component))
 104			continue;
 105
 106		if (!component->driver->compr_ops ||
 107		    !component->driver->compr_ops->free)
 108			continue;
 109
 110		component->driver->compr_ops->free(cstream);
 111	}
 112
 113	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
 114		platform->driver->compr_ops->free(cstream);
 115plat_err:
 116	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 117		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 118out:
 119	mutex_unlock(&rtd->pcm_mutex);
 120	return ret;
 121}
 122
 123static int soc_compr_open_fe(struct snd_compr_stream *cstream)
 124{
 125	struct snd_soc_pcm_runtime *fe = cstream->private_data;
 126	struct snd_pcm_substream *fe_substream =
 127		 fe->pcm->streams[cstream->direction].substream;
 128	struct snd_soc_platform *platform = fe->platform;
 129	struct snd_soc_component *component;
 130	struct snd_soc_rtdcom_list *rtdcom;
 131	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 132	struct snd_soc_dpcm *dpcm;
 133	struct snd_soc_dapm_widget_list *list;
 134	int stream;
 135	int ret = 0, __ret;
 136
 137	if (cstream->direction == SND_COMPRESS_PLAYBACK)
 138		stream = SNDRV_PCM_STREAM_PLAYBACK;
 139	else
 140		stream = SNDRV_PCM_STREAM_CAPTURE;
 
 
 141
 142	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 
 
 143
 144	if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
 145		ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
 146		if (ret < 0) {
 147			dev_err(cpu_dai->dev,
 148				"Compress ASoC: can't open interface %s: %d\n",
 149				cpu_dai->name, ret);
 150			goto out;
 151		}
 152	}
 153
 154	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->open) {
 155		ret = platform->driver->compr_ops->open(cstream);
 156		if (ret < 0) {
 157			dev_err(platform->dev,
 158				"Compress ASoC: can't open platform %s: %d\n",
 159				platform->component.name, ret);
 160			goto plat_err;
 161		}
 162	}
 163
 164	for_each_rtdcom(fe, rtdcom) {
 165		component = rtdcom->component;
 
 166
 167		/* ignore duplication for now */
 168		if (platform && (component == &platform->component))
 169			continue;
 170
 171		if (!component->driver->compr_ops ||
 172		    !component->driver->compr_ops->open)
 173			continue;
 
 
 
 174
 175		__ret = component->driver->compr_ops->open(cstream);
 176		if (__ret < 0) {
 177			dev_err(component->dev,
 178				"Compress ASoC: can't open platform %s: %d\n",
 179				component->name, __ret);
 180			ret = __ret;
 181		}
 182	}
 183	if (ret < 0)
 184		goto machine_err;
 185
 186	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
 187		ret = fe->dai_link->compr_ops->startup(cstream);
 188		if (ret < 0) {
 189			pr_err("Compress ASoC: %s startup failed: %d\n",
 190			       fe->dai_link->name, ret);
 191			goto machine_err;
 192		}
 193	}
 194
 195	fe->dpcm[stream].runtime = fe_substream->runtime;
 196
 197	ret = dpcm_path_get(fe, stream, &list);
 198	if (ret < 0)
 199		goto fe_err;
 200	else if (ret == 0)
 201		dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
 202			fe->dai_link->name, stream ? "capture" : "playback");
 203
 204	/* calculate valid and active FE <-> BE dpcms */
 205	dpcm_process_paths(fe, stream, &list, 1);
 206
 207	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 208
 209	ret = dpcm_be_dai_startup(fe, stream);
 210	if (ret < 0) {
 211		/* clean up all links */
 212		list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
 213			dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
 214
 215		dpcm_be_disconnect(fe, stream);
 216		fe->dpcm[stream].runtime = NULL;
 217		goto path_err;
 218	}
 219
 
 
 
 
 
 
 
 
 
 
 
 
 220	dpcm_clear_pending_state(fe, stream);
 221	dpcm_path_put(&list);
 222
 223	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
 224	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 225
 226	snd_soc_runtime_activate(fe, stream);
 
 227
 228	mutex_unlock(&fe->card->mutex);
 229
 230	return 0;
 231
 232path_err:
 233	dpcm_path_put(&list);
 234fe_err:
 235	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
 236		fe->dai_link->compr_ops->shutdown(cstream);
 237machine_err:
 238	for_each_rtdcom(fe, rtdcom) {
 239		component = rtdcom->component;
 240
 241		/* ignore duplication for now */
 242		if (platform && (component == &platform->component))
 243			continue;
 244
 245		if (!component->driver->compr_ops ||
 246		    !component->driver->compr_ops->free)
 247			continue;
 248
 249		component->driver->compr_ops->free(cstream);
 250	}
 251
 252	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
 253		platform->driver->compr_ops->free(cstream);
 254plat_err:
 255	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 256		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 257out:
 
 
 
 258	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 259	mutex_unlock(&fe->card->mutex);
 260	return ret;
 261}
 262
 263/*
 264 * Power down the audio subsystem pmdown_time msecs after close is called.
 265 * This is to ensure there are no pops or clicks in between any music tracks
 266 * due to DAPM power cycling.
 267 */
 268static void close_delayed_work(struct work_struct *work)
 269{
 270	struct snd_soc_pcm_runtime *rtd =
 271			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
 272	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 273
 274	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 275
 276	dev_dbg(rtd->dev,
 277		"Compress ASoC: pop wq checking: %s status: %s waiting: %s\n",
 278		codec_dai->driver->playback.stream_name,
 279		codec_dai->playback_active ? "active" : "inactive",
 280		rtd->pop_wait ? "yes" : "no");
 281
 282	/* are we waiting on this codec DAI stream */
 283	if (rtd->pop_wait == 1) {
 284		rtd->pop_wait = 0;
 285		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
 286					  SND_SOC_DAPM_STREAM_STOP);
 287	}
 288
 289	mutex_unlock(&rtd->pcm_mutex);
 290}
 291
 292static int soc_compr_free(struct snd_compr_stream *cstream)
 293{
 294	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 295	struct snd_soc_platform *platform = rtd->platform;
 296	struct snd_soc_component *component;
 297	struct snd_soc_rtdcom_list *rtdcom;
 298	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 299	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 300	int stream;
 301
 302	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 303
 304	if (cstream->direction == SND_COMPRESS_PLAYBACK)
 305		stream = SNDRV_PCM_STREAM_PLAYBACK;
 306	else
 307		stream = SNDRV_PCM_STREAM_CAPTURE;
 308
 309	snd_soc_runtime_deactivate(rtd, stream);
 310
 311	snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
 312
 313	if (!cpu_dai->active)
 314		cpu_dai->rate = 0;
 315
 316	if (!codec_dai->active)
 317		codec_dai->rate = 0;
 318
 319	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
 320		rtd->dai_link->compr_ops->shutdown(cstream);
 321
 322	for_each_rtdcom(rtd, rtdcom) {
 323		component = rtdcom->component;
 324
 325		/* ignore duplication for now */
 326		if (platform && (component == &platform->component))
 327			continue;
 328
 329		if (!component->driver->compr_ops ||
 330		    !component->driver->compr_ops->free)
 331			continue;
 332
 333		component->driver->compr_ops->free(cstream);
 334	}
 335
 336	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
 337		platform->driver->compr_ops->free(cstream);
 338
 339	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 340		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 341
 342	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
 343		if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
 344			snd_soc_dapm_stream_event(rtd,
 345					SNDRV_PCM_STREAM_PLAYBACK,
 346					SND_SOC_DAPM_STREAM_STOP);
 347		} else {
 348			rtd->pop_wait = 1;
 349			queue_delayed_work(system_power_efficient_wq,
 350					   &rtd->delayed_work,
 351					   msecs_to_jiffies(rtd->pmdown_time));
 352		}
 353	} else {
 354		/* capture streams can be powered down now */
 355		snd_soc_dapm_stream_event(rtd,
 356			SNDRV_PCM_STREAM_CAPTURE,
 357			SND_SOC_DAPM_STREAM_STOP);
 358	}
 359
 360	mutex_unlock(&rtd->pcm_mutex);
 361	return 0;
 362}
 363
 364static int soc_compr_free_fe(struct snd_compr_stream *cstream)
 365{
 366	struct snd_soc_pcm_runtime *fe = cstream->private_data;
 367	struct snd_soc_platform *platform = fe->platform;
 368	struct snd_soc_component *component;
 369	struct snd_soc_rtdcom_list *rtdcom;
 370	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 371	struct snd_soc_dpcm *dpcm;
 372	int stream, ret;
 373
 374	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 375
 376	if (cstream->direction == SND_COMPRESS_PLAYBACK)
 377		stream = SNDRV_PCM_STREAM_PLAYBACK;
 378	else
 379		stream = SNDRV_PCM_STREAM_CAPTURE;
 380
 
 381	snd_soc_runtime_deactivate(fe, stream);
 382
 383	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 384
 385	ret = dpcm_be_dai_hw_free(fe, stream);
 386	if (ret < 0)
 387		dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
 388
 389	ret = dpcm_be_dai_shutdown(fe, stream);
 390
 391	/* mark FE's links ready to prune */
 392	list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
 393		dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
 394
 395	dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
 396
 397	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
 398	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 399
 400	dpcm_be_disconnect(fe, stream);
 401
 402	fe->dpcm[stream].runtime = NULL;
 403
 404	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
 405		fe->dai_link->compr_ops->shutdown(cstream);
 406
 407	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
 408		platform->driver->compr_ops->free(cstream);
 409
 410	for_each_rtdcom(fe, rtdcom) {
 411		component = rtdcom->component;
 412
 413		/* ignore duplication for now */
 414		if (platform && (component == &platform->component))
 415			continue;
 416
 417		if (!component->driver->compr_ops ||
 418		    !component->driver->compr_ops->free)
 419			continue;
 420
 421		component->driver->compr_ops->free(cstream);
 422	}
 423
 424	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 425		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 426
 427	mutex_unlock(&fe->card->mutex);
 428	return 0;
 429}
 430
 431static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
 432{
 433
 434	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 435	struct snd_soc_platform *platform = rtd->platform;
 436	struct snd_soc_component *component;
 437	struct snd_soc_rtdcom_list *rtdcom;
 438	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 439	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 440	int ret = 0, __ret;
 441
 442	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 443
 444	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
 445		ret = platform->driver->compr_ops->trigger(cstream, cmd);
 446		if (ret < 0)
 447			goto out;
 448	}
 449
 450	for_each_rtdcom(rtd, rtdcom) {
 451		component = rtdcom->component;
 452
 453		/* ignore duplication for now */
 454		if (platform && (component == &platform->component))
 455			continue;
 456
 457		if (!component->driver->compr_ops ||
 458		    !component->driver->compr_ops->trigger)
 459			continue;
 460
 461		__ret = component->driver->compr_ops->trigger(cstream, cmd);
 462		if (__ret < 0)
 463			ret = __ret;
 464	}
 465	if (ret < 0)
 466		goto out;
 467
 468	if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
 469		cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
 470
 471	switch (cmd) {
 472	case SNDRV_PCM_TRIGGER_START:
 473		snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
 474		break;
 475	case SNDRV_PCM_TRIGGER_STOP:
 476		snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
 477		break;
 478	}
 479
 480out:
 481	mutex_unlock(&rtd->pcm_mutex);
 482	return ret;
 483}
 484
 485static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
 486{
 487	struct snd_soc_pcm_runtime *fe = cstream->private_data;
 488	struct snd_soc_platform *platform = fe->platform;
 489	struct snd_soc_component *component;
 490	struct snd_soc_rtdcom_list *rtdcom;
 491	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 492	int ret = 0, __ret, stream;
 493
 494	if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
 495		cmd == SND_COMPR_TRIGGER_DRAIN) {
 496
 497		if (platform &&
 498		    platform->driver->compr_ops &&
 499		    platform->driver->compr_ops->trigger)
 500			return platform->driver->compr_ops->trigger(cstream,
 501								    cmd);
 502
 503		for_each_rtdcom(fe, rtdcom) {
 504			component = rtdcom->component;
 505
 506			/* ignore duplication for now */
 507			if (platform && (component == &platform->component))
 508				continue;
 509
 510			if (!component->driver->compr_ops ||
 511			    !component->driver->compr_ops->trigger)
 512				continue;
 513
 514			__ret = component->driver->compr_ops->trigger(cstream, cmd);
 515			if (__ret < 0)
 516				ret = __ret;
 517		}
 518		return ret;
 519	}
 520
 521	if (cstream->direction == SND_COMPRESS_PLAYBACK)
 522		stream = SNDRV_PCM_STREAM_PLAYBACK;
 523	else
 524		stream = SNDRV_PCM_STREAM_CAPTURE;
 525
 
 526
 527	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 
 
 528
 529	if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) {
 530		ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
 531		if (ret < 0)
 532			goto out;
 533	}
 534
 535	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
 536		ret = platform->driver->compr_ops->trigger(cstream, cmd);
 537		if (ret < 0)
 538			goto out;
 539	}
 540
 541	for_each_rtdcom(fe, rtdcom) {
 542		component = rtdcom->component;
 543
 544		/* ignore duplication for now */
 545		if (platform && (component == &platform->component))
 546			continue;
 547
 548		if (!component->driver->compr_ops ||
 549		    !component->driver->compr_ops->trigger)
 550			continue;
 551
 552		__ret = component->driver->compr_ops->trigger(cstream, cmd);
 553		if (__ret < 0)
 554			ret = __ret;
 555	}
 556	if (ret < 0)
 557		goto out;
 558
 559	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 560
 561	ret = dpcm_be_dai_trigger(fe, stream, cmd);
 562
 563	switch (cmd) {
 564	case SNDRV_PCM_TRIGGER_START:
 565	case SNDRV_PCM_TRIGGER_RESUME:
 566	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 567		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
 568		break;
 569	case SNDRV_PCM_TRIGGER_STOP:
 570	case SNDRV_PCM_TRIGGER_SUSPEND:
 571		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
 572		break;
 573	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 574		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
 575		break;
 576	}
 577
 578out:
 579	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 580	mutex_unlock(&fe->card->mutex);
 581	return ret;
 582}
 583
 584static int soc_compr_set_params(struct snd_compr_stream *cstream,
 585					struct snd_compr_params *params)
 586{
 587	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 588	struct snd_soc_platform *platform = rtd->platform;
 589	struct snd_soc_component *component;
 590	struct snd_soc_rtdcom_list *rtdcom;
 591	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 592	int ret = 0, __ret;
 593
 594	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 595
 596	/* first we call set_params for the platform driver
 597	 * this should configure the soc side
 598	 * if the machine has compressed ops then we call that as well
 599	 * expectation is that platform and machine will configure everything
 600	 * for this compress path, like configuring pcm port for codec
 601	 */
 602	if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
 603		ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
 604		if (ret < 0)
 605			goto err;
 606	}
 607
 608	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
 609		ret = platform->driver->compr_ops->set_params(cstream, params);
 610		if (ret < 0)
 611			goto err;
 612	}
 613
 614	for_each_rtdcom(rtd, rtdcom) {
 615		component = rtdcom->component;
 
 
 
 
 
 
 
 
 616
 617		/* ignore duplication for now */
 618		if (platform && (component == &platform->component))
 619			continue;
 620
 621		if (!component->driver->compr_ops ||
 622		    !component->driver->compr_ops->set_params)
 623			continue;
 624
 625		__ret = component->driver->compr_ops->set_params(cstream, params);
 626		if (__ret < 0)
 627			ret = __ret;
 628	}
 629	if (ret < 0)
 630		goto err;
 631
 632	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
 633		ret = rtd->dai_link->compr_ops->set_params(cstream);
 634		if (ret < 0)
 635			goto err;
 636	}
 637
 638	if (cstream->direction == SND_COMPRESS_PLAYBACK)
 639		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
 640					SND_SOC_DAPM_STREAM_START);
 641	else
 642		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
 643					SND_SOC_DAPM_STREAM_START);
 644
 645	/* cancel any delayed stream shutdown that is pending */
 646	rtd->pop_wait = 0;
 647	mutex_unlock(&rtd->pcm_mutex);
 648
 649	cancel_delayed_work_sync(&rtd->delayed_work);
 650
 651	return ret;
 652
 653err:
 654	mutex_unlock(&rtd->pcm_mutex);
 655	return ret;
 656}
 657
 658static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
 659					struct snd_compr_params *params)
 660{
 661	struct snd_soc_pcm_runtime *fe = cstream->private_data;
 662	struct snd_pcm_substream *fe_substream =
 663		 fe->pcm->streams[cstream->direction].substream;
 664	struct snd_soc_platform *platform = fe->platform;
 665	struct snd_soc_component *component;
 666	struct snd_soc_rtdcom_list *rtdcom;
 667	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 668	int ret = 0, __ret, stream;
 669
 670	if (cstream->direction == SND_COMPRESS_PLAYBACK)
 671		stream = SNDRV_PCM_STREAM_PLAYBACK;
 672	else
 673		stream = SNDRV_PCM_STREAM_CAPTURE;
 674
 675	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 676
 677	if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
 678		ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
 679		if (ret < 0)
 680			goto out;
 681	}
 682
 683	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
 684		ret = platform->driver->compr_ops->set_params(cstream, params);
 685		if (ret < 0)
 686			goto out;
 687	}
 688
 689	for_each_rtdcom(fe, rtdcom) {
 690		component = rtdcom->component;
 691
 692		/* ignore duplication for now */
 693		if (platform && (component == &platform->component))
 694			continue;
 695
 696		if (!component->driver->compr_ops ||
 697		    !component->driver->compr_ops->set_params)
 698			continue;
 699
 700		__ret = component->driver->compr_ops->set_params(cstream, params);
 701		if (__ret < 0)
 702			ret = __ret;
 703	}
 704	if (ret < 0)
 705		goto out;
 706
 707	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
 708		ret = fe->dai_link->compr_ops->set_params(cstream);
 709		if (ret < 0)
 710			goto out;
 711	}
 712
 713	/*
 714	 * Create an empty hw_params for the BE as the machine driver must
 715	 * fix this up to match DSP decoder and ASRC configuration.
 716	 * I.e. machine driver fixup for compressed BE is mandatory.
 717	 */
 718	memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
 719		sizeof(struct snd_pcm_hw_params));
 720
 721	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
 722
 
 723	ret = dpcm_be_dai_hw_params(fe, stream);
 
 724	if (ret < 0)
 725		goto out;
 726
 
 727	ret = dpcm_be_dai_prepare(fe, stream);
 
 
 
 
 
 728	if (ret < 0)
 729		goto out;
 730
 
 
 
 
 
 
 
 
 731	dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
 
 732	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
 733
 734out:
 735	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
 736	mutex_unlock(&fe->card->mutex);
 737	return ret;
 738}
 739
 740static int soc_compr_get_params(struct snd_compr_stream *cstream,
 741					struct snd_codec *params)
 742{
 743	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 744	struct snd_soc_platform *platform = rtd->platform;
 745	struct snd_soc_component *component;
 746	struct snd_soc_rtdcom_list *rtdcom;
 747	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 748	int ret = 0, __ret;
 749
 750	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 751
 752	if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
 753		ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
 754		if (ret < 0)
 755			goto err;
 756	}
 757
 758	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_params) {
 759		ret = platform->driver->compr_ops->get_params(cstream, params);
 760		if (ret < 0)
 761			goto err;
 762	}
 763
 764	for_each_rtdcom(rtd, rtdcom) {
 765		component = rtdcom->component;
 766
 767		/* ignore duplication for now */
 768		if (platform && (component == &platform->component))
 769			continue;
 770
 771		if (!component->driver->compr_ops ||
 772		    !component->driver->compr_ops->get_params)
 773			continue;
 774
 775		__ret = component->driver->compr_ops->get_params(cstream, params);
 776		if (__ret < 0)
 777			ret = __ret;
 778	}
 779
 780err:
 781	mutex_unlock(&rtd->pcm_mutex);
 782	return ret;
 783}
 784
 785static int soc_compr_get_caps(struct snd_compr_stream *cstream,
 786				struct snd_compr_caps *caps)
 787{
 788	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 789	struct snd_soc_platform *platform = rtd->platform;
 790	struct snd_soc_component *component;
 791	struct snd_soc_rtdcom_list *rtdcom;
 792	int ret = 0, __ret;
 793
 794	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 795
 796	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_caps) {
 797		ret = platform->driver->compr_ops->get_caps(cstream, caps);
 798		if (ret < 0)
 799			goto err;
 800	}
 801
 802	for_each_rtdcom(rtd, rtdcom) {
 803		component = rtdcom->component;
 804
 805		/* ignore duplication for now */
 806		if (platform && (component == &platform->component))
 807			continue;
 808
 809		if (!component->driver->compr_ops ||
 810		    !component->driver->compr_ops->get_caps)
 811			continue;
 812
 813		__ret = component->driver->compr_ops->get_caps(cstream, caps);
 814		if (__ret < 0)
 815			ret = __ret;
 816	}
 817
 818err:
 819	mutex_unlock(&rtd->pcm_mutex);
 820	return ret;
 821}
 822
 823static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
 824				struct snd_compr_codec_caps *codec)
 825{
 826	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 827	struct snd_soc_platform *platform = rtd->platform;
 828	struct snd_soc_component *component;
 829	struct snd_soc_rtdcom_list *rtdcom;
 830	int ret = 0, __ret;
 831
 832	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 833
 834	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) {
 835		ret = platform->driver->compr_ops->get_codec_caps(cstream, codec);
 836		if (ret < 0)
 837			goto err;
 838	}
 839
 840	for_each_rtdcom(rtd, rtdcom) {
 841		component = rtdcom->component;
 842
 843		/* ignore duplication for now */
 844		if (platform && (component == &platform->component))
 845			continue;
 846
 847		if (!component->driver->compr_ops ||
 848		    !component->driver->compr_ops->get_codec_caps)
 849			continue;
 850
 851		__ret = component->driver->compr_ops->get_codec_caps(cstream, codec);
 852		if (__ret < 0)
 853			ret = __ret;
 854	}
 855
 
 856err:
 857	mutex_unlock(&rtd->pcm_mutex);
 858	return ret;
 859}
 860
 861static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
 862{
 863	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 864	struct snd_soc_platform *platform = rtd->platform;
 865	struct snd_soc_component *component;
 866	struct snd_soc_rtdcom_list *rtdcom;
 867	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 868	int ret = 0, __ret;
 869
 870	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 871
 872	if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
 873		ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
 874		if (ret < 0)
 875			goto err;
 876	}
 877
 878	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->ack) {
 879		ret = platform->driver->compr_ops->ack(cstream, bytes);
 880		if (ret < 0)
 881			goto err;
 882	}
 883
 884	for_each_rtdcom(rtd, rtdcom) {
 885		component = rtdcom->component;
 886
 887		/* ignore duplication for now */
 888		if (platform && (component == &platform->component))
 889			continue;
 890
 891		if (!component->driver->compr_ops ||
 892		    !component->driver->compr_ops->ack)
 893			continue;
 894
 895		__ret = component->driver->compr_ops->ack(cstream, bytes);
 896		if (__ret < 0)
 897			ret = __ret;
 898	}
 899
 
 900err:
 901	mutex_unlock(&rtd->pcm_mutex);
 902	return ret;
 903}
 904
 905static int soc_compr_pointer(struct snd_compr_stream *cstream,
 906			struct snd_compr_tstamp *tstamp)
 907{
 908	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 909	struct snd_soc_platform *platform = rtd->platform;
 910	struct snd_soc_component *component;
 911	struct snd_soc_rtdcom_list *rtdcom;
 912	int ret = 0, __ret;
 913	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 914
 915	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 916
 917	if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
 918		cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
 
 919
 920	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->pointer) {
 921		ret = platform->driver->compr_ops->pointer(cstream, tstamp);
 922		if (ret < 0)
 923			goto err;
 924	}
 925
 926	for_each_rtdcom(rtd, rtdcom) {
 927		component = rtdcom->component;
 928
 929		/* ignore duplication for now */
 930		if (platform && (component == &platform->component))
 931			continue;
 932
 933		if (!component->driver->compr_ops ||
 934		    !component->driver->compr_ops->pointer)
 935			continue;
 936
 937		__ret = component->driver->compr_ops->pointer(cstream, tstamp);
 938		if (__ret < 0)
 939			ret = __ret;
 940	}
 941
 942err:
 943	mutex_unlock(&rtd->pcm_mutex);
 944	return ret;
 945}
 946
 947static int soc_compr_copy(struct snd_compr_stream *cstream,
 948			  char __user *buf, size_t count)
 949{
 950	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 951	struct snd_soc_platform *platform = rtd->platform;
 952	struct snd_soc_component *component;
 953	struct snd_soc_rtdcom_list *rtdcom;
 954	int ret = 0;
 955
 956	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 957
 958	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->copy) {
 959		ret = platform->driver->compr_ops->copy(cstream, buf, count);
 960		if (ret < 0)
 961			goto err;
 962	}
 963
 964	for_each_rtdcom(rtd, rtdcom) {
 965		component = rtdcom->component;
 966
 967		/* ignore duplication for now */
 968		if (platform && (component == &platform->component))
 969			continue;
 970
 971		if (!component->driver->compr_ops ||
 972		    !component->driver->compr_ops->copy)
 973			continue;
 974
 975		ret = component->driver->compr_ops->copy(cstream, buf, count);
 976		break;
 977	}
 978
 979err:
 980	mutex_unlock(&rtd->pcm_mutex);
 981	return ret;
 982}
 983
 984static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
 985				struct snd_compr_metadata *metadata)
 986{
 987	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 988	struct snd_soc_platform *platform = rtd->platform;
 989	struct snd_soc_component *component;
 990	struct snd_soc_rtdcom_list *rtdcom;
 991	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 992	int ret = 0, __ret;
 993
 994	if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
 995		ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
 996		if (ret < 0)
 997			return ret;
 998	}
 999
1000	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_metadata) {
1001		ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
1002		if (ret < 0)
1003			return ret;
1004	}
1005
1006	for_each_rtdcom(rtd, rtdcom) {
1007		component = rtdcom->component;
1008
1009		/* ignore duplication for now */
1010		if (platform && (component == &platform->component))
1011			continue;
1012
1013		if (!component->driver->compr_ops ||
1014		    !component->driver->compr_ops->set_metadata)
1015			continue;
1016
1017		__ret = component->driver->compr_ops->set_metadata(cstream, metadata);
1018		if (__ret < 0)
1019			ret = __ret;
1020	}
1021
1022	return ret;
1023}
1024
1025static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
1026				struct snd_compr_metadata *metadata)
1027{
1028	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
1029	struct snd_soc_platform *platform = rtd->platform;
1030	struct snd_soc_component *component;
1031	struct snd_soc_rtdcom_list *rtdcom;
1032	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1033	int ret = 0, __ret;
1034
1035	if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
1036		ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
1037		if (ret < 0)
1038			return ret;
1039	}
1040
1041	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_metadata) {
1042		ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
1043		if (ret < 0)
1044			return ret;
1045	}
1046
1047	for_each_rtdcom(rtd, rtdcom) {
1048		component = rtdcom->component;
1049
1050		/* ignore duplication for now */
1051		if (platform && (component == &platform->component))
1052			continue;
1053
1054		if (!component->driver->compr_ops ||
1055		    !component->driver->compr_ops->get_metadata)
1056			continue;
1057
1058		__ret = component->driver->compr_ops->get_metadata(cstream, metadata);
1059		if (__ret < 0)
1060			ret = __ret;
1061	}
1062
1063	return ret;
1064}
1065
1066/* ASoC Compress operations */
1067static struct snd_compr_ops soc_compr_ops = {
1068	.open		= soc_compr_open,
1069	.free		= soc_compr_free,
1070	.set_params	= soc_compr_set_params,
1071	.set_metadata   = soc_compr_set_metadata,
1072	.get_metadata	= soc_compr_get_metadata,
1073	.get_params	= soc_compr_get_params,
1074	.trigger	= soc_compr_trigger,
1075	.pointer	= soc_compr_pointer,
1076	.ack		= soc_compr_ack,
1077	.get_caps	= soc_compr_get_caps,
1078	.get_codec_caps = soc_compr_get_codec_caps
1079};
1080
1081/* ASoC Dynamic Compress operations */
1082static struct snd_compr_ops soc_compr_dyn_ops = {
1083	.open		= soc_compr_open_fe,
1084	.free		= soc_compr_free_fe,
1085	.set_params	= soc_compr_set_params_fe,
1086	.get_params	= soc_compr_get_params,
1087	.set_metadata   = soc_compr_set_metadata,
1088	.get_metadata	= soc_compr_get_metadata,
1089	.trigger	= soc_compr_trigger_fe,
1090	.pointer	= soc_compr_pointer,
1091	.ack		= soc_compr_ack,
1092	.get_caps	= soc_compr_get_caps,
1093	.get_codec_caps = soc_compr_get_codec_caps
1094};
1095
1096/**
1097 * snd_soc_new_compress - create a new compress.
1098 *
1099 * @rtd: The runtime for which we will create compress
1100 * @num: the device index number (zero based - shared with normal PCMs)
1101 *
1102 * Return: 0 for success, else error.
1103 */
1104int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
1105{
1106	struct snd_soc_platform *platform = rtd->platform;
1107	struct snd_soc_component *component;
1108	struct snd_soc_rtdcom_list *rtdcom;
1109	struct snd_soc_dai *codec_dai = rtd->codec_dai;
1110	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1111	struct snd_compr *compr;
1112	struct snd_pcm *be_pcm;
1113	char new_name[64];
1114	int ret = 0, direction = 0;
1115	int playback = 0, capture = 0;
 
1116
1117	if (rtd->num_codecs > 1) {
 
 
 
 
 
 
 
 
1118		dev_err(rtd->card->dev,
1119			"Compress ASoC: Multicodec not supported\n");
 
 
 
 
 
1120		return -EINVAL;
1121	}
1122
1123	/* check client and interface hw capabilities */
1124	if (codec_dai->driver->playback.channels_min)
 
1125		playback = 1;
1126	if (codec_dai->driver->capture.channels_min)
 
1127		capture = 1;
1128
1129	capture = capture && cpu_dai->driver->capture.channels_min;
1130	playback = playback && cpu_dai->driver->playback.channels_min;
1131
1132	/*
1133	 * Compress devices are unidirectional so only one of the directions
1134	 * should be set, check for that (xor)
1135	 */
1136	if (playback + capture != 1) {
1137		dev_err(rtd->card->dev,
1138			"Compress ASoC: Invalid direction for P %d, C %d\n",
1139			playback, capture);
1140		return -EINVAL;
1141	}
1142
1143	if (playback)
1144		direction = SND_COMPRESS_PLAYBACK;
1145	else
1146		direction = SND_COMPRESS_CAPTURE;
1147
1148	compr = kzalloc(sizeof(*compr), GFP_KERNEL);
1149	if (!compr)
1150		return -ENOMEM;
1151
1152	compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
1153				  GFP_KERNEL);
1154	if (!compr->ops) {
1155		ret = -ENOMEM;
1156		goto compr_err;
1157	}
1158
1159	if (rtd->dai_link->dynamic) {
1160		snprintf(new_name, sizeof(new_name), "(%s)",
1161			rtd->dai_link->stream_name);
1162
1163		ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
1164				rtd->dai_link->dpcm_playback,
1165				rtd->dai_link->dpcm_capture, &be_pcm);
1166		if (ret < 0) {
1167			dev_err(rtd->card->dev,
1168				"Compress ASoC: can't create compressed for %s: %d\n",
1169				rtd->dai_link->name, ret);
1170			goto compr_err;
1171		}
1172
 
 
 
1173		rtd->pcm = be_pcm;
1174		rtd->fe_compr = 1;
1175		if (rtd->dai_link->dpcm_playback)
1176			be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
1177		else if (rtd->dai_link->dpcm_capture)
1178			be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
1179		memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
1180	} else {
1181		snprintf(new_name, sizeof(new_name), "%s %s-%d",
1182			rtd->dai_link->stream_name, codec_dai->name, num);
1183
1184		memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
1185	}
1186
1187
1188	/* Add copy callback for not memory mapped DSPs */
1189	if (platform && platform->driver->compr_ops && platform->driver->compr_ops->copy)
1190		compr->ops->copy = soc_compr_copy;
1191
1192	for_each_rtdcom(rtd, rtdcom) {
1193		component = rtdcom->component;
1194
1195		/* ignore duplication for now */
1196		if (platform && (component == &platform->component))
1197			continue;
1198
1199		if (!component->driver->compr_ops ||
1200		    !component->driver->compr_ops->copy)
1201			continue;
1202
1203		compr->ops->copy = soc_compr_copy;
1204	}
1205
1206
1207	mutex_init(&compr->lock);
1208	ret = snd_compress_new(rtd->card->snd_card, num, direction,
1209				new_name, compr);
1210	if (ret < 0) {
1211		component = rtd->codec_dai->component;
1212		dev_err(component->dev,
1213			"Compress ASoC: can't create compress for codec %s: %d\n",
1214			component->name, ret);
1215		goto compr_err;
1216	}
1217
1218	/* DAPM dai link stream work */
1219	INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
1220
1221	rtd->compr = compr;
1222	compr->private_data = rtd;
1223
1224	dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
1225		 codec_dai->name, cpu_dai->name);
1226	return ret;
1227
1228compr_err:
1229	kfree(compr);
1230	return ret;
1231}
1232EXPORT_SYMBOL_GPL(snd_soc_new_compress);