aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8994.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-26 16:29:29 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-27 13:42:11 -0400
commitc340304dd8855a61a2e1bcdd5bde6b90408481a9 (patch)
tree720076a2eb7c4f6464851ddfa58b6aa66acbe6c5 /sound/soc/codecs/wm8994.c
parentaf31a227e1abee06ccd88c2c52f4fb36b786cebe (diff)
ASoC: wm_hubs: Factor out class W management
Since the analogue portions of the checks for class W are the same over all the devices factor out these checks into wm_hubs and while we're at it also use wm_hubs_dac_hp_direct() to enable class W optimisations on more paths. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r--sound/soc/codecs/wm8994.c91
1 files changed, 15 insertions, 76 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 2475e1c10334..d2db63022607 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -945,27 +945,12 @@ static int vmid_event(struct snd_soc_dapm_widget *w,
945 return 0; 945 return 0;
946} 946}
947 947
948static void wm8994_update_class_w(struct snd_soc_codec *codec) 948static bool wm8994_check_class_w_digital(struct snd_soc_codec *codec)
949{ 949{
950 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
951 int enable = 1;
952 int source = 0; /* GCC flow analysis can't track enable */ 950 int source = 0; /* GCC flow analysis can't track enable */
953 int reg, reg_r; 951 int reg, reg_r;
954 952
955 /* Only support direct DAC->headphone paths */ 953 /* We also need the same AIF source for L/R and only one path */
956 reg = snd_soc_read(codec, WM8994_OUTPUT_MIXER_1);
957 if (!(reg & WM8994_DAC1L_TO_HPOUT1L)) {
958 dev_vdbg(codec->dev, "HPL connected to output mixer\n");
959 enable = 0;
960 }
961
962 reg = snd_soc_read(codec, WM8994_OUTPUT_MIXER_2);
963 if (!(reg & WM8994_DAC1R_TO_HPOUT1R)) {
964 dev_vdbg(codec->dev, "HPR connected to output mixer\n");
965 enable = 0;
966 }
967
968 /* We also need the same setting for L/R and only one path */
969 reg = snd_soc_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING); 954 reg = snd_soc_read(codec, WM8994_DAC1_LEFT_MIXER_ROUTING);
970 switch (reg) { 955 switch (reg) {
971 case WM8994_AIF2DACL_TO_DAC1L: 956 case WM8994_AIF2DACL_TO_DAC1L:
@@ -982,28 +967,20 @@ static void wm8994_update_class_w(struct snd_soc_codec *codec)
982 break; 967 break;
983 default: 968 default:
984 dev_vdbg(codec->dev, "DAC mixer setting: %x\n", reg); 969 dev_vdbg(codec->dev, "DAC mixer setting: %x\n", reg);
985 enable = 0; 970 return false;
986 break;
987 } 971 }
988 972
989 reg_r = snd_soc_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING); 973 reg_r = snd_soc_read(codec, WM8994_DAC1_RIGHT_MIXER_ROUTING);
990 if (reg_r != reg) { 974 if (reg_r != reg) {
991 dev_vdbg(codec->dev, "Left and right DAC mixers different\n"); 975 dev_vdbg(codec->dev, "Left and right DAC mixers different\n");
992 enable = 0; 976 return false;
993 } 977 }
994 978
995 if (enable) { 979 /* Set the source up */
996 dev_dbg(codec->dev, "Class W enabled\n"); 980 snd_soc_update_bits(codec, WM8994_CLASS_W_1,
997 snd_soc_update_bits(codec, WM8994_CLASS_W_1, 981 WM8994_CP_DYN_SRC_SEL_MASK, source);
998 WM8994_CP_DYN_PWR |
999 WM8994_CP_DYN_SRC_SEL_MASK,
1000 source | WM8994_CP_DYN_PWR);
1001 982
1002 } else { 983 return true;
1003 dev_dbg(codec->dev, "Class W disabled\n");
1004 snd_soc_update_bits(codec, WM8994_CLASS_W_1,
1005 WM8994_CP_DYN_PWR, 0);
1006 }
1007} 984}
1008 985
1009static int late_enable_ev(struct snd_soc_dapm_widget *w, 986static int late_enable_ev(struct snd_soc_dapm_widget *w,
@@ -1120,45 +1097,6 @@ static int dac_ev(struct snd_soc_dapm_widget *w,
1120 return 0; 1097 return 0;
1121} 1098}
1122 1099
1123static const char *hp_mux_text[] = {
1124 "Mixer",
1125 "DAC",
1126};
1127
1128#define WM8994_HP_ENUM(xname, xenum) \
1129{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1130 .info = snd_soc_info_enum_double, \
1131 .get = snd_soc_dapm_get_enum_double, \
1132 .put = wm8994_put_hp_enum, \
1133 .private_value = (unsigned long)&xenum }
1134
1135static int wm8994_put_hp_enum(struct snd_kcontrol *kcontrol,
1136 struct snd_ctl_elem_value *ucontrol)
1137{
1138 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
1139 struct snd_soc_dapm_widget *w = wlist->widgets[0];
1140 struct snd_soc_codec *codec = w->codec;
1141 int ret;
1142
1143 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
1144
1145 wm8994_update_class_w(codec);
1146
1147 return ret;
1148}
1149
1150static const struct soc_enum hpl_enum =
1151 SOC_ENUM_SINGLE(WM8994_OUTPUT_MIXER_1, 8, 2, hp_mux_text);
1152
1153static const struct snd_kcontrol_new hpl_mux =
1154 WM8994_HP_ENUM("Left Headphone Mux", hpl_enum);
1155
1156static const struct soc_enum hpr_enum =
1157 SOC_ENUM_SINGLE(WM8994_OUTPUT_MIXER_2, 8, 2, hp_mux_text);
1158
1159static const struct snd_kcontrol_new hpr_mux =
1160 WM8994_HP_ENUM("Right Headphone Mux", hpr_enum);
1161
1162static const char *adc_mux_text[] = { 1100static const char *adc_mux_text[] = {
1163 "ADC", 1101 "ADC",
1164 "DMIC", 1102 "DMIC",
@@ -1270,7 +1208,7 @@ static int wm8994_put_class_w(struct snd_kcontrol *kcontrol,
1270 1208
1271 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); 1209 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
1272 1210
1273 wm8994_update_class_w(codec); 1211 wm_hubs_update_class_w(codec);
1274 1212
1275 return ret; 1213 return ret;
1276} 1214}
@@ -1413,9 +1351,9 @@ SND_SOC_DAPM_MIXER_E("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
1413SND_SOC_DAPM_MIXER_E("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, 1351SND_SOC_DAPM_MIXER_E("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
1414 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer), 1352 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer),
1415 late_enable_ev, SND_SOC_DAPM_PRE_PMU), 1353 late_enable_ev, SND_SOC_DAPM_PRE_PMU),
1416SND_SOC_DAPM_MUX_E("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux, 1354SND_SOC_DAPM_MUX_E("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpl_mux,
1417 late_enable_ev, SND_SOC_DAPM_PRE_PMU), 1355 late_enable_ev, SND_SOC_DAPM_PRE_PMU),
1418SND_SOC_DAPM_MUX_E("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux, 1356SND_SOC_DAPM_MUX_E("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpr_mux,
1419 late_enable_ev, SND_SOC_DAPM_PRE_PMU), 1357 late_enable_ev, SND_SOC_DAPM_PRE_PMU),
1420 1358
1421SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) 1359SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev)
@@ -1429,8 +1367,8 @@ SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
1429 left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), 1367 left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
1430SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, 1368SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0,
1431 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), 1369 right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
1432SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), 1370SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpl_mux),
1433SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), 1371SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpr_mux),
1434}; 1372};
1435 1373
1436static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = { 1374static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = {
@@ -3829,7 +3767,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3829 break; 3767 break;
3830 } 3768 }
3831 3769
3832 wm8994_update_class_w(codec); 3770 wm8994->hubs.check_class_w_digital = wm8994_check_class_w_digital;
3771 wm_hubs_update_class_w(codec);
3833 3772
3834 wm8994_handle_pdata(wm8994); 3773 wm8994_handle_pdata(wm8994);
3835 3774