aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/tlv320aic3x.c83
1 files changed, 65 insertions, 18 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index c60ead948ea6..5f8a7c4045c2 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -70,6 +70,7 @@ struct aic3x_priv {
70 unsigned int sysclk; 70 unsigned int sysclk;
71 int master; 71 int master;
72 int gpio_reset; 72 int gpio_reset;
73 int power;
73#define AIC3X_MODEL_3X 0 74#define AIC3X_MODEL_3X 0
74#define AIC3X_MODEL_33 1 75#define AIC3X_MODEL_33 1
75#define AIC3X_MODEL_3007 2 76#define AIC3X_MODEL_3007 2
@@ -1028,6 +1029,64 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
1028 return 0; 1029 return 0;
1029} 1030}
1030 1031
1032static int aic3x_init_3007(struct snd_soc_codec *codec)
1033{
1034 u8 tmp1, tmp2, *cache = codec->reg_cache;
1035
1036 /*
1037 * There is no need to cache writes to undocumented page 0xD but
1038 * respective page 0 register cache entries must be preserved
1039 */
1040 tmp1 = cache[0xD];
1041 tmp2 = cache[0x8];
1042 /* Class-D speaker driver init; datasheet p. 46 */
1043 snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D);
1044 snd_soc_write(codec, 0xD, 0x0D);
1045 snd_soc_write(codec, 0x8, 0x5C);
1046 snd_soc_write(codec, 0x8, 0x5D);
1047 snd_soc_write(codec, 0x8, 0x5C);
1048 snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00);
1049 cache[0xD] = tmp1;
1050 cache[0x8] = tmp2;
1051
1052 return 0;
1053}
1054
1055static int aic3x_set_power(struct snd_soc_codec *codec, int power)
1056{
1057 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1058 int i, ret;
1059 u8 *cache = codec->reg_cache;
1060
1061 if (power) {
1062 ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
1063 aic3x->supplies);
1064 if (ret)
1065 goto out;
1066 aic3x->power = 1;
1067 if (aic3x->gpio_reset >= 0) {
1068 udelay(1);
1069 gpio_set_value(aic3x->gpio_reset, 1);
1070 }
1071
1072 /* Sync reg_cache with the hardware */
1073 codec->cache_only = 0;
1074 for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++)
1075 snd_soc_write(codec, i, cache[i]);
1076 if (aic3x->model == AIC3X_MODEL_3007)
1077 aic3x_init_3007(codec);
1078 codec->cache_sync = 0;
1079 } else {
1080 aic3x->power = 0;
1081 if (aic3x->gpio_reset >= 0)
1082 gpio_set_value(aic3x->gpio_reset, 0);
1083 ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies),
1084 aic3x->supplies);
1085 }
1086out:
1087 return ret;
1088}
1089
1031static int aic3x_set_bias_level(struct snd_soc_codec *codec, 1090static int aic3x_set_bias_level(struct snd_soc_codec *codec,
1032 enum snd_soc_bias_level level) 1091 enum snd_soc_bias_level level)
1033{ 1092{
@@ -1047,6 +1106,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
1047 } 1106 }
1048 break; 1107 break;
1049 case SND_SOC_BIAS_STANDBY: 1108 case SND_SOC_BIAS_STANDBY:
1109 if (!aic3x->power)
1110 aic3x_set_power(codec, 1);
1050 if (codec->bias_level == SND_SOC_BIAS_PREPARE && 1111 if (codec->bias_level == SND_SOC_BIAS_PREPARE &&
1051 aic3x->master) { 1112 aic3x->master) {
1052 /* disable pll */ 1113 /* disable pll */
@@ -1056,6 +1117,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
1056 } 1117 }
1057 break; 1118 break;
1058 case SND_SOC_BIAS_OFF: 1119 case SND_SOC_BIAS_OFF:
1120 if (aic3x->power)
1121 aic3x_set_power(codec, 0);
1059 break; 1122 break;
1060 } 1123 }
1061 codec->bias_level = level; 1124 codec->bias_level = level;
@@ -1155,17 +1218,6 @@ static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state)
1155 1218
1156static int aic3x_resume(struct snd_soc_codec *codec) 1219static int aic3x_resume(struct snd_soc_codec *codec)
1157{ 1220{
1158 int i;
1159 u8 data[2];
1160 u8 *cache = codec->reg_cache;
1161
1162 /* Sync reg_cache with the hardware */
1163 for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++) {
1164 data[0] = i;
1165 data[1] = cache[i];
1166 codec->hw_write(codec->control_data, data, 2);
1167 }
1168
1169 aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1221 aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1170 1222
1171 return 0; 1223 return 0;
@@ -1247,13 +1299,7 @@ static int aic3x_init(struct snd_soc_codec *codec)
1247 snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); 1299 snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
1248 1300
1249 if (aic3x->model == AIC3X_MODEL_3007) { 1301 if (aic3x->model == AIC3X_MODEL_3007) {
1250 /* Class-D speaker driver init; datasheet p. 46 */ 1302 aic3x_init_3007(codec);
1251 snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D);
1252 snd_soc_write(codec, 0xD, 0x0D);
1253 snd_soc_write(codec, 0x8, 0x5C);
1254 snd_soc_write(codec, 0x8, 0x5D);
1255 snd_soc_write(codec, 0x8, 0x5C);
1256 snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00);
1257 snd_soc_write(codec, CLASSD_CTRL, 0); 1303 snd_soc_write(codec, CLASSD_CTRL, 0);
1258 } 1304 }
1259 1305
@@ -1299,6 +1345,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
1299 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); 1345 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
1300 goto err_enable; 1346 goto err_enable;
1301 } 1347 }
1348 aic3x->power = 1;
1302 1349
1303 if (aic3x->gpio_reset >= 0) { 1350 if (aic3x->gpio_reset >= 0) {
1304 udelay(1); 1351 udelay(1);