From 3635bf09a89cf92b80ac44198c5c8f0989624ea6 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 13 Nov 2013 18:56:24 +0800 Subject: ASoC: soc-pcm: add symmetry for channels and sample bits Some SoCs can only work in mono or stereo mode at one time. So if we let them capture a mono stream while playing a stereo stream, there might be a problem occur to one of these two streams: double paced or slowed down. In soc-pcm.c, we have soc_pcm_apply_symmetry() to apply the rate symmetry. But we don't have one for channels. Likewise, we can treat symmetric_rate as a solution for those SoCs or CODECs which can not handle asymmetrical LRCLK. But it's also impossible for them to handle asymmetrical BCLK. And accodring to BCLK = LRCLK * channel number * slot size(fixed or sample bits), sample bits might also be a problem if they are not using a fixed slot size. Thus, this patch applys symmetry for channels and sample bits. Meanwhile, there might be a race between two substreams if starting simultaneously. Previously, we only added warning to compalin but still using conservative way to let it carry on. However, this patch rejects the second stream with any unmatched parameter to make sure the first existing stream won't be broken. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 130 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 107 insertions(+), 23 deletions(-) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 42782c01e413..ed1e077114a2 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -84,30 +84,97 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; int ret; - if (!soc_dai->driver->symmetric_rates && - !rtd->dai_link->symmetric_rates) - return 0; + if (soc_dai->rate && (soc_dai->driver->symmetric_rates || + rtd->dai_link->symmetric_rates)) { + dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", + soc_dai->rate); + + ret = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, + soc_dai->rate, soc_dai->rate); + if (ret < 0) { + dev_err(soc_dai->dev, + "ASoC: Unable to apply rate constraint: %d\n", + ret); + return ret; + } + } - /* This can happen if multiple streams are starting simultaneously - - * the second can need to get its constraints before the first has - * picked a rate. Complain and allow the application to carry on. - */ - if (!soc_dai->rate) { - dev_warn(soc_dai->dev, - "ASoC: Not enforcing symmetric_rates due to race\n"); - return 0; + if (soc_dai->channels && (soc_dai->driver->symmetric_channels || + rtd->dai_link->symmetric_channels)) { + dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n", + soc_dai->channels); + + ret = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_CHANNELS, + soc_dai->channels, + soc_dai->channels); + if (ret < 0) { + dev_err(soc_dai->dev, + "ASoC: Unable to apply channel symmetry constraint: %d\n", + ret); + return ret; + } } - dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n", soc_dai->rate); + if (soc_dai->sample_bits && (soc_dai->driver->symmetric_samplebits || + rtd->dai_link->symmetric_samplebits)) { + dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n", + soc_dai->sample_bits); - ret = snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_RATE, - soc_dai->rate, soc_dai->rate); - if (ret < 0) { - dev_err(soc_dai->dev, - "ASoC: Unable to apply rate symmetry constraint: %d\n", - ret); - return ret; + ret = snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_SAMPLE_BITS, + soc_dai->sample_bits, + soc_dai->sample_bits); + if (ret < 0) { + dev_err(soc_dai->dev, + "ASoC: Unable to apply sample bits symmetry constraint: %d\n", + ret); + return ret; + } + } + + return 0; +} + +static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + unsigned int rate, channels, sample_bits, symmetry; + + rate = params_rate(params); + channels = params_channels(params); + sample_bits = snd_pcm_format_physical_width(params_format(params)); + + /* reject unmatched parameters when applying symmetry */ + symmetry = cpu_dai->driver->symmetric_rates || + codec_dai->driver->symmetric_rates || + rtd->dai_link->symmetric_rates; + if (symmetry && cpu_dai->rate && cpu_dai->rate != rate) { + dev_err(rtd->dev, "ASoC: unmatched rate symmetry: %d - %d\n", + cpu_dai->rate, rate); + return -EINVAL; + } + + symmetry = cpu_dai->driver->symmetric_channels || + codec_dai->driver->symmetric_channels || + rtd->dai_link->symmetric_channels; + if (symmetry && cpu_dai->channels && cpu_dai->channels != channels) { + dev_err(rtd->dev, "ASoC: unmatched channel symmetry: %d - %d\n", + cpu_dai->channels, channels); + return -EINVAL; + } + + symmetry = cpu_dai->driver->symmetric_samplebits || + codec_dai->driver->symmetric_samplebits || + rtd->dai_link->symmetric_samplebits; + if (symmetry && cpu_dai->sample_bits && cpu_dai->sample_bits != sample_bits) { + dev_err(rtd->dev, "ASoC: unmatched sample bits symmetry: %d - %d\n", + cpu_dai->sample_bits, sample_bits); + return -EINVAL; } return 0; @@ -384,11 +451,17 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) codec->active--; /* clear the corresponding DAIs rate when inactive */ - if (!cpu_dai->active) + if (!cpu_dai->active) { cpu_dai->rate = 0; + cpu_dai->channels = 0; + cpu_dai->sample_bits = 0; + } - if (!codec_dai->active) + if (!codec_dai->active) { codec_dai->rate = 0; + codec_dai->channels = 0; + codec_dai->sample_bits = 0; + } /* Muting the DAC suppresses artifacts caused during digital * shutdown, for example from stopping clocks. @@ -525,6 +598,10 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + ret = soc_pcm_params_symmetry(substream, params); + if (ret) + goto out; + if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) { ret = rtd->dai_link->ops->hw_params(substream, params); if (ret < 0) { @@ -561,9 +638,16 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, } } - /* store the rate for each DAIs */ + /* store the parameters for each DAIs */ cpu_dai->rate = params_rate(params); + cpu_dai->channels = params_channels(params); + cpu_dai->sample_bits = + snd_pcm_format_physical_width(params_format(params)); + codec_dai->rate = params_rate(params); + codec_dai->channels = params_channels(params); + codec_dai->sample_bits = + snd_pcm_format_physical_width(params_format(params)); out: mutex_unlock(&rtd->pcm_mutex); -- cgit v1.2.3 From d3383420c969c25deffd33270ebe321e8401191a Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 20 Nov 2013 18:37:09 +0800 Subject: ASoC: soc-pcm: move DAIs parameters cleaning into hw_free() We're now applying soc_hw_params_symmetry() to reject unmatched parameters while we clear parameters in soc_pcm_close(). So here's a use case might be broken by this mechanism: aplay -Dhw:0 44100.wav 48000.wav 32000.wav In this case, we call soc_pcm_open()->soc_pcm_hw_params()->soc_pcm_hw_free() ->soc_pcm_hw_params()->soc_pcm_hw_free()->soc_pcm_close() in order. As we only clear parameters in soc_pcm_close(). The parameters would be remained in the system even if the playback of 44100.wav is finished. Thus, this patch is trying to move parameters cleaning into hw_free() so that the system can continue to serve this kind of use case. Also, since we set them in hw_params(), it should be better to clear them in hw_free() for symmetry. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ed1e077114a2..170ff9695753 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -450,19 +450,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) codec_dai->active--; codec->active--; - /* clear the corresponding DAIs rate when inactive */ - if (!cpu_dai->active) { - cpu_dai->rate = 0; - cpu_dai->channels = 0; - cpu_dai->sample_bits = 0; - } - - if (!codec_dai->active) { - codec_dai->rate = 0; - codec_dai->channels = 0; - codec_dai->sample_bits = 0; - } - /* Muting the DAC suppresses artifacts caused during digital * shutdown, for example from stopping clocks. */ @@ -682,6 +669,19 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass); + /* clear the corresponding DAIs parameters when going to be inactive */ + if (cpu_dai->active == 1) { + cpu_dai->rate = 0; + cpu_dai->channels = 0; + cpu_dai->sample_bits = 0; + } + + if (codec_dai->active == 1) { + codec_dai->rate = 0; + codec_dai->channels = 0; + codec_dai->sample_bits = 0; + } + /* apply codec digital mute */ if (!codec->active) snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); -- cgit v1.2.3 From 62e5f676f6a063e1ab0d6b8fcaef2feb026ee00e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 30 Nov 2013 17:38:58 +0100 Subject: ASoC: Set SNDRV_PCM_INFO_JOINT_DUPLEX for PCMs with symmetry constraints If there are symmetry constraints between the playback and the capture channel set the SNDRV_PCM_INFO_JOINT_DUPLEX flag to let userspace know about this. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 170ff9695753..f3592f142832 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -180,6 +180,21 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, return 0; } +static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai_driver *cpu_driver = rtd->cpu_dai->driver; + struct snd_soc_dai_driver *codec_driver = rtd->codec_dai->driver; + struct snd_soc_dai_link *link = rtd->dai_link; + + return cpu_driver->symmetric_rates || codec_driver->symmetric_rates || + link->symmetric_rates || cpu_driver->symmetric_channels || + codec_driver->symmetric_channels || link->symmetric_channels || + cpu_driver->symmetric_samplebits || + codec_driver->symmetric_samplebits || + link->symmetric_samplebits; +} + /* * List of sample sizes that might go over the bus for parameter * application. There ought to be a wildcard sample size for things @@ -309,6 +324,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) &cpu_dai_drv->capture); } + if (soc_pcm_has_symmetry(substream)) + runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; + ret = -EINVAL; snd_pcm_limit_hw_rates(runtime); if (!runtime->hw.rates) { -- cgit v1.2.3 From 0b4bbae85e046042af76a65920db4bb5509c97bd Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 4 Dec 2013 11:18:37 +0800 Subject: ASoC: soc-pcm: Drop the redundant snd_soc_dai_digital_mute() in soc_pcm_close() This patch removed the redundant snd_soc_dai_digital_mute() in close() since it's better to mute in hw_free() which's slightly earlier and symmetrical for the case of reconfiguration: 'aplay 44k1.wav 48k.wav', for example, will be open()->hw_params()->prepare(unmute)->playi1ng->hw_free(mute)->hw_params()-> parepare(unmute)->playing->hw_free(mute)->close() Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 42782c01e413..89d594138773 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -390,11 +390,6 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) if (!codec_dai->active) codec_dai->rate = 0; - /* Muting the DAC suppresses artifacts caused during digital - * shutdown, for example from stopping clocks. - */ - snd_soc_dai_digital_mute(codec_dai, 1, substream->stream); - if (cpu_dai->driver->ops->shutdown) cpu_dai->driver->ops->shutdown(substream, cpu_dai); -- cgit v1.2.3 From 08ae9b456d393dfd1bbe7619b994189be6a26449 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 6 Jan 2014 14:19:06 +0100 Subject: ASoC: dpcm: Add helper function for initializing runtime pcm We have the same code for initializing the runtime pcm on both the playback and the capture path. Factor this out into a common helper function. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 10f29a0ad5a6..b649e32791df 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1228,6 +1228,17 @@ unwind: return err; } +static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, + struct snd_soc_pcm_stream *stream) +{ + runtime->hw.rate_min = stream->rate_min; + runtime->hw.rate_max = stream->rate_max; + runtime->hw.channels_min = stream->channels_min; + runtime->hw.channels_max = stream->channels_max; + runtime->hw.formats &= stream->formats; + runtime->hw.rates = stream->rates; +} + static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -1235,21 +1246,10 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - runtime->hw.rate_min = cpu_dai_drv->playback.rate_min; - runtime->hw.rate_max = cpu_dai_drv->playback.rate_max; - runtime->hw.channels_min = cpu_dai_drv->playback.channels_min; - runtime->hw.channels_max = cpu_dai_drv->playback.channels_max; - runtime->hw.formats &= cpu_dai_drv->playback.formats; - runtime->hw.rates = cpu_dai_drv->playback.rates; - } else { - runtime->hw.rate_min = cpu_dai_drv->capture.rate_min; - runtime->hw.rate_max = cpu_dai_drv->capture.rate_max; - runtime->hw.channels_min = cpu_dai_drv->capture.channels_min; - runtime->hw.channels_max = cpu_dai_drv->capture.channels_max; - runtime->hw.formats &= cpu_dai_drv->capture.formats; - runtime->hw.rates = cpu_dai_drv->capture.rates; - } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dpcm_init_runtime_hw(runtime, &cpu_dai_drv->playback); + else + dpcm_init_runtime_hw(runtime, &cpu_dai_drv->capture); } static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) -- cgit v1.2.3 From 002220a90db8ab9a6313887934dec25b54404cbd Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 6 Jan 2014 14:19:07 +0100 Subject: ASoC: dpcm: Allow PCMs to omit the set of supported formats Allow PCMs that do not impose any restrictions on the supported formats to set the formats field to 0, Instead of assuming that this means that the PCM does not support any formats (which doesn't make much sense), assume that it supports all formats. This brings the behavior of DPCM closer to that of non-DPCM. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b649e32791df..feb0f2843026 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1235,7 +1235,10 @@ static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, runtime->hw.rate_max = stream->rate_max; runtime->hw.channels_min = stream->channels_min; runtime->hw.channels_max = stream->channels_max; - runtime->hw.formats &= stream->formats; + if (runtime->hw.formats) + runtime->hw.formats &= stream->formats; + else + runtime->hw.formats = stream->formats; runtime->hw.rates = stream->rates; } -- cgit v1.2.3 From dcf0fa27a56025793a700e81edd261ee3369e294 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Fri, 3 Jan 2014 09:19:18 +0100 Subject: ASoC: pcm: Fix lack of platform bespoke_trigger() call When the platform driver has no ops, the platform function bespoke_trigger() is no more called. The problem was introduced by the commit c5914b0aaea6494aaa9e415cbd32f8b7eb604af0 "ASoC: pcm: Check for ops before deferencing them" Signed-off-by: Jean-Francois Moine Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index feb0f2843026..d70eecd9e168 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -769,7 +769,7 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream, return ret; } - if (platform->driver->ops && platform->driver->bespoke_trigger) { + if (platform->driver->bespoke_trigger) { ret = platform->driver->bespoke_trigger(substream, cmd); if (ret < 0) return ret; -- cgit v1.2.3 From 1e9de42f4324b91ce2e9da0939cab8fc6ae93893 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Tue, 7 Jan 2014 17:51:42 +0000 Subject: ASoC: dpcm: Explicitly set BE DAI link supported stream directions Some BE DAIs can be "dummy" (when the DSP is controlling the DAI) and as such wont have set a minimum number of playback or capture channels required for BE DAI registration (to establish supported stream directions). Force machine drivers to explicitly set whether they support playback and capture stream directions for every BE DAIs. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 42782c01e413..141a302e4e77 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2026,10 +2026,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) int ret = 0, playback = 0, capture = 0; if (rtd->dai_link->dynamic || rtd->dai_link->no_pcm) { - if (cpu_dai->driver->playback.channels_min) - playback = 1; - if (cpu_dai->driver->capture.channels_min) - capture = 1; + playback = rtd->dai_link->dpcm_playback; + capture = rtd->dai_link->dpcm_capture; } else { if (codec_dai->driver->playback.channels_min && cpu_dai->driver->playback.channels_min) -- cgit v1.2.3 From 16d7ea9167839d0b971ab29030886280595dd5fc Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 6 Jan 2014 14:19:16 +0100 Subject: ASoC: Allow PCMs to restrict the supported formats Some DMA cores might add additional restrictions on which in memory audio formats can be supported by the compound sound card. If the PCM component specifies a set of formats it supports (by setting the formats field to non 0) take these into account when calculating the format set for the compound sound card. Signed-off-by: Lars-Peter Clausen Tested-by: Shawn Guo Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 141a302e4e77..e7f16b54a97d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -158,7 +158,10 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw, cpu_stream->channels_min); hw->channels_max = min(codec_stream->channels_max, cpu_stream->channels_max); - hw->formats = codec_stream->formats & cpu_stream->formats; + if (hw->formats) + hw->formats &= codec_stream->formats & cpu_stream->formats; + else + hw->formats = codec_stream->formats & cpu_stream->formats; hw->rates = codec_stream->rates & cpu_stream->rates; if (codec_stream->rates & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) -- cgit v1.2.3 From 817873f4b155b22a24c48d6a38ee32007e2d856e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 11 Jan 2014 10:24:40 +0100 Subject: ASoC: pcm: Properly initialize hw->rate_max If none of the components (CODEC or CPU DAI) sets a maximum sample rate we'll end up with the rate_max field of the runtime hardware set to 0. (Note that it is still possible for the components to constrain the supported sample rates using other methods, e.g. setting a list constraint) If rate_max is 0 this means that the sound card doesn't support any rates at all, which is not the desired result. So initialize rate_max to UINT_MAX. For symmetry reasons also set rate_min to 0. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 1a617fde46e6..2b8949647e32 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -170,6 +170,9 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime, & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) hw->rates |= codec_stream->rates; + hw->rate_min = 0; + hw->rate_max = UINT_MAX; + snd_pcm_limit_hw_rates(runtime); hw->rate_min = max(hw->rate_min, cpu_stream->rate_min); -- cgit v1.2.3 From 55dcdb5051930dee75e9e2c0da90bc82ee3dcd77 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 11 Jan 2014 10:24:44 +0100 Subject: ASoC: pcm: Use snd_pcm_rate_mask_intersect() helper Instead of open-coding the intersecting of two rate masks (and getting slightly wrong for some of the corner cases) use the new snd_pcm_rate_mask_intersect() helper function. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 2b8949647e32..4bbda0a4ee03 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -162,13 +162,8 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime, hw->formats &= codec_stream->formats & cpu_stream->formats; else hw->formats = codec_stream->formats & cpu_stream->formats; - hw->rates = codec_stream->rates & cpu_stream->rates; - if (codec_stream->rates - & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) - hw->rates |= cpu_stream->rates; - if (cpu_stream->rates - & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) - hw->rates |= codec_stream->rates; + hw->rates = snd_pcm_rate_mask_intersect(codec_stream->rates, + cpu_stream->rates); hw->rate_min = 0; hw->rate_max = UINT_MAX; -- cgit v1.2.3 From 23607025303af6e84bc2cd4cabe89c21f6a22a3f Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Fri, 17 Jan 2014 17:03:55 +0000 Subject: ASoC: DPCM: make some DPCM API calls non static for compressed usage The ASoC compressed code needs to call the internal DPCM APIs in order to dynamically route compressed data to different DAIs. Signed-off-by: Liam Girdwood Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'sound/soc/soc-pcm.c') diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 42782c01e413..64bf3f827aac 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -58,7 +58,7 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams); /* DPCM stream event, send event to FE and all active BEs. */ -static int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, +int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, int event) { struct snd_soc_dpcm *dpcm; @@ -773,7 +773,7 @@ static void dpcm_be_reparent(struct snd_soc_pcm_runtime *fe, } /* disconnect a BE and FE */ -static void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) +void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dpcm *dpcm, *d; @@ -869,7 +869,7 @@ static int widget_in_list(struct snd_soc_dapm_widget_list *list, return 0; } -static int dpcm_path_get(struct snd_soc_pcm_runtime *fe, +int dpcm_path_get(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list_) { struct snd_soc_dai *cpu_dai = fe->cpu_dai; @@ -891,11 +891,6 @@ static int dpcm_path_get(struct snd_soc_pcm_runtime *fe, return paths; } -static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list) -{ - kfree(*list); -} - static int dpcm_prune_paths(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list_) { @@ -965,7 +960,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, continue; /* don't connect if FE is not running */ - if (!fe->dpcm[stream].runtime) + if (!fe->dpcm[stream].runtime && !fe->fe_compr) continue; /* newly connected FE and BE */ @@ -990,7 +985,7 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, * Find the corresponding BE DAIs that source or sink audio to this * FE substream. */ -static int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, +int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list, int new) { if (new) @@ -999,7 +994,7 @@ static int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, return dpcm_prune_paths(fe, stream, list); } -static void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream) +void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dpcm *dpcm; @@ -1037,7 +1032,7 @@ static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe, } } -static int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) +int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dpcm *dpcm; int err, count = 0; @@ -1186,7 +1181,7 @@ be_err: return ret; } -static int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream) +int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dpcm *dpcm; @@ -1247,7 +1242,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) return 0; } -static int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) +int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dpcm *dpcm; @@ -1312,7 +1307,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) return 0; } -static int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) +int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dpcm *dpcm; int ret; @@ -1442,7 +1437,7 @@ static int dpcm_do_trigger(struct snd_soc_dpcm *dpcm, return ret; } -static int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, +int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd) { struct snd_soc_dpcm *dpcm; @@ -1610,7 +1605,7 @@ out: return ret; } -static int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) +int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dpcm *dpcm; int ret = 0; -- cgit v1.2.3