Linux Audio

Check our new training course

Loading...
v4.10.11
  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_dai *cpu_dai = rtd->cpu_dai;
 34	int ret = 0;
 35
 36	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 37
 38	if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
 39		ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
 40		if (ret < 0) {
 41			dev_err(cpu_dai->dev, "Compress ASoC: can't open interface %s: %d\n",
 
 42				cpu_dai->name, ret);
 43			goto out;
 44		}
 45	}
 46
 47	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
 48		ret = platform->driver->compr_ops->open(cstream);
 49		if (ret < 0) {
 50			pr_err("compress asoc: can't open platform %s\n",
 51				platform->component.name);
 52			goto plat_err;
 53		}
 54	}
 55
 56	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
 57		ret = rtd->dai_link->compr_ops->startup(cstream);
 58		if (ret < 0) {
 59			pr_err("compress asoc: %s startup failed\n", rtd->dai_link->name);
 
 
 60			goto machine_err;
 61		}
 62	}
 63
 64	snd_soc_runtime_activate(rtd, cstream->direction);
 65
 66	mutex_unlock(&rtd->pcm_mutex);
 67
 68	return 0;
 69
 70machine_err:
 71	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
 72		platform->driver->compr_ops->free(cstream);
 73plat_err:
 74	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
 75		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
 76out:
 77	mutex_unlock(&rtd->pcm_mutex);
 78	return ret;
 79}
 80
 81static int soc_compr_open_fe(struct snd_compr_stream *cstream)
 82{
 83	struct snd_soc_pcm_runtime *fe = cstream->private_data;
 84	struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
 85	struct snd_soc_platform *platform = fe->platform;
 
 86	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
 87	struct snd_soc_dpcm *dpcm;
 88	struct snd_soc_dapm_widget_list *list;
 89	int stream;
 90	int ret = 0;
 91
 92	if (cstream->direction == SND_COMPRESS_PLAYBACK)
 93		stream = SNDRV_PCM_STREAM_PLAYBACK;
 94	else
 95		stream = SNDRV_PCM_STREAM_CAPTURE;
 96
 97	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
 98
 99	if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
100		ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
101		if (ret < 0) {
102			dev_err(cpu_dai->dev, "Compress ASoC: can't open interface %s: %d\n",
103				cpu_dai->name, ret);
104			goto out;
105		}
106	}
107
108
109	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
110		ret = platform->driver->compr_ops->open(cstream);
111		if (ret < 0) {
112			pr_err("compress asoc: can't open platform %s\n",
113				platform->component.name);
114			goto plat_err;
115		}
116	}
117
118	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
119		ret = fe->dai_link->compr_ops->startup(cstream);
120		if (ret < 0) {
121			pr_err("compress asoc: %s startup failed\n", fe->dai_link->name);
122			goto machine_err;
123		}
124	}
125
126	fe->dpcm[stream].runtime = fe_substream->runtime;
127
128	ret = dpcm_path_get(fe, stream, &list);
129	if (ret < 0)
130		goto fe_err;
131	else if (ret == 0)
132		dev_dbg(fe->dev, "ASoC: %s no valid %s route\n",
133			fe->dai_link->name, stream ? "capture" : "playback");
134
135	/* calculate valid and active FE <-> BE dpcms */
136	dpcm_process_paths(fe, stream, &list, 1);
 
137
138	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
139
140	ret = dpcm_be_dai_startup(fe, stream);
141	if (ret < 0) {
142		/* clean up all links */
143		list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
144			dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
145
146		dpcm_be_disconnect(fe, stream);
147		fe->dpcm[stream].runtime = NULL;
148		goto path_err;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149	}
150
151	dpcm_clear_pending_state(fe, stream);
152	dpcm_path_put(&list);
153
154	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
155	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
156
157	snd_soc_runtime_activate(fe, stream);
158
159	mutex_unlock(&fe->card->mutex);
160
161	return 0;
162
163path_err:
164	dpcm_path_put(&list);
165fe_err:
166	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
167		fe->dai_link->compr_ops->shutdown(cstream);
168machine_err:
169	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
170		platform->driver->compr_ops->free(cstream);
171plat_err:
172	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
173		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
174out:
 
 
175	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
176	mutex_unlock(&fe->card->mutex);
177	return ret;
178}
179
180/*
181 * Power down the audio subsystem pmdown_time msecs after close is called.
182 * This is to ensure there are no pops or clicks in between any music tracks
183 * due to DAPM power cycling.
184 */
185static void close_delayed_work(struct work_struct *work)
186{
187	struct snd_soc_pcm_runtime *rtd =
188			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
189	struct snd_soc_dai *codec_dai = rtd->codec_dai;
190
191	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
192
193	dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
194		 codec_dai->driver->playback.stream_name,
195		 codec_dai->playback_active ? "active" : "inactive",
196		 rtd->pop_wait ? "yes" : "no");
 
