summaryrefslogtreecommitdiff
path: root/sound/soc/soc-compress.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-compress.c')
-rw-r--r--sound/soc/soc-compress.c194
1 files changed, 166 insertions, 28 deletions
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index c1addf49c4f2..736b9c45e59a 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -409,6 +409,37 @@ err:
return ret;
}
+static void dpcm_be_hw_params_prepare(void *data)
+{
+ struct snd_compr_stream *cstream = data;
+ struct snd_soc_pcm_runtime *fe = cstream->private_data;
+ struct snd_soc_pcm_runtime *be = cstream->be;
+ int stream, ret;
+
+ if (cstream->direction == SND_COMPRESS_PLAYBACK)
+ stream = SNDRV_PCM_STREAM_PLAYBACK;
+ else
+ stream = SNDRV_PCM_STREAM_CAPTURE;
+
+ ret = dpcm_fe_dai_hw_params_be(fe, be,
+ &fe->dpcm[stream].hw_params, stream);
+ if (ret < 0) {
+ fe->err_ops = ret;
+ return;
+ }
+
+ ret = dpcm_fe_dai_prepare_be(fe, be, stream);
+ if (ret < 0) {
+ fe->err_ops = ret;
+ return;
+ }
+}
+
+static void dpcm_be_hw_params_prepare_async(void *data, async_cookie_t cookie)
+{
+ dpcm_be_hw_params_prepare(data);
+}
+
static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
struct snd_compr_params *params)
{
@@ -416,7 +447,11 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
struct snd_pcm_substream *fe_substream =
fe->pcm->streams[cstream->direction].substream;
struct snd_soc_platform *platform = fe->platform;
- int ret = 0, stream;
+ struct snd_soc_pcm_runtime *be_list[DPCM_MAX_BE_USERS];
+ struct snd_soc_dpcm *dpcm;
+ int ret = 0, stream, i, j = 0;
+
+ ASYNC_DOMAIN_EXCLUSIVE(async_domain);
if (cstream->direction == SND_COMPRESS_PLAYBACK)
stream = SNDRV_PCM_STREAM_PLAYBACK;
@@ -425,36 +460,112 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
- if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
- ret = platform->driver->compr_ops->set_params(cstream, params);
+ if (!(fe->dai_link->async_ops & ASYNC_DPCM_SND_SOC_HW_PARAMS)) {
+ /* first we call set_params for the platform driver
+ * this should configure the soc side
+ * if the machine has compressed ops then we call that as well
+ * expectation is that platform and machine will configure
+ * everything for this compress path, like configuring pcm
+ * port for codec
+ */
+ if (platform->driver->compr_ops &&
+ platform->driver->compr_ops->set_params) {
+ ret = platform->driver->compr_ops->set_params(cstream,
+ params);
+ if (ret < 0)
+ goto out;
+ }
+
+ if (fe->dai_link->compr_ops &&
+ fe->dai_link->compr_ops->set_params) {
+ ret = fe->dai_link->compr_ops->set_params(cstream);
+ if (ret < 0)
+ goto out;
+ }
+
+ /*
+ * Create an empty hw_params for the BE as the machine
+ * driver must fix this up to match DSP decoder and
+ * ASRC configuration.
+ * I.e. machine driver fixup for compressed BE is
+ * mandatory.
+ */
+ memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
+ sizeof(struct snd_pcm_hw_params));
+
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
+ ret = dpcm_be_dai_hw_params(fe, stream);
if (ret < 0)
goto out;
- }
- if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
- ret = fe->dai_link->compr_ops->set_params(cstream);
+ ret = dpcm_be_dai_prepare(fe, stream);
if (ret < 0)
goto out;
- }
-
- /*
- * Create an empty hw_params for the BE as the machine driver must
- * fix this up to match DSP decoder and ASRC configuration.
- * I.e. machine driver fixup for compressed BE is mandatory.
- */
- memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
- sizeof(struct snd_pcm_hw_params));
-
- fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
-
- ret = dpcm_be_dai_hw_params(fe, stream);
- if (ret < 0)
- goto out;
+ } else {
+ /*
+ * Create an empty hw_params for the BE as the machine
+ * driver must fix this up to match DSP decoder and
+ * ASRC configuration.
+ * I.e. machine driver fixup for compressed BE is
+ * mandatory.
+ */
+ memset(&fe->dpcm[fe_substream->stream].hw_params, 0,
+ sizeof(struct snd_pcm_hw_params));
+
+ fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
+
+ list_for_each_entry(dpcm,
+ &fe->dpcm[stream].be_clients, list_be) {
+ struct snd_soc_pcm_runtime *be = dpcm->be;
+
+ if (be->dai_link->async_ops &
+ ASYNC_DPCM_SND_SOC_HW_PARAMS) {
+ cstream->be = be;
+ async_schedule_domain(
+ dpcm_be_hw_params_prepare_async,
+ cstream, &async_domain);
+ } else {
+ be_list[j++] = be;
+ if (j == DPCM_MAX_BE_USERS) {
+ dev_dbg(fe->dev,
+ "ASoC: MAX backend users!\n");
+ break;
+ }
+ }
+ }
+ for (i = 0; i < j; i++) {
+ cstream->be = be_list[i];
+ dpcm_be_hw_params_prepare(cstream);
+ }
+ /* first we call set_params for the platform driver
+ * this should configure the soc side
+ * if the machine has compressed ops then we call that as well
+ * expectation is that platform and machine will configure
+ * everything this compress path, like configuring pcm port
+ * for codec
+ */
+ if (platform->driver->compr_ops &&
+ platform->driver->compr_ops->set_params) {
+ ret = platform->driver->compr_ops->set_params(cstream,
+ params);
+ if (ret < 0)
+ goto exit;
+ }
- ret = dpcm_be_dai_prepare(fe, stream);
- if (ret < 0)
- goto out;
+ dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
+ if (fe->dai_link->compr_ops &&
+ fe->dai_link->compr_ops->set_params) {
+ ret = fe->dai_link->compr_ops->set_params(cstream);
+ if (ret < 0)
+ goto exit;
+ }
+exit:
+ async_synchronize_full_domain(&async_domain);
+ if (fe->err_ops < 0 || ret < 0)
+ goto out;
+ }
dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_START);
fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE;
@@ -532,14 +643,15 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream,
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
+ int ret = 0;
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
if (platform->driver->compr_ops && platform->driver->compr_ops->pointer)
- platform->driver->compr_ops->pointer(cstream, tstamp);
+ ret = platform->driver->compr_ops->pointer(cstream, tstamp);
mutex_unlock(&rtd->pcm_mutex);
- return 0;
+ return ret;
}
static int soc_compr_copy(struct snd_compr_stream *cstream,
@@ -558,6 +670,22 @@ static int soc_compr_copy(struct snd_compr_stream *cstream,
return ret;
}
+static int sst_compr_set_next_track_param(struct snd_compr_stream *cstream,
+ union snd_codec_options *codec_options)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_platform *platform = rtd->platform;
+ int ret = 0;
+
+ if (platform->driver->compr_ops &&
+ platform->driver->compr_ops->set_next_track_param)
+ ret = platform->driver->compr_ops->set_next_track_param(cstream,
+ codec_options);
+
+ return ret;
+}
+
+
static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
struct snd_compr_metadata *metadata)
{
@@ -590,6 +718,7 @@ static struct snd_compr_ops soc_compr_ops = {
.free = soc_compr_free,
.set_params = soc_compr_set_params,
.set_metadata = soc_compr_set_metadata,
+ .set_next_track_param = sst_compr_set_next_track_param,
.get_metadata = soc_compr_get_metadata,
.get_params = soc_compr_get_params,
.trigger = soc_compr_trigger,
@@ -606,6 +735,7 @@ static struct snd_compr_ops soc_compr_dyn_ops = {
.set_params = soc_compr_set_params_fe,
.get_params = soc_compr_get_params,
.set_metadata = soc_compr_set_metadata,
+ .set_next_track_param = sst_compr_set_next_track_param,
.get_metadata = soc_compr_get_metadata,
.trigger = soc_compr_trigger_fe,
.pointer = soc_compr_pointer,
@@ -721,8 +851,16 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
rtd->compr = compr;
compr->private_data = rtd;
- printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
- cpu_dai->name);
+ if (platform->driver->pcm_new) {
+ ret = platform->driver->pcm_new(rtd);
+ if (ret < 0) {
+ pr_err("asoc: compress pcm constructor failed\n");
+ goto compr_err;
+ }
+ }
+
+ dev_dbg(rtd->card->dev, "compress asoc: %s <-> %s mapping ok\n",
+ codec_dai->name, cpu_dai->name);
return ret;
compr_err: