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