197
198	/* are we waiting on this codec DAI stream */
199	if (rtd->pop_wait == 1) {
200		rtd->pop_wait = 0;
201		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
202					  SND_SOC_DAPM_STREAM_STOP);
203	}
204
205	mutex_unlock(&rtd->pcm_mutex);
206}
207
208static int soc_compr_free(struct snd_compr_stream *cstream)
209{
210	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
211	struct snd_soc_platform *platform = rtd->platform;
212	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
213	struct snd_soc_dai *codec_dai = rtd->codec_dai;
214	int stream;
215
216	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
217
218	if (cstream->direction == SND_COMPRESS_PLAYBACK)
219		stream = SNDRV_PCM_STREAM_PLAYBACK;
220	else
221		stream = SNDRV_PCM_STREAM_CAPTURE;
222
223	snd_soc_runtime_deactivate(rtd, stream);
224
225	snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
226
227	if (!cpu_dai->active)
228		cpu_dai->rate = 0;
229
230	if (!codec_dai->active)
231		codec_dai->rate = 0;
232
233
234	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
235		rtd->dai_link->compr_ops->shutdown(cstream);
236
237	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
238		platform->driver->compr_ops->free(cstream);
239
240	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
241		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
242
243	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
244		if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
245			snd_soc_dapm_stream_event(rtd,
246					SNDRV_PCM_STREAM_PLAYBACK,
247					SND_SOC_DAPM_STREAM_STOP);
248		} else {
249			rtd->pop_wait = 1;
250			queue_delayed_work(system_power_efficient_wq,
251					   &rtd->delayed_work,
252					   msecs_to_jiffies(rtd->pmdown_time));
253		}
254	} else {
255		/* capture streams can be powered down now */
256		snd_soc_dapm_stream_event(rtd,
257			SNDRV_PCM_STREAM_CAPTURE,
258			SND_SOC_DAPM_STREAM_STOP);
259	}
260
261	mutex_unlock(&rtd->pcm_mutex);
262	return 0;
263}
264
265static int soc_compr_free_fe(struct snd_compr_stream *cstream)
266{
267	struct snd_soc_pcm_runtime *fe = cstream->private_data;
268	struct snd_soc_platform *platform = fe->platform;
269	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
270	struct snd_soc_dpcm *dpcm;
271	int stream, ret;
272
273	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
274
275	if (cstream->direction == SND_COMPRESS_PLAYBACK)
276		stream = SNDRV_PCM_STREAM_PLAYBACK;
277	else
278		stream = SNDRV_PCM_STREAM_CAPTURE;
279
280	snd_soc_runtime_deactivate(fe, stream);
281
282	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
283
284	ret = dpcm_be_dai_hw_free(fe, stream);
285	if (ret < 0)
286		dev_err(fe->dev, "compressed hw_free failed %d\n", ret);
287
288	ret = dpcm_be_dai_shutdown(fe, stream);
289
290	/* mark FE's links ready to prune */
291	list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
292		dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
293
294	dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
295
296	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
297	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
298
299	dpcm_be_disconnect(fe, stream);
300
301	fe->dpcm[stream].runtime = NULL;
302
303	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
304		fe->dai_link->compr_ops->shutdown(cstream);
305
306	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
307		platform->driver->compr_ops->free(cstream);
308
309	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
310		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
311
312	mutex_unlock(&fe->card->mutex);
313	return 0;
314}
315
316static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
 
317{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
 
 
 
 
 
319	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
320	struct snd_soc_platform *platform = rtd->platform;
321	struct snd_soc_dai *codec_dai = rtd->codec_dai;
322	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
323	int ret = 0;
324
325	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
326
327	if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
328		ret = platform->driver->compr_ops->trigger(cstream, cmd);
329		if (ret < 0)
330			goto out;
331	}
332
333	if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
334		cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
335
336
337	switch (cmd) {
338	case SNDRV_PCM_TRIGGER_START:
339		snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
340		break;
341	case SNDRV_PCM_TRIGGER_STOP:
342		snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
343		break;
344	}
345
346out:
347	mutex_unlock(&rtd->pcm_mutex);
348	return ret;
349}
350
351static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
352{
353	struct snd_soc_pcm_runtime *fe = cstream->private_data;
354	struct snd_soc_platform *platform = fe->platform;
355	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
356	int ret = 0, stream;
357
358	if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
359		cmd == SND_COMPR_TRIGGER_DRAIN) {
360
361		if (platform->driver->compr_ops &&
362		    platform->driver->compr_ops->trigger)
363			return platform->driver->compr_ops->trigger(cstream,
364								    cmd);
365	}
366
367	if (cstream->direction == SND_COMPRESS_PLAYBACK)
368		stream = SNDRV_PCM_STREAM_PLAYBACK;
369	else
370		stream = SNDRV_PCM_STREAM_CAPTURE;
371
372
373	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
374
375	if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) {
376		ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
377		if (ret < 0)
378			goto out;
379	}
380
381	if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
382		ret = platform->driver->compr_ops->trigger(cstream, cmd);
383		if (ret < 0)
384			goto out;
385	}
386
387	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
388
389	ret = dpcm_be_dai_trigger(fe, stream, cmd);
390
391	switch (cmd) {
392	case SNDRV_PCM_TRIGGER_START:
393	case SNDRV_PCM_TRIGGER_RESUME:
394	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
395		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
396		break;
397	case SNDRV_PCM_TRIGGER_STOP:
398	case SNDRV_PCM_TRIGGER_SUSPEND:
399		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
400		break;
401	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
402		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
403		break;
404	}
405
406out:
407	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
408	mutex_unlock(&fe->card->mutex);
409	return ret;
410}
411
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412static int soc_compr_set_params(struct snd_compr_stream *cstream,
413					struct snd_compr_params *params)
414{
415	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
416	struct snd_soc_platform *platform = rtd->platform;
417	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
418	int ret = 0;
419
420	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
421
422	/* first we call set_params for the platform driver
423	 * this should configure the soc side
424	 * if the machine has compressed ops then we call that as well
425	 * expectation is that platform and machine will configure everything
426	 * for this compress path, like configuring pcm port for codec
 
427	 */
428	if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
429		ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
430		if (ret < 0)
431			goto err;
432	}
433
434	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
435		ret = platform->driver->compr_ops->set_params(cstream, params);
436		if (ret < 0)
437			goto err;
438	}
439
440	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
441		ret = rtd->dai_link->compr_ops->set_params(cstream);
442		if (ret < 0)
443			goto err;
444	}
445
446	if (cstream->direction == SND_COMPRESS_PLAYBACK)
447		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
448					SND_SOC_DAPM_STREAM_START);
449	else
450		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
451					SND_SOC_DAPM_STREAM_START);
452
453	/* cancel any delayed stream shutdown that is pending */
454	rtd->pop_wait = 0;
455	mutex_unlock(&rtd->pcm_mutex);
456
457	cancel_delayed_work_sync(&rtd->delayed_work);
458
459	return ret;
460
461err:
462	mutex_unlock(&rtd->pcm_mutex);
463	return ret;
464}
465
466static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
467					struct snd_compr_params *params)
468{
469	struct snd_soc_pcm_runtime *fe = cstream->private_data;
470	struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
471	struct snd_soc_platform *platform = fe->platform;
472	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
473	int ret = 0, stream;
474
475	if (cstream->direction == SND_COMPRESS_PLAYBACK)
476		stream = SNDRV_PCM_STREAM_PLAYBACK;
477	else
478		stream = SNDRV_PCM_STREAM_CAPTURE;
479
480	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
481
482	if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
483		ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
484		if (ret < 0)
485			goto out;
486	}
487
488	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
489		ret = platform->driver->compr_ops->set_params(cstream, params);
490		if (ret < 0)
491			goto out;
492	}
493
494	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
495		ret = fe->dai_link->compr_ops->set_params(cstream);
496		if (ret < 0)
497			goto out;
498	}
499
500	/*
501	 * Create an empty hw_params for the BE as the machine driver must
502	 * fix this up to match DSP decoder and ASRC configuration.
503	 * I.e. machine driver fixup for compressed BE is mandatory.
504	 */
505	memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
506		sizeof(struct snd_pcm_hw_params));
507
508	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
509
510	ret = dpcm_be_dai_hw_params(fe, stream);
511	if (ret < 0)
512		goto out;
513
514	ret = dpcm_be_dai_prepare(fe, stream);
515	if (ret < 0)
516		goto out;
517
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
518	dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
519	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
520
521out:
522	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
523	mutex_unlock(&fe->card->mutex);
524	return ret;
525}
526
527static int soc_compr_get_params(struct snd_compr_stream *cstream,
528					struct snd_codec *params)
529{
530	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
531	struct snd_soc_platform *platform = rtd->platform;
 
532	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
533	int ret = 0;
534
535	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
536
537	if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
538		ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
539		if (ret < 0)
540			goto err;
541	}
542
543	if (platform->driver->compr_ops && platform->driver->compr_ops->get_params)
544		ret = platform->driver->compr_ops->get_params(cstream, params);
 
 
 
 
 
 
 
 
545
546err:
547	mutex_unlock(&rtd->pcm_mutex);
548	return ret;
549}
550
551static int soc_compr_get_caps(struct snd_compr_stream *cstream,
552				struct snd_compr_caps *caps)
553{
554	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
555	struct snd_soc_platform *platform = rtd->platform;
 
556	int ret = 0;
557
558	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
559
560	if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps)
561		ret = platform->driver->compr_ops->get_caps(cstream, caps);
562
563	mutex_unlock(&rtd->pcm_mutex);
 
 
 
 
 
 
 
 
564	return ret;
565}
566
567static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
568				struct snd_compr_codec_caps *codec)
569{
570	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
571	struct snd_soc_platform *platform = rtd->platform;
 
572	int ret = 0;
573
574	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
575
576	if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps)
577		ret = platform->driver->compr_ops->get_codec_caps(cstream, codec);
 
 
 
 
 
 
 
 
 
