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.c118
1 files changed, 70 insertions, 48 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 4a6d56c3fed9..71a69908ccf6 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -38,6 +38,8 @@
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/gpio.h>
42#include <linux/regulator/consumer.h>
41#include <linux/platform_device.h> 43#include <linux/platform_device.h>
42#include <linux/slab.h> 44#include <linux/slab.h>
43#include <sound/core.h> 45#include <sound/core.h>
@@ -47,16 +49,25 @@
47#include <sound/soc-dapm.h> 49#include <sound/soc-dapm.h>
48#include <sound/initval.h> 50#include <sound/initval.h>
49#include <sound/tlv.h> 51#include <sound/tlv.h>
52#include <sound/tlv320aic3x.h>
50 53
51#include "tlv320aic3x.h" 54#include "tlv320aic3x.h"
52 55
53#define AIC3X_VERSION "0.2" 56#define AIC3X_NUM_SUPPLIES 4
57static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
58 "IOVDD", /* I/O Voltage */
59 "DVDD", /* Digital Core Voltage */
60 "AVDD", /* Analog DAC Voltage */
61 "DRVDD", /* ADC Analog and Output Driver Voltage */
62};
54 63
55/* codec private data */ 64/* codec private data */
56struct aic3x_priv { 65struct aic3x_priv {
57 struct snd_soc_codec codec; 66 struct snd_soc_codec codec;
67 struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
58 unsigned int sysclk; 68 unsigned int sysclk;
59 int master; 69 int master;
70 int gpio_reset;
60}; 71};
61 72
62/* 73/*
@@ -764,7 +775,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
764 struct snd_soc_pcm_runtime *rtd = substream->private_data; 775 struct snd_soc_pcm_runtime *rtd = substream->private_data;
765 struct snd_soc_device *socdev = rtd->socdev; 776 struct snd_soc_device *socdev = rtd->socdev;
766 struct snd_soc_codec *codec = socdev->card->codec; 777 struct snd_soc_codec *codec = socdev->card->codec;
767 struct aic3x_priv *aic3x = codec->private_data; 778 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
768 int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; 779 int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
769 u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; 780 u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
770 u16 d, pll_d = 1; 781 u16 d, pll_d = 1;
@@ -931,7 +942,7 @@ static int aic3x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
931 int clk_id, unsigned int freq, int dir) 942 int clk_id, unsigned int freq, int dir)
932{ 943{
933 struct snd_soc_codec *codec = codec_dai->codec; 944 struct snd_soc_codec *codec = codec_dai->codec;
934 struct aic3x_priv *aic3x = codec->private_data; 945 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
935 946
936 aic3x->sysclk = freq; 947 aic3x->sysclk = freq;
937 return 0; 948 return 0;
@@ -941,7 +952,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
941 unsigned int fmt) 952 unsigned int fmt)
942{ 953{
943 struct snd_soc_codec *codec = codec_dai->codec; 954 struct snd_soc_codec *codec = codec_dai->codec;
944 struct aic3x_priv *aic3x = codec->private_data; 955 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
945 u8 iface_areg, iface_breg; 956 u8 iface_areg, iface_breg;
946 int delay = 0; 957 int delay = 0;
947 958
@@ -995,12 +1006,13 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
995static int aic3x_set_bias_level(struct snd_soc_codec *codec, 1006static int aic3x_set_bias_level(struct snd_soc_codec *codec,
996 enum snd_soc_bias_level level) 1007 enum snd_soc_bias_level level)
997{ 1008{
998 struct aic3x_priv *aic3x = codec->private_data; 1009 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
999 u8 reg; 1010 u8 reg;
1000 1011
1001 switch (level) { 1012 switch (level) {
1002 case SND_SOC_BIAS_ON: 1013 case SND_SOC_BIAS_ON:
1003 /* all power is driven by DAPM system */ 1014 break;
1015 case SND_SOC_BIAS_PREPARE:
1004 if (aic3x->master) { 1016 if (aic3x->master) {
1005 /* enable pll */ 1017 /* enable pll */
1006 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); 1018 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
@@ -1008,48 +1020,9 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
1008 reg | PLL_ENABLE); 1020 reg | PLL_ENABLE);
1009 } 1021 }
1010 break; 1022 break;
1011 case SND_SOC_BIAS_PREPARE:
1012 break;
1013 case SND_SOC_BIAS_STANDBY: 1023 case SND_SOC_BIAS_STANDBY:
1014 /* 1024 /* fall through and disable pll */
1015 * all power is driven by DAPM system,
1016 * so output power is safe if bypass was set
1017 */
1018 if (aic3x->master) {
1019 /* disable pll */
1020 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
1021 aic3x_write(codec, AIC3X_PLL_PROGA_REG,
1022 reg & ~PLL_ENABLE);
1023 }
1024 break;
1025 case SND_SOC_BIAS_OFF: 1025 case SND_SOC_BIAS_OFF:
1026 /* force all power off */
1027 reg = aic3x_read_reg_cache(codec, LINE1L_2_LADC_CTRL);
1028 aic3x_write(codec, LINE1L_2_LADC_CTRL, reg & ~LADC_PWR_ON);
1029 reg = aic3x_read_reg_cache(codec, LINE1R_2_RADC_CTRL);
1030 aic3x_write(codec, LINE1R_2_RADC_CTRL, reg & ~RADC_PWR_ON);
1031
1032 reg = aic3x_read_reg_cache(codec, DAC_PWR);
1033 aic3x_write(codec, DAC_PWR, reg & ~(LDAC_PWR_ON | RDAC_PWR_ON));
1034
1035 reg = aic3x_read_reg_cache(codec, HPLOUT_CTRL);
1036 aic3x_write(codec, HPLOUT_CTRL, reg & ~HPLOUT_PWR_ON);
1037 reg = aic3x_read_reg_cache(codec, HPROUT_CTRL);
1038 aic3x_write(codec, HPROUT_CTRL, reg & ~HPROUT_PWR_ON);
1039
1040 reg = aic3x_read_reg_cache(codec, HPLCOM_CTRL);
1041 aic3x_write(codec, HPLCOM_CTRL, reg & ~HPLCOM_PWR_ON);
1042 reg = aic3x_read_reg_cache(codec, HPRCOM_CTRL);
1043 aic3x_write(codec, HPRCOM_CTRL, reg & ~HPRCOM_PWR_ON);
1044
1045 reg = aic3x_read_reg_cache(codec, MONOLOPM_CTRL);
1046 aic3x_write(codec, MONOLOPM_CTRL, reg & ~MONOLOPM_PWR_ON);
1047
1048 reg = aic3x_read_reg_cache(codec, LLOPM_CTRL);
1049 aic3x_write(codec, LLOPM_CTRL, reg & ~LLOPM_PWR_ON);
1050 reg = aic3x_read_reg_cache(codec, RLOPM_CTRL);
1051 aic3x_write(codec, RLOPM_CTRL, reg & ~RLOPM_PWR_ON);
1052
1053 if (aic3x->master) { 1026 if (aic3x->master) {
1054 /* disable pll */ 1027 /* disable pll */
1055 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); 1028 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
@@ -1171,7 +1144,7 @@ static int aic3x_resume(struct platform_device *pdev)
1171 codec->hw_write(codec->control_data, data, 2); 1144 codec->hw_write(codec->control_data, data, 2);
1172 } 1145 }
1173 1146
1174 aic3x_set_bias_level(codec, codec->suspend_bias_level); 1147 aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1175 1148
1176 return 0; 1149 return 0;
1177} 1150}
@@ -1309,6 +1282,13 @@ static int aic3x_unregister(struct aic3x_priv *aic3x)
1309 snd_soc_unregister_dai(&aic3x_dai); 1282 snd_soc_unregister_dai(&aic3x_dai);
1310 snd_soc_unregister_codec(&aic3x->codec); 1283 snd_soc_unregister_codec(&aic3x->codec);
1311 1284
1285 if (aic3x->gpio_reset >= 0) {
1286 gpio_set_value(aic3x->gpio_reset, 0);
1287 gpio_free(aic3x->gpio_reset);
1288 }
1289 regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
1290 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
1291
1312 kfree(aic3x); 1292 kfree(aic3x);
1313 aic3x_codec = NULL; 1293 aic3x_codec = NULL;
1314 1294
@@ -1330,6 +1310,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
1330{ 1310{
1331 struct snd_soc_codec *codec; 1311 struct snd_soc_codec *codec;
1332 struct aic3x_priv *aic3x; 1312 struct aic3x_priv *aic3x;
1313 struct aic3x_pdata *pdata = i2c->dev.platform_data;
1314 int ret, i;
1333 1315
1334 aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); 1316 aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
1335 if (aic3x == NULL) { 1317 if (aic3x == NULL) {
@@ -1339,13 +1321,53 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
1339 1321
1340 codec = &aic3x->codec; 1322 codec = &aic3x->codec;
1341 codec->dev = &i2c->dev; 1323 codec->dev = &i2c->dev;
1342 codec->private_data = aic3x; 1324 snd_soc_codec_set_drvdata(codec, aic3x);
1343 codec->control_data = i2c; 1325 codec->control_data = i2c;
1344 codec->hw_write = (hw_write_t) i2c_master_send; 1326 codec->hw_write = (hw_write_t) i2c_master_send;
1345 1327
1346 i2c_set_clientdata(i2c, aic3x); 1328 i2c_set_clientdata(i2c, aic3x);
1347 1329
1330 aic3x->gpio_reset = -1;
1331 if (pdata && pdata->gpio_reset >= 0) {
1332 ret = gpio_request(pdata->gpio_reset, "tlv320aic3x reset");
1333 if (ret != 0)
1334 goto err_gpio;
1335 aic3x->gpio_reset = pdata->gpio_reset;
1336 gpio_direction_output(aic3x->gpio_reset, 0);
1337 }
1338
1339 for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
1340 aic3x->supplies[i].supply = aic3x_supply_names[i];
1341
1342 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
1343 aic3x->supplies);
1344 if (ret != 0) {
1345 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
1346 goto err_get;
1347 }
1348
1349 ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
1350 aic3x->supplies);
1351 if (ret != 0) {
1352 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
1353 goto err_enable;
1354 }
1355
1356 if (aic3x->gpio_reset >= 0) {
1357 udelay(1);
1358 gpio_set_value(aic3x->gpio_reset, 1);
1359 }
1360
1348 return aic3x_register(codec); 1361 return aic3x_register(codec);
1362
1363err_enable:
1364 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
1365err_get:
1366 if (aic3x->gpio_reset >= 0)
1367 gpio_free(aic3x->gpio_reset);
1368err_gpio:
1369 kfree(aic3x);
1370 return ret;
1349} 1371}
1350 1372
1351static int aic3x_i2c_remove(struct i2c_client *client) 1373static int aic3x_i2c_remove(struct i2c_client *client)