diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-04-26 16:29:29 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-04-27 13:42:11 -0400 |
commit | c340304dd8855a61a2e1bcdd5bde6b90408481a9 (patch) | |
tree | 720076a2eb7c4f6464851ddfa58b6aa66acbe6c5 /sound/soc/codecs/wm8994.c | |
parent | af31a227e1abee06ccd88c2c52f4fb36b786cebe (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.c | 91 |
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 | ||
948 | static void wm8994_update_class_w(struct snd_soc_codec *codec) | 948 | static 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 | ||
1009 | static int late_enable_ev(struct snd_soc_dapm_widget *w, | 986 | static 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 | ||
1123 | static 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 | |||
1135 | static 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 | |||
1150 | static const struct soc_enum hpl_enum = | ||
1151 | SOC_ENUM_SINGLE(WM8994_OUTPUT_MIXER_1, 8, 2, hp_mux_text); | ||
1152 | |||
1153 | static const struct snd_kcontrol_new hpl_mux = | ||
1154 | WM8994_HP_ENUM("Left Headphone Mux", hpl_enum); | ||
1155 | |||
1156 | static const struct soc_enum hpr_enum = | ||
1157 | SOC_ENUM_SINGLE(WM8994_OUTPUT_MIXER_2, 8, 2, hp_mux_text); | ||
1158 | |||
1159 | static const struct snd_kcontrol_new hpr_mux = | ||
1160 | WM8994_HP_ENUM("Right Headphone Mux", hpr_enum); | ||
1161 | |||
1162 | static const char *adc_mux_text[] = { | 1100 | static 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, | |||
1413 | SND_SOC_DAPM_MIXER_E("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, | 1351 | SND_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), |
1416 | SND_SOC_DAPM_MUX_E("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux, | 1354 | SND_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), |
1418 | SND_SOC_DAPM_MUX_E("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux, | 1356 | SND_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 | ||
1421 | SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) | 1359 | SND_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)), |
1430 | SND_SOC_DAPM_MIXER("SPKR", WM8994_POWER_MANAGEMENT_3, 9, 0, | 1368 | SND_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)), |
1432 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), | 1370 | SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpl_mux), |
1433 | SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), | 1371 | SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &wm_hubs_hpr_mux), |
1434 | }; | 1372 | }; |
1435 | 1373 | ||
1436 | static const struct snd_soc_dapm_widget wm8994_dac_revd_widgets[] = { | 1374 | static 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 | ||