aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-09-22 18:33:23 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-09-22 18:38:06 -0400
commita89be93c28cd656d1c3c49fe627666b3bbecd45a (patch)
tree6fab96dafd3fc11d07616e59ebb3c643341a9c88
parent8fed54aec8fa5bc6ebfee95454a2cb33101ad917 (diff)
ASoC: wm2000: Add regulator support
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/codecs/wm2000.c53
1 files changed, 47 insertions, 6 deletions
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 6675477a63cb..b723e910fcdc 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -31,6 +31,7 @@
31#include <linux/i2c.h> 31#include <linux/i2c.h>
32#include <linux/regmap.h> 32#include <linux/regmap.h>
33#include <linux/debugfs.h> 33#include <linux/debugfs.h>
34#include <linux/regulator/consumer.h>
34#include <linux/slab.h> 35#include <linux/slab.h>
35#include <sound/core.h> 36#include <sound/core.h>
36#include <sound/pcm.h> 37#include <sound/pcm.h>
@@ -43,6 +44,14 @@
43 44
44#include "wm2000.h" 45#include "wm2000.h"
45 46
47#define WM2000_NUM_SUPPLIES 3
48
49static const char *wm2000_supplies[WM2000_NUM_SUPPLIES] = {
50 "SPKVDD",
51 "DBVDD",
52 "DCVDD",
53};
54
46enum wm2000_anc_mode { 55enum wm2000_anc_mode {
47 ANC_ACTIVE = 0, 56 ANC_ACTIVE = 0,
48 ANC_BYPASS = 1, 57 ANC_BYPASS = 1,
@@ -54,6 +63,8 @@ struct wm2000_priv {
54 struct i2c_client *i2c; 63 struct i2c_client *i2c;
55 struct regmap *regmap; 64 struct regmap *regmap;
56 65
66 struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES];
67
57 enum wm2000_anc_mode anc_mode; 68 enum wm2000_anc_mode anc_mode;
58 69
59 unsigned int anc_active:1; 70 unsigned int anc_active:1;
@@ -126,6 +137,12 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue)
126 137
127 dev_dbg(&i2c->dev, "Beginning power up\n"); 138 dev_dbg(&i2c->dev, "Beginning power up\n");
128 139
140 ret = regulator_bulk_enable(WM2000_NUM_SUPPLIES, wm2000->supplies);
141 if (ret != 0) {
142 dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
143 return ret;
144 }
145
129 if (!wm2000->mclk_div) { 146 if (!wm2000->mclk_div) {
130 dev_dbg(&i2c->dev, "Disabling MCLK divider\n"); 147 dev_dbg(&i2c->dev, "Disabling MCLK divider\n");
131 wm2000_write(i2c, WM2000_REG_SYS_CTL2, 148 wm2000_write(i2c, WM2000_REG_SYS_CTL2,
@@ -143,12 +160,14 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue)
143 if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, 160 if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT,
144 WM2000_ANC_ENG_IDLE)) { 161 WM2000_ANC_ENG_IDLE)) {
145 dev_err(&i2c->dev, "ANC engine failed to reset\n"); 162 dev_err(&i2c->dev, "ANC engine failed to reset\n");
163 regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
146 return -ETIMEDOUT; 164 return -ETIMEDOUT;
147 } 165 }
148 166
149 if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, 167 if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
150 WM2000_STATUS_BOOT_COMPLETE)) { 168 WM2000_STATUS_BOOT_COMPLETE)) {
151 dev_err(&i2c->dev, "ANC engine failed to initialise\n"); 169 dev_err(&i2c->dev, "ANC engine failed to initialise\n");
170 regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
152 return -ETIMEDOUT; 171 return -ETIMEDOUT;
153 } 172 }
154 173
@@ -163,11 +182,13 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue)
163 wm2000->anc_download_size); 182 wm2000->anc_download_size);
164 if (ret < 0) { 183 if (ret < 0) {
165 dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret); 184 dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret);
185 regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
166 return ret; 186 return ret;
167 } 187 }
168 if (ret != wm2000->anc_download_size) { 188 if (ret != wm2000->anc_download_size) {
169 dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n", 189 dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n",
170 ret, wm2000->anc_download_size); 190 ret, wm2000->anc_download_size);
191 regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
171 return -EIO; 192 return -EIO;
172 } 193 }
173 194
@@ -201,6 +222,7 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue)
201 if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, 222 if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
202 WM2000_STATUS_MOUSE_ACTIVE)) { 223 WM2000_STATUS_MOUSE_ACTIVE)) {
203 dev_err(&i2c->dev, "Timed out waiting for device\n"); 224 dev_err(&i2c->dev, "Timed out waiting for device\n");
225 regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
204 return -ETIMEDOUT; 226 return -ETIMEDOUT;
205 } 227 }
206 228
@@ -238,6 +260,8 @@ static int wm2000_power_down(struct i2c_client *i2c, int analogue)
238 return -ETIMEDOUT; 260 return -ETIMEDOUT;
239 } 261 }
240 262
263 regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
264
241 dev_dbg(&i2c->dev, "powered off\n"); 265 dev_dbg(&i2c->dev, "powered off\n");
242 wm2000->anc_mode = ANC_OFF; 266 wm2000->anc_mode = ANC_OFF;
243 267
@@ -747,7 +771,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
747 struct wm2000_platform_data *pdata; 771 struct wm2000_platform_data *pdata;
748 const char *filename; 772 const char *filename;
749 const struct firmware *fw = NULL; 773 const struct firmware *fw = NULL;
750 int ret; 774 int ret, i;
751 int reg; 775 int reg;
752 u16 id; 776 u16 id;
753 777
@@ -768,6 +792,22 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
768 goto out; 792 goto out;
769 } 793 }
770 794
795 for (i = 0; i < WM2000_NUM_SUPPLIES; i++)
796 wm2000->supplies[i].supply = wm2000_supplies[i];
797
798 ret = devm_regulator_bulk_get(&i2c->dev, WM2000_NUM_SUPPLIES,
799 wm2000->supplies);
800 if (ret != 0) {
801 dev_err(&i2c->dev, "Failed to get supplies: %d\n", ret);
802 return ret;
803 }
804
805 ret = regulator_bulk_enable(WM2000_NUM_SUPPLIES, wm2000->supplies);
806 if (ret != 0) {
807 dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
808 return ret;
809 }
810
771 /* Verify that this is a WM2000 */ 811 /* Verify that this is a WM2000 */
772 reg = wm2000_read(i2c, WM2000_REG_ID1); 812 reg = wm2000_read(i2c, WM2000_REG_ID1);
773 id = reg << 8; 813 id = reg << 8;
@@ -777,7 +817,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
777 if (id != 0x2000) { 817 if (id != 0x2000) {
778 dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id); 818 dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id);
779 ret = -ENODEV; 819 ret = -ENODEV;
780 goto out; 820 goto err_supplies;
781 } 821 }
782 822
783 reg = wm2000_read(i2c, WM2000_REG_REVISON); 823 reg = wm2000_read(i2c, WM2000_REG_REVISON);
@@ -796,7 +836,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
796 ret = request_firmware(&fw, filename, &i2c->dev); 836 ret = request_firmware(&fw, filename, &i2c->dev);
797 if (ret != 0) { 837 if (ret != 0) {
798 dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret); 838 dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret);
799 goto out; 839 goto err_supplies;
800 } 840 }
801 841
802 /* Pre-cook the concatenation of the register address onto the image */ 842 /* Pre-cook the concatenation of the register address onto the image */
@@ -807,7 +847,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
807 if (wm2000->anc_download == NULL) { 847 if (wm2000->anc_download == NULL) {
808 dev_err(&i2c->dev, "Out of memory\n"); 848 dev_err(&i2c->dev, "Out of memory\n");
809 ret = -ENOMEM; 849 ret = -ENOMEM;
810 goto out; 850 goto err_supplies;
811 } 851 }
812 852
813 wm2000->anc_download[0] = 0x80; 853 wm2000->anc_download[0] = 0x80;
@@ -822,8 +862,9 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
822 wm2000_reset(wm2000); 862 wm2000_reset(wm2000);
823 863
824 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0); 864 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0);
825 if (!ret) 865
826 goto out; 866err_supplies:
867 regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies);
827 868
828out: 869out:
829 release_firmware(fw); 870 release_firmware(fw);