xref: /openbmc/linux/sound/soc/soc-compress.c (revision 8f70e515)
11245b700SNamarta Kohli /*
21245b700SNamarta Kohli  * soc-compress.c  --  ALSA SoC Compress
31245b700SNamarta Kohli  *
41245b700SNamarta Kohli  * Copyright (C) 2012 Intel Corp.
51245b700SNamarta Kohli  *
61245b700SNamarta Kohli  * Authors: Namarta Kohli <namartax.kohli@intel.com>
71245b700SNamarta Kohli  *          Ramesh Babu K V <ramesh.babu@linux.intel.com>
81245b700SNamarta Kohli  *          Vinod Koul <vinod.koul@linux.intel.com>
91245b700SNamarta Kohli  *
101245b700SNamarta Kohli  *  This program is free software; you can redistribute  it and/or modify it
111245b700SNamarta Kohli  *  under  the terms of  the GNU General  Public License as published by the
121245b700SNamarta Kohli  *  Free Software Foundation;  either version 2 of the  License, or (at your
131245b700SNamarta Kohli  *  option) any later version.
141245b700SNamarta Kohli  *
151245b700SNamarta Kohli  */
161245b700SNamarta Kohli 
171245b700SNamarta Kohli #include <linux/kernel.h>
181245b700SNamarta Kohli #include <linux/init.h>
191245b700SNamarta Kohli #include <linux/delay.h>
201245b700SNamarta Kohli #include <linux/slab.h>
211245b700SNamarta Kohli #include <linux/workqueue.h>
221245b700SNamarta Kohli #include <sound/core.h>
231245b700SNamarta Kohli #include <sound/compress_params.h>
241245b700SNamarta Kohli #include <sound/compress_driver.h>
251245b700SNamarta Kohli #include <sound/soc.h>
261245b700SNamarta Kohli #include <sound/initval.h>
272a99ef0fSLiam Girdwood #include <sound/soc-dpcm.h>
281245b700SNamarta Kohli 
291245b700SNamarta Kohli static int soc_compr_open(struct snd_compr_stream *cstream)
301245b700SNamarta Kohli {
311245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
321245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
331245b700SNamarta Kohli 	int ret = 0;
341245b700SNamarta Kohli 
3515e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
3615e2e619SCharles Keepax 
371245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
381245b700SNamarta Kohli 		ret = platform->driver->compr_ops->open(cstream);
391245b700SNamarta Kohli 		if (ret < 0) {
40f4333203SLars-Peter Clausen 			pr_err("compress asoc: can't open platform %s\n",
41f4333203SLars-Peter Clausen 				platform->component.name);
421245b700SNamarta Kohli 			goto out;
431245b700SNamarta Kohli 		}
441245b700SNamarta Kohli 	}
451245b700SNamarta Kohli 
461245b700SNamarta Kohli 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
471245b700SNamarta Kohli 		ret = rtd->dai_link->compr_ops->startup(cstream);
481245b700SNamarta Kohli 		if (ret < 0) {
491245b700SNamarta Kohli 			pr_err("compress asoc: %s startup failed\n", rtd->dai_link->name);
501245b700SNamarta Kohli 			goto machine_err;
511245b700SNamarta Kohli 		}
521245b700SNamarta Kohli 	}
531245b700SNamarta Kohli 
5424894b76SLars-Peter Clausen 	snd_soc_runtime_activate(rtd, cstream->direction);
551245b700SNamarta Kohli 
5615e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
5715e2e619SCharles Keepax 
581245b700SNamarta Kohli 	return 0;
591245b700SNamarta Kohli 
601245b700SNamarta Kohli machine_err:
611245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
621245b700SNamarta Kohli 		platform->driver->compr_ops->free(cstream);
631245b700SNamarta Kohli out:
6415e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
651245b700SNamarta Kohli 	return ret;
661245b700SNamarta Kohli }
671245b700SNamarta Kohli 
682a99ef0fSLiam Girdwood static int soc_compr_open_fe(struct snd_compr_stream *cstream)
692a99ef0fSLiam Girdwood {
702a99ef0fSLiam Girdwood 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
712a99ef0fSLiam Girdwood 	struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
722a99ef0fSLiam Girdwood 	struct snd_soc_platform *platform = fe->platform;
732a99ef0fSLiam Girdwood 	struct snd_soc_dpcm *dpcm;
742a99ef0fSLiam Girdwood 	struct snd_soc_dapm_widget_list *list;
752a99ef0fSLiam Girdwood 	int stream;
762a99ef0fSLiam Girdwood 	int ret = 0;
772a99ef0fSLiam Girdwood 
782a99ef0fSLiam Girdwood 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
792a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_PLAYBACK;
802a99ef0fSLiam Girdwood 	else
812a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_CAPTURE;
822a99ef0fSLiam Girdwood 
832a99ef0fSLiam Girdwood 	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
842a99ef0fSLiam Girdwood 
852a99ef0fSLiam Girdwood 	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
862a99ef0fSLiam Girdwood 		ret = platform->driver->compr_ops->open(cstream);
872a99ef0fSLiam Girdwood 		if (ret < 0) {
88f4333203SLars-Peter Clausen 			pr_err("compress asoc: can't open platform %s\n",
89f4333203SLars-Peter Clausen 				platform->component.name);
902a99ef0fSLiam Girdwood 			goto out;
912a99ef0fSLiam Girdwood 		}
922a99ef0fSLiam Girdwood 	}
932a99ef0fSLiam Girdwood 
942a99ef0fSLiam Girdwood 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
952a99ef0fSLiam Girdwood 		ret = fe->dai_link->compr_ops->startup(cstream);
962a99ef0fSLiam Girdwood 		if (ret < 0) {
972a99ef0fSLiam Girdwood 			pr_err("compress asoc: %s startup failed\n", fe->dai_link->name);
982a99ef0fSLiam Girdwood 			goto machine_err;
992a99ef0fSLiam Girdwood 		}
1002a99ef0fSLiam Girdwood 	}
1012a99ef0fSLiam Girdwood 
1022a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime = fe_substream->runtime;
1032a99ef0fSLiam Girdwood 
1048f70e515SQiao Zhou 	ret = dpcm_path_get(fe, stream, &list);
1058f70e515SQiao Zhou 	if (ret < 0) {
1068f70e515SQiao Zhou 		mutex_unlock(&fe->card->mutex);
1078f70e515SQiao Zhou 		goto fe_err;
1088f70e515SQiao Zhou 	} else if (ret == 0) {
1092a99ef0fSLiam Girdwood 		dev_dbg(fe->dev, "ASoC: %s no valid %s route\n",
1102a99ef0fSLiam Girdwood 			fe->dai_link->name, stream ? "capture" : "playback");
1112a99ef0fSLiam Girdwood 	}
1122a99ef0fSLiam Girdwood 
1132a99ef0fSLiam Girdwood 	/* calculate valid and active FE <-> BE dpcms */
1142a99ef0fSLiam Girdwood 	dpcm_process_paths(fe, stream, &list, 1);
1152a99ef0fSLiam Girdwood 
1162a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1172a99ef0fSLiam Girdwood 
1182a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_startup(fe, stream);
1192a99ef0fSLiam Girdwood 	if (ret < 0) {
1202a99ef0fSLiam Girdwood 		/* clean up all links */
1212a99ef0fSLiam Girdwood 		list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
1222a99ef0fSLiam Girdwood 			dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
1232a99ef0fSLiam Girdwood 
1242a99ef0fSLiam Girdwood 		dpcm_be_disconnect(fe, stream);
1252a99ef0fSLiam Girdwood 		fe->dpcm[stream].runtime = NULL;
1262a99ef0fSLiam Girdwood 		goto fe_err;
1272a99ef0fSLiam Girdwood 	}
1282a99ef0fSLiam Girdwood 
1292a99ef0fSLiam Girdwood 	dpcm_clear_pending_state(fe, stream);
1302a99ef0fSLiam Girdwood 	dpcm_path_put(&list);
1312a99ef0fSLiam Girdwood 
1322a99ef0fSLiam Girdwood 	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1332a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1342a99ef0fSLiam Girdwood 
13524894b76SLars-Peter Clausen 	snd_soc_runtime_activate(fe, stream);
1362a99ef0fSLiam Girdwood 
1372a99ef0fSLiam Girdwood 	mutex_unlock(&fe->card->mutex);
1382a99ef0fSLiam Girdwood 
1392a99ef0fSLiam Girdwood 	return 0;
1402a99ef0fSLiam Girdwood 
1412a99ef0fSLiam Girdwood fe_err:
1422a99ef0fSLiam Girdwood 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
1432a99ef0fSLiam Girdwood 		fe->dai_link->compr_ops->shutdown(cstream);
1442a99ef0fSLiam Girdwood machine_err:
1452a99ef0fSLiam Girdwood 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
1462a99ef0fSLiam Girdwood 		platform->driver->compr_ops->free(cstream);
1472a99ef0fSLiam Girdwood out:
1482a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1492a99ef0fSLiam Girdwood 	mutex_unlock(&fe->card->mutex);
1502a99ef0fSLiam Girdwood 	return ret;
1512a99ef0fSLiam Girdwood }
1522a99ef0fSLiam Girdwood 
153202c8f70SCharles Keepax /*
154202c8f70SCharles Keepax  * Power down the audio subsystem pmdown_time msecs after close is called.
155202c8f70SCharles Keepax  * This is to ensure there are no pops or clicks in between any music tracks
156202c8f70SCharles Keepax  * due to DAPM power cycling.
157202c8f70SCharles Keepax  */
158202c8f70SCharles Keepax static void close_delayed_work(struct work_struct *work)
159202c8f70SCharles Keepax {
160202c8f70SCharles Keepax 	struct snd_soc_pcm_runtime *rtd =
161202c8f70SCharles Keepax 			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
162202c8f70SCharles Keepax 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
163202c8f70SCharles Keepax 
164202c8f70SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
165202c8f70SCharles Keepax 
166202c8f70SCharles Keepax 	dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
167202c8f70SCharles Keepax 		 codec_dai->driver->playback.stream_name,
168202c8f70SCharles Keepax 		 codec_dai->playback_active ? "active" : "inactive",
169202c8f70SCharles Keepax 		 rtd->pop_wait ? "yes" : "no");
170202c8f70SCharles Keepax 
171202c8f70SCharles Keepax 	/* are we waiting on this codec DAI stream */
172202c8f70SCharles Keepax 	if (rtd->pop_wait == 1) {
173202c8f70SCharles Keepax 		rtd->pop_wait = 0;
174202c8f70SCharles Keepax 		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
175202c8f70SCharles Keepax 					  SND_SOC_DAPM_STREAM_STOP);
176202c8f70SCharles Keepax 	}
177202c8f70SCharles Keepax 
178202c8f70SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
179202c8f70SCharles Keepax }
180202c8f70SCharles Keepax 
1811245b700SNamarta Kohli static int soc_compr_free(struct snd_compr_stream *cstream)
1821245b700SNamarta Kohli {
1831245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
1841245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
1851245b700SNamarta Kohli 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1861245b700SNamarta Kohli 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
18724894b76SLars-Peter Clausen 	int stream;
1881245b700SNamarta Kohli 
18915e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
19015e2e619SCharles Keepax 
19124894b76SLars-Peter Clausen 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
19224894b76SLars-Peter Clausen 		stream = SNDRV_PCM_STREAM_PLAYBACK;
19324894b76SLars-Peter Clausen 	else
19424894b76SLars-Peter Clausen 		stream = SNDRV_PCM_STREAM_CAPTURE;
19524894b76SLars-Peter Clausen 
19624894b76SLars-Peter Clausen 	snd_soc_runtime_deactivate(rtd, stream);
1971245b700SNamarta Kohli 
198da18396fSMark Brown 	snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
199da18396fSMark Brown 
2001245b700SNamarta Kohli 	if (!cpu_dai->active)
2011245b700SNamarta Kohli 		cpu_dai->rate = 0;
2021245b700SNamarta Kohli 
2031245b700SNamarta Kohli 	if (!codec_dai->active)
2041245b700SNamarta Kohli 		codec_dai->rate = 0;
2051245b700SNamarta Kohli 
2061245b700SNamarta Kohli 
2071245b700SNamarta Kohli 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
2081245b700SNamarta Kohli 		rtd->dai_link->compr_ops->shutdown(cstream);
2091245b700SNamarta Kohli 
2101245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
2111245b700SNamarta Kohli 		platform->driver->compr_ops->free(cstream);
2121245b700SNamarta Kohli 
2131245b700SNamarta Kohli 	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
214208a1589SLars-Peter Clausen 		if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
2151245b700SNamarta Kohli 			snd_soc_dapm_stream_event(rtd,
2161245b700SNamarta Kohli 					SNDRV_PCM_STREAM_PLAYBACK,
2171245b700SNamarta Kohli 					SND_SOC_DAPM_STREAM_STOP);
2188c3d2aa4SCharles Keepax 		} else {
2199bffb1fbSMisael Lopez Cruz 			rtd->pop_wait = 1;
2203d24cfe4SMark Brown 			queue_delayed_work(system_power_efficient_wq,
2213d24cfe4SMark Brown 					   &rtd->delayed_work,
2221245b700SNamarta Kohli 					   msecs_to_jiffies(rtd->pmdown_time));
2238c3d2aa4SCharles Keepax 		}
2241245b700SNamarta Kohli 	} else {
2251245b700SNamarta Kohli 		/* capture streams can be powered down now */
2261245b700SNamarta Kohli 		snd_soc_dapm_stream_event(rtd,
2271245b700SNamarta Kohli 			SNDRV_PCM_STREAM_CAPTURE,
2281245b700SNamarta Kohli 			SND_SOC_DAPM_STREAM_STOP);
2291245b700SNamarta Kohli 	}
2301245b700SNamarta Kohli 
23115e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
2321245b700SNamarta Kohli 	return 0;
2331245b700SNamarta Kohli }
2341245b700SNamarta Kohli 
2352a99ef0fSLiam Girdwood static int soc_compr_free_fe(struct snd_compr_stream *cstream)
2362a99ef0fSLiam Girdwood {
2372a99ef0fSLiam Girdwood 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
2382a99ef0fSLiam Girdwood 	struct snd_soc_platform *platform = fe->platform;
2392a99ef0fSLiam Girdwood 	struct snd_soc_dpcm *dpcm;
2402a99ef0fSLiam Girdwood 	int stream, ret;
2412a99ef0fSLiam Girdwood 
2422a99ef0fSLiam Girdwood 	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
2432a99ef0fSLiam Girdwood 
24424894b76SLars-Peter Clausen 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
2452a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_PLAYBACK;
24624894b76SLars-Peter Clausen 	else
2472a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_CAPTURE;
2482a99ef0fSLiam Girdwood 
24924894b76SLars-Peter Clausen 	snd_soc_runtime_deactivate(fe, stream);
2502a99ef0fSLiam Girdwood 
2512a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
2522a99ef0fSLiam Girdwood 
2532a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_hw_free(fe, stream);
2542a99ef0fSLiam Girdwood 	if (ret < 0)
2552a99ef0fSLiam Girdwood 		dev_err(fe->dev, "compressed hw_free failed %d\n", ret);
2562a99ef0fSLiam Girdwood 
2572a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_shutdown(fe, stream);
2582a99ef0fSLiam Girdwood 
2592a99ef0fSLiam Girdwood 	/* mark FE's links ready to prune */
2602a99ef0fSLiam Girdwood 	list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
2612a99ef0fSLiam Girdwood 		dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
2622a99ef0fSLiam Girdwood 
2632a99ef0fSLiam Girdwood 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
2642a99ef0fSLiam Girdwood 		dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
2652a99ef0fSLiam Girdwood 	else
2662a99ef0fSLiam Girdwood 		dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
2672a99ef0fSLiam Girdwood 
2682a99ef0fSLiam Girdwood 	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
2692a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
2702a99ef0fSLiam Girdwood 
2712a99ef0fSLiam Girdwood 	dpcm_be_disconnect(fe, stream);
2722a99ef0fSLiam Girdwood 
2732a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime = NULL;
2742a99ef0fSLiam Girdwood 
2752a99ef0fSLiam Girdwood 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
2762a99ef0fSLiam Girdwood 		fe->dai_link->compr_ops->shutdown(cstream);
2772a99ef0fSLiam Girdwood 
2782a99ef0fSLiam Girdwood 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
2792a99ef0fSLiam Girdwood 		platform->driver->compr_ops->free(cstream);
2802a99ef0fSLiam Girdwood 
2812a99ef0fSLiam Girdwood 	mutex_unlock(&fe->card->mutex);
2822a99ef0fSLiam Girdwood 	return 0;
2832a99ef0fSLiam Girdwood }
2842a99ef0fSLiam Girdwood 
2851245b700SNamarta Kohli static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
2861245b700SNamarta Kohli {
2871245b700SNamarta Kohli 
2881245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2891245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
2901245b700SNamarta Kohli 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
2911245b700SNamarta Kohli 	int ret = 0;
2921245b700SNamarta Kohli 
29315e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
29415e2e619SCharles Keepax 
2951245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
2961245b700SNamarta Kohli 		ret = platform->driver->compr_ops->trigger(cstream, cmd);
2971245b700SNamarta Kohli 		if (ret < 0)
29815e2e619SCharles Keepax 			goto out;
2991245b700SNamarta Kohli 	}
3001245b700SNamarta Kohli 
301e38b9b74SMark Brown 	switch (cmd) {
302e38b9b74SMark Brown 	case SNDRV_PCM_TRIGGER_START:
303da18396fSMark Brown 		snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
304e38b9b74SMark Brown 		break;
305e38b9b74SMark Brown 	case SNDRV_PCM_TRIGGER_STOP:
306da18396fSMark Brown 		snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
307e38b9b74SMark Brown 		break;
308e38b9b74SMark Brown 	}
3091245b700SNamarta Kohli 
31015e2e619SCharles Keepax out:
31115e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
3121245b700SNamarta Kohli 	return ret;
3131245b700SNamarta Kohli }
3141245b700SNamarta Kohli 
3152a99ef0fSLiam Girdwood static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
3162a99ef0fSLiam Girdwood {
3172a99ef0fSLiam Girdwood 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
3182a99ef0fSLiam Girdwood 	struct snd_soc_platform *platform = fe->platform;
3192a99ef0fSLiam Girdwood 	int ret = 0, stream;
3202a99ef0fSLiam Girdwood 
3212a99ef0fSLiam Girdwood 	if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
3222a99ef0fSLiam Girdwood 		cmd == SND_COMPR_TRIGGER_DRAIN) {
3232a99ef0fSLiam Girdwood 
3242a99ef0fSLiam Girdwood 		if (platform->driver->compr_ops &&
3252a99ef0fSLiam Girdwood 		    platform->driver->compr_ops->trigger)
32615b8e94fSDan Carpenter 			return platform->driver->compr_ops->trigger(cstream,
32715b8e94fSDan Carpenter 								    cmd);
3282a99ef0fSLiam Girdwood 	}
3292a99ef0fSLiam Girdwood 
3302a99ef0fSLiam Girdwood 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
3312a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_PLAYBACK;
3322a99ef0fSLiam Girdwood 	else
3332a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_CAPTURE;
3342a99ef0fSLiam Girdwood 
3352a99ef0fSLiam Girdwood 
3362a99ef0fSLiam Girdwood 	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
3372a99ef0fSLiam Girdwood 
3382a99ef0fSLiam Girdwood 	if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
3392a99ef0fSLiam Girdwood 		ret = platform->driver->compr_ops->trigger(cstream, cmd);
3402a99ef0fSLiam Girdwood 		if (ret < 0)
3412a99ef0fSLiam Girdwood 			goto out;
3422a99ef0fSLiam Girdwood 	}
3432a99ef0fSLiam Girdwood 
3442a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
3452a99ef0fSLiam Girdwood 
3462a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_trigger(fe, stream, cmd);
3472a99ef0fSLiam Girdwood 
3482a99ef0fSLiam Girdwood 	switch (cmd) {
3492a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_START:
3502a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_RESUME:
3512a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
3522a99ef0fSLiam Girdwood 		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
3532a99ef0fSLiam Girdwood 		break;
3542a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_STOP:
3552a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_SUSPEND:
3562a99ef0fSLiam Girdwood 		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
3572a99ef0fSLiam Girdwood 		break;
3582a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
3592a99ef0fSLiam Girdwood 		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
3602a99ef0fSLiam Girdwood 		break;
3612a99ef0fSLiam Girdwood 	}
3622a99ef0fSLiam Girdwood 
3632a99ef0fSLiam Girdwood out:
3642a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
3652a99ef0fSLiam Girdwood 	mutex_unlock(&fe->card->mutex);
3662a99ef0fSLiam Girdwood 	return ret;
3672a99ef0fSLiam Girdwood }
3682a99ef0fSLiam Girdwood 
3691245b700SNamarta Kohli static int soc_compr_set_params(struct snd_compr_stream *cstream,
3701245b700SNamarta Kohli 					struct snd_compr_params *params)
3711245b700SNamarta Kohli {
3721245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
3731245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
3741245b700SNamarta Kohli 	int ret = 0;
3751245b700SNamarta Kohli 
37615e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
37715e2e619SCharles Keepax 
3781245b700SNamarta Kohli 	/* first we call set_params for the platform driver
3791245b700SNamarta Kohli 	 * this should configure the soc side
3801245b700SNamarta Kohli 	 * if the machine has compressed ops then we call that as well
3811245b700SNamarta Kohli 	 * expectation is that platform and machine will configure everything
3821245b700SNamarta Kohli 	 * for this compress path, like configuring pcm port for codec
3831245b700SNamarta Kohli 	 */
3841245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
3851245b700SNamarta Kohli 		ret = platform->driver->compr_ops->set_params(cstream, params);
3861245b700SNamarta Kohli 		if (ret < 0)
387fa40ef20SCharles Keepax 			goto err;
3881245b700SNamarta Kohli 	}
3891245b700SNamarta Kohli 
3901245b700SNamarta Kohli 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
3911245b700SNamarta Kohli 		ret = rtd->dai_link->compr_ops->set_params(cstream);
3921245b700SNamarta Kohli 		if (ret < 0)
393fa40ef20SCharles Keepax 			goto err;
3941245b700SNamarta Kohli 	}
3951245b700SNamarta Kohli 
3962c071ed7SCharles Keepax 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
3971245b700SNamarta Kohli 		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
3981245b700SNamarta Kohli 					SND_SOC_DAPM_STREAM_START);
3992c071ed7SCharles Keepax 	else
4002c071ed7SCharles Keepax 		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
4012c071ed7SCharles Keepax 					SND_SOC_DAPM_STREAM_START);
4021245b700SNamarta Kohli 
403fa40ef20SCharles Keepax 	/* cancel any delayed stream shutdown that is pending */
404fa40ef20SCharles Keepax 	rtd->pop_wait = 0;
405fa40ef20SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
406fa40ef20SCharles Keepax 
407fa40ef20SCharles Keepax 	cancel_delayed_work_sync(&rtd->delayed_work);
408fa40ef20SCharles Keepax 
409fa40ef20SCharles Keepax 	return ret;
410fa40ef20SCharles Keepax 
411fa40ef20SCharles Keepax err:
41215e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
4131245b700SNamarta Kohli 	return ret;
4141245b700SNamarta Kohli }
4151245b700SNamarta Kohli 
4162a99ef0fSLiam Girdwood static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
4172a99ef0fSLiam Girdwood 					struct snd_compr_params *params)
4182a99ef0fSLiam Girdwood {
4192a99ef0fSLiam Girdwood 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
4202a99ef0fSLiam Girdwood 	struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
4212a99ef0fSLiam Girdwood 	struct snd_soc_platform *platform = fe->platform;
4222a99ef0fSLiam Girdwood 	int ret = 0, stream;
4232a99ef0fSLiam Girdwood 
4242a99ef0fSLiam Girdwood 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
4252a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_PLAYBACK;
4262a99ef0fSLiam Girdwood 	else
4272a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_CAPTURE;
4282a99ef0fSLiam Girdwood 
4292a99ef0fSLiam Girdwood 	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
4302a99ef0fSLiam Girdwood 
4312a99ef0fSLiam Girdwood 	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
4322a99ef0fSLiam Girdwood 		ret = platform->driver->compr_ops->set_params(cstream, params);
4332a99ef0fSLiam Girdwood 		if (ret < 0)
4342a99ef0fSLiam Girdwood 			goto out;
4352a99ef0fSLiam Girdwood 	}
4362a99ef0fSLiam Girdwood 
4372a99ef0fSLiam Girdwood 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
4382a99ef0fSLiam Girdwood 		ret = fe->dai_link->compr_ops->set_params(cstream);
4392a99ef0fSLiam Girdwood 		if (ret < 0)
4402a99ef0fSLiam Girdwood 			goto out;
4412a99ef0fSLiam Girdwood 	}
4422a99ef0fSLiam Girdwood 
4432a99ef0fSLiam Girdwood 	/*
4442a99ef0fSLiam Girdwood 	 * Create an empty hw_params for the BE as the machine driver must
4452a99ef0fSLiam Girdwood 	 * fix this up to match DSP decoder and ASRC configuration.
4462a99ef0fSLiam Girdwood 	 * I.e. machine driver fixup for compressed BE is mandatory.
4472a99ef0fSLiam Girdwood 	 */
4482a99ef0fSLiam Girdwood 	memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
4492a99ef0fSLiam Girdwood 		sizeof(struct snd_pcm_hw_params));
4502a99ef0fSLiam Girdwood 
4512a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
4522a99ef0fSLiam Girdwood 
4532a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_hw_params(fe, stream);
4542a99ef0fSLiam Girdwood 	if (ret < 0)
4552a99ef0fSLiam Girdwood 		goto out;
4562a99ef0fSLiam Girdwood 
4572a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_prepare(fe, stream);
4582a99ef0fSLiam Girdwood 	if (ret < 0)
4592a99ef0fSLiam Girdwood 		goto out;
4602a99ef0fSLiam Girdwood 
4612a99ef0fSLiam Girdwood 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
4622a99ef0fSLiam Girdwood 		dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
4632a99ef0fSLiam Girdwood 	else
4642a99ef0fSLiam Girdwood 		dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
4652a99ef0fSLiam Girdwood 
4662a99ef0fSLiam Girdwood 	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
4672a99ef0fSLiam Girdwood 
4682a99ef0fSLiam Girdwood out:
4692a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
4702a99ef0fSLiam Girdwood 	mutex_unlock(&fe->card->mutex);
4712a99ef0fSLiam Girdwood 	return ret;
4722a99ef0fSLiam Girdwood }
4732a99ef0fSLiam Girdwood 
4741245b700SNamarta Kohli static int soc_compr_get_params(struct snd_compr_stream *cstream,
4751245b700SNamarta Kohli 					struct snd_codec *params)
4761245b700SNamarta Kohli {
4771245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
4781245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
4791245b700SNamarta Kohli 	int ret = 0;
4801245b700SNamarta Kohli 
48115e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
48215e2e619SCharles Keepax 
4831245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_params)
4841245b700SNamarta Kohli 		ret = platform->driver->compr_ops->get_params(cstream, params);
4851245b700SNamarta Kohli 
48615e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
4871245b700SNamarta Kohli 	return ret;
4881245b700SNamarta Kohli }
4891245b700SNamarta Kohli 
4901245b700SNamarta Kohli static int soc_compr_get_caps(struct snd_compr_stream *cstream,
4911245b700SNamarta Kohli 				struct snd_compr_caps *caps)
4921245b700SNamarta Kohli {
4931245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
4941245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
4951245b700SNamarta Kohli 	int ret = 0;
4961245b700SNamarta Kohli 
49715e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
49815e2e619SCharles Keepax 
4991245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps)
5001245b700SNamarta Kohli 		ret = platform->driver->compr_ops->get_caps(cstream, caps);
5011245b700SNamarta Kohli 
50215e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
5031245b700SNamarta Kohli 	return ret;
5041245b700SNamarta Kohli }
5051245b700SNamarta Kohli 
5061245b700SNamarta Kohli static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
5071245b700SNamarta Kohli 				struct snd_compr_codec_caps *codec)
5081245b700SNamarta Kohli {
5091245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5101245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
5111245b700SNamarta Kohli 	int ret = 0;
5121245b700SNamarta Kohli 
51315e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
51415e2e619SCharles Keepax 
5151245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps)
5161245b700SNamarta Kohli 		ret = platform->driver->compr_ops->get_codec_caps(cstream, codec);
5171245b700SNamarta Kohli 
51815e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
5191245b700SNamarta Kohli 	return ret;
5201245b700SNamarta Kohli }
5211245b700SNamarta Kohli 
5221245b700SNamarta Kohli static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
5231245b700SNamarta Kohli {
5241245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5251245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
5261245b700SNamarta Kohli 	int ret = 0;
5271245b700SNamarta Kohli 
52815e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
52915e2e619SCharles Keepax 
5301245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->ack)
5311245b700SNamarta Kohli 		ret = platform->driver->compr_ops->ack(cstream, bytes);
5321245b700SNamarta Kohli 
53315e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
5341245b700SNamarta Kohli 	return ret;
5351245b700SNamarta Kohli }
5361245b700SNamarta Kohli 
5371245b700SNamarta Kohli static int soc_compr_pointer(struct snd_compr_stream *cstream,
5381245b700SNamarta Kohli 			struct snd_compr_tstamp *tstamp)
5391245b700SNamarta Kohli {
5401245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5411245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
5421245b700SNamarta Kohli 
54315e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
54415e2e619SCharles Keepax 
5451245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->pointer)
5461245b700SNamarta Kohli 		 platform->driver->compr_ops->pointer(cstream, tstamp);
5471245b700SNamarta Kohli 
54815e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
5491245b700SNamarta Kohli 	return 0;
5501245b700SNamarta Kohli }
5511245b700SNamarta Kohli 
5521f88eb0fSCharles Keepax static int soc_compr_copy(struct snd_compr_stream *cstream,
5534daf891cSCharles Keepax 			  char __user *buf, size_t count)
5541f88eb0fSCharles Keepax {
5551f88eb0fSCharles Keepax 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5561f88eb0fSCharles Keepax 	struct snd_soc_platform *platform = rtd->platform;
5571f88eb0fSCharles Keepax 	int ret = 0;
5581f88eb0fSCharles Keepax 
5591f88eb0fSCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
5601f88eb0fSCharles Keepax 
5611f88eb0fSCharles Keepax 	if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
5621f88eb0fSCharles Keepax 		ret = platform->driver->compr_ops->copy(cstream, buf, count);
5631f88eb0fSCharles Keepax 
5641f88eb0fSCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
5651f88eb0fSCharles Keepax 	return ret;
5661f88eb0fSCharles Keepax }
5671f88eb0fSCharles Keepax 
56802bd90e8SVinod Koul static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
56936953d98SJeeja KP 				struct snd_compr_metadata *metadata)
57036953d98SJeeja KP {
57136953d98SJeeja KP 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
57236953d98SJeeja KP 	struct snd_soc_platform *platform = rtd->platform;
57336953d98SJeeja KP 	int ret = 0;
57436953d98SJeeja KP 
57536953d98SJeeja KP 	if (platform->driver->compr_ops && platform->driver->compr_ops->set_metadata)
57636953d98SJeeja KP 		ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
57736953d98SJeeja KP 
57836953d98SJeeja KP 	return ret;
57936953d98SJeeja KP }
58036953d98SJeeja KP 
58102bd90e8SVinod Koul static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
58236953d98SJeeja KP 				struct snd_compr_metadata *metadata)
58336953d98SJeeja KP {
58436953d98SJeeja KP 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
58536953d98SJeeja KP 	struct snd_soc_platform *platform = rtd->platform;
58636953d98SJeeja KP 	int ret = 0;
58736953d98SJeeja KP 
58836953d98SJeeja KP 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_metadata)
58936953d98SJeeja KP 		ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
59036953d98SJeeja KP 
59136953d98SJeeja KP 	return ret;
59236953d98SJeeja KP }
5932a99ef0fSLiam Girdwood 
5941245b700SNamarta Kohli /* ASoC Compress operations */
5951245b700SNamarta Kohli static struct snd_compr_ops soc_compr_ops = {
5961245b700SNamarta Kohli 	.open		= soc_compr_open,
5971245b700SNamarta Kohli 	.free		= soc_compr_free,
5981245b700SNamarta Kohli 	.set_params	= soc_compr_set_params,
59902bd90e8SVinod Koul 	.set_metadata   = soc_compr_set_metadata,
60002bd90e8SVinod Koul 	.get_metadata	= soc_compr_get_metadata,
6011245b700SNamarta Kohli 	.get_params	= soc_compr_get_params,
6021245b700SNamarta Kohli 	.trigger	= soc_compr_trigger,
6031245b700SNamarta Kohli 	.pointer	= soc_compr_pointer,
6041245b700SNamarta Kohli 	.ack		= soc_compr_ack,
6051245b700SNamarta Kohli 	.get_caps	= soc_compr_get_caps,
6061245b700SNamarta Kohli 	.get_codec_caps = soc_compr_get_codec_caps
6071245b700SNamarta Kohli };
6081245b700SNamarta Kohli 
6092a99ef0fSLiam Girdwood /* ASoC Dynamic Compress operations */
6102a99ef0fSLiam Girdwood static struct snd_compr_ops soc_compr_dyn_ops = {
6112a99ef0fSLiam Girdwood 	.open		= soc_compr_open_fe,
6122a99ef0fSLiam Girdwood 	.free		= soc_compr_free_fe,
6132a99ef0fSLiam Girdwood 	.set_params	= soc_compr_set_params_fe,
6142a99ef0fSLiam Girdwood 	.get_params	= soc_compr_get_params,
6152a99ef0fSLiam Girdwood 	.set_metadata   = soc_compr_set_metadata,
6162a99ef0fSLiam Girdwood 	.get_metadata	= soc_compr_get_metadata,
6172a99ef0fSLiam Girdwood 	.trigger	= soc_compr_trigger_fe,
6182a99ef0fSLiam Girdwood 	.pointer	= soc_compr_pointer,
6192a99ef0fSLiam Girdwood 	.ack		= soc_compr_ack,
6202a99ef0fSLiam Girdwood 	.get_caps	= soc_compr_get_caps,
6212a99ef0fSLiam Girdwood 	.get_codec_caps = soc_compr_get_codec_caps
6222a99ef0fSLiam Girdwood };
6232a99ef0fSLiam Girdwood 
6241245b700SNamarta Kohli /* create a new compress */
6251245b700SNamarta Kohli int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
6261245b700SNamarta Kohli {
6271245b700SNamarta Kohli 	struct snd_soc_codec *codec = rtd->codec;
6281f88eb0fSCharles Keepax 	struct snd_soc_platform *platform = rtd->platform;
6291245b700SNamarta Kohli 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
6301245b700SNamarta Kohli 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
6311245b700SNamarta Kohli 	struct snd_compr *compr;
6322a99ef0fSLiam Girdwood 	struct snd_pcm *be_pcm;
6331245b700SNamarta Kohli 	char new_name[64];
6341245b700SNamarta Kohli 	int ret = 0, direction = 0;
6351245b700SNamarta Kohli 
6368151d5e6SBenoit Cousson 	if (rtd->num_codecs > 1) {
6378151d5e6SBenoit Cousson 		dev_err(rtd->card->dev, "Multicodec not supported for compressed stream\n");
6388151d5e6SBenoit Cousson 		return -EINVAL;
6398151d5e6SBenoit Cousson 	}
6408151d5e6SBenoit Cousson 
6411245b700SNamarta Kohli 	/* check client and interface hw capabilities */
6421245b700SNamarta Kohli 	snprintf(new_name, sizeof(new_name), "%s %s-%d",
6431245b700SNamarta Kohli 			rtd->dai_link->stream_name, codec_dai->name, num);
644daa2db59SCharles Keepax 
645daa2db59SCharles Keepax 	if (codec_dai->driver->playback.channels_min)
6461245b700SNamarta Kohli 		direction = SND_COMPRESS_PLAYBACK;
647daa2db59SCharles Keepax 	else if (codec_dai->driver->capture.channels_min)
648daa2db59SCharles Keepax 		direction = SND_COMPRESS_CAPTURE;
649daa2db59SCharles Keepax 	else
650daa2db59SCharles Keepax 		return -EINVAL;
651daa2db59SCharles Keepax 
6521245b700SNamarta Kohli 	compr = kzalloc(sizeof(*compr), GFP_KERNEL);
6531245b700SNamarta Kohli 	if (compr == NULL) {
6541245b700SNamarta Kohli 		snd_printk(KERN_ERR "Cannot allocate compr\n");
6551245b700SNamarta Kohli 		return -ENOMEM;
6561245b700SNamarta Kohli 	}
6571245b700SNamarta Kohli 
6581f88eb0fSCharles Keepax 	compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
6591f88eb0fSCharles Keepax 				  GFP_KERNEL);
6601f88eb0fSCharles Keepax 	if (compr->ops == NULL) {
6611f88eb0fSCharles Keepax 		dev_err(rtd->card->dev, "Cannot allocate compressed ops\n");
6621f88eb0fSCharles Keepax 		ret = -ENOMEM;
6631f88eb0fSCharles Keepax 		goto compr_err;
6641f88eb0fSCharles Keepax 	}
6652a99ef0fSLiam Girdwood 
6662a99ef0fSLiam Girdwood 	if (rtd->dai_link->dynamic) {
6672a99ef0fSLiam Girdwood 		snprintf(new_name, sizeof(new_name), "(%s)",
6682a99ef0fSLiam Girdwood 			rtd->dai_link->stream_name);
6692a99ef0fSLiam Girdwood 
6702a99ef0fSLiam Girdwood 		ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
6712a99ef0fSLiam Girdwood 				1, 0, &be_pcm);
6722a99ef0fSLiam Girdwood 		if (ret < 0) {
6732a99ef0fSLiam Girdwood 			dev_err(rtd->card->dev, "ASoC: can't create compressed for %s\n",
6742a99ef0fSLiam Girdwood 				rtd->dai_link->name);
6752a99ef0fSLiam Girdwood 			goto compr_err;
6762a99ef0fSLiam Girdwood 		}
6772a99ef0fSLiam Girdwood 
6782a99ef0fSLiam Girdwood 		rtd->pcm = be_pcm;
6792a99ef0fSLiam Girdwood 		rtd->fe_compr = 1;
6802a99ef0fSLiam Girdwood 		be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
6812a99ef0fSLiam Girdwood 		be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
6822a99ef0fSLiam Girdwood 		memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
6832a99ef0fSLiam Girdwood 	} else
6841f88eb0fSCharles Keepax 		memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
6851f88eb0fSCharles Keepax 
6861f88eb0fSCharles Keepax 	/* Add copy callback for not memory mapped DSPs */
6871f88eb0fSCharles Keepax 	if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
6881f88eb0fSCharles Keepax 		compr->ops->copy = soc_compr_copy;
6891f88eb0fSCharles Keepax 
6901245b700SNamarta Kohli 	mutex_init(&compr->lock);
6911245b700SNamarta Kohli 	ret = snd_compress_new(rtd->card->snd_card, num, direction, compr);
6921245b700SNamarta Kohli 	if (ret < 0) {
6931245b700SNamarta Kohli 		pr_err("compress asoc: can't create compress for codec %s\n",
694f4333203SLars-Peter Clausen 			codec->component.name);
6951f88eb0fSCharles Keepax 		goto compr_err;
6961245b700SNamarta Kohli 	}
6971245b700SNamarta Kohli 
698202c8f70SCharles Keepax 	/* DAPM dai link stream work */
699202c8f70SCharles Keepax 	INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
700202c8f70SCharles Keepax 
7011245b700SNamarta Kohli 	rtd->compr = compr;
7021245b700SNamarta Kohli 	compr->private_data = rtd;
7031245b700SNamarta Kohli 
7041245b700SNamarta Kohli 	printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
7051245b700SNamarta Kohli 		cpu_dai->name);
7061245b700SNamarta Kohli 	return ret;
7071f88eb0fSCharles Keepax 
7081f88eb0fSCharles Keepax compr_err:
7091f88eb0fSCharles Keepax 	kfree(compr);
7101f88eb0fSCharles Keepax 	return ret;
7111245b700SNamarta Kohli }
712