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