aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs
diff options
context:
space:
mode:
authorIlkka Koskinen <ilkka.koskinen@nokia.com>2009-12-04 06:49:10 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-12-04 07:35:08 -0500
commit3a7aaed714bbe3c071000d720f0cce186d1897a4 (patch)
treee817947015af4ce7cff7975153d4a140d257da8a /sound/soc/codecs
parentf1608cca9dd80231004e468b57a7a8eef80a9cd7 (diff)
ASoC: tlv320dac33: 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: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/tlv320dac33.c92
1 files changed, 79 insertions, 13 deletions
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 9c8903dbe647..5037454974b6 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -30,6 +30,7 @@
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/interrupt.h> 31#include <linux/interrupt.h>
32#include <linux/gpio.h> 32#include <linux/gpio.h>
33#include <linux/regulator/consumer.h>
33#include <sound/core.h> 34#include <sound/core.h>
34#include <sound/pcm.h> 35#include <sound/pcm.h>
35#include <sound/pcm_params.h> 36#include <sound/pcm_params.h>
@@ -58,11 +59,19 @@ enum dac33_state {
58 DAC33_FLUSH, 59 DAC33_FLUSH,
59}; 60};
60 61
62#define DAC33_NUM_SUPPLIES 3
63static const char *dac33_supply_names[DAC33_NUM_SUPPLIES] = {
64 "AVDD",
65 "DVDD",
66 "IOVDD",
67};
68
61struct tlv320dac33_priv { 69struct tlv320dac33_priv {
62 struct mutex mutex; 70 struct mutex mutex;
63 struct workqueue_struct *dac33_wq; 71 struct workqueue_struct *dac33_wq;
64 struct work_struct work; 72 struct work_struct work;
65 struct snd_soc_codec codec; 73 struct snd_soc_codec codec;
74 struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES];
66 int power_gpio; 75 int power_gpio;
67 int chip_power; 76 int chip_power;
68 int irq; 77 int irq;
@@ -297,28 +306,49 @@ static inline void dac33_soft_power(struct snd_soc_codec *codec, int power)
297 dac33_write(codec, DAC33_PWR_CTRL, reg); 306 dac33_write(codec, DAC33_PWR_CTRL, reg);
298} 307}
299 308
300static void dac33_hard_power(struct snd_soc_codec *codec, int power) 309static int dac33_hard_power(struct snd_soc_codec *codec, int power)
301{ 310{
302 struct tlv320dac33_priv *dac33 = codec->private_data; 311 struct tlv320dac33_priv *dac33 = codec->private_data;
312 int ret;
303 313
304 mutex_lock(&dac33->mutex); 314 mutex_lock(&dac33->mutex);
305 if (power) { 315 if (power) {
306 if (dac33->power_gpio >= 0) { 316 ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies),
307 gpio_set_value(dac33->power_gpio, 1); 317 dac33->supplies);
308 dac33->chip_power = 1; 318 if (ret != 0) {
309 /* Restore registers */ 319 dev_err(codec->dev,
310 dac33_restore_regs(codec); 320 "Failed to enable supplies: %d\n", ret);
321 goto exit;
311 } 322 }
323
324 if (dac33->power_gpio >= 0)
325 gpio_set_value(dac33->power_gpio, 1);
326
327 dac33->chip_power = 1;
328
329 /* Restore registers */
330 dac33_restore_regs(codec);
331
312 dac33_soft_power(codec, 1); 332 dac33_soft_power(codec, 1);
313 } else { 333 } else {
314 dac33_soft_power(codec, 0); 334 dac33_soft_power(codec, 0);
315 if (dac33->power_gpio >= 0) { 335 if (dac33->power_gpio >= 0)
316 gpio_set_value(dac33->power_gpio, 0); 336 gpio_set_value(dac33->power_gpio, 0);
317 dac33->chip_power = 0; 337
338 ret = regulator_bulk_disable(ARRAY_SIZE(dac33->supplies),
339 dac33->supplies);
340 if (ret != 0) {
341 dev_err(codec->dev,
342 "Failed to disable supplies: %d\n", ret);
343 goto exit;
318 } 344 }
345
346 dac33->chip_power = 0;
319 } 347 }
320 mutex_unlock(&dac33->mutex);
321 348
349exit:
350 mutex_unlock(&dac33->mutex);
351 return ret;
322} 352}
323 353
324static int dac33_get_nsample(struct snd_kcontrol *kcontrol, 354static int dac33_get_nsample(struct snd_kcontrol *kcontrol,
@@ -469,6 +499,8 @@ static int dac33_add_widgets(struct snd_soc_codec *codec)
469static int dac33_set_bias_level(struct snd_soc_codec *codec, 499static int dac33_set_bias_level(struct snd_soc_codec *codec,
470 enum snd_soc_bias_level level) 500 enum snd_soc_bias_level level)
471{ 501{
502 int ret;
503
472 switch (level) { 504 switch (level) {
473 case SND_SOC_BIAS_ON: 505 case SND_SOC_BIAS_ON:
474 dac33_soft_power(codec, 1); 506 dac33_soft_power(codec, 1);
@@ -476,12 +508,19 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec,
476 case SND_SOC_BIAS_PREPARE: 508 case SND_SOC_BIAS_PREPARE:
477 break; 509 break;
478 case SND_SOC_BIAS_STANDBY: 510 case SND_SOC_BIAS_STANDBY:
479 if (codec->bias_level == SND_SOC_BIAS_OFF) 511 if (codec->bias_level == SND_SOC_BIAS_OFF) {
480 dac33_hard_power(codec, 1); 512 ret = dac33_hard_power(codec, 1);
513 if (ret != 0)
514 return ret;
515 }
516
481 dac33_soft_power(codec, 0); 517 dac33_soft_power(codec, 0);
482 break; 518 break;
483 case SND_SOC_BIAS_OFF: 519 case SND_SOC_BIAS_OFF:
484 dac33_hard_power(codec, 0); 520 ret = dac33_hard_power(codec, 0);
521 if (ret != 0)
522 return ret;
523
485 break; 524 break;
486 } 525 }
487 codec->bias_level = level; 526 codec->bias_level = level;
@@ -959,6 +998,9 @@ static int dac33_soc_probe(struct platform_device *pdev)
959 /* power on device */ 998 /* power on device */
960 dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 999 dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
961 1000
1001 /* Bias level configuration has enabled regulator an extra time */
1002 regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies);
1003
962 return 0; 1004 return 0;
963 1005
964pcm_err: 1006pcm_err:
@@ -1039,7 +1081,7 @@ static int dac33_i2c_probe(struct i2c_client *client,
1039 struct tlv320dac33_platform_data *pdata; 1081 struct tlv320dac33_platform_data *pdata;
1040 struct tlv320dac33_priv *dac33; 1082 struct tlv320dac33_priv *dac33;
1041 struct snd_soc_codec *codec; 1083 struct snd_soc_codec *codec;
1042 int ret = 0; 1084 int ret, i;
1043 1085
1044 if (client->dev.platform_data == NULL) { 1086 if (client->dev.platform_data == NULL) {
1045 dev_err(&client->dev, "Platform data not set\n"); 1087 dev_err(&client->dev, "Platform data not set\n");
@@ -1130,6 +1172,24 @@ static int dac33_i2c_probe(struct i2c_client *client,
1130 } 1172 }
1131 } 1173 }
1132 1174
1175 for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++)
1176 dac33->supplies[i].supply = dac33_supply_names[i];
1177
1178 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(dac33->supplies),
1179 dac33->supplies);
1180
1181 if (ret != 0) {
1182 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
1183 goto err_get;
1184 }
1185
1186 ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies),
1187 dac33->supplies);
1188 if (ret != 0) {
1189 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
1190 goto err_enable;
1191 }
1192
1133 ret = snd_soc_register_codec(codec); 1193 ret = snd_soc_register_codec(codec);
1134 if (ret != 0) { 1194 if (ret != 0) {
1135 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 1195 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
@@ -1149,6 +1209,10 @@ static int dac33_i2c_probe(struct i2c_client *client,
1149 return ret; 1209 return ret;
1150 1210
1151error_codec: 1211error_codec:
1212 regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies);
1213err_enable:
1214 regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
1215err_get:
1152 if (dac33->irq >= 0) { 1216 if (dac33->irq >= 0) {
1153 free_irq(dac33->irq, &dac33->codec); 1217 free_irq(dac33->irq, &dac33->codec);
1154 destroy_workqueue(dac33->dac33_wq); 1218 destroy_workqueue(dac33->dac33_wq);
@@ -1177,6 +1241,8 @@ static int dac33_i2c_remove(struct i2c_client *client)
1177 if (dac33->irq >= 0) 1241 if (dac33->irq >= 0)
1178 free_irq(dac33->irq, &dac33->codec); 1242 free_irq(dac33->irq, &dac33->codec);
1179 1243
1244 regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
1245
1180 destroy_workqueue(dac33->dac33_wq); 1246 destroy_workqueue(dac33->dac33_wq);
1181 snd_soc_unregister_dai(&dac33_dai); 1247 snd_soc_unregister_dai(&dac33_dai);
1182 snd_soc_unregister_codec(&dac33->codec); 1248 snd_soc_unregister_codec(&dac33->codec);