aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlkka Koskinen <ilkka.koskinen@nokia.com>2009-12-09 05:05:50 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-12-16 12:31:04 -0500
commit7c4e6492205b677a5786b85bcf72ce7c8f4adf15 (patch)
tree80c318cd3a918f408f86843937505bc3af1b8fe9
parent0fe692292a26f57b6522fe859cc8b2549ec0cd97 (diff)
ASoC: tpa6130a2: Add support for regulator framework
Take the regulator framework in use for managing the power sources Signed-off-by: Ilkka Koskinen <ilkka.koskinen@nokia.com> Acked-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Acked-by: Eduardo Valentin <eduardo.valentin@nokia.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/codecs/tpa6130a2.c87
1 files changed, 70 insertions, 17 deletions
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 6b650c1aa3d1..0eb33d49942e 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -25,6 +25,7 @@
25#include <linux/device.h> 25#include <linux/device.h>
26#include <linux/i2c.h> 26#include <linux/i2c.h>
27#include <linux/gpio.h> 27#include <linux/gpio.h>
28#include <linux/regulator/consumer.h>
28#include <sound/tpa6130a2-plat.h> 29#include <sound/tpa6130a2-plat.h>
29#include <sound/soc.h> 30#include <sound/soc.h>
30#include <sound/soc-dapm.h> 31#include <sound/soc-dapm.h>
@@ -34,10 +35,17 @@
34 35
35static struct i2c_client *tpa6130a2_client; 36static struct i2c_client *tpa6130a2_client;
36 37
38#define TPA6130A2_NUM_SUPPLIES 2
39static const char *tpa6130a2_supply_names[TPA6130A2_NUM_SUPPLIES] = {
40 "CPVSS",
41 "Vdd",
42};
43
37/* This struct is used to save the context */ 44/* This struct is used to save the context */
38struct tpa6130a2_data { 45struct tpa6130a2_data {
39 struct mutex mutex; 46 struct mutex mutex;
40 unsigned char regs[TPA6130A2_CACHEREGNUM]; 47 unsigned char regs[TPA6130A2_CACHEREGNUM];
48 struct regulator_bulk_data supplies[TPA6130A2_NUM_SUPPLIES];
41 int power_gpio; 49 int power_gpio;
42 unsigned char power_state; 50 unsigned char power_state;
43}; 51};
@@ -106,10 +114,11 @@ static void tpa6130a2_initialize(void)
106 tpa6130a2_i2c_write(i, data->regs[i]); 114 tpa6130a2_i2c_write(i, data->regs[i]);
107} 115}
108 116
109static void tpa6130a2_power(int power) 117static int tpa6130a2_power(int power)
110{ 118{
111 struct tpa6130a2_data *data; 119 struct tpa6130a2_data *data;
112 u8 val; 120 u8 val;
121 int ret;
113 122
114 BUG_ON(tpa6130a2_client == NULL); 123 BUG_ON(tpa6130a2_client == NULL);
115 data = i2c_get_clientdata(tpa6130a2_client); 124 data = i2c_get_clientdata(tpa6130a2_client);
@@ -117,11 +126,20 @@ static void tpa6130a2_power(int power)
117 mutex_lock(&data->mutex); 126 mutex_lock(&data->mutex);
118 if (power) { 127 if (power) {
119 /* Power on */ 128 /* Power on */
120 if (data->power_gpio >= 0) { 129 if (data->power_gpio >= 0)
121 gpio_set_value(data->power_gpio, 1); 130 gpio_set_value(data->power_gpio, 1);
122 data->power_state = 1; 131
123 tpa6130a2_initialize(); 132 ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies),
133 data->supplies);
134 if (ret != 0) {
135 dev_err(&tpa6130a2_client->dev,
136 "Failed to enable supplies: %d\n", ret);
137 goto exit;
124 } 138 }
139
140 data->power_state = 1;
141 tpa6130a2_initialize();
142
125 /* Clear SWS */ 143 /* Clear SWS */
126 val = tpa6130a2_read(TPA6130A2_REG_CONTROL); 144 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
127 val &= ~TPA6130A2_SWS; 145 val &= ~TPA6130A2_SWS;
@@ -131,13 +149,25 @@ static void tpa6130a2_power(int power)
131 val = tpa6130a2_read(TPA6130A2_REG_CONTROL); 149 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
132 val |= TPA6130A2_SWS; 150 val |= TPA6130A2_SWS;
133 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); 151 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
152
134 /* Power off */ 153 /* Power off */
135 if (data->power_gpio >= 0) { 154 if (data->power_gpio >= 0)
136 gpio_set_value(data->power_gpio, 0); 155 gpio_set_value(data->power_gpio, 0);
137 data->power_state = 0; 156
157 ret = regulator_bulk_disable(ARRAY_SIZE(data->supplies),
158 data->supplies);
159 if (ret != 0) {
160 dev_err(&tpa6130a2_client->dev,
161 "Failed to disable supplies: %d\n", ret);
162 goto exit;
138 } 163 }
164
165 data->power_state = 0;
139 } 166 }
167
168exit:
140 mutex_unlock(&data->mutex); 169 mutex_unlock(&data->mutex);
170 return ret;
141} 171}
142 172
143static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, 173static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol,
@@ -299,15 +329,17 @@ static int tpa6130a2_right_event(struct snd_soc_dapm_widget *w,
299static int tpa6130a2_supply_event(struct snd_soc_dapm_widget *w, 329static int tpa6130a2_supply_event(struct snd_soc_dapm_widget *w,
300 struct snd_kcontrol *kcontrol, int event) 330 struct snd_kcontrol *kcontrol, int event)
301{ 331{
332 int ret = 0;
333
302 switch (event) { 334 switch (event) {
303 case SND_SOC_DAPM_POST_PMU: 335 case SND_SOC_DAPM_POST_PMU:
304 tpa6130a2_power(1); 336 ret = tpa6130a2_power(1);
305 break; 337 break;
306 case SND_SOC_DAPM_POST_PMD: 338 case SND_SOC_DAPM_POST_PMD:
307 tpa6130a2_power(0); 339 ret = tpa6130a2_power(0);
308 break; 340 break;
309 } 341 }
310 return 0; 342 return ret;
311} 343}
312 344
313static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = { 345static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
@@ -352,7 +384,7 @@ static int tpa6130a2_probe(struct i2c_client *client,
352 struct device *dev; 384 struct device *dev;
353 struct tpa6130a2_data *data; 385 struct tpa6130a2_data *data;
354 struct tpa6130a2_platform_data *pdata; 386 struct tpa6130a2_platform_data *pdata;
355 int ret; 387 int i, ret;
356 388
357 dev = &client->dev; 389 dev = &client->dev;
358 390
@@ -387,15 +419,25 @@ static int tpa6130a2_probe(struct i2c_client *client,
387 if (ret < 0) { 419 if (ret < 0) {
388 dev_err(dev, "Failed to request power GPIO (%d)\n", 420 dev_err(dev, "Failed to request power GPIO (%d)\n",
389 data->power_gpio); 421 data->power_gpio);
390 goto fail; 422 goto err_gpio;
391 } 423 }
392 gpio_direction_output(data->power_gpio, 0); 424 gpio_direction_output(data->power_gpio, 0);
393 } else {
394 data->power_state = 1;
395 tpa6130a2_initialize();
396 } 425 }
397 426
398 tpa6130a2_power(1); 427 for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
428 data->supplies[i].supply = tpa6130a2_supply_names[i];
429
430 ret = regulator_bulk_get(dev, ARRAY_SIZE(data->supplies),
431 data->supplies);
432 if (ret != 0) {
433 dev_err(dev, "Failed to request supplies: %d\n", ret);
434 goto err_regulator;
435 }
436
437 ret = tpa6130a2_power(1);
438 if (ret != 0)
439 goto err_power;
440
399 441
400 /* Read version */ 442 /* Read version */
401 ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) & 443 ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) &
@@ -404,10 +446,18 @@ static int tpa6130a2_probe(struct i2c_client *client,
404 dev_warn(dev, "UNTESTED version detected (%d)\n", ret); 446 dev_warn(dev, "UNTESTED version detected (%d)\n", ret);
405 447
406 /* Disable the chip */ 448 /* Disable the chip */
407 tpa6130a2_power(0); 449 ret = tpa6130a2_power(0);
450 if (ret != 0)
451 goto err_power;
408 452
409 return 0; 453 return 0;
410fail: 454
455err_power:
456 regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies);
457err_regulator:
458 if (data->power_gpio >= 0)
459 gpio_free(data->power_gpio);
460err_gpio:
411 kfree(data); 461 kfree(data);
412 i2c_set_clientdata(tpa6130a2_client, NULL); 462 i2c_set_clientdata(tpa6130a2_client, NULL);
413 tpa6130a2_client = NULL; 463 tpa6130a2_client = NULL;
@@ -423,6 +473,9 @@ static int tpa6130a2_remove(struct i2c_client *client)
423 473
424 if (data->power_gpio >= 0) 474 if (data->power_gpio >= 0)
425 gpio_free(data->power_gpio); 475 gpio_free(data->power_gpio);
476
477 regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies);
478
426 kfree(data); 479 kfree(data);
427 tpa6130a2_client = NULL; 480 tpa6130a2_client = NULL;
428 481