aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc-dai.h1
-rw-r--r--include/sound/soc.h6
-rw-r--r--sound/soc/soc-core.c38
3 files changed, 45 insertions, 0 deletions
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 13676472ddfc..22b729fbbf84 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -208,6 +208,7 @@ struct snd_soc_dai {
208 /* DAI capabilities */ 208 /* DAI capabilities */
209 struct snd_soc_pcm_stream capture; 209 struct snd_soc_pcm_stream capture;
210 struct snd_soc_pcm_stream playback; 210 struct snd_soc_pcm_stream playback;
211 unsigned int symmetric_rates:1;
211 212
212 /* DAI runtime info */ 213 /* DAI runtime info */
213 struct snd_pcm_runtime *runtime; 214 struct snd_pcm_runtime *runtime;
diff --git a/include/sound/soc.h b/include/sound/soc.h
index a40bc6f316fc..b1f2f8819fea 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -417,6 +417,12 @@ struct snd_soc_dai_link {
417 /* codec/machine specific init - e.g. add machine controls */ 417 /* codec/machine specific init - e.g. add machine controls */
418 int (*init)(struct snd_soc_codec *codec); 418 int (*init)(struct snd_soc_codec *codec);
419 419
420 /* Symmetry requirements */
421 unsigned int symmetric_rates:1;
422
423 /* Symmetry data - only valid if symmetry is being enforced */
424 unsigned int rate;
425
420 /* DAI pcm */ 426 /* DAI pcm */
421 struct snd_pcm *pcm; 427 struct snd_pcm *pcm;
422}; 428};
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 99712f652d0d..dd28009f8969 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -113,6 +113,35 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
113} 113}
114#endif 114#endif
115 115
116static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
117{
118 struct snd_soc_pcm_runtime *rtd = substream->private_data;
119 struct snd_soc_device *socdev = rtd->socdev;
120 struct snd_soc_card *card = socdev->card;
121 struct snd_soc_dai_link *machine = rtd->dai;
122 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
123 struct snd_soc_dai *codec_dai = machine->codec_dai;
124 int ret;
125
126 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates ||
127 machine->symmetric_rates) {
128 dev_dbg(card->dev, "Symmetry forces %dHz rate\n",
129 machine->rate);
130
131 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
132 SNDRV_PCM_HW_PARAM_RATE,
133 machine->rate,
134 machine->rate);
135 if (ret < 0) {
136 dev_err(card->dev,
137 "Unable to apply rate symmetry constraint: %d\n", ret);
138 return ret;
139 }
140 }
141
142 return 0;
143}
144
116/* 145/*
117 * Called by ALSA when a PCM substream is opened, the runtime->hw record is 146 * Called by ALSA when a PCM substream is opened, the runtime->hw record is
118 * then initialized and any private data can be allocated. This also calls 147 * then initialized and any private data can be allocated. This also calls
@@ -221,6 +250,13 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
221 goto machine_err; 250 goto machine_err;
222 } 251 }
223 252
253 /* Symmetry only applies if we've already got an active stream. */
254 if (cpu_dai->active || codec_dai->active) {
255 ret = soc_pcm_apply_symmetry(substream);
256 if (ret != 0)
257 goto machine_err;
258 }
259
224 pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); 260 pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
225 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); 261 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
226 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, 262 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
@@ -521,6 +557,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
521 } 557 }
522 } 558 }
523 559
560 machine->rate = params_rate(params);
561
524out: 562out:
525 mutex_unlock(&pcm_mutex); 563 mutex_unlock(&pcm_mutex);
526 return ret; 564 return ret;