xref: /openbmc/linux/sound/soc/soc-compress.c (revision 24894b76)
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) {
401245b700SNamarta Kohli 			pr_err("compress asoc: can't open platform %s\n", platform->name);
411245b700SNamarta Kohli 			goto out;
421245b700SNamarta Kohli 		}
431245b700SNamarta Kohli 	}
441245b700SNamarta Kohli 
451245b700SNamarta Kohli 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
461245b700SNamarta Kohli 		ret = rtd->dai_link->compr_ops->startup(cstream);
471245b700SNamarta Kohli 		if (ret < 0) {
481245b700SNamarta Kohli 			pr_err("compress asoc: %s startup failed\n", rtd->dai_link->name);
491245b700SNamarta Kohli 			goto machine_err;
501245b700SNamarta Kohli 		}
511245b700SNamarta Kohli 	}
521245b700SNamarta Kohli 
5324894b76SLars-Peter Clausen 	snd_soc_runtime_activate(rtd, cstream->direction);
541245b700SNamarta Kohli 
5515e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
5615e2e619SCharles Keepax 
571245b700SNamarta Kohli 	return 0;
581245b700SNamarta Kohli 
591245b700SNamarta Kohli machine_err:
601245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
611245b700SNamarta Kohli 		platform->driver->compr_ops->free(cstream);
621245b700SNamarta Kohli out:
6315e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
641245b700SNamarta Kohli 	return ret;
651245b700SNamarta Kohli }
661245b700SNamarta Kohli 
672a99ef0fSLiam Girdwood static int soc_compr_open_fe(struct snd_compr_stream *cstream)
682a99ef0fSLiam Girdwood {
692a99ef0fSLiam Girdwood 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
702a99ef0fSLiam Girdwood 	struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
712a99ef0fSLiam Girdwood 	struct snd_soc_platform *platform = fe->platform;
722a99ef0fSLiam Girdwood 	struct snd_soc_dpcm *dpcm;
732a99ef0fSLiam Girdwood 	struct snd_soc_dapm_widget_list *list;
742a99ef0fSLiam Girdwood 	int stream;
752a99ef0fSLiam Girdwood 	int ret = 0;
762a99ef0fSLiam Girdwood 
772a99ef0fSLiam Girdwood 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
782a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_PLAYBACK;
792a99ef0fSLiam Girdwood 	else
802a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_CAPTURE;
812a99ef0fSLiam Girdwood 
822a99ef0fSLiam Girdwood 	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
832a99ef0fSLiam Girdwood 
842a99ef0fSLiam Girdwood 	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
852a99ef0fSLiam Girdwood 		ret = platform->driver->compr_ops->open(cstream);
862a99ef0fSLiam Girdwood 		if (ret < 0) {
872a99ef0fSLiam Girdwood 			pr_err("compress asoc: can't open platform %s\n", platform->name);
882a99ef0fSLiam Girdwood 			goto out;
892a99ef0fSLiam Girdwood 		}
902a99ef0fSLiam Girdwood 	}
912a99ef0fSLiam Girdwood 
922a99ef0fSLiam Girdwood 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
932a99ef0fSLiam Girdwood 		ret = fe->dai_link->compr_ops->startup(cstream);
942a99ef0fSLiam Girdwood 		if (ret < 0) {
952a99ef0fSLiam Girdwood 			pr_err("compress asoc: %s startup failed\n", fe->dai_link->name);
962a99ef0fSLiam Girdwood 			goto machine_err;
972a99ef0fSLiam Girdwood 		}
982a99ef0fSLiam Girdwood 	}
992a99ef0fSLiam Girdwood 
1002a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime = fe_substream->runtime;
1012a99ef0fSLiam Girdwood 
1022a99ef0fSLiam Girdwood 	if (dpcm_path_get(fe, stream, &list) <= 0) {
1032a99ef0fSLiam Girdwood 		dev_dbg(fe->dev, "ASoC: %s no valid %s route\n",
1042a99ef0fSLiam Girdwood 			fe->dai_link->name, stream ? "capture" : "playback");
1052a99ef0fSLiam Girdwood 	}
1062a99ef0fSLiam Girdwood 
1072a99ef0fSLiam Girdwood 	/* calculate valid and active FE <-> BE dpcms */
1082a99ef0fSLiam Girdwood 	dpcm_process_paths(fe, stream, &list, 1);
1092a99ef0fSLiam Girdwood 
1102a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
1112a99ef0fSLiam Girdwood 
1122a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_startup(fe, stream);
1132a99ef0fSLiam Girdwood 	if (ret < 0) {
1142a99ef0fSLiam Girdwood 		/* clean up all links */
1152a99ef0fSLiam Girdwood 		list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
1162a99ef0fSLiam Girdwood 			dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
1172a99ef0fSLiam Girdwood 
1182a99ef0fSLiam Girdwood 		dpcm_be_disconnect(fe, stream);
1192a99ef0fSLiam Girdwood 		fe->dpcm[stream].runtime = NULL;
1202a99ef0fSLiam Girdwood 		goto fe_err;
1212a99ef0fSLiam Girdwood 	}
1222a99ef0fSLiam Girdwood 
1232a99ef0fSLiam Girdwood 	dpcm_clear_pending_state(fe, stream);
1242a99ef0fSLiam Girdwood 	dpcm_path_put(&list);
1252a99ef0fSLiam Girdwood 
1262a99ef0fSLiam Girdwood 	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN;
1272a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1282a99ef0fSLiam Girdwood 
12924894b76SLars-Peter Clausen 	snd_soc_runtime_activate(fe, stream);
1302a99ef0fSLiam Girdwood 
1312a99ef0fSLiam Girdwood 	mutex_unlock(&fe->card->mutex);
1322a99ef0fSLiam Girdwood 
1332a99ef0fSLiam Girdwood 	return 0;
1342a99ef0fSLiam Girdwood 
1352a99ef0fSLiam Girdwood fe_err:
1362a99ef0fSLiam Girdwood 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
1372a99ef0fSLiam Girdwood 		fe->dai_link->compr_ops->shutdown(cstream);
1382a99ef0fSLiam Girdwood machine_err:
1392a99ef0fSLiam Girdwood 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
1402a99ef0fSLiam Girdwood 		platform->driver->compr_ops->free(cstream);
1412a99ef0fSLiam Girdwood out:
1422a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
1432a99ef0fSLiam Girdwood 	mutex_unlock(&fe->card->mutex);
1442a99ef0fSLiam Girdwood 	return ret;
1452a99ef0fSLiam Girdwood }
1462a99ef0fSLiam Girdwood 
147202c8f70SCharles Keepax /*
148202c8f70SCharles Keepax  * Power down the audio subsystem pmdown_time msecs after close is called.
149202c8f70SCharles Keepax  * This is to ensure there are no pops or clicks in between any music tracks
150202c8f70SCharles Keepax  * due to DAPM power cycling.
151202c8f70SCharles Keepax  */
152202c8f70SCharles Keepax static void close_delayed_work(struct work_struct *work)
153202c8f70SCharles Keepax {
154202c8f70SCharles Keepax 	struct snd_soc_pcm_runtime *rtd =
155202c8f70SCharles Keepax 			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
156202c8f70SCharles Keepax 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
157202c8f70SCharles Keepax 
158202c8f70SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
159202c8f70SCharles Keepax 
160202c8f70SCharles Keepax 	dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
161202c8f70SCharles Keepax 		 codec_dai->driver->playback.stream_name,
162202c8f70SCharles Keepax 		 codec_dai->playback_active ? "active" : "inactive",
163202c8f70SCharles Keepax 		 rtd->pop_wait ? "yes" : "no");
164202c8f70SCharles Keepax 
165202c8f70SCharles Keepax 	/* are we waiting on this codec DAI stream */
166202c8f70SCharles Keepax 	if (rtd->pop_wait == 1) {
167202c8f70SCharles Keepax 		rtd->pop_wait = 0;
168202c8f70SCharles Keepax 		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
169202c8f70SCharles Keepax 					  SND_SOC_DAPM_STREAM_STOP);
170202c8f70SCharles Keepax 	}
171202c8f70SCharles Keepax 
172202c8f70SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
173202c8f70SCharles Keepax }
174202c8f70SCharles Keepax 
1751245b700SNamarta Kohli static int soc_compr_free(struct snd_compr_stream *cstream)
1761245b700SNamarta Kohli {
1771245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
1781245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
1791245b700SNamarta Kohli 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1801245b700SNamarta Kohli 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
18124894b76SLars-Peter Clausen 	int stream;
1821245b700SNamarta Kohli 
18315e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
18415e2e619SCharles Keepax 
18524894b76SLars-Peter Clausen 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
18624894b76SLars-Peter Clausen 		stream = SNDRV_PCM_STREAM_PLAYBACK;
18724894b76SLars-Peter Clausen 	else
18824894b76SLars-Peter Clausen 		stream = SNDRV_PCM_STREAM_CAPTURE;
18924894b76SLars-Peter Clausen 
19024894b76SLars-Peter Clausen 	snd_soc_runtime_deactivate(rtd, stream);
1911245b700SNamarta Kohli 
192da18396fSMark Brown 	snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
193da18396fSMark Brown 
1941245b700SNamarta Kohli 	if (!cpu_dai->active)
1951245b700SNamarta Kohli 		cpu_dai->rate = 0;
1961245b700SNamarta Kohli 
1971245b700SNamarta Kohli 	if (!codec_dai->active)
1981245b700SNamarta Kohli 		codec_dai->rate = 0;
1991245b700SNamarta Kohli 
2001245b700SNamarta Kohli 
2011245b700SNamarta Kohli 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
2021245b700SNamarta Kohli 		rtd->dai_link->compr_ops->shutdown(cstream);
2031245b700SNamarta Kohli 
2041245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
2051245b700SNamarta Kohli 		platform->driver->compr_ops->free(cstream);
2061245b700SNamarta Kohli 	cpu_dai->runtime = NULL;
2071245b700SNamarta Kohli 
2081245b700SNamarta Kohli 	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
209208a1589SLars-Peter Clausen 		if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
2101245b700SNamarta Kohli 			snd_soc_dapm_stream_event(rtd,
2111245b700SNamarta Kohli 					SNDRV_PCM_STREAM_PLAYBACK,
2121245b700SNamarta Kohli 					SND_SOC_DAPM_STREAM_STOP);
2138c3d2aa4SCharles Keepax 		} else {
2149bffb1fbSMisael Lopez Cruz 			rtd->pop_wait = 1;
2153d24cfe4SMark Brown 			queue_delayed_work(system_power_efficient_wq,
2163d24cfe4SMark Brown 					   &rtd->delayed_work,
2171245b700SNamarta Kohli 					   msecs_to_jiffies(rtd->pmdown_time));
2188c3d2aa4SCharles Keepax 		}
2191245b700SNamarta Kohli 	} else {
2201245b700SNamarta Kohli 		/* capture streams can be powered down now */
2211245b700SNamarta Kohli 		snd_soc_dapm_stream_event(rtd,
2221245b700SNamarta Kohli 			SNDRV_PCM_STREAM_CAPTURE,
2231245b700SNamarta Kohli 			SND_SOC_DAPM_STREAM_STOP);
2241245b700SNamarta Kohli 	}
2251245b700SNamarta Kohli 
22615e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
2271245b700SNamarta Kohli 	return 0;
2281245b700SNamarta Kohli }
2291245b700SNamarta Kohli 
2302a99ef0fSLiam Girdwood static int soc_compr_free_fe(struct snd_compr_stream *cstream)
2312a99ef0fSLiam Girdwood {
2322a99ef0fSLiam Girdwood 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
2332a99ef0fSLiam Girdwood 	struct snd_soc_platform *platform = fe->platform;
2342a99ef0fSLiam Girdwood 	struct snd_soc_dpcm *dpcm;
2352a99ef0fSLiam Girdwood 	int stream, ret;
2362a99ef0fSLiam Girdwood 
2372a99ef0fSLiam Girdwood 	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
2382a99ef0fSLiam Girdwood 
23924894b76SLars-Peter Clausen 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
2402a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_PLAYBACK;
24124894b76SLars-Peter Clausen 	else
2422a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_CAPTURE;
2432a99ef0fSLiam Girdwood 
24424894b76SLars-Peter Clausen 	snd_soc_runtime_deactivate(fe, stream);
2452a99ef0fSLiam Girdwood 
2462a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
2472a99ef0fSLiam Girdwood 
2482a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_hw_free(fe, stream);
2492a99ef0fSLiam Girdwood 	if (ret < 0)
2502a99ef0fSLiam Girdwood 		dev_err(fe->dev, "compressed hw_free failed %d\n", ret);
2512a99ef0fSLiam Girdwood 
2522a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_shutdown(fe, stream);
2532a99ef0fSLiam Girdwood 
2542a99ef0fSLiam Girdwood 	/* mark FE's links ready to prune */
2552a99ef0fSLiam Girdwood 	list_for_each_entry(dpcm, &fe->dpcm[stream].be_clients, list_be)
2562a99ef0fSLiam Girdwood 		dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
2572a99ef0fSLiam Girdwood 
2582a99ef0fSLiam Girdwood 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
2592a99ef0fSLiam Girdwood 		dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
2602a99ef0fSLiam Girdwood 	else
2612a99ef0fSLiam Girdwood 		dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_STOP);
2622a99ef0fSLiam Girdwood 
2632a99ef0fSLiam Girdwood 	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE;
2642a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
2652a99ef0fSLiam Girdwood 
2662a99ef0fSLiam Girdwood 	dpcm_be_disconnect(fe, stream);
2672a99ef0fSLiam Girdwood 
2682a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime = NULL;
2692a99ef0fSLiam Girdwood 
2702a99ef0fSLiam Girdwood 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
2712a99ef0fSLiam Girdwood 		fe->dai_link->compr_ops->shutdown(cstream);
2722a99ef0fSLiam Girdwood 
2732a99ef0fSLiam Girdwood 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
2742a99ef0fSLiam Girdwood 		platform->driver->compr_ops->free(cstream);
2752a99ef0fSLiam Girdwood 
2762a99ef0fSLiam Girdwood 	mutex_unlock(&fe->card->mutex);
2772a99ef0fSLiam Girdwood 	return 0;
2782a99ef0fSLiam Girdwood }
2792a99ef0fSLiam Girdwood 
2801245b700SNamarta Kohli static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
2811245b700SNamarta Kohli {
2821245b700SNamarta Kohli 
2831245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2841245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
2851245b700SNamarta Kohli 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
2861245b700SNamarta Kohli 	int ret = 0;
2871245b700SNamarta Kohli 
28815e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
28915e2e619SCharles Keepax 
2901245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
2911245b700SNamarta Kohli 		ret = platform->driver->compr_ops->trigger(cstream, cmd);
2921245b700SNamarta Kohli 		if (ret < 0)
29315e2e619SCharles Keepax 			goto out;
2941245b700SNamarta Kohli 	}
2951245b700SNamarta Kohli 
296e38b9b74SMark Brown 	switch (cmd) {
297e38b9b74SMark Brown 	case SNDRV_PCM_TRIGGER_START:
298da18396fSMark Brown 		snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
299e38b9b74SMark Brown 		break;
300e38b9b74SMark Brown 	case SNDRV_PCM_TRIGGER_STOP:
301da18396fSMark Brown 		snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
302e38b9b74SMark Brown 		break;
303e38b9b74SMark Brown 	}
3041245b700SNamarta Kohli 
30515e2e619SCharles Keepax out:
30615e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
3071245b700SNamarta Kohli 	return ret;
3081245b700SNamarta Kohli }
3091245b700SNamarta Kohli 
3102a99ef0fSLiam Girdwood static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
3112a99ef0fSLiam Girdwood {
3122a99ef0fSLiam Girdwood 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
3132a99ef0fSLiam Girdwood 	struct snd_soc_platform *platform = fe->platform;
3142a99ef0fSLiam Girdwood 	int ret = 0, stream;
3152a99ef0fSLiam Girdwood 
3162a99ef0fSLiam Girdwood 	if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
3172a99ef0fSLiam Girdwood 		cmd == SND_COMPR_TRIGGER_DRAIN) {
3182a99ef0fSLiam Girdwood 
3192a99ef0fSLiam Girdwood 		if (platform->driver->compr_ops &&
3202a99ef0fSLiam Girdwood 			platform->driver->compr_ops->trigger)
3212a99ef0fSLiam Girdwood 		return platform->driver->compr_ops->trigger(cstream, cmd);
3222a99ef0fSLiam Girdwood 	}
3232a99ef0fSLiam Girdwood 
3242a99ef0fSLiam Girdwood 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
3252a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_PLAYBACK;
3262a99ef0fSLiam Girdwood 	else
3272a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_CAPTURE;
3282a99ef0fSLiam Girdwood 
3292a99ef0fSLiam Girdwood 
3302a99ef0fSLiam Girdwood 	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
3312a99ef0fSLiam Girdwood 
3322a99ef0fSLiam Girdwood 	if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
3332a99ef0fSLiam Girdwood 		ret = platform->driver->compr_ops->trigger(cstream, cmd);
3342a99ef0fSLiam Girdwood 		if (ret < 0)
3352a99ef0fSLiam Girdwood 			goto out;
3362a99ef0fSLiam Girdwood 	}
3372a99ef0fSLiam Girdwood 
3382a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
3392a99ef0fSLiam Girdwood 
3402a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_trigger(fe, stream, cmd);
3412a99ef0fSLiam Girdwood 
3422a99ef0fSLiam Girdwood 	switch (cmd) {
3432a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_START:
3442a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_RESUME:
3452a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
3462a99ef0fSLiam Girdwood 		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_START;
3472a99ef0fSLiam Girdwood 		break;
3482a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_STOP:
3492a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_SUSPEND:
3502a99ef0fSLiam Girdwood 		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
3512a99ef0fSLiam Girdwood 		break;
3522a99ef0fSLiam Girdwood 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
3532a99ef0fSLiam Girdwood 		fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
3542a99ef0fSLiam Girdwood 		break;
3552a99ef0fSLiam Girdwood 	}
3562a99ef0fSLiam Girdwood 
3572a99ef0fSLiam Girdwood out:
3582a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
3592a99ef0fSLiam Girdwood 	mutex_unlock(&fe->card->mutex);
3602a99ef0fSLiam Girdwood 	return ret;
3612a99ef0fSLiam Girdwood }
3622a99ef0fSLiam Girdwood 
3631245b700SNamarta Kohli static int soc_compr_set_params(struct snd_compr_stream *cstream,
3641245b700SNamarta Kohli 					struct snd_compr_params *params)
3651245b700SNamarta Kohli {
3661245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
3671245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
3681245b700SNamarta Kohli 	int ret = 0;
3691245b700SNamarta Kohli 
37015e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
37115e2e619SCharles Keepax 
3721245b700SNamarta Kohli 	/* first we call set_params for the platform driver
3731245b700SNamarta Kohli 	 * this should configure the soc side
3741245b700SNamarta Kohli 	 * if the machine has compressed ops then we call that as well
3751245b700SNamarta Kohli 	 * expectation is that platform and machine will configure everything
3761245b700SNamarta Kohli 	 * for this compress path, like configuring pcm port for codec
3771245b700SNamarta Kohli 	 */
3781245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
3791245b700SNamarta Kohli 		ret = platform->driver->compr_ops->set_params(cstream, params);
3801245b700SNamarta Kohli 		if (ret < 0)
381fa40ef20SCharles Keepax 			goto err;
3821245b700SNamarta Kohli 	}
3831245b700SNamarta Kohli 
3841245b700SNamarta Kohli 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
3851245b700SNamarta Kohli 		ret = rtd->dai_link->compr_ops->set_params(cstream);
3861245b700SNamarta Kohli 		if (ret < 0)
387fa40ef20SCharles Keepax 			goto err;
3881245b700SNamarta Kohli 	}
3891245b700SNamarta Kohli 
3902c071ed7SCharles Keepax 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
3911245b700SNamarta Kohli 		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
3921245b700SNamarta Kohli 					SND_SOC_DAPM_STREAM_START);
3932c071ed7SCharles Keepax 	else
3942c071ed7SCharles Keepax 		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
3952c071ed7SCharles Keepax 					SND_SOC_DAPM_STREAM_START);
3961245b700SNamarta Kohli 
397fa40ef20SCharles Keepax 	/* cancel any delayed stream shutdown that is pending */
398fa40ef20SCharles Keepax 	rtd->pop_wait = 0;
399fa40ef20SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
400fa40ef20SCharles Keepax 
401fa40ef20SCharles Keepax 	cancel_delayed_work_sync(&rtd->delayed_work);
402fa40ef20SCharles Keepax 
403fa40ef20SCharles Keepax 	return ret;
404fa40ef20SCharles Keepax 
405fa40ef20SCharles Keepax err:
40615e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
4071245b700SNamarta Kohli 	return ret;
4081245b700SNamarta Kohli }
4091245b700SNamarta Kohli 
4102a99ef0fSLiam Girdwood static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
4112a99ef0fSLiam Girdwood 					struct snd_compr_params *params)
4122a99ef0fSLiam Girdwood {
4132a99ef0fSLiam Girdwood 	struct snd_soc_pcm_runtime *fe = cstream->private_data;
4142a99ef0fSLiam Girdwood 	struct snd_pcm_substream *fe_substream = fe->pcm->streams[0].substream;
4152a99ef0fSLiam Girdwood 	struct snd_soc_platform *platform = fe->platform;
4162a99ef0fSLiam Girdwood 	int ret = 0, stream;
4172a99ef0fSLiam Girdwood 
4182a99ef0fSLiam Girdwood 	if (cstream->direction == SND_COMPRESS_PLAYBACK)
4192a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_PLAYBACK;
4202a99ef0fSLiam Girdwood 	else
4212a99ef0fSLiam Girdwood 		stream = SNDRV_PCM_STREAM_CAPTURE;
4222a99ef0fSLiam Girdwood 
4232a99ef0fSLiam Girdwood 	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
4242a99ef0fSLiam Girdwood 
4252a99ef0fSLiam Girdwood 	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
4262a99ef0fSLiam Girdwood 		ret = platform->driver->compr_ops->set_params(cstream, params);
4272a99ef0fSLiam Girdwood 		if (ret < 0)
4282a99ef0fSLiam Girdwood 			goto out;
4292a99ef0fSLiam Girdwood 	}
4302a99ef0fSLiam Girdwood 
4312a99ef0fSLiam Girdwood 	if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
4322a99ef0fSLiam Girdwood 		ret = fe->dai_link->compr_ops->set_params(cstream);
4332a99ef0fSLiam Girdwood 		if (ret < 0)
4342a99ef0fSLiam Girdwood 			goto out;
4352a99ef0fSLiam Girdwood 	}
4362a99ef0fSLiam Girdwood 
4372a99ef0fSLiam Girdwood 	/*
4382a99ef0fSLiam Girdwood 	 * Create an empty hw_params for the BE as the machine driver must
4392a99ef0fSLiam Girdwood 	 * fix this up to match DSP decoder and ASRC configuration.
4402a99ef0fSLiam Girdwood 	 * I.e. machine driver fixup for compressed BE is mandatory.
4412a99ef0fSLiam Girdwood 	 */
4422a99ef0fSLiam Girdwood 	memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
4432a99ef0fSLiam Girdwood 		sizeof(struct snd_pcm_hw_params));
4442a99ef0fSLiam Girdwood 
4452a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
4462a99ef0fSLiam Girdwood 
4472a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_hw_params(fe, stream);
4482a99ef0fSLiam Girdwood 	if (ret < 0)
4492a99ef0fSLiam Girdwood 		goto out;
4502a99ef0fSLiam Girdwood 
4512a99ef0fSLiam Girdwood 	ret = dpcm_be_dai_prepare(fe, stream);
4522a99ef0fSLiam Girdwood 	if (ret < 0)
4532a99ef0fSLiam Girdwood 		goto out;
4542a99ef0fSLiam Girdwood 
4552a99ef0fSLiam Girdwood 	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
4562a99ef0fSLiam Girdwood 		dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
4572a99ef0fSLiam Girdwood 	else
4582a99ef0fSLiam Girdwood 		dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
4592a99ef0fSLiam Girdwood 
4602a99ef0fSLiam Girdwood 	fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
4612a99ef0fSLiam Girdwood 
4622a99ef0fSLiam Girdwood out:
4632a99ef0fSLiam Girdwood 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
4642a99ef0fSLiam Girdwood 	mutex_unlock(&fe->card->mutex);
4652a99ef0fSLiam Girdwood 	return ret;
4662a99ef0fSLiam Girdwood }
4672a99ef0fSLiam Girdwood 
4681245b700SNamarta Kohli static int soc_compr_get_params(struct snd_compr_stream *cstream,
4691245b700SNamarta Kohli 					struct snd_codec *params)
4701245b700SNamarta Kohli {
4711245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
4721245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
4731245b700SNamarta Kohli 	int ret = 0;
4741245b700SNamarta Kohli 
47515e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
47615e2e619SCharles Keepax 
4771245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_params)
4781245b700SNamarta Kohli 		ret = platform->driver->compr_ops->get_params(cstream, params);
4791245b700SNamarta Kohli 
48015e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
4811245b700SNamarta Kohli 	return ret;
4821245b700SNamarta Kohli }
4831245b700SNamarta Kohli 
4841245b700SNamarta Kohli static int soc_compr_get_caps(struct snd_compr_stream *cstream,
4851245b700SNamarta Kohli 				struct snd_compr_caps *caps)
4861245b700SNamarta Kohli {
4871245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
4881245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
4891245b700SNamarta Kohli 	int ret = 0;
4901245b700SNamarta Kohli 
49115e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
49215e2e619SCharles Keepax 
4931245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps)
4941245b700SNamarta Kohli 		ret = platform->driver->compr_ops->get_caps(cstream, caps);
4951245b700SNamarta Kohli 
49615e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
4971245b700SNamarta Kohli 	return ret;
4981245b700SNamarta Kohli }
4991245b700SNamarta Kohli 
5001245b700SNamarta Kohli static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
5011245b700SNamarta Kohli 				struct snd_compr_codec_caps *codec)
5021245b700SNamarta Kohli {
5031245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5041245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
5051245b700SNamarta Kohli 	int ret = 0;
5061245b700SNamarta Kohli 
50715e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
50815e2e619SCharles Keepax 
5091245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps)
5101245b700SNamarta Kohli 		ret = platform->driver->compr_ops->get_codec_caps(cstream, codec);
5111245b700SNamarta Kohli 
51215e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
5131245b700SNamarta Kohli 	return ret;
5141245b700SNamarta Kohli }
5151245b700SNamarta Kohli 
5161245b700SNamarta Kohli static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
5171245b700SNamarta Kohli {
5181245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5191245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
5201245b700SNamarta Kohli 	int ret = 0;
5211245b700SNamarta Kohli 
52215e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
52315e2e619SCharles Keepax 
5241245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->ack)
5251245b700SNamarta Kohli 		ret = platform->driver->compr_ops->ack(cstream, bytes);
5261245b700SNamarta Kohli 
52715e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
5281245b700SNamarta Kohli 	return ret;
5291245b700SNamarta Kohli }
5301245b700SNamarta Kohli 
5311245b700SNamarta Kohli static int soc_compr_pointer(struct snd_compr_stream *cstream,
5321245b700SNamarta Kohli 			struct snd_compr_tstamp *tstamp)
5331245b700SNamarta Kohli {
5341245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5351245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
5361245b700SNamarta Kohli 
53715e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
53815e2e619SCharles Keepax 
5391245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->pointer)
5401245b700SNamarta Kohli 		 platform->driver->compr_ops->pointer(cstream, tstamp);
5411245b700SNamarta Kohli 
54215e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
5431245b700SNamarta Kohli 	return 0;
5441245b700SNamarta Kohli }
5451245b700SNamarta Kohli 
5461f88eb0fSCharles Keepax static int soc_compr_copy(struct snd_compr_stream *cstream,
5474daf891cSCharles Keepax 			  char __user *buf, size_t count)
5481f88eb0fSCharles Keepax {
5491f88eb0fSCharles Keepax 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
5501f88eb0fSCharles Keepax 	struct snd_soc_platform *platform = rtd->platform;
5511f88eb0fSCharles Keepax 	int ret = 0;
5521f88eb0fSCharles Keepax 
5531f88eb0fSCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
5541f88eb0fSCharles Keepax 
5551f88eb0fSCharles Keepax 	if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
5561f88eb0fSCharles Keepax 		ret = platform->driver->compr_ops->copy(cstream, buf, count);
5571f88eb0fSCharles Keepax 
5581f88eb0fSCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
5591f88eb0fSCharles Keepax 	return ret;
5601f88eb0fSCharles Keepax }
5611f88eb0fSCharles Keepax 
56202bd90e8SVinod Koul static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
56336953d98SJeeja KP 				struct snd_compr_metadata *metadata)
56436953d98SJeeja KP {
56536953d98SJeeja KP 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
56636953d98SJeeja KP 	struct snd_soc_platform *platform = rtd->platform;
56736953d98SJeeja KP 	int ret = 0;
56836953d98SJeeja KP 
56936953d98SJeeja KP 	if (platform->driver->compr_ops && platform->driver->compr_ops->set_metadata)
57036953d98SJeeja KP 		ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
57136953d98SJeeja KP 
57236953d98SJeeja KP 	return ret;
57336953d98SJeeja KP }
57436953d98SJeeja KP 
57502bd90e8SVinod Koul static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
57636953d98SJeeja KP 				struct snd_compr_metadata *metadata)
57736953d98SJeeja KP {
57836953d98SJeeja KP 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
57936953d98SJeeja KP 	struct snd_soc_platform *platform = rtd->platform;
58036953d98SJeeja KP 	int ret = 0;
58136953d98SJeeja KP 
58236953d98SJeeja KP 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_metadata)
58336953d98SJeeja KP 		ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
58436953d98SJeeja KP 
58536953d98SJeeja KP 	return ret;
58636953d98SJeeja KP }
5872a99ef0fSLiam Girdwood 
5881245b700SNamarta Kohli /* ASoC Compress operations */
5891245b700SNamarta Kohli static struct snd_compr_ops soc_compr_ops = {
5901245b700SNamarta Kohli 	.open		= soc_compr_open,
5911245b700SNamarta Kohli 	.free		= soc_compr_free,
5921245b700SNamarta Kohli 	.set_params	= soc_compr_set_params,
59302bd90e8SVinod Koul 	.set_metadata   = soc_compr_set_metadata,
59402bd90e8SVinod Koul 	.get_metadata	= soc_compr_get_metadata,
5951245b700SNamarta Kohli 	.get_params	= soc_compr_get_params,
5961245b700SNamarta Kohli 	.trigger	= soc_compr_trigger,
5971245b700SNamarta Kohli 	.pointer	= soc_compr_pointer,
5981245b700SNamarta Kohli 	.ack		= soc_compr_ack,
5991245b700SNamarta Kohli 	.get_caps	= soc_compr_get_caps,
6001245b700SNamarta Kohli 	.get_codec_caps = soc_compr_get_codec_caps
6011245b700SNamarta Kohli };
6021245b700SNamarta Kohli 
6032a99ef0fSLiam Girdwood /* ASoC Dynamic Compress operations */
6042a99ef0fSLiam Girdwood static struct snd_compr_ops soc_compr_dyn_ops = {
6052a99ef0fSLiam Girdwood 	.open		= soc_compr_open_fe,
6062a99ef0fSLiam Girdwood 	.free		= soc_compr_free_fe,
6072a99ef0fSLiam Girdwood 	.set_params	= soc_compr_set_params_fe,
6082a99ef0fSLiam Girdwood 	.get_params	= soc_compr_get_params,
6092a99ef0fSLiam Girdwood 	.set_metadata   = soc_compr_set_metadata,
6102a99ef0fSLiam Girdwood 	.get_metadata	= soc_compr_get_metadata,
6112a99ef0fSLiam Girdwood 	.trigger	= soc_compr_trigger_fe,
6122a99ef0fSLiam Girdwood 	.pointer	= soc_compr_pointer,
6132a99ef0fSLiam Girdwood 	.ack		= soc_compr_ack,
6142a99ef0fSLiam Girdwood 	.get_caps	= soc_compr_get_caps,
6152a99ef0fSLiam Girdwood 	.get_codec_caps = soc_compr_get_codec_caps
6162a99ef0fSLiam Girdwood };
6172a99ef0fSLiam Girdwood 
6181245b700SNamarta Kohli /* create a new compress */
6191245b700SNamarta Kohli int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
6201245b700SNamarta Kohli {
6211245b700SNamarta Kohli 	struct snd_soc_codec *codec = rtd->codec;
6221f88eb0fSCharles Keepax 	struct snd_soc_platform *platform = rtd->platform;
6231245b700SNamarta Kohli 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
6241245b700SNamarta Kohli 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
6251245b700SNamarta Kohli 	struct snd_compr *compr;
6262a99ef0fSLiam Girdwood 	struct snd_pcm *be_pcm;
6271245b700SNamarta Kohli 	char new_name[64];
6281245b700SNamarta Kohli 	int ret = 0, direction = 0;
6291245b700SNamarta Kohli 
6301245b700SNamarta Kohli 	/* check client and interface hw capabilities */
6311245b700SNamarta Kohli 	snprintf(new_name, sizeof(new_name), "%s %s-%d",
6321245b700SNamarta Kohli 			rtd->dai_link->stream_name, codec_dai->name, num);
633daa2db59SCharles Keepax 
634daa2db59SCharles Keepax 	if (codec_dai->driver->playback.channels_min)
6351245b700SNamarta Kohli 		direction = SND_COMPRESS_PLAYBACK;
636daa2db59SCharles Keepax 	else if (codec_dai->driver->capture.channels_min)
637daa2db59SCharles Keepax 		direction = SND_COMPRESS_CAPTURE;
638daa2db59SCharles Keepax 	else
639daa2db59SCharles Keepax 		return -EINVAL;
640daa2db59SCharles Keepax 
6411245b700SNamarta Kohli 	compr = kzalloc(sizeof(*compr), GFP_KERNEL);
6421245b700SNamarta Kohli 	if (compr == NULL) {
6431245b700SNamarta Kohli 		snd_printk(KERN_ERR "Cannot allocate compr\n");
6441245b700SNamarta Kohli 		return -ENOMEM;
6451245b700SNamarta Kohli 	}
6461245b700SNamarta Kohli 
6471f88eb0fSCharles Keepax 	compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
6481f88eb0fSCharles Keepax 				  GFP_KERNEL);
6491f88eb0fSCharles Keepax 	if (compr->ops == NULL) {
6501f88eb0fSCharles Keepax 		dev_err(rtd->card->dev, "Cannot allocate compressed ops\n");
6511f88eb0fSCharles Keepax 		ret = -ENOMEM;
6521f88eb0fSCharles Keepax 		goto compr_err;
6531f88eb0fSCharles Keepax 	}
6542a99ef0fSLiam Girdwood 
6552a99ef0fSLiam Girdwood 	if (rtd->dai_link->dynamic) {
6562a99ef0fSLiam Girdwood 		snprintf(new_name, sizeof(new_name), "(%s)",
6572a99ef0fSLiam Girdwood 			rtd->dai_link->stream_name);
6582a99ef0fSLiam Girdwood 
6592a99ef0fSLiam Girdwood 		ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num,
6602a99ef0fSLiam Girdwood 				1, 0, &be_pcm);
6612a99ef0fSLiam Girdwood 		if (ret < 0) {
6622a99ef0fSLiam Girdwood 			dev_err(rtd->card->dev, "ASoC: can't create compressed for %s\n",
6632a99ef0fSLiam Girdwood 				rtd->dai_link->name);
6642a99ef0fSLiam Girdwood 			goto compr_err;
6652a99ef0fSLiam Girdwood 		}
6662a99ef0fSLiam Girdwood 
6672a99ef0fSLiam Girdwood 		rtd->pcm = be_pcm;
6682a99ef0fSLiam Girdwood 		rtd->fe_compr = 1;
6692a99ef0fSLiam Girdwood 		be_pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->private_data = rtd;
6702a99ef0fSLiam Girdwood 		be_pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->private_data = rtd;
6712a99ef0fSLiam Girdwood 		memcpy(compr->ops, &soc_compr_dyn_ops, sizeof(soc_compr_dyn_ops));
6722a99ef0fSLiam Girdwood 	} else
6731f88eb0fSCharles Keepax 		memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
6741f88eb0fSCharles Keepax 
6751f88eb0fSCharles Keepax 	/* Add copy callback for not memory mapped DSPs */
6761f88eb0fSCharles Keepax 	if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
6771f88eb0fSCharles Keepax 		compr->ops->copy = soc_compr_copy;
6781f88eb0fSCharles Keepax 
6791245b700SNamarta Kohli 	mutex_init(&compr->lock);
6801245b700SNamarta Kohli 	ret = snd_compress_new(rtd->card->snd_card, num, direction, compr);
6811245b700SNamarta Kohli 	if (ret < 0) {
6821245b700SNamarta Kohli 		pr_err("compress asoc: can't create compress for codec %s\n",
6831245b700SNamarta Kohli 			codec->name);
6841f88eb0fSCharles Keepax 		goto compr_err;
6851245b700SNamarta Kohli 	}
6861245b700SNamarta Kohli 
687202c8f70SCharles Keepax 	/* DAPM dai link stream work */
688202c8f70SCharles Keepax 	INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
689202c8f70SCharles Keepax 
6901245b700SNamarta Kohli 	rtd->compr = compr;
6911245b700SNamarta Kohli 	compr->private_data = rtd;
6921245b700SNamarta Kohli 
6931245b700SNamarta Kohli 	printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
6941245b700SNamarta Kohli 		cpu_dai->name);
6951245b700SNamarta Kohli 	return ret;
6961f88eb0fSCharles Keepax 
6971f88eb0fSCharles Keepax compr_err:
6981f88eb0fSCharles Keepax 	kfree(compr);
6991f88eb0fSCharles Keepax 	return ret;
7001245b700SNamarta Kohli }
701