aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/tlv320aic3x.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/tlv320aic3x.c')
-rw-r--r--sound/soc/codecs/tlv320aic3x.c81
1 files changed, 39 insertions, 42 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 556123b4059c..584bc1e67f76 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -38,6 +38,7 @@
38#include <linux/delay.h> 38#include <linux/delay.h>
39#include <linux/pm.h> 39#include <linux/pm.h>
40#include <linux/i2c.h> 40#include <linux/i2c.h>
41#include <linux/regulator/consumer.h>
41#include <linux/platform_device.h> 42#include <linux/platform_device.h>
42#include <sound/core.h> 43#include <sound/core.h>
43#include <sound/pcm.h> 44#include <sound/pcm.h>
@@ -49,11 +50,18 @@
49 50
50#include "tlv320aic3x.h" 51#include "tlv320aic3x.h"
51 52
52#define AIC3X_VERSION "0.2" 53#define AIC3X_NUM_SUPPLIES 4
54static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
55 "IOVDD", /* I/O Voltage */
56 "DVDD", /* Digital Core Voltage */
57 "AVDD", /* Analog DAC Voltage */
58 "DRVDD", /* ADC Analog and Output Driver Voltage */
59};
53 60
54/* codec private data */ 61/* codec private data */
55struct aic3x_priv { 62struct aic3x_priv {
56 struct snd_soc_codec codec; 63 struct snd_soc_codec codec;
64 struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
57 unsigned int sysclk; 65 unsigned int sysclk;
58 int master; 66 int master;
59}; 67};
@@ -999,7 +1007,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
999 1007
1000 switch (level) { 1008 switch (level) {
1001 case SND_SOC_BIAS_ON: 1009 case SND_SOC_BIAS_ON:
1002 /* all power is driven by DAPM system */ 1010 break;
1011 case SND_SOC_BIAS_PREPARE:
1003 if (aic3x->master) { 1012 if (aic3x->master) {
1004 /* enable pll */ 1013 /* enable pll */
1005 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); 1014 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
@@ -1007,48 +1016,9 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
1007 reg | PLL_ENABLE); 1016 reg | PLL_ENABLE);
1008 } 1017 }
1009 break; 1018 break;
1010 case SND_SOC_BIAS_PREPARE:
1011 break;
1012 case SND_SOC_BIAS_STANDBY: 1019 case SND_SOC_BIAS_STANDBY:
1013 /* 1020 /* fall through and disable pll */
1014 * all power is driven by DAPM system,
1015 * so output power is safe if bypass was set
1016 */
1017 if (aic3x->master) {
1018 /* disable pll */
1019 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
1020 aic3x_write(codec, AIC3X_PLL_PROGA_REG,
1021 reg & ~PLL_ENABLE);
1022 }
1023 break;
1024 case SND_SOC_BIAS_OFF: 1021 case SND_SOC_BIAS_OFF:
1025 /* force all power off */
1026 reg = aic3x_read_reg_cache(codec, LINE1L_2_LADC_CTRL);
1027 aic3x_write(codec, LINE1L_2_LADC_CTRL, reg & ~LADC_PWR_ON);
1028 reg = aic3x_read_reg_cache(codec, LINE1R_2_RADC_CTRL);
1029 aic3x_write(codec, LINE1R_2_RADC_CTRL, reg & ~RADC_PWR_ON);
1030
1031 reg = aic3x_read_reg_cache(codec, DAC_PWR);
1032 aic3x_write(codec, DAC_PWR, reg & ~(LDAC_PWR_ON | RDAC_PWR_ON));
1033
1034 reg = aic3x_read_reg_cache(codec, HPLOUT_CTRL);
1035 aic3x_write(codec, HPLOUT_CTRL, reg & ~HPLOUT_PWR_ON);
1036 reg = aic3x_read_reg_cache(codec, HPROUT_CTRL);
1037 aic3x_write(codec, HPROUT_CTRL, reg & ~HPROUT_PWR_ON);
1038
1039 reg = aic3x_read_reg_cache(codec, HPLCOM_CTRL);
1040 aic3x_write(codec, HPLCOM_CTRL, reg & ~HPLCOM_PWR_ON);
1041 reg = aic3x_read_reg_cache(codec, HPRCOM_CTRL);
1042 aic3x_write(codec, HPRCOM_CTRL, reg & ~HPRCOM_PWR_ON);
1043
1044 reg = aic3x_read_reg_cache(codec, MONOLOPM_CTRL);
1045 aic3x_write(codec, MONOLOPM_CTRL, reg & ~MONOLOPM_PWR_ON);
1046
1047 reg = aic3x_read_reg_cache(codec, LLOPM_CTRL);
1048 aic3x_write(codec, LLOPM_CTRL, reg & ~LLOPM_PWR_ON);
1049 reg = aic3x_read_reg_cache(codec, RLOPM_CTRL);
1050 aic3x_write(codec, RLOPM_CTRL, reg & ~RLOPM_PWR_ON);
1051
1052 if (aic3x->master) { 1022 if (aic3x->master) {
1053 /* disable pll */ 1023 /* disable pll */
1054 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); 1024 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
@@ -1308,6 +1278,9 @@ static int aic3x_unregister(struct aic3x_priv *aic3x)
1308 snd_soc_unregister_dai(&aic3x_dai); 1278 snd_soc_unregister_dai(&aic3x_dai);
1309 snd_soc_unregister_codec(&aic3x->codec); 1279 snd_soc_unregister_codec(&aic3x->codec);
1310 1280
1281 regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
1282 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
1283
1311 kfree(aic3x); 1284 kfree(aic3x);
1312 aic3x_codec = NULL; 1285 aic3x_codec = NULL;
1313 1286
@@ -1329,6 +1302,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
1329{ 1302{
1330 struct snd_soc_codec *codec; 1303 struct snd_soc_codec *codec;
1331 struct aic3x_priv *aic3x; 1304 struct aic3x_priv *aic3x;
1305 int ret, i;
1332 1306
1333 aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); 1307 aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
1334 if (aic3x == NULL) { 1308 if (aic3x == NULL) {
@@ -1344,7 +1318,30 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
1344 1318
1345 i2c_set_clientdata(i2c, aic3x); 1319 i2c_set_clientdata(i2c, aic3x);
1346 1320
1321 for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
1322 aic3x->supplies[i].supply = aic3x_supply_names[i];
1323
1324 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
1325 aic3x->supplies);
1326 if (ret != 0) {
1327 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
1328 goto err_get;
1329 }
1330
1331 ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
1332 aic3x->supplies);
1333 if (ret != 0) {
1334 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
1335 goto err_enable;
1336 }
1337
1347 return aic3x_register(codec); 1338 return aic3x_register(codec);
1339
1340err_enable:
1341 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
1342err_get:
1343 kfree(aic3x);
1344 return ret;
1348} 1345}
1349 1346
1350static int aic3x_i2c_remove(struct i2c_client *client) 1347static int aic3x_i2c_remove(struct i2c_client *client)