diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-12-13 03:29:00 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-12-24 10:42:33 -0500 |
commit | 514cfd6dd72508b79030c8504764a73a7261b713 (patch) | |
tree | 94bb3b9dc270b9acc979aa79cef4367c51ce0a41 /sound/soc/codecs | |
parent | a49f0d1ea3ec94fc7cf33a7c36a16343b74bd565 (diff) |
ASoC: wm2000: Integrate with clock API
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>
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/wm2000.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 1cbe88f01d63..0aba8ce424ca 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
29 | #include <linux/clk.h> | ||
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
30 | #include <linux/pm.h> | 31 | #include <linux/pm.h> |
31 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
@@ -62,6 +63,7 @@ enum wm2000_anc_mode { | |||
62 | struct wm2000_priv { | 63 | struct wm2000_priv { |
63 | struct i2c_client *i2c; | 64 | struct i2c_client *i2c; |
64 | struct regmap *regmap; | 65 | struct regmap *regmap; |
66 | struct clk *mclk; | ||
65 | 67 | ||
66 | struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES]; | 68 | struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES]; |
67 | 69 | ||
@@ -550,6 +552,15 @@ static int wm2000_anc_transition(struct wm2000_priv *wm2000, | |||
550 | return -EINVAL; | 552 | return -EINVAL; |
551 | } | 553 | } |
552 | 554 | ||
555 | /* Maintain clock while active */ | ||
556 | if (anc_transitions[i].source == ANC_OFF) { | ||
557 | ret = clk_prepare_enable(wm2000->mclk); | ||
558 | if (ret != 0) { | ||
559 | dev_err(&i2c->dev, "Failed to enable MCLK: %d\n", ret); | ||
560 | return ret; | ||
561 | } | ||
562 | } | ||
563 | |||
553 | for (j = 0; j < ARRAY_SIZE(anc_transitions[j].step); j++) { | 564 | for (j = 0; j < ARRAY_SIZE(anc_transitions[j].step); j++) { |
554 | if (!anc_transitions[i].step[j]) | 565 | if (!anc_transitions[i].step[j]) |
555 | break; | 566 | break; |
@@ -559,7 +570,10 @@ static int wm2000_anc_transition(struct wm2000_priv *wm2000, | |||
559 | return ret; | 570 | return ret; |
560 | } | 571 | } |
561 | 572 | ||
562 | return 0; | 573 | if (anc_transitions[i].dest == ANC_OFF) |
574 | clk_disable_unprepare(wm2000->mclk); | ||
575 | |||
576 | return ret; | ||
563 | } | 577 | } |
564 | 578 | ||
565 | static int wm2000_anc_set_mode(struct wm2000_priv *wm2000) | 579 | static int wm2000_anc_set_mode(struct wm2000_priv *wm2000) |
@@ -823,6 +837,13 @@ static int wm2000_i2c_probe(struct i2c_client *i2c, | |||
823 | reg = wm2000_read(i2c, WM2000_REG_REVISON); | 837 | reg = wm2000_read(i2c, WM2000_REG_REVISON); |
824 | dev_info(&i2c->dev, "revision %c\n", reg + 'A'); | 838 | dev_info(&i2c->dev, "revision %c\n", reg + 'A'); |
825 | 839 | ||
840 | wm2000->mclk = devm_clk_get(&i2c->dev, "MCLK"); | ||
841 | if (IS_ERR(wm2000->mclk)) { | ||
842 | ret = PTR_ERR(wm2000->mclk); | ||
843 | dev_err(&i2c->dev, "Failed to get MCLK: %d\n", ret); | ||
844 | goto err_supplies; | ||
845 | } | ||
846 | |||
826 | filename = "wm2000_anc.bin"; | 847 | filename = "wm2000_anc.bin"; |
827 | pdata = dev_get_platdata(&i2c->dev); | 848 | pdata = dev_get_platdata(&i2c->dev); |
828 | if (pdata) { | 849 | if (pdata) { |