ASoC: wm2000: Integrate with clock API
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Thu, 13 Dec 2012 08:29:00 +0000 (17:29 +0900)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 24 Dec 2012 15:42:33 +0000 (15:42 +0000)
Request MCLK as a clock and then enable it when carrying out a state
transtion and while ANC is active, minimising system power consumption
in idle modes.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
sound/soc/codecs/wm2000.c

index 1cbe88f01d634137e0d7e85218556e1c81710d59..0aba8ce424caf880fd28391cc4854df86e1b28b6 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/firmware.h>
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
@@ -62,6 +63,7 @@ enum wm2000_anc_mode {
 struct wm2000_priv {
        struct i2c_client *i2c;
        struct regmap *regmap;
+       struct clk *mclk;
 
        struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES];
 
@@ -550,6 +552,15 @@ static int wm2000_anc_transition(struct wm2000_priv *wm2000,
                return -EINVAL;
        }
 
+       /* Maintain clock while active */
+       if (anc_transitions[i].source == ANC_OFF) {
+               ret = clk_prepare_enable(wm2000->mclk);
+               if (ret != 0) {
+                       dev_err(&i2c->dev, "Failed to enable MCLK: %d\n", ret);
+                       return ret;
+               }
+       }
+
        for (j = 0; j < ARRAY_SIZE(anc_transitions[j].step); j++) {
                if (!anc_transitions[i].step[j])
                        break;
@@ -559,7 +570,10 @@ static int wm2000_anc_transition(struct wm2000_priv *wm2000,
                        return ret;
        }
 
-       return 0;
+       if (anc_transitions[i].dest == ANC_OFF)
+               clk_disable_unprepare(wm2000->mclk);
+
+       return ret;
 }
 
 static int wm2000_anc_set_mode(struct wm2000_priv *wm2000)
@@ -823,6 +837,13 @@ static int wm2000_i2c_probe(struct i2c_client *i2c,
        reg = wm2000_read(i2c, WM2000_REG_REVISON);
        dev_info(&i2c->dev, "revision %c\n", reg + 'A');
 
+       wm2000->mclk = devm_clk_get(&i2c->dev, "MCLK");
+       if (IS_ERR(wm2000->mclk)) {
+               ret = PTR_ERR(wm2000->mclk);
+               dev_err(&i2c->dev, "Failed to get MCLK: %d\n", ret);
+               goto err_supplies;
+       }
+
        filename = "wm2000_anc.bin";
        pdata = dev_get_platdata(&i2c->dev);
        if (pdata) {