Skip to content

Commit

Permalink
ASoC: soc-core: symmetry checking for each DAIs separately
Browse files Browse the repository at this point in the history
The orginal code does not cover the case that one DAI such as codec
may be shared between other two DAIs(CPU).
When do symmetry checking, altough the codec DAI requires symmetry,
the two CPU DAIs may still be configured to run on different rates.

We change to check each DAI's state separately instead of only checking
the dai link to prevent this issue.

Signed-off-by: Dong Aisheng <[email protected]>
Tested-by: Wolfram Sang <[email protected]>
Acked-by: Liam Girdwood <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
  • Loading branch information
Dong Aisheng authored and broonie committed Sep 21, 2011
1 parent 548aae8 commit 1784102
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 17 deletions.
3 changes: 3 additions & 0 deletions include/sound/soc-dai.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ struct snd_soc_dai {
void *playback_dma_data;
void *capture_dma_data;

/* Symmetry data - only valid if symmetry is being enforced */
unsigned int rate;

/* parent platform/codec */
union {
struct snd_soc_platform *platform;
Expand Down
2 changes: 0 additions & 2 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -851,8 +851,6 @@ struct snd_soc_pcm_runtime {
unsigned int complete:1;
unsigned int dev_registered:1;

/* Symmetry data - only valid if symmetry is being enforced */
unsigned int rate;
long pmdown_time;

/* runtime devices */
Expand Down
40 changes: 25 additions & 15 deletions sound/soc/soc-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,33 @@
#include <sound/soc.h>
#include <sound/initval.h>

static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
struct snd_soc_dai *soc_dai)
{
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;
int ret;

if (!codec_dai->driver->symmetric_rates &&
!cpu_dai->driver->symmetric_rates &&
if (!soc_dai->driver->symmetric_rates &&
!rtd->dai_link->symmetric_rates)
return 0;

/* 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 (!rtd->rate) {
dev_warn(&rtd->dev,
if (!soc_dai->rate) {
dev_warn(soc_dai->dev,
"Not enforcing symmetric_rates due to race\n");
return 0;
}

dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate);
dev_dbg(soc_dai->dev, "Symmetry forces %dHz rate\n", soc_dai->rate);

ret = snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE,
rtd->rate, rtd->rate);
soc_dai->rate, soc_dai->rate);
if (ret < 0) {
dev_err(&rtd->dev,
dev_err(soc_dai->dev,
"Unable to apply rate symmetry constraint: %d\n", ret);
return ret;
}
Expand Down Expand Up @@ -185,8 +183,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
}

/* Symmetry only applies if we've already got an active stream. */
if (cpu_dai->active || codec_dai->active) {
ret = soc_pcm_apply_symmetry(substream);
if (cpu_dai->active) {
ret = soc_pcm_apply_symmetry(substream, cpu_dai);
if (ret != 0)
goto config_err;
}

if (codec_dai->active) {
ret = soc_pcm_apply_symmetry(substream, codec_dai);
if (ret != 0)
goto config_err;
}
Expand Down Expand Up @@ -288,8 +292,12 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
codec_dai->active--;
codec->active--;

if (!cpu_dai->active && !codec_dai->active)
rtd->rate = 0;
/* clear the corresponding DAIs rate when inactive */
if (!cpu_dai->active)
cpu_dai->rate = 0;

if (!codec_dai->active)
codec_dai->rate = 0;

/* Muting the DAC suppresses artifacts caused during digital
* shutdown, for example from stopping clocks.
Expand Down Expand Up @@ -447,7 +455,9 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
}
}

rtd->rate = params_rate(params);
/* store the rate for each DAIs */
cpu_dai->rate = params_rate(params);
codec_dai->rate = params_rate(params);

out:
mutex_unlock(&rtd->pcm_mutex);
Expand Down

0 comments on commit 1784102

Please sign in to comment.