Commit e369bd00 authored by Sergej Sawazki's avatar Sergej Sawazki Committed by Mark Brown

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: default avatarSergej Sawazki <ce3a@gmx.de>
Acked-by: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 2d52d172
...@@ -125,18 +125,6 @@ static const struct snd_soc_dapm_route wm8741_dapm_routes[] = { ...@@ -125,18 +125,6 @@ static const struct snd_soc_dapm_route wm8741_dapm_routes[] = {
{ "VOUTRN", NULL, "DACR" }, { "VOUTRN", NULL, "DACR" },
}; };
static struct {
int value;
int ratio;
} lrclk_ratios[WM8741_NUM_RATES] = {
{ 1, 128 },
{ 2, 192 },
{ 3, 256 },
{ 4, 384 },
{ 5, 512 },
{ 6, 768 },
};
static const unsigned int rates_11289[] = { static const unsigned int rates_11289[] = {
44100, 88200, 44100, 88200,
}; };
...@@ -209,25 +197,16 @@ static const struct snd_pcm_hw_constraint_list constraints_36864 = { ...@@ -209,25 +197,16 @@ static const struct snd_pcm_hw_constraint_list constraints_36864 = {
.list = rates_36864, .list = rates_36864,
}; };
static int wm8741_startup(struct snd_pcm_substream *substream, static int wm8741_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai) struct snd_soc_dai *dai)
{ {
struct snd_soc_codec *codec = dai->codec; struct snd_soc_codec *codec = dai->codec;
struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
/* The set of sample rates that can be supported depends on the if (wm8741->sysclk)
* MCLK supplied to the CODEC - enforce this. snd_pcm_hw_constraint_list(substream->runtime, 0,
*/ SNDRV_PCM_HW_PARAM_RATE,
if (!wm8741->sysclk) { wm8741->sysclk_constraints);
dev_err(codec->dev,
"No MCLK configured, call set_sysclk() on init\n");
return -EINVAL;
}
snd_pcm_hw_constraint_list(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
wm8741->sysclk_constraints);
return 0; return 0;
} }
...@@ -241,17 +220,24 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream, ...@@ -241,17 +220,24 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC; u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC;
int i; int i;
/* Find a supported LRCLK ratio */ /* The set of sample rates that can be supported depends on the
for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { * MCLK supplied to the CODEC - enforce this.
if (wm8741->sysclk / params_rate(params) == */
lrclk_ratios[i].ratio) if (!wm8741->sysclk) {
dev_err(codec->dev,
"No MCLK configured, call set_sysclk() on init or in hw_params\n");
return -EINVAL;
}
/* Find a supported LRCLK rate */
for (i = 0; i < wm8741->sysclk_constraints->count; i++) {
if (wm8741->sysclk_constraints->list[i] == params_rate(params))
break; break;
} }
/* Should never happen, should be handled by constraints */ if (i == wm8741->sysclk_constraints->count) {
if (i == ARRAY_SIZE(lrclk_ratios)) { dev_err(codec->dev, "LRCLK %d unsupported with MCLK %d\n",
dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n", params_rate(params), wm8741->sysclk);
wm8741->sysclk / params_rate(params));
return -EINVAL; return -EINVAL;
} }
...@@ -274,8 +260,8 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream, ...@@ -274,8 +260,8 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
return -EINVAL; return -EINVAL;
} }
dev_dbg(codec->dev, "wm8741_hw_params: bit size param = %d", dev_dbg(codec->dev, "wm8741_hw_params: bit size param = %d, rate param = %d",
params_width(params)); params_width(params), params_rate(params));
snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface); snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface);
return 0; return 0;
...@@ -290,6 +276,11 @@ static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai, ...@@ -290,6 +276,11 @@ static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai,
dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq); dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq);
switch (freq) { switch (freq) {
case 0:
wm8741->sysclk_constraints = NULL;
wm8741->sysclk = freq;
return 0;
case 11289600: case 11289600:
wm8741->sysclk_constraints = &constraints_11289; wm8741->sysclk_constraints = &constraints_11289;
wm8741->sysclk = freq; wm8741->sysclk = freq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment