xref: /openbmc/linux/sound/soc/soc-compress.c (revision 239480ab)
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 = 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 
163 path_err:
164 	dpcm_path_put(&list);
165 fe_err:
166 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
167 		fe->dai_link->compr_ops->shutdown(cstream);
168 machine_err:
169 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
170 		platform->driver->compr_ops->free(cstream);
171 plat_err:
172 	if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
173 		cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
174 out:
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  */
185 static 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 
208 static 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 
265 static 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 
316 static 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 
346 out:
347 	mutex_unlock(&rtd->pcm_mutex);
348 	return ret;
349 }
350 
351 static 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 
406 out:
407 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
408 	mutex_unlock(&fe->card->mutex);
409 	return ret;
410 }
411 
412 static 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 
461 err:
462 	mutex_unlock(&rtd->pcm_mutex);
463 	return ret;
464 }
465 
466 static 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 
521 out:
522 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
523 	mutex_unlock(&fe->card->mutex);
524 	return ret;
525 }
526 
527 static 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 
546 err:
547 	mutex_unlock(&rtd->pcm_mutex);
548 	return ret;
549 }
550 
551 static 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 
567 static 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 
583 static 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 
601 err:
602 	mutex_unlock(&rtd->pcm_mutex);
603 	return ret;
604 }
605 
606 static 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 
626 static 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 
642 static 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 
662 static 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 */
683 static 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 */
698 static 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  */
720 int 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 
829 compr_err:
830 	kfree(compr);
831 	return ret;
832 }
833 EXPORT_SYMBOL_GPL(snd_soc_new_compress);
834