ASoC: wm8741: Allow master clock switching
authorSergej Sawazki <ce3a@gmx.de>
Sat, 6 Jun 2015 09:25:48 +0000 (11:25 +0200)
committerMark Brown <broonie@kernel.org>
Mon, 8 Jun 2015 17:59:45 +0000 (18:59 +0100)
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>
sound/soc/codecs/wm8741.c

index 09ff01f..b346237 100644 (file)
@@ -125,18 +125,6 @@ static const struct snd_soc_dapm_route wm8741_dapm_routes[] = {
        { "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[] = {
        44100, 88200,
 };
@@ -209,25 +197,16 @@ static const struct snd_pcm_hw_constraint_list constraints_36864 = {
        .list   = rates_36864,
 };
 
-
 static int wm8741_startup(struct snd_pcm_substream *substream,
                          struct snd_soc_dai *dai)
 {
        struct snd_soc_codec *codec = dai->codec;
        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
 
-       /* The set of sample rates that can be supported depends on the
-        * MCLK supplied to the CODEC - enforce this.
-        */
-       if (!wm8741->sysclk) {
-               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);
+       if (wm8741->sysclk)
+               snd_pcm_hw_constraint_list(substream->runtime, 0,
+                               SNDRV_PCM_HW_PARAM_RATE,
+                               wm8741->sysclk_constraints);
 
        return 0;
 }
@@ -241,17 +220,24 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
        u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC;
        int i;
 
-       /* Find a supported LRCLK ratio */
-       for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
-               if (wm8741->sysclk / params_rate(params) ==
-                   lrclk_ratios[i].ratio)
+       /* The set of sample rates that can be supported depends on the
+        * MCLK supplied to the CODEC - enforce this.
+        */
+       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;
        }
 
-       /* Should never happen, should be handled by constraints */
-       if (i == ARRAY_SIZE(lrclk_ratios)) {
-               dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n",
-                       wm8741->sysclk / params_rate(params));
+       if (i == wm8741->sysclk_constraints->count) {
+               dev_err(codec->dev, "LRCLK %d unsupported with MCLK %d\n",
+                       params_rate(params), wm8741->sysclk);
                return -EINVAL;
        }
 
@@ -274,8 +260,8 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       dev_dbg(codec->dev, "wm8741_hw_params:    bit size param = %d",
-               params_width(params));
+       dev_dbg(codec->dev, "wm8741_hw_params:    bit size param = %d, rate param = %d",
+               params_width(params), params_rate(params));
 
        snd_soc_write(codec, WM8741_FORMAT_CONTROL, iface);
        return 0;
@@ -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);
 
        switch (freq) {
+       case 0:
+               wm8741->sysclk_constraints = NULL;
+               wm8741->sysclk = freq;
+               return 0;
+
        case 11289600:
                wm8741->sysclk_constraints = &constraints_11289;
                wm8741->sysclk = freq;