xref: /openbmc/linux/sound/soc/soc-compress.c (revision daa2db59)
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>
271245b700SNamarta Kohli 
281245b700SNamarta Kohli static int soc_compr_open(struct snd_compr_stream *cstream)
291245b700SNamarta Kohli {
301245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
311245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
321245b700SNamarta Kohli 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
331245b700SNamarta Kohli 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
341245b700SNamarta Kohli 	int ret = 0;
351245b700SNamarta Kohli 
3615e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
3715e2e619SCharles Keepax 
381245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
391245b700SNamarta Kohli 		ret = platform->driver->compr_ops->open(cstream);
401245b700SNamarta Kohli 		if (ret < 0) {
411245b700SNamarta Kohli 			pr_err("compress asoc: can't open platform %s\n", platform->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 
541245b700SNamarta Kohli 	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
551245b700SNamarta Kohli 		cpu_dai->playback_active++;
561245b700SNamarta Kohli 		codec_dai->playback_active++;
571245b700SNamarta Kohli 	} else {
581245b700SNamarta Kohli 		cpu_dai->capture_active++;
591245b700SNamarta Kohli 		codec_dai->capture_active++;
601245b700SNamarta Kohli 	}
611245b700SNamarta Kohli 
621245b700SNamarta Kohli 	cpu_dai->active++;
631245b700SNamarta Kohli 	codec_dai->active++;
641245b700SNamarta Kohli 	rtd->codec->active++;
651245b700SNamarta Kohli 
6615e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
6715e2e619SCharles Keepax 
681245b700SNamarta Kohli 	return 0;
691245b700SNamarta Kohli 
701245b700SNamarta Kohli machine_err:
711245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
721245b700SNamarta Kohli 		platform->driver->compr_ops->free(cstream);
731245b700SNamarta Kohli out:
7415e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
751245b700SNamarta Kohli 	return ret;
761245b700SNamarta Kohli }
771245b700SNamarta Kohli 
78202c8f70SCharles Keepax /*
79202c8f70SCharles Keepax  * Power down the audio subsystem pmdown_time msecs after close is called.
80202c8f70SCharles Keepax  * This is to ensure there are no pops or clicks in between any music tracks
81202c8f70SCharles Keepax  * due to DAPM power cycling.
82202c8f70SCharles Keepax  */
83202c8f70SCharles Keepax static void close_delayed_work(struct work_struct *work)
84202c8f70SCharles Keepax {
85202c8f70SCharles Keepax 	struct snd_soc_pcm_runtime *rtd =
86202c8f70SCharles Keepax 			container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
87202c8f70SCharles Keepax 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
88202c8f70SCharles Keepax 
89202c8f70SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
90202c8f70SCharles Keepax 
91202c8f70SCharles Keepax 	dev_dbg(rtd->dev, "ASoC: pop wq checking: %s status: %s waiting: %s\n",
92202c8f70SCharles Keepax 		 codec_dai->driver->playback.stream_name,
93202c8f70SCharles Keepax 		 codec_dai->playback_active ? "active" : "inactive",
94202c8f70SCharles Keepax 		 rtd->pop_wait ? "yes" : "no");
95202c8f70SCharles Keepax 
96202c8f70SCharles Keepax 	/* are we waiting on this codec DAI stream */
97202c8f70SCharles Keepax 	if (rtd->pop_wait == 1) {
98202c8f70SCharles Keepax 		rtd->pop_wait = 0;
99202c8f70SCharles Keepax 		snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
100202c8f70SCharles Keepax 					  SND_SOC_DAPM_STREAM_STOP);
101202c8f70SCharles Keepax 	}
102202c8f70SCharles Keepax 
103202c8f70SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
104202c8f70SCharles Keepax }
105202c8f70SCharles Keepax 
1061245b700SNamarta Kohli static int soc_compr_free(struct snd_compr_stream *cstream)
1071245b700SNamarta Kohli {
1081245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
1091245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
1101245b700SNamarta Kohli 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1111245b700SNamarta Kohli 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
1121245b700SNamarta Kohli 	struct snd_soc_codec *codec = rtd->codec;
1131245b700SNamarta Kohli 
11415e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
11515e2e619SCharles Keepax 
1161245b700SNamarta Kohli 	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
1171245b700SNamarta Kohli 		cpu_dai->playback_active--;
1181245b700SNamarta Kohli 		codec_dai->playback_active--;
1191245b700SNamarta Kohli 	} else {
1201245b700SNamarta Kohli 		cpu_dai->capture_active--;
1211245b700SNamarta Kohli 		codec_dai->capture_active--;
1221245b700SNamarta Kohli 	}
1231245b700SNamarta Kohli 
124da18396fSMark Brown 	snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
125da18396fSMark Brown 
1261245b700SNamarta Kohli 	cpu_dai->active--;
1271245b700SNamarta Kohli 	codec_dai->active--;
1281245b700SNamarta Kohli 	codec->active--;
1291245b700SNamarta Kohli 
1301245b700SNamarta Kohli 	if (!cpu_dai->active)
1311245b700SNamarta Kohli 		cpu_dai->rate = 0;
1321245b700SNamarta Kohli 
1331245b700SNamarta Kohli 	if (!codec_dai->active)
1341245b700SNamarta Kohli 		codec_dai->rate = 0;
1351245b700SNamarta Kohli 
1361245b700SNamarta Kohli 
1371245b700SNamarta Kohli 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
1381245b700SNamarta Kohli 		rtd->dai_link->compr_ops->shutdown(cstream);
1391245b700SNamarta Kohli 
1401245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->free)
1411245b700SNamarta Kohli 		platform->driver->compr_ops->free(cstream);
1421245b700SNamarta Kohli 	cpu_dai->runtime = NULL;
1431245b700SNamarta Kohli 
1441245b700SNamarta Kohli 	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
1451245b700SNamarta Kohli 		if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
1461245b700SNamarta Kohli 		    rtd->dai_link->ignore_pmdown_time) {
1471245b700SNamarta Kohli 			snd_soc_dapm_stream_event(rtd,
1481245b700SNamarta Kohli 					SNDRV_PCM_STREAM_PLAYBACK,
1491245b700SNamarta Kohli 					SND_SOC_DAPM_STREAM_STOP);
1508c3d2aa4SCharles Keepax 		} else {
1519bffb1fbSMisael Lopez Cruz 			rtd->pop_wait = 1;
1521245b700SNamarta Kohli 			schedule_delayed_work(&rtd->delayed_work,
1531245b700SNamarta Kohli 				msecs_to_jiffies(rtd->pmdown_time));
1548c3d2aa4SCharles Keepax 		}
1551245b700SNamarta Kohli 	} else {
1561245b700SNamarta Kohli 		/* capture streams can be powered down now */
1571245b700SNamarta Kohli 		snd_soc_dapm_stream_event(rtd,
1581245b700SNamarta Kohli 			SNDRV_PCM_STREAM_CAPTURE,
1591245b700SNamarta Kohli 			SND_SOC_DAPM_STREAM_STOP);
1601245b700SNamarta Kohli 	}
1611245b700SNamarta Kohli 
16215e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
1631245b700SNamarta Kohli 	return 0;
1641245b700SNamarta Kohli }
1651245b700SNamarta Kohli 
1661245b700SNamarta Kohli static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
1671245b700SNamarta Kohli {
1681245b700SNamarta Kohli 
1691245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
1701245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
1711245b700SNamarta Kohli 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
1721245b700SNamarta Kohli 	int ret = 0;
1731245b700SNamarta Kohli 
17415e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
17515e2e619SCharles Keepax 
1761245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
1771245b700SNamarta Kohli 		ret = platform->driver->compr_ops->trigger(cstream, cmd);
1781245b700SNamarta Kohli 		if (ret < 0)
17915e2e619SCharles Keepax 			goto out;
1801245b700SNamarta Kohli 	}
1811245b700SNamarta Kohli 
182e38b9b74SMark Brown 	switch (cmd) {
183e38b9b74SMark Brown 	case SNDRV_PCM_TRIGGER_START:
184da18396fSMark Brown 		snd_soc_dai_digital_mute(codec_dai, 0, cstream->direction);
185e38b9b74SMark Brown 		break;
186e38b9b74SMark Brown 	case SNDRV_PCM_TRIGGER_STOP:
187da18396fSMark Brown 		snd_soc_dai_digital_mute(codec_dai, 1, cstream->direction);
188e38b9b74SMark Brown 		break;
189e38b9b74SMark Brown 	}
1901245b700SNamarta Kohli 
19115e2e619SCharles Keepax out:
19215e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
1931245b700SNamarta Kohli 	return ret;
1941245b700SNamarta Kohli }
1951245b700SNamarta Kohli 
1961245b700SNamarta Kohli static int soc_compr_set_params(struct snd_compr_stream *cstream,
1971245b700SNamarta Kohli 					struct snd_compr_params *params)
1981245b700SNamarta Kohli {
1991245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2001245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
2011245b700SNamarta Kohli 	int ret = 0;
2021245b700SNamarta Kohli 
20315e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
20415e2e619SCharles Keepax 
2051245b700SNamarta Kohli 	/* first we call set_params for the platform driver
2061245b700SNamarta Kohli 	 * this should configure the soc side
2071245b700SNamarta Kohli 	 * if the machine has compressed ops then we call that as well
2081245b700SNamarta Kohli 	 * expectation is that platform and machine will configure everything
2091245b700SNamarta Kohli 	 * for this compress path, like configuring pcm port for codec
2101245b700SNamarta Kohli 	 */
2111245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
2121245b700SNamarta Kohli 		ret = platform->driver->compr_ops->set_params(cstream, params);
2131245b700SNamarta Kohli 		if (ret < 0)
214fa40ef20SCharles Keepax 			goto err;
2151245b700SNamarta Kohli 	}
2161245b700SNamarta Kohli 
2171245b700SNamarta Kohli 	if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
2181245b700SNamarta Kohli 		ret = rtd->dai_link->compr_ops->set_params(cstream);
2191245b700SNamarta Kohli 		if (ret < 0)
220fa40ef20SCharles Keepax 			goto err;
2211245b700SNamarta Kohli 	}
2221245b700SNamarta Kohli 
2231245b700SNamarta Kohli 	snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
2241245b700SNamarta Kohli 				SND_SOC_DAPM_STREAM_START);
2251245b700SNamarta Kohli 
226fa40ef20SCharles Keepax 	/* cancel any delayed stream shutdown that is pending */
227fa40ef20SCharles Keepax 	rtd->pop_wait = 0;
228fa40ef20SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
229fa40ef20SCharles Keepax 
230fa40ef20SCharles Keepax 	cancel_delayed_work_sync(&rtd->delayed_work);
231fa40ef20SCharles Keepax 
232fa40ef20SCharles Keepax 	return ret;
233fa40ef20SCharles Keepax 
234fa40ef20SCharles Keepax err:
23515e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
2361245b700SNamarta Kohli 	return ret;
2371245b700SNamarta Kohli }
2381245b700SNamarta Kohli 
2391245b700SNamarta Kohli static int soc_compr_get_params(struct snd_compr_stream *cstream,
2401245b700SNamarta Kohli 					struct snd_codec *params)
2411245b700SNamarta Kohli {
2421245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2431245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
2441245b700SNamarta Kohli 	int ret = 0;
2451245b700SNamarta Kohli 
24615e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
24715e2e619SCharles Keepax 
2481245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_params)
2491245b700SNamarta Kohli 		ret = platform->driver->compr_ops->get_params(cstream, params);
2501245b700SNamarta Kohli 
25115e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
2521245b700SNamarta Kohli 	return ret;
2531245b700SNamarta Kohli }
2541245b700SNamarta Kohli 
2551245b700SNamarta Kohli static int soc_compr_get_caps(struct snd_compr_stream *cstream,
2561245b700SNamarta Kohli 				struct snd_compr_caps *caps)
2571245b700SNamarta Kohli {
2581245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2591245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
2601245b700SNamarta Kohli 	int ret = 0;
2611245b700SNamarta Kohli 
26215e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
26315e2e619SCharles Keepax 
2641245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps)
2651245b700SNamarta Kohli 		ret = platform->driver->compr_ops->get_caps(cstream, caps);
2661245b700SNamarta Kohli 
26715e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
2681245b700SNamarta Kohli 	return ret;
2691245b700SNamarta Kohli }
2701245b700SNamarta Kohli 
2711245b700SNamarta Kohli static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
2721245b700SNamarta Kohli 				struct snd_compr_codec_caps *codec)
2731245b700SNamarta Kohli {
2741245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2751245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
2761245b700SNamarta Kohli 	int ret = 0;
2771245b700SNamarta Kohli 
27815e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
27915e2e619SCharles Keepax 
2801245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps)
2811245b700SNamarta Kohli 		ret = platform->driver->compr_ops->get_codec_caps(cstream, codec);
2821245b700SNamarta Kohli 
28315e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
2841245b700SNamarta Kohli 	return ret;
2851245b700SNamarta Kohli }
2861245b700SNamarta Kohli 
2871245b700SNamarta Kohli static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
2881245b700SNamarta Kohli {
2891245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
2901245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
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->ack)
2961245b700SNamarta Kohli 		ret = platform->driver->compr_ops->ack(cstream, bytes);
2971245b700SNamarta Kohli 
29815e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
2991245b700SNamarta Kohli 	return ret;
3001245b700SNamarta Kohli }
3011245b700SNamarta Kohli 
3021245b700SNamarta Kohli static int soc_compr_pointer(struct snd_compr_stream *cstream,
3031245b700SNamarta Kohli 			struct snd_compr_tstamp *tstamp)
3041245b700SNamarta Kohli {
3051245b700SNamarta Kohli 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
3061245b700SNamarta Kohli 	struct snd_soc_platform *platform = rtd->platform;
3071245b700SNamarta Kohli 
30815e2e619SCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
30915e2e619SCharles Keepax 
3101245b700SNamarta Kohli 	if (platform->driver->compr_ops && platform->driver->compr_ops->pointer)
3111245b700SNamarta Kohli 		 platform->driver->compr_ops->pointer(cstream, tstamp);
3121245b700SNamarta Kohli 
31315e2e619SCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
3141245b700SNamarta Kohli 	return 0;
3151245b700SNamarta Kohli }
3161245b700SNamarta Kohli 
3171f88eb0fSCharles Keepax static int soc_compr_copy(struct snd_compr_stream *cstream,
3184daf891cSCharles Keepax 			  char __user *buf, size_t count)
3191f88eb0fSCharles Keepax {
3201f88eb0fSCharles Keepax 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
3211f88eb0fSCharles Keepax 	struct snd_soc_platform *platform = rtd->platform;
3221f88eb0fSCharles Keepax 	int ret = 0;
3231f88eb0fSCharles Keepax 
3241f88eb0fSCharles Keepax 	mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
3251f88eb0fSCharles Keepax 
3261f88eb0fSCharles Keepax 	if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
3271f88eb0fSCharles Keepax 		ret = platform->driver->compr_ops->copy(cstream, buf, count);
3281f88eb0fSCharles Keepax 
3291f88eb0fSCharles Keepax 	mutex_unlock(&rtd->pcm_mutex);
3301f88eb0fSCharles Keepax 	return ret;
3311f88eb0fSCharles Keepax }
3321f88eb0fSCharles Keepax 
33336953d98SJeeja KP static int sst_compr_set_metadata(struct snd_compr_stream *cstream,
33436953d98SJeeja KP 				struct snd_compr_metadata *metadata)
33536953d98SJeeja KP {
33636953d98SJeeja KP 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
33736953d98SJeeja KP 	struct snd_soc_platform *platform = rtd->platform;
33836953d98SJeeja KP 	int ret = 0;
33936953d98SJeeja KP 
34036953d98SJeeja KP 	if (platform->driver->compr_ops && platform->driver->compr_ops->set_metadata)
34136953d98SJeeja KP 		ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
34236953d98SJeeja KP 
34336953d98SJeeja KP 	return ret;
34436953d98SJeeja KP }
34536953d98SJeeja KP 
34636953d98SJeeja KP static int sst_compr_get_metadata(struct snd_compr_stream *cstream,
34736953d98SJeeja KP 				struct snd_compr_metadata *metadata)
34836953d98SJeeja KP {
34936953d98SJeeja KP 	struct snd_soc_pcm_runtime *rtd = cstream->private_data;
35036953d98SJeeja KP 	struct snd_soc_platform *platform = rtd->platform;
35136953d98SJeeja KP 	int ret = 0;
35236953d98SJeeja KP 
35336953d98SJeeja KP 	if (platform->driver->compr_ops && platform->driver->compr_ops->get_metadata)
35436953d98SJeeja KP 		ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
35536953d98SJeeja KP 
35636953d98SJeeja KP 	return ret;
35736953d98SJeeja KP }
3581245b700SNamarta Kohli /* ASoC Compress operations */
3591245b700SNamarta Kohli static struct snd_compr_ops soc_compr_ops = {
3601245b700SNamarta Kohli 	.open		= soc_compr_open,
3611245b700SNamarta Kohli 	.free		= soc_compr_free,
3621245b700SNamarta Kohli 	.set_params	= soc_compr_set_params,
36336953d98SJeeja KP 	.set_metadata   = sst_compr_set_metadata,
36436953d98SJeeja KP 	.get_metadata	= sst_compr_get_metadata,
3651245b700SNamarta Kohli 	.get_params	= soc_compr_get_params,
3661245b700SNamarta Kohli 	.trigger	= soc_compr_trigger,
3671245b700SNamarta Kohli 	.pointer	= soc_compr_pointer,
3681245b700SNamarta Kohli 	.ack		= soc_compr_ack,
3691245b700SNamarta Kohli 	.get_caps	= soc_compr_get_caps,
3701245b700SNamarta Kohli 	.get_codec_caps = soc_compr_get_codec_caps
3711245b700SNamarta Kohli };
3721245b700SNamarta Kohli 
3731245b700SNamarta Kohli /* create a new compress */
3741245b700SNamarta Kohli int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
3751245b700SNamarta Kohli {
3761245b700SNamarta Kohli 	struct snd_soc_codec *codec = rtd->codec;
3771f88eb0fSCharles Keepax 	struct snd_soc_platform *platform = rtd->platform;
3781245b700SNamarta Kohli 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
3791245b700SNamarta Kohli 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
3801245b700SNamarta Kohli 	struct snd_compr *compr;
3811245b700SNamarta Kohli 	char new_name[64];
3821245b700SNamarta Kohli 	int ret = 0, direction = 0;
3831245b700SNamarta Kohli 
3841245b700SNamarta Kohli 	/* check client and interface hw capabilities */
3851245b700SNamarta Kohli 	snprintf(new_name, sizeof(new_name), "%s %s-%d",
3861245b700SNamarta Kohli 			rtd->dai_link->stream_name, codec_dai->name, num);
387daa2db59SCharles Keepax 
388daa2db59SCharles Keepax 	if (codec_dai->driver->playback.channels_min)
3891245b700SNamarta Kohli 		direction = SND_COMPRESS_PLAYBACK;
390daa2db59SCharles Keepax 	else if (codec_dai->driver->capture.channels_min)
391daa2db59SCharles Keepax 		direction = SND_COMPRESS_CAPTURE;
392daa2db59SCharles Keepax 	else
393daa2db59SCharles Keepax 		return -EINVAL;
394daa2db59SCharles Keepax 
3951245b700SNamarta Kohli 	compr = kzalloc(sizeof(*compr), GFP_KERNEL);
3961245b700SNamarta Kohli 	if (compr == NULL) {
3971245b700SNamarta Kohli 		snd_printk(KERN_ERR "Cannot allocate compr\n");
3981245b700SNamarta Kohli 		return -ENOMEM;
3991245b700SNamarta Kohli 	}
4001245b700SNamarta Kohli 
4011f88eb0fSCharles Keepax 	compr->ops = devm_kzalloc(rtd->card->dev, sizeof(soc_compr_ops),
4021f88eb0fSCharles Keepax 				  GFP_KERNEL);
4031f88eb0fSCharles Keepax 	if (compr->ops == NULL) {
4041f88eb0fSCharles Keepax 		dev_err(rtd->card->dev, "Cannot allocate compressed ops\n");
4051f88eb0fSCharles Keepax 		ret = -ENOMEM;
4061f88eb0fSCharles Keepax 		goto compr_err;
4071f88eb0fSCharles Keepax 	}
4081f88eb0fSCharles Keepax 	memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
4091f88eb0fSCharles Keepax 
4101f88eb0fSCharles Keepax 	/* Add copy callback for not memory mapped DSPs */
4111f88eb0fSCharles Keepax 	if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
4121f88eb0fSCharles Keepax 		compr->ops->copy = soc_compr_copy;
4131f88eb0fSCharles Keepax 
4141245b700SNamarta Kohli 	mutex_init(&compr->lock);
4151245b700SNamarta Kohli 	ret = snd_compress_new(rtd->card->snd_card, num, direction, compr);
4161245b700SNamarta Kohli 	if (ret < 0) {
4171245b700SNamarta Kohli 		pr_err("compress asoc: can't create compress for codec %s\n",
4181245b700SNamarta Kohli 			codec->name);
4191f88eb0fSCharles Keepax 		goto compr_err;
4201245b700SNamarta Kohli 	}
4211245b700SNamarta Kohli 
422202c8f70SCharles Keepax 	/* DAPM dai link stream work */
423202c8f70SCharles Keepax 	INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
424202c8f70SCharles Keepax 
4251245b700SNamarta Kohli 	rtd->compr = compr;
4261245b700SNamarta Kohli 	compr->private_data = rtd;
4271245b700SNamarta Kohli 
4281245b700SNamarta Kohli 	printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
4291245b700SNamarta Kohli 		cpu_dai->name);
4301245b700SNamarta Kohli 	return ret;
4311f88eb0fSCharles Keepax 
4321f88eb0fSCharles Keepax compr_err:
4331f88eb0fSCharles Keepax 	kfree(compr);
4341f88eb0fSCharles Keepax 	return ret;
4351245b700SNamarta Kohli }
436