summaryrefslogtreecommitdiff
path: root/sound/soc/soc-pcm.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2015-12-19 13:03:18 +0300
committerThomas Gleixner <tglx@linutronix.de>2015-12-19 13:03:18 +0300
commitd267b8d6c65ed7636a412ca479b96df7c0f5b27b (patch)
treef613d83fab377bf3599eb9ffc3cdf34df0a6e48e /sound/soc/soc-pcm.c
parent42baa2581c92f8d07e7260506c8d41caf14b0fc3 (diff)
parent1eab0e42450c6038e2bb17da438370fe639973f3 (diff)
downloadlinux-d267b8d6c65ed7636a412ca479b96df7c0f5b27b.tar.xz
Merge branch 'linus' into x86/apic
Pull in update changes so we can apply conflicting patches
Diffstat (limited to 'sound/soc/soc-pcm.c')
-rw-r--r--sound/soc/soc-pcm.c59
1 files changed, 53 insertions, 6 deletions
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 70e4b9d8bdcd..c86dc96e8986 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -34,6 +34,24 @@
#define DPCM_MAX_BE_USERS 8
+/*
+ * snd_soc_dai_stream_valid() - check if a DAI supports the given stream
+ *
+ * Returns true if the DAI supports the indicated stream type.
+ */
+static bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream)
+{
+ struct snd_soc_pcm_stream *codec_stream;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ codec_stream = &dai->driver->playback;
+ else
+ codec_stream = &dai->driver->capture;
+
+ /* If the codec specifies any rate at all, it supports the stream. */
+ return codec_stream->rates;
+}
+
/**
* snd_soc_runtime_activate() - Increment active count for PCM runtime components
* @rtd: ASoC PCM runtime that is activated
@@ -182,9 +200,9 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %dHz rate\n",
soc_dai->rate);
- ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+ ret = snd_pcm_hw_constraint_single(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE,
- soc_dai->rate, soc_dai->rate);
+ soc_dai->rate);
if (ret < 0) {
dev_err(soc_dai->dev,
"ASoC: Unable to apply rate constraint: %d\n",
@@ -198,9 +216,8 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d channel(s)\n",
soc_dai->channels);
- ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+ ret = snd_pcm_hw_constraint_single(substream->runtime,
SNDRV_PCM_HW_PARAM_CHANNELS,
- soc_dai->channels,
soc_dai->channels);
if (ret < 0) {
dev_err(soc_dai->dev,
@@ -215,9 +232,8 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
dev_dbg(soc_dai->dev, "ASoC: Symmetry forces %d sample bits\n",
soc_dai->sample_bits);
- ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+ ret = snd_pcm_hw_constraint_single(substream->runtime,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
- soc_dai->sample_bits,
soc_dai->sample_bits);
if (ret < 0) {
dev_err(soc_dai->dev,
@@ -371,6 +387,20 @@ static void soc_pcm_init_runtime_hw(struct snd_pcm_substream *substream)
/* first calculate min/max only for CODECs in the DAI link */
for (i = 0; i < rtd->num_codecs; i++) {
+
+ /*
+ * Skip CODECs which don't support the current stream type.
+ * Otherwise, since the rate, channel, and format values will
+ * zero in that case, we would have no usable settings left,
+ * causing the resulting setup to fail.
+ * At least one CODEC should match, otherwise we should have
+ * bailed out on a higher level, since there would be no
+ * CODEC to support the transfer direction in that case.
+ */
+ if (!snd_soc_dai_stream_valid(rtd->codec_dais[i],
+ substream->stream))
+ continue;
+
codec_dai_drv = rtd->codec_dais[i]->driver;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
codec_stream = &codec_dai_drv->playback;
@@ -827,6 +857,23 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
struct snd_pcm_hw_params codec_params;
+ /*
+ * Skip CODECs which don't support the current stream type,
+ * the idea being that if a CODEC is not used for the currently
+ * set up transfer direction, it should not need to be
+ * configured, especially since the configuration used might
+ * not even be supported by that CODEC. There may be cases
+ * however where a CODEC needs to be set up although it is
+ * actually not being used for the transfer, e.g. if a
+ * capture-only CODEC is acting as an LRCLK and/or BCLK master
+ * for the DAI link including a playback-only CODEC.
+ * If this becomes necessary, we will have to augment the
+ * machine driver setup with information on how to act, so
+ * we can do the right thing here.
+ */
+ if (!snd_soc_dai_stream_valid(codec_dai, substream->stream))
+ continue;
+
/* copy params for each codec */
codec_params = *params;