summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorSergej Sawazki <ce3a@gmx.de>2015-06-06 05:25:48 -0400
committerMark Brown <broonie@kernel.org>2015-06-08 13:59:45 -0400
commite369bd006fd67f981d64cf526c4a8b51438fffb2 (patch)
tree51e4b534cdf39d451f16d38e3be85f585685ce36 /sound
parent2d52d172398249f523b24cff9b84aee4e7b8e1b6 (diff)
ASoC: wm8741: Allow master clock switching
The set of supported sample rates depends on the master clock supplied to the codec. Allow the machine driver to set the required master clock in hw_params(). Signed-off-by: Sergej Sawazki <ce3a@gmx.de> Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/wm8741.c61
1 files changed, 26 insertions, 35 deletions
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 09ff01f2fc1e..b34623786e35 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -125,18 +125,6 @@ static const struct snd_soc_dapm_route wm8741_dapm_routes[] = {
125 { "VOUTRN", NULL, "DACR" }, 125 { "VOUTRN", NULL, "DACR" },
126}; 126};
127 127
128static struct {
129 int value;
130 int ratio;
131} lrclk_ratios[WM8741_NUM_RATES] = {
132 { 1, 128 },
133 { 2, 192 },
134 { 3, 256 },
135 { 4, 384 },
136 { 5, 512 },
137 { 6, 768 },
138};
139
140static const unsigned int rates_11289[] = { 128static const unsigned int rates_11289[] = {
141 44100, 88200, 129 44100, 88200,
142}; 130};
@@ -209,25 +197,16 @@ static const struct snd_pcm_hw_constraint_list constraints_36864 = {
209 .list = rates_36864, 197 .list = rates_36864,
210}; 198};
211 199
212
213static int wm8741_startup(struct snd_pcm_substream *substream, 200static int wm8741_startup(struct snd_pcm_substream *substream,
214 struct snd_soc_dai *dai) 201 struct snd_soc_dai *dai)
215{ 202{
216 struct snd_soc_codec *codec = dai->codec; 203 struct snd_soc_codec *codec = dai->codec;
217 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); 204 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
218 205
219 /* The set of sample rates that can be supported depends on the 206 if (wm8741->sysclk)
220 * MCLK supplied to the CODEC - enforce this. 207 snd_pcm_hw_constraint_list(substream->runtime, 0,
221 */ 208 SNDRV_PCM_HW_PARAM_RATE,
222 if (!wm8741->sysclk) { 209 wm8741->sysclk_constraints);
223 dev_err(codec->dev,
224 "No MCLK configured, call set_sysclk() on init\n");
225 return -EINVAL;
226 }
227
228 snd_pcm_hw_constraint_list(substream->runtime, 0,
229 SNDRV_PCM_HW_PARAM_RATE,
230 wm8741->sysclk_constraints);
231 210
232 return 0; 211 return 0;
233} 212}
@@ -241,17 +220,24 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
241 u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC; 220 u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC;
242 int i; 221 int i;
243 222
244 /* Find a supported LRCLK ratio */ 223 /* The set of sample rates that can be supported depends on the
245 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { 224 * MCLK supplied to the CODEC - enforce this.
246 if (wm8741->sysclk / params_rate(params) == 225 */
247 lrclk_ratios[i].ratio) 226 if (!wm8741->sysclk) {
227 dev_err(codec->dev,
228 "No MCLK configured, call set_sysclk() on init or in hw_params\n");
229 return -EINVAL;
230 }
231
232 /* Find a supported LRCLK rate */
233 for (i = 0; i < wm8741->sysclk_constraints->count; i++) {
234 if (wm8741->sysclk_constraints->list[i] == params_rate(params))
248 break; 235 break;
249 } 236 }
250 237
251 /* Should never happen, should be handled by constraints */ 238 if (i == wm8741->sysclk_constraints->count) {
252 if (i == ARRAY_SIZE(lrclk_ratios)) { 239 dev_err(codec->dev, "LRCLK %d unsupported with MCLK %d\n",
253 dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n", 240 params_rate(params), wm8741->sysclk);
254 wm8741->sysclk / params_rate(params));
255 return -EINVAL; 241 return -EINVAL;
256 } 242 }
257 243
@@ -274,8 +260,8 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
274 return -EINVAL; 260 return -EINVAL;
275 } 261 }
276 262
277 dev_dbg(codec->dev, "wm8741_hw_params: bit size param = %d", 263 dev_dbg(codec->dev, "wm8741_hw_params: bit size param = %d, rate param = %d",
278 params_width(params)); 264 params_width(params), params_rate(params));
279 265
280 snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface); 266 snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface);
281 return 0; 267 return 0;
@@ -290,6 +276,11 @@ static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai,
290 dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq); 276 dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq);
291 277
292 switch (freq) { 278 switch (freq) {
279 case 0:
280 wm8741->sysclk_constraints = NULL;
281 wm8741->sysclk = freq;
282 return 0;
283
293 case 11289600: 284 case 11289600:
294 wm8741->sysclk_constraints = &constraints_11289; 285 wm8741->sysclk_constraints = &constraints_11289;
295 wm8741->sysclk = freq; 286 wm8741->sysclk = freq;