578
579	mutex_unlock(&rtd->pcm_mutex);
580	return ret;
581}
582
583static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
584{
585	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
586	struct snd_soc_platform *platform = rtd->platform;
 
587	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
588	int ret = 0;
589
590	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
591
592	if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
593		ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
594		if (ret < 0)
595			goto err;
596	}
597
598	if (platform->driver->compr_ops && platform->driver->compr_ops->ack)
599		ret = platform->driver->compr_ops->ack(cstream, bytes);
 
 
 
 
 
 
 
 
 
600
601err:
602	mutex_unlock(&rtd->pcm_mutex);
603	return ret;
604}
605
606static int soc_compr_pointer(struct snd_compr_stream *cstream,
607			struct snd_compr_tstamp *tstamp)
608{
609	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
610	struct snd_soc_platform *platform = rtd->platform;
 
611	int ret = 0;
612	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
613
614	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
615
616	if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
617		cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
618
619	if (platform->driver->compr_ops && platform->driver->compr_ops->pointer)
620		ret = platform->driver->compr_ops->pointer(cstream, tstamp);
 
 
 
 
621
622	mutex_unlock(&rtd->pcm_mutex);
 
 
 
 
623	return ret;
624}
625
626static int soc_compr_copy(struct snd_compr_stream *cstream,
627			  char __user *buf, size_t count)
628{
629	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
630	struct snd_soc_platform *platform = rtd->platform;
 
631	int ret = 0;
632
633	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
 
 
 
634
635	if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
636		ret = platform->driver->compr_ops->copy(cstream, buf, count);
 
 
 
 
 
637
638	mutex_unlock(&rtd->pcm_mutex);
639	return ret;
640}
641
642static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
643				struct snd_compr_metadata *metadata)
644{
645	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
646	struct snd_soc_platform *platform = rtd->platform;
 
647	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
648	int ret = 0;
649
650	if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
651		ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
652		if (ret < 0)
653			return ret;
654	}
655
656	if (platform->driver->compr_ops && platform->driver->compr_ops->set_metadata)
657		ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
658
659	return ret;
 
 
 
 
 
 
 
 
 
 
660}
661
662static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
663				struct snd_compr_metadata *metadata)
664{
665	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
666	struct snd_soc_platform *platform = rtd->platform;
 
667	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
668	int ret = 0;
669
670	if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
671		ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
672		if (ret < 0)
673			return ret;
674	}
675
676	if (platform->driver->compr_ops && platform->driver->compr_ops->get_metadata)
677		ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
678
679	return ret;
 
 
 
 
 
 
 
 
680}
681
682/* ASoC Compress operations */
683static struct snd_compr_ops soc_compr_ops = {
684	.open		= soc_compr_open,
685	.free		= soc_compr_free,
686	.set_params	= soc_compr_set_params,
687	.set_metadata   = soc_compr_set_metadata,
688	.get_metadata	= soc_compr_get_metadata,
689	.get_params	= soc_compr_get_params,
690	.trigger	= soc_compr_trigger,
691	.pointer	= soc_compr_pointer,
692	.ack		= soc_compr_ack,
693	.get_caps	= soc_compr_get_caps,
694	.get_codec_caps = soc_compr_get_codec_caps
695};
696
697/* ASoC Dynamic Compress operations */
698static struct snd_compr_ops soc_compr_dyn_ops = {
699	.open		= soc_compr_open_fe,
700	.free		= soc_compr_free_fe,
701	.set_params	= soc_compr_set_params_fe,
702	.get_params	= soc_compr_get_params,
703	.set_metadata   = soc_compr_set_metadata,
704	.get_metadata	= soc_compr_get_metadata,
705	.trigger	= soc_compr_trigger_fe,
706	.pointer	= soc_compr_pointer,
707	.ack		= soc_compr_ack,
708	.get_caps	= soc_compr_get_caps,
709	.get_codec_caps = soc_compr_get_codec_caps
710};
711
712/**
713 * snd_soc_new_compress - create a new compress.
714 *
715 * @rtd: The runtime for which we will create compress
716 * @num: the device index number (zero based - shared with normal PCMs)
717 *
718 * Return: 0 for success, else error.
719 */
720int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
721{
722	struct snd_soc_codec *codec = rtd->codec;
723	struct snd_soc_platform *platform = rtd->platform;
724	struct snd_soc_dai *codec_dai = rtd->codec_dai;
725	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
726	struct snd_compr *compr;
727	struct snd_pcm *be_pcm;
728	char new_name[64];
729	int ret = 0, direction = 0;
730	int playback = 0, capture = 0;
731
732	if (rtd->num_codecs > 1) {
733		dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n");
 
734		return -EINVAL;
735	}
736
737	/* check client and interface hw capabilities */
738	snprintf(new_name, sizeof(new_name), "%s %s-%d",
739			rtd->dai_link->stream_name, codec_dai->name, num);
740
741	if (codec_dai->driver->playback.channels_min)
742		playback = 1;
743	if (codec_dai->driver->capture.channels_min)
 
744		capture = 1;
745
746	capture = capture && cpu_dai->driver->capture.channels_min;
747	playback = playback && cpu_dai->driver->playback.channels_min;
748
749	/*
750	 * Compress devices are unidirectional so only one of the directions
751	 * should be set, check for that (xor)
752	 */
753	if (playback + capture != 1) {
754		dev_err(rtd->card->dev, "Invalid direction for compress P %d, C %d\n",
755				playback, capture);
 
756		return -EINVAL;
757	}
758
759	if(playback)
760		direction = SND_COMPRESS_PLAYBACK;
761	else
762		direction = SND_COMPRESS_CAPTURE;
763
764	compr = kzalloc(sizeof(*compr), GFP_KERNEL);
765	if (compr == NULL) {
766		snd_printk(KERN_ERR "Cannot allocate compr\n");
767		return -ENOMEM;
768	}
769
770	compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
771				  GFP_KERNEL);
772	if (compr->ops == NULL) {
773		dev_err(rtd->card->dev, "Cannot allocate compressed ops\n");
774		ret = -ENOMEM;
775		goto compr_err;
776	}
777
778	if (rtd->dai_link->dynamic) {
779		snprintf(new_name, sizeof(new_name), "(%s)",
780			rtd->dai_link->stream_name);
781
782		ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
783				rtd->dai_link->dpcm_playback,
784				rtd->dai_link->dpcm_capture, &be_pcm);
785		if (ret < 0) {
786			dev_err(rtd->card->dev, "ASoC: can't create compressed for %s\n",
787				rtd->dai_link->name);
788			goto compr_err;
 
789		}
790
791		rtd->pcm = be_pcm;
792		rtd->fe_compr = 1;
793		if (rtd->dai_link->dpcm_playback)
794			be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
795		else if (rtd->dai_link->dpcm_capture)
796			be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
797		memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
798	} else
 
 
 
