ASoC: pcm: Always honor DAI min and max sample rate constraints

snd_pcm_limit_hw_rates() will initialize the minimum and maximum sample rate for
the PCM stream based on the rates specified in the rates field. Since we call
snd_pcm_limit_hw_rates() after soc_pcm_init_runtime_hw() it will essentially
overwrite the min and max rate set in soc_pcm_init_runtime_hw(). This may cause
the minimum or maximum rate to be set to a value outside the range of one of the
components if one of the components sets either SNDRV_PCM_RATE_CONTINUOUS or
SNDRV_PCM_RATE_KNOT and the other component specified a discrete rate via
SNDRV_PCM_RATE_[0-9]* that is outside of the first component's rate range. To
fix this first calculate the minimum and maximum rates using
snd_pcm_limit_hw_rates() and then on top of that apply the contraints specified
in the snd_soc_pcm_stream structs.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Takashi iwai <tiwai@suse.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 9441e17..11a90cd 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -148,12 +148,12 @@
 	}
 }
 
-static void soc_pcm_init_runtime_hw(struct snd_pcm_hardware *hw,
+static void soc_pcm_init_runtime_hw(struct snd_pcm_runtime *runtime,
 	struct snd_soc_pcm_stream *codec_stream,
 	struct snd_soc_pcm_stream *cpu_stream)
 {
-	hw->rate_min = max(codec_stream->rate_min, cpu_stream->rate_min);
-	hw->rate_max = min_not_zero(codec_stream->rate_max, cpu_stream->rate_max);
+	struct snd_pcm_hardware *hw = &runtime->hw;
+
 	hw->channels_min = max(codec_stream->channels_min,
 		cpu_stream->channels_min);
 	hw->channels_max = min(codec_stream->channels_max,
@@ -166,6 +166,13 @@
 	if (cpu_stream->rates
 		& (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
 		hw->rates |= codec_stream->rates;
+
+	snd_pcm_limit_hw_rates(runtime);
+
+	hw->rate_min = max(hw->rate_min, cpu_stream->rate_min);
+	hw->rate_min = max(hw->rate_min, codec_stream->rate_min);
+	hw->rate_max = min_not_zero(hw->rate_max, cpu_stream->rate_max);
+	hw->rate_max = min_not_zero(hw->rate_max, codec_stream->rate_max);
 }
 
 /*
@@ -235,15 +242,14 @@
 
 	/* Check that the codec and cpu DAIs are compatible */
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->playback,
+		soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->playback,
 			&cpu_dai_drv->playback);
 	} else {
-		soc_pcm_init_runtime_hw(&runtime->hw, &codec_dai_drv->capture,
+		soc_pcm_init_runtime_hw(runtime, &codec_dai_drv->capture,
 			&cpu_dai_drv->capture);
 	}
 
 	ret = -EINVAL;
-	snd_pcm_limit_hw_rates(runtime);
 	if (!runtime->hw.rates) {
 		printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n",
 			codec_dai->name, cpu_dai->name);