aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8904.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-02-03 14:51:33 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-02-04 05:42:21 -0500
commite4bc669610d75106a00b0f96f2410ac5898ef1ca (patch)
tree3ccf94cde511c01c464f2355e19e279c5049442d /sound/soc/codecs/wm8904.c
parentc133421800d9d1dfec0c98de6c9da0a7a99e0573 (diff)
ASoC: Optimise WM8904 output stage power control
Handle the output PGAs as part of the output powerup since they can never be powered separately and reorder things so that we remove the output shorts after both line and headphone outputs have been brought up, minimising the opportunity for any issues. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/codecs/wm8904.c')
-rw-r--r--sound/soc/codecs/wm8904.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index dc782c43a7cb..80dd8df0b864 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -979,6 +979,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
979 int dcs_l, dcs_r; 979 int dcs_l, dcs_r;
980 int dcs_l_reg, dcs_r_reg; 980 int dcs_l_reg, dcs_r_reg;
981 int timeout; 981 int timeout;
982 int pwr_reg;
982 983
983 /* This code is shared between HP and LINEOUT; we do all our 984 /* This code is shared between HP and LINEOUT; we do all our
984 * power management in stereo pairs to avoid latency issues so 985 * power management in stereo pairs to avoid latency issues so
@@ -988,6 +989,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
988 989
989 switch (reg) { 990 switch (reg) {
990 case WM8904_ANALOGUE_HP_0: 991 case WM8904_ANALOGUE_HP_0:
992 pwr_reg = WM8904_POWER_MANAGEMENT_2;
991 dcs_mask = WM8904_DCS_ENA_CHAN_0 | WM8904_DCS_ENA_CHAN_1; 993 dcs_mask = WM8904_DCS_ENA_CHAN_0 | WM8904_DCS_ENA_CHAN_1;
992 dcs_r_reg = WM8904_DC_SERVO_8; 994 dcs_r_reg = WM8904_DC_SERVO_8;
993 dcs_l_reg = WM8904_DC_SERVO_9; 995 dcs_l_reg = WM8904_DC_SERVO_9;
@@ -995,6 +997,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
995 dcs_r = 1; 997 dcs_r = 1;
996 break; 998 break;
997 case WM8904_ANALOGUE_LINEOUT_0: 999 case WM8904_ANALOGUE_LINEOUT_0:
1000 pwr_reg = WM8904_POWER_MANAGEMENT_3;
998 dcs_mask = WM8904_DCS_ENA_CHAN_2 | WM8904_DCS_ENA_CHAN_3; 1001 dcs_mask = WM8904_DCS_ENA_CHAN_2 | WM8904_DCS_ENA_CHAN_3;
999 dcs_r_reg = WM8904_DC_SERVO_6; 1002 dcs_r_reg = WM8904_DC_SERVO_6;
1000 dcs_l_reg = WM8904_DC_SERVO_7; 1003 dcs_l_reg = WM8904_DC_SERVO_7;
@@ -1007,12 +1010,18 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
1007 } 1010 }
1008 1011
1009 switch (event) { 1012 switch (event) {
1010 case SND_SOC_DAPM_POST_PMU: 1013 case SND_SOC_DAPM_PRE_PMU:
1014 /* Power on the PGAs */
1015 snd_soc_update_bits(codec, pwr_reg,
1016 WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA,
1017 WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA);
1018
1011 /* Power on the amplifier */ 1019 /* Power on the amplifier */
1012 snd_soc_update_bits(codec, reg, 1020 snd_soc_update_bits(codec, reg,
1013 WM8904_HPL_ENA | WM8904_HPR_ENA, 1021 WM8904_HPL_ENA | WM8904_HPR_ENA,
1014 WM8904_HPL_ENA | WM8904_HPR_ENA); 1022 WM8904_HPL_ENA | WM8904_HPR_ENA);
1015 1023
1024
1016 /* Enable the first stage */ 1025 /* Enable the first stage */
1017 snd_soc_update_bits(codec, reg, 1026 snd_soc_update_bits(codec, reg,
1018 WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY, 1027 WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY,
@@ -1064,7 +1073,9 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
1064 snd_soc_update_bits(codec, reg, 1073 snd_soc_update_bits(codec, reg,
1065 WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP, 1074 WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP,
1066 WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP); 1075 WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP);
1076 break;
1067 1077
1078 case SND_SOC_DAPM_POST_PMU:
1068 /* Unshort the output itself */ 1079 /* Unshort the output itself */
1069 snd_soc_update_bits(codec, reg, 1080 snd_soc_update_bits(codec, reg,
1070 WM8904_HPL_RMV_SHORT | 1081 WM8904_HPL_RMV_SHORT |
@@ -1079,7 +1090,9 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
1079 snd_soc_update_bits(codec, reg, 1090 snd_soc_update_bits(codec, reg,
1080 WM8904_HPL_RMV_SHORT | 1091 WM8904_HPL_RMV_SHORT |
1081 WM8904_HPR_RMV_SHORT, 0); 1092 WM8904_HPR_RMV_SHORT, 0);
1093 break;
1082 1094
1095 case SND_SOC_DAPM_POST_PMD:
1083 /* Cache the DC servo configuration; this will be 1096 /* Cache the DC servo configuration; this will be
1084 * invalidated if we change the configuration. */ 1097 * invalidated if we change the configuration. */
1085 wm8904->dcs_state[dcs_l] = snd_soc_read(codec, dcs_l_reg); 1098 wm8904->dcs_state[dcs_l] = snd_soc_read(codec, dcs_l_reg);
@@ -1094,6 +1107,11 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
1094 WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY | 1107 WM8904_HPL_ENA_DLY | WM8904_HPR_ENA_DLY |
1095 WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP, 1108 WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP,
1096 0); 1109 0);
1110
1111 /* PGAs too */
1112 snd_soc_update_bits(codec, pwr_reg,
1113 WM8904_HPL_PGA_ENA | WM8904_HPR_PGA_ENA,
1114 0);
1097 break; 1115 break;
1098 } 1116 }
1099 1117
@@ -1212,18 +1230,20 @@ SND_SOC_DAPM_DAC("DACR", NULL, WM8904_POWER_MANAGEMENT_6, 2, 0),
1212SND_SOC_DAPM_SUPPLY("Charge pump", WM8904_CHARGE_PUMP_0, 0, 0, cp_event, 1230SND_SOC_DAPM_SUPPLY("Charge pump", WM8904_CHARGE_PUMP_0, 0, 0, cp_event,
1213 SND_SOC_DAPM_POST_PMU), 1231 SND_SOC_DAPM_POST_PMU),
1214 1232
1215SND_SOC_DAPM_PGA("HPL PGA", WM8904_POWER_MANAGEMENT_2, 1, 0, NULL, 0), 1233SND_SOC_DAPM_PGA("HPL PGA", SND_SOC_NOPM, 1, 0, NULL, 0),
1216SND_SOC_DAPM_PGA("HPR PGA", WM8904_POWER_MANAGEMENT_2, 0, 0, NULL, 0), 1234SND_SOC_DAPM_PGA("HPR PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
1217 1235
1218SND_SOC_DAPM_PGA("LINEL PGA", WM8904_POWER_MANAGEMENT_3, 1, 0, NULL, 0), 1236SND_SOC_DAPM_PGA("LINEL PGA", SND_SOC_NOPM, 1, 0, NULL, 0),
1219SND_SOC_DAPM_PGA("LINER PGA", WM8904_POWER_MANAGEMENT_3, 0, 0, NULL, 0), 1237SND_SOC_DAPM_PGA("LINER PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
1220 1238
1221SND_SOC_DAPM_PGA_E("Headphone Output", SND_SOC_NOPM, WM8904_ANALOGUE_HP_0, 1239SND_SOC_DAPM_PGA_E("Headphone Output", SND_SOC_NOPM, WM8904_ANALOGUE_HP_0,
1222 0, NULL, 0, out_pga_event, 1240 0, NULL, 0, out_pga_event,
1223 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 1241 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
1242 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
1224SND_SOC_DAPM_PGA_E("Line Output", SND_SOC_NOPM, WM8904_ANALOGUE_LINEOUT_0, 1243SND_SOC_DAPM_PGA_E("Line Output", SND_SOC_NOPM, WM8904_ANALOGUE_LINEOUT_0,
1225 0, NULL, 0, out_pga_event, 1244 0, NULL, 0, out_pga_event,
1226 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 1245 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
1246 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
1227 1247
1228SND_SOC_DAPM_OUTPUT("HPOUTL"), 1248SND_SOC_DAPM_OUTPUT("HPOUTL"),
1229SND_SOC_DAPM_OUTPUT("HPOUTR"), 1249SND_SOC_DAPM_OUTPUT("HPOUTR"),