799		memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
 
800
801	/* Add copy callback for not memory mapped DSPs */
802	if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
803		compr->ops->copy = soc_compr_copy;
804
805	mutex_init(&compr->lock);
 
 
806
807	snprintf(new_name, sizeof(new_name), "%s %s-%d",
808		 rtd->dai_link->stream_name,
809		 rtd->codec_dai->name, num);
810
 
811	ret = snd_compress_new(rtd->card->snd_card, num, direction,
812				new_name, compr);
813	if (ret < 0) {
814		pr_err("compress asoc: can't create compress for codec %s\n",
815			codec->component.name);
816		goto compr_err;
 
 
817	}
818
819	/* DAPM dai link stream work */
820	INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
821
822	rtd->compr = compr;
823	compr->private_data = rtd;
824
825	printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
826		cpu_dai->name);
827	return ret;
828
829compr_err:
830	kfree(compr);
831	return ret;
832}
833EXPORT_SYMBOL_GPL(snd_soc_new_compress);
v5.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
 23static int soc_compr_components_open(struct snd_compr_stream *cstream,
 24				     struct snd_soc_component **last)
 25{
 26	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 27	struct snd_soc_component *component;
 28	struct snd_soc_rtdcom_list *rtdcom;
 29	int ret;
 30
 31	for_each_rtdcom(rtd, rtdcom) {
 32		component = rtdcom->component;
 33
 34		if (!component->driver->compr_ops ||
 35		    !component->driver->compr_ops->open)
 36			continue;
 37
 38		ret = component->driver->compr_ops->open(cstream);
 39		if (ret < 0) {
 40			dev_err(component->dev,
 41				"Compress ASoC: can't open platform %s: %d\n",
 42				component->name, ret);
 43
 44			*last = component;
 45			return ret;
 46		}
 47	}
 48
 49	*last = NULL;
 50	return 0;
 51}
 52
 53static int soc_compr_components_free(struct snd_compr_stream *cstream,
 54				     struct snd_soc_component *last)
 55{
 56	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 57	struct snd_soc_component *component;
 58	struct snd_soc_rtdcom_list *rtdcom;
 59
 60	for_each_rtdcom(rtd, rtdcom) {
 61		component = rtdcom->component;
 62
 63		if (component == last)
 64			break;
 65
 66		if (!component->driver->compr_ops ||
 67		    !component->driver->compr_ops->free)
 68			continue;
 69
 70		component->driver->compr_ops->free(cstream);
 71	}
 72
 73	return 0;
 74}
 75
 76static int soc_compr_open(struct snd_compr_stream *cstream)
 77{
 78	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 79	struct snd_soc_component *component;
 80	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 81	int ret;
 82
 83	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
 84
 85	if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
 86		ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
 87		if (ret < 0) {
 88			dev_err(cpu_dai->dev,
 89				"Compress ASoC: can't open interface %s: %d\n",
 90				cpu_dai->name, ret);
 91			goto out;
 92		}
 93	}
 94
 95	ret = soc_compr_components_open(cstream, &component);
 96	if (ret < 0)
 97		goto machine_err;
 
 
 
 
 
 98
 99	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
100		ret = rtd->dai_link->compr_ops->startup(cstream);
101		if (ret < 0) {
102			dev_err(rtd->dev,
103				"Compress ASoC: %s startup failed: %d\n",
104				rtd->dai_link->name, ret);
105			goto machine_err;
106		}
107	}
108
109	snd_soc_runtime_activate(rtd, cstream->direction);
110
111	mutex_unlock(&rtd->card->pcm_mutex);
112
113	return 0;
114
115machine_err:
116	soc_compr_components_free(cstream, component);
117
 
118	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
119		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
120out:
121	mutex_unlock(&rtd->card->pcm_mutex);
122	return ret;
123}
124
125static int soc_compr_open_fe(struct snd_compr_stream *cstream)
126{
127	struct snd_soc_pcm_runtime *fe = cstream->private_data;
128	struct snd_pcm_substream *fe_substream =
129		 fe->pcm->streams[cstream->direction].substream;
130	struct snd_soc_component *component;
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;
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	fe->dpcm[stream].runtime = fe_substream->runtime;
144
145	ret = dpcm_path_get(fe, stream, &list);
146	if (ret < 0)
147		goto be_err;
148	else if (ret == 0)
149		dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n",
150			fe->dai_link->name, stream ? "capture" : "playback");
 
151	/* calculate valid and active FE <-> BE dpcms */
152	dpcm_process_paths(fe, stream, &list, 1);
153	fe->dpcm[stream].runtime = fe_substream->runtime;
154
155	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
156
157	ret = dpcm_be_dai_startup(fe, stream);
158	if (ret < 0) {
159		/* clean up all links */
160		for_each_dpcm_be(fe, stream, dpcm)
161			dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
162
163		dpcm_be_disconnect(fe, stream);
164		fe->dpcm[stream].runtime = NULL;
165		goto out;
166	}
167
168	if (cpu_dai->driver->cops && cpu_dai->driver->cops->startup) {
169		ret = cpu_dai->driver->cops->startup(cstream, cpu_dai);
170		if (ret < 0) {
171			dev_err(cpu_dai->dev,
172				"Compress ASoC: can't open interface %s: %d\n",
173				cpu_dai->name, ret);
174			goto out;
175		}
176	}
177
178	ret = soc_compr_components_open(cstream, &component);
179	if (ret < 0)
180		goto open_err;
181
182	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
183		ret = fe->dai_link->compr_ops->startup(cstream);
184		if (ret < 0) {
185			pr_err("Compress ASoC: %s startup failed: %d\n",
186			       fe->dai_link->name, ret);
187			goto machine_err;
188		}
189	}
190
191	dpcm_clear_pending_state(fe, stream);
192	dpcm_path_put(&list);
193
194	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
195	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
196
197	snd_soc_runtime_activate(fe, stream);
198
199	mutex_unlock(&fe->card->mutex);
200
201	return 0;
202
 
 
 
 
 
203machine_err:
204	soc_compr_components_free(cstream, component);
205open_err:
 
206	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
207		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
208out:
209	dpcm_path_put(&list);
210be_err:
211	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
212	mutex_unlock(&fe->card->mutex);
213	return ret;
214}
215
216/*
217 * Power down the audio subsystem pmdown_time msecs after close is called.
218 * This is to ensure there are no pops or clicks in between any music tracks
219 * due to DAPM power cycling.
220 */
221static void close_delayed_work(struct work_struct *work)
222{
223	struct snd_soc_pcm_runtime *rtd =
224			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
225	struct snd_soc_dai *codec_dai = rtd->codec_dai;
226
227	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
228
229	dev_dbg(rtd->dev,
230		"Compress ASoC: pop wq checking: %s status: %s waiting: %s\n",
231		codec_dai->driver->playback.stream_name,
232		codec_dai->playback_active ? "active" : "inactive",
233		rtd->pop_wait ? "yes" : "no");
234
235	/* are we waiting on this codec DAI stream */
236	if (rtd->pop_wait == 1) {
237		rtd->pop_wait = 0;
238		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
239					  SND_SOC_DAPM_STREAM_STOP);
240	}
241
242	mutex_unlock(&rtd->card->pcm_mutex);
243}
244
245static int soc_compr_free(struct snd_compr_stream *cstream)
246{
247	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 
248	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
249	struct snd_soc_dai *codec_dai = rtd->codec_dai;
250	int stream;
251
252	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
253
254	if (cstream->direction == SND_COMPRESS_PLAYBACK)
255		stream = SNDRV_PCM_STREAM_PLAYBACK;
256	else
257		stream = SNDRV_PCM_STREAM_CAPTURE;
258
259	snd_soc_runtime_deactivate(rtd, stream);
260
261	snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
262
263	if (!cpu_dai->active)
264		cpu_dai->rate = 0;
265
266	if (!codec_dai->active)
267		codec_dai->rate = 0;
268
 
269	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
270		rtd->dai_link->compr_ops->shutdown(cstream);
271
272	soc_compr_components_free(cstream, NULL);
 
273
274	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
275		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
276
277	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
278		if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
279			snd_soc_dapm_stream_event(rtd,
280						  SNDRV_PCM_STREAM_PLAYBACK,
281						  SND_SOC_DAPM_STREAM_STOP);
282		} else {
283			rtd->pop_wait = 1;
284			queue_delayed_work(system_power_efficient_wq,
285					   &rtd->delayed_work,
286					   msecs_to_jiffies(rtd->pmdown_time));
287		}
288	} else {
289		/* capture streams can be powered down now */
290		snd_soc_dapm_stream_event(rtd,
291					  SNDRV_PCM_STREAM_CAPTURE,
292					  SND_SOC_DAPM_STREAM_STOP);
293	}
294
295	mutex_unlock(&rtd->card->pcm_mutex);
296	return 0;
297}
298
299static int soc_compr_free_fe(struct snd_compr_stream *cstream)
300{
301	struct snd_soc_pcm_runtime *fe = cstream->private_data;
 
302	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
303	struct snd_soc_dpcm *dpcm;
304	int stream, ret;
305
306	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
307
308	if (cstream->direction == SND_COMPRESS_PLAYBACK)
309		stream = SNDRV_PCM_STREAM_PLAYBACK;
310	else
311		stream = SNDRV_PCM_STREAM_CAPTURE;
312
313	snd_soc_runtime_deactivate(fe, stream);
314
315	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
316
317	ret = dpcm_be_dai_hw_free(fe, stream);
318	if (ret < 0)
319		dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret);
320
321	ret = dpcm_be_dai_shutdown(fe, stream);
322
323	/* mark FE's links ready to prune */
324	for_each_dpcm_be(fe, stream, dpcm)
325		dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
326
327	dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
328
329	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
330	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
331
332	dpcm_be_disconnect(fe, stream);
333
334	fe->dpcm[stream].runtime = NULL;
335
336	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
337		fe->dai_link->compr_ops->shutdown(cstream);
338
339	soc_compr_components_free(cstream, NULL);
 
