]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
ASoC: wm8994: Add support for setting MCLK clock rate
authorSylwester Nawrocki <s.nawrocki@samsung.com>
Fri, 20 Sep 2019 13:02:12 +0000 (15:02 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 1 Oct 2019 11:10:10 +0000 (12:10 +0100)
Extend the set_sysclk() handler so we also set frequency of the MCLK1,
MCLK2 clocks through clk API when those clocks are specified in DT.

Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Link: https://lore.kernel.org/r/20190920130218.32690-4-s.nawrocki@samsung.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h

index c3d06e8bc54f20293f6490a56669e920eeae3a29..35fbaa0138bf18113b0f98f2c6fa5536501cb83f 100644 (file)
@@ -167,12 +167,12 @@ static int configure_aif_clock(struct snd_soc_component *component, int aif)
 
        switch (wm8994->sysclk[aif]) {
        case WM8994_SYSCLK_MCLK1:
-               rate = wm8994->mclk[0];
+               rate = wm8994->mclk_rate[0];
                break;
 
        case WM8994_SYSCLK_MCLK2:
                reg1 |= 0x8;
-               rate = wm8994->mclk[1];
+               rate = wm8994->mclk_rate[1];
                break;
 
        case WM8994_SYSCLK_FLL1:
@@ -2367,12 +2367,29 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
        return _wm8994_set_fll(dai->component, id, src, freq_in, freq_out);
 }
 
+static int wm8994_set_mclk_rate(struct wm8994_priv *wm8994, unsigned int id,
+                               unsigned int *freq)
+{
+       int ret;
+
+       if (!wm8994->mclk[id].clk || *freq == wm8994->mclk_rate[id])
+               return 0;
+
+       ret = clk_set_rate(wm8994->mclk[id].clk, *freq);
+       if (ret < 0)
+               return ret;
+
+       *freq = clk_get_rate(wm8994->mclk[id].clk);
+
+       return 0;
+}
+
 static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
                int clk_id, unsigned int freq, int dir)
 {
        struct snd_soc_component *component = dai->component;
        struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
-       int i;
+       int ret, i;
 
        switch (dai->id) {
        case 1:
@@ -2387,7 +2404,12 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
        switch (clk_id) {
        case WM8994_SYSCLK_MCLK1:
                wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK1;
-               wm8994->mclk[0] = freq;
+
+               ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq);
+               if (ret < 0)
+                       return ret;
+
+               wm8994->mclk_rate[0] = freq;
                dev_dbg(dai->dev, "AIF%d using MCLK1 at %uHz\n",
                        dai->id, freq);
                break;
@@ -2395,7 +2417,12 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
        case WM8994_SYSCLK_MCLK2:
                /* TODO: Set GPIO AF */
                wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK2;
-               wm8994->mclk[1] = freq;
+
+               ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq);
+               if (ret < 0)
+                       return ret;
+
+               wm8994->mclk_rate[1] = freq;
                dev_dbg(dai->dev, "AIF%d using MCLK2 at %uHz\n",
                        dai->id, freq);
                break;
@@ -4447,6 +4474,7 @@ static const struct snd_soc_component_driver soc_component_dev_wm8994 = {
 static int wm8994_probe(struct platform_device *pdev)
 {
        struct wm8994_priv *wm8994;
+       int ret;
 
        wm8994 = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_priv),
                              GFP_KERNEL);
@@ -4458,6 +4486,16 @@ static int wm8994_probe(struct platform_device *pdev)
 
        wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
 
+       wm8994->mclk[WM8994_MCLK1].id = "MCLK1";
+       wm8994->mclk[WM8994_MCLK2].id = "MCLK2";
+
+       ret = devm_clk_bulk_get_optional(pdev->dev.parent, ARRAY_SIZE(wm8994->mclk),
+                                        wm8994->mclk);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to get clocks: %d\n", ret);
+               return ret;
+       }
+
        pm_runtime_enable(&pdev->dev);
        pm_runtime_idle(&pdev->dev);
 
index 1d6f2abe1c1137bb6edfac9d1907234ba5df3777..41c4b126114de0836db05a4a0ed6993f442eda4a 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef _WM8994_H
 #define _WM8994_H
 
+#include <linux/clk.h>
 #include <sound/soc.h>
 #include <linux/firmware.h>
 #include <linux/completion.h>
 
 #include "wm_hubs.h"
 
+enum {
+       WM8994_MCLK1,
+       WM8994_MCLK2,
+       WM8994_NUM_MCLK
+};
+
 /* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
 #define WM8994_SYSCLK_MCLK1 1
 #define WM8994_SYSCLK_MCLK2 2
@@ -73,9 +80,10 @@ struct wm8994;
 struct wm8994_priv {
        struct wm_hubs_data hubs;
        struct wm8994 *wm8994;
+       struct clk_bulk_data mclk[WM8994_NUM_MCLK];
        int sysclk[2];
        int sysclk_rate[2];
-       int mclk[2];
+       int mclk_rate[2];
        int aifclk[2];
        int aifdiv[2];
        int channels[2];