diff options
| -rw-r--r-- | sound/soc/codecs/tlv320aic3x.c | 83 |
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 | ||
| 1032 | static 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 | |||
| 1055 | static 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 | } | ||
| 1086 | out: | ||
| 1087 | return ret; | ||
| 1088 | } | ||
| 1089 | |||
| 1031 | static int aic3x_set_bias_level(struct snd_soc_codec *codec, | 1090 | static 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 | ||
| 1156 | static int aic3x_resume(struct snd_soc_codec *codec) | 1219 | static 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); |