340
341	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
342		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
343
344	mutex_unlock(&fe->card->mutex);
345	return 0;
346}
347
348static int soc_compr_components_trigger(struct snd_compr_stream *cstream,
349					int cmd)
350{
351	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
352	struct snd_soc_component *component;
353	struct snd_soc_rtdcom_list *rtdcom;
354	int ret;
355
356	for_each_rtdcom(rtd, rtdcom) {
357		component = rtdcom->component;
358
359		if (!component->driver->compr_ops ||
360		    !component->driver->compr_ops->trigger)
361			continue;
362
363		ret = component->driver->compr_ops->trigger(cstream, cmd);
364		if (ret < 0)
365			return ret;
366	}
367
368	return 0;
369}
370
371static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
372{
373	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 
374	struct snd_soc_dai *codec_dai = rtd->codec_dai;
375	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
376	int ret;
377
378	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
379
380	ret = soc_compr_components_trigger(cstream, cmd);
381	if (ret < 0)
382		goto out;
 
 
383
384	if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
385		cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
386
 
387	switch (cmd) {
388	case SNDRV_PCM_TRIGGER_START:
389		snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
390		break;
391	case SNDRV_PCM_TRIGGER_STOP:
392		snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
393		break;
394	}
395
396out:
397	mutex_unlock(&rtd->card->pcm_mutex);
398	return ret;
399}
400
401static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
402{
403	struct snd_soc_pcm_runtime *fe = cstream->private_data;
 
404	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
405	int ret, stream;
406
407	if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
408	    cmd == SND_COMPR_TRIGGER_DRAIN)
409		return soc_compr_components_trigger(cstream, cmd);
 
 
 
 
 
410
411	if (cstream->direction == SND_COMPRESS_PLAYBACK)
412		stream = SNDRV_PCM_STREAM_PLAYBACK;
413	else
414		stream = SNDRV_PCM_STREAM_CAPTURE;
415
 
416	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
417
418	if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger) {
419		ret = cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
420		if (ret < 0)
421			goto out;
422	}
423
424	ret = soc_compr_components_trigger(cstream, cmd);
425	if (ret < 0)
426		goto out;
 
 
427
428	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
429
430	ret = dpcm_be_dai_trigger(fe, stream, cmd);
431
432	switch (cmd) {
433	case SNDRV_PCM_TRIGGER_START:
434	case SNDRV_PCM_TRIGGER_RESUME:
435	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
436		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
437		break;
438	case SNDRV_PCM_TRIGGER_STOP:
439	case SNDRV_PCM_TRIGGER_SUSPEND:
440		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
441		break;
442	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
443		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
444		break;
445	}
446
447out:
448	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
449	mutex_unlock(&fe->card->mutex);
450	return ret;
451}
452
453static int soc_compr_components_set_params(struct snd_compr_stream *cstream,
454					   struct snd_compr_params *params)
455{
456	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
457	struct snd_soc_component *component;
458	struct snd_soc_rtdcom_list *rtdcom;
459	int ret;
460
461	for_each_rtdcom(rtd, rtdcom) {
462		component = rtdcom->component;
463
464		if (!component->driver->compr_ops ||
465		    !component->driver->compr_ops->set_params)
466			continue;
467
468		ret = component->driver->compr_ops->set_params(cstream, params);
469		if (ret < 0)
470			return ret;
471	}
472
473	return 0;
474}
475
476static int soc_compr_set_params(struct snd_compr_stream *cstream,
477				struct snd_compr_params *params)
478{
479	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
 
480	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
481	int ret;
482
483	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
484
485	/*
486	 * First we call set_params for the CPU DAI, then the component
487	 * driver this should configure the SoC side. If the machine has
488	 * compressed ops then we call that as well. The expectation is
489	 * that these callbacks will configure everything for this compress
490	 * path, like configuring a PCM port for a CODEC.
491	 */
492	if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
493		ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
494		if (ret < 0)
495			goto err;
496	}
497
498	ret = soc_compr_components_set_params(cstream, params);
499	if (ret < 0)
500		goto err;
 
 
501
502	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
503		ret = rtd->dai_link->compr_ops->set_params(cstream);
504		if (ret < 0)
505			goto err;
506	}
507
508	if (cstream->direction == SND_COMPRESS_PLAYBACK)
509		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
510					  SND_SOC_DAPM_STREAM_START);
511	else
512		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
513					  SND_SOC_DAPM_STREAM_START);
514
515	/* cancel any delayed stream shutdown that is pending */
516	rtd->pop_wait = 0;
517	mutex_unlock(&rtd->card->pcm_mutex);
518
519	cancel_delayed_work_sync(&rtd->delayed_work);
520
521	return 0;
522
523err:
524	mutex_unlock(&rtd->card->pcm_mutex);
525	return ret;
526}
527
528static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
529				   struct snd_compr_params *params)
530{
531	struct snd_soc_pcm_runtime *fe = cstream->private_data;
532	struct snd_pcm_substream *fe_substream =
533		 fe->pcm->streams[cstream->direction].substream;
534	struct snd_soc_dai *cpu_dai = fe->cpu_dai;
535	int ret, stream;
536
537	if (cstream->direction == SND_COMPRESS_PLAYBACK)
538		stream = SNDRV_PCM_STREAM_PLAYBACK;
539	else
540		stream = SNDRV_PCM_STREAM_CAPTURE;
541
542	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
543
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
544	/*
545	 * Create an empty hw_params for the BE as the machine driver must
546	 * fix this up to match DSP decoder and ASRC configuration.
547	 * I.e. machine driver fixup for compressed BE is mandatory.
548	 */
549	memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
550		sizeof(struct snd_pcm_hw_params));
551
552	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
553
554	ret = dpcm_be_dai_hw_params(fe, stream);
555	if (ret < 0)
556		goto out;
557
558	ret = dpcm_be_dai_prepare(fe, stream);
559	if (ret < 0)
560		goto out;
561
562	if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_params) {
563		ret = cpu_dai->driver->cops->set_params(cstream, params, cpu_dai);
564		if (ret < 0)
565			goto out;
566	}
567
568	ret = soc_compr_components_set_params(cstream, params);
569	if (ret < 0)
570		goto out;
571
572	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
573		ret = fe->dai_link->compr_ops->set_params(cstream);
574		if (ret < 0)
575			goto out;
576	}
577
578	dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
579	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
580
581out:
582	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
583	mutex_unlock(&fe->card->mutex);
584	return ret;
585}
586
587static int soc_compr_get_params(struct snd_compr_stream *cstream,
588				struct snd_codec *params)
589{
590	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
591	struct snd_soc_component *component;
592	struct snd_soc_rtdcom_list *rtdcom;
593	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
594	int ret = 0;
595
596	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
597
598	if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_params) {
599		ret = cpu_dai->driver->cops->get_params(cstream, params, cpu_dai);
600		if (ret < 0)
601			goto err;
602	}
603
604	for_each_rtdcom(rtd, rtdcom) {
605		component = rtdcom->component;
606
607		if (!component->driver->compr_ops ||
608		    !component->driver->compr_ops->get_params)
609			continue;
610
611		ret = component->driver->compr_ops->get_params(cstream, params);
612		break;
613	}
614
615err:
616	mutex_unlock(&rtd->card->pcm_mutex);
617	return ret;
618}
619
620static int soc_compr_get_caps(struct snd_compr_stream *cstream,
621			      struct snd_compr_caps *caps)
622{
623	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
624	struct snd_soc_component *component;
625	struct snd_soc_rtdcom_list *rtdcom;
626	int ret = 0;
627
628	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
629
630	for_each_rtdcom(rtd, rtdcom) {
631		component = rtdcom->component;
632
633		if (!component->driver->compr_ops ||
634		    !component->driver->compr_ops->get_caps)
635			continue;
636
637		ret = component->driver->compr_ops->get_caps(cstream, caps);
638		break;
639	}
640
641	mutex_unlock(&rtd->card->pcm_mutex);
642	return ret;
643}
644
645static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
646				    struct snd_compr_codec_caps *codec)
647{
648	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
649	struct snd_soc_component *component;
650	struct snd_soc_rtdcom_list *rtdcom;
651	int ret = 0;
652
653	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
654
655	for_each_rtdcom(rtd, rtdcom) {
656		component = rtdcom->component;
657
658		if (!component->driver->compr_ops ||
659		    !component->driver->compr_ops->get_codec_caps)
660			continue;
661
662		ret = component->driver->compr_ops->get_codec_caps(cstream,
663								   codec);
664		break;
665	}
666
667	mutex_unlock(&rtd->card->pcm_mutex);
668	return ret;
669}
670
671static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
672{
673	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
674	struct snd_soc_component *component;
675	struct snd_soc_rtdcom_list *rtdcom;
676	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
677	int ret = 0;
678
679	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
680
681	if (cpu_dai->driver->cops && cpu_dai->driver->cops->ack) {
682		ret = cpu_dai->driver->cops->ack(cstream, bytes, cpu_dai);
683		if (ret < 0)
684			goto err;
685	}
686
687	for_each_rtdcom(rtd, rtdcom) {
688		component = rtdcom->component;
689
690		if (!component->driver->compr_ops ||
691		    !component->driver->compr_ops->ack)
692			continue;
693
694		ret = component->driver->compr_ops->ack(cstream, bytes);
695		if (ret < 0)
696			goto err;
697	}
698
699err:
700	mutex_unlock(&rtd->card->pcm_mutex);
701	return ret;
702}
703
704static int soc_compr_pointer(struct snd_compr_stream *cstream,
705			     struct snd_compr_tstamp *tstamp)
706{
707	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
708	struct snd_soc_component *component;
709	struct snd_soc_rtdcom_list *rtdcom;
710	int ret = 0;
711	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
712
713	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
714
715	if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
716		cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
717
718	for_each_rtdcom(rtd, rtdcom) {
719		component = rtdcom->component;
720
721		if (!component->driver->compr_ops ||
722		    !component->driver->compr_ops->pointer)
723			continue;
724
725		ret = component->driver->compr_ops->pointer(cstream, tstamp);
726		break;
727	}
728
729	mutex_unlock(&rtd->card->pcm_mutex);
730	return ret;
731}
732
733static int soc_compr_copy(struct snd_compr_stream *cstream,
734			  char __user *buf, size_t count)
735{
736	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
737	struct snd_soc_component *component;
738	struct snd_soc_rtdcom_list *rtdcom;
739	int ret = 0;
740
741	mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
742
743	for_each_rtdcom(rtd, rtdcom) {
744		component = rtdcom->component;
745
746		if (!component->driver->compr_ops ||
747		    !component->driver->compr_ops->copy)
748			continue;
749
750		ret = component->driver->compr_ops->copy(cstream, buf, count);
751		break;
752	}
753
754	mutex_unlock(&rtd->card->pcm_mutex);
755	return ret;
756}
757
758static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
759				  struct snd_compr_metadata *metadata)
760{
761	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
762	struct snd_soc_component *component;
763	struct snd_soc_rtdcom_list *rtdcom;
764	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
765	int ret;
766
767	if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
768		ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
769		if (ret < 0)
770			return ret;
771	}
772
773	for_each_rtdcom(rtd, rtdcom) {
774		component = rtdcom->component;
775
776		if (!component->driver->compr_ops ||
777		    !component->driver->compr_ops->set_metadata)
778			continue;
779
780		ret = component->driver->compr_ops->set_metadata(cstream,
781								 metadata);
782		if (ret < 0)
783			return ret;
784	}
785
786	return 0;
787}
788
789static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
790				  struct snd_compr_metadata *metadata)
791{
792	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
793	struct snd_soc_component *component;
794	struct snd_soc_rtdcom_list *rtdcom;
795	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
796	int ret;
797
798	if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
799		ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
800		if (ret < 0)
801			return ret;
802	}
803
804	for_each_rtdcom(rtd, rtdcom) {
805		component = rtdcom->component;
806
807		if (!component->driver->compr_ops ||
808		    !component->driver->compr_ops->get_metadata)
809			continue;
810
811		return component->driver->compr_ops->get_metadata(cstream,
812								  metadata);
813	}
814
815	return 0;
816}
817
818/* ASoC Compress operations */
819static struct snd_compr_ops soc_compr_ops = {
820	.open		= soc_compr_open,
821	.free		= soc_compr_free,
822	.set_params	= soc_compr_set_params,
823	.set_metadata   = soc_compr_set_metadata,
824	.get_metadata	= soc_compr_get_metadata,
825	.get_params	= soc_compr_get_params,
826	.trigger	= soc_compr_trigger,
827	.pointer	= soc_compr_pointer,
828	.ack		= soc_compr_ack,
829	.get_caps	= soc_compr_get_caps,
830	.get_codec_caps = soc_compr_get_codec_caps
831};
832
833/* ASoC Dynamic Compress operations */
834static struct snd_compr_ops soc_compr_dyn_ops = {
835	.open		= soc_compr_open_fe,
836	.free		= soc_compr_free_fe,
837	.set_params	= soc_compr_set_params_fe,
838	.get_params	= soc_compr_get_params,
839	.set_metadata   = soc_compr_set_metadata,
840	.get_metadata	= soc_compr_get_metadata,
841	.trigger	= soc_compr_trigger_fe,
842	.pointer	= soc_compr_pointer,
843	.ack		= soc_compr_ack,
844	.get_caps	= soc_compr_get_caps,
845	.get_codec_caps = soc_compr_get_codec_caps
846};
847
848/**
849 * snd_soc_new_compress - create a new compress.
850 *
851 * @rtd: The runtime for which we will create compress
852 * @num: the device index number (zero based - shared with normal PCMs)
853 *
854 * Return: 0 for success, else error.
855 */
856int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
857{
858	struct snd_soc_component *component;
859	struct snd_soc_rtdcom_list *rtdcom;
860	struct snd_soc_dai *codec_dai = rtd->codec_dai;
861	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
862	struct snd_compr *compr;
863	struct snd_pcm *be_pcm;
864	char new_name[64];
865	int ret = 0, direction = 0;
866	int playback = 0, capture = 0;
867
868	if (rtd->num_codecs > 1) {
869		dev_err(rtd->card->dev,
870			"Compress ASoC: Multicodec not supported\n");
871		return -EINVAL;
872	}
873
874	/* check client and interface hw capabilities */
875	if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
876	    snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_PLAYBACK))
 
 
877		playback = 1;
878	if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
879	    snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_CAPTURE))
880		capture = 1;
881
 
 
 
882	/*
883	 * Compress devices are unidirectional so only one of the directions
884	 * should be set, check for that (xor)
885	 */
886	if (playback + capture != 1) {
887		dev_err(rtd->card->dev,
888			"Compress ASoC: Invalid direction for P %d, C %d\n",
889			playback, capture);
890		return -EINVAL;
891	}
892
893	if (playback)
894		direction = SND_COMPRESS_PLAYBACK;
895	else
896		direction = SND_COMPRESS_CAPTURE;
897
898	compr = devm_kzalloc(rtd->card->dev, sizeof(*compr), GFP_KERNEL);
899	if (!compr)
 
900		return -ENOMEM;
 
901
902	compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
903				  GFP_KERNEL);
904	if (!compr->ops)
905		return -ENOMEM;
 
 
 
906
907	if (rtd->dai_link->dynamic) {
908		snprintf(new_name, sizeof(new_name), "(%s)",
909			rtd->dai_link->stream_name);
910
911		ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
912				rtd->dai_link->dpcm_playback,
913				rtd->dai_link->dpcm_capture, &be_pcm);
914		if (ret < 0) {
915			dev_err(rtd->card->dev,
916				"Compress ASoC: can't create compressed for %s: %d\n",
917				rtd->dai_link->name, ret);
918			return ret;
919		}
920
921		rtd->pcm = be_pcm;
922		rtd->fe_compr = 1;
923		if (rtd->dai_link->dpcm_playback)
924			be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
925		else if (rtd->dai_link->dpcm_capture)
926			be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
927		memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
928	} else {
929		snprintf(new_name, sizeof(new_name), "%s %s-%d",
930			rtd->dai_link->stream_name, codec_dai->name, num);
931
932		memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
933	}
934
935	for_each_rtdcom(rtd, rtdcom) {
936		component = rtdcom->component;
 
937
938		if (!component->driver->compr_ops ||
939		    !component->driver->compr_ops->copy)
940			continue;
941
942		compr->ops->copy = soc_compr_copy;
943		break;
944	}
945
946	mutex_init(&compr->lock);
947	ret = snd_compress_new(rtd->card->snd_card, num, direction,
948				new_name, compr);
949	if (ret < 0) {
950		component = rtd->codec_dai->component;
951		dev_err(component->dev,
952			"Compress ASoC: can't create compress for codec %s: %d\n",
953			component->name, ret);
954		return ret;
955	}
956
957	/* DAPM dai link stream work */
958	INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
959
960	rtd->compr = compr;
961	compr->private_data = rtd;
962
963	dev_info(rtd->card->dev, "Compress ASoC: %s <-> %s mapping ok\n",
964		 codec_dai->name, cpu_dai->name);
 
965
966	return 0;
 
 
967}
968EXPORT_SYMBOL_GPL(snd_soc_new_compress);