aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/wm8993.c4
-rw-r--r--sound/soc/codecs/wm8994.c5
-rw-r--r--sound/soc/codecs/wm_hubs.c113
-rw-r--r--sound/soc/codecs/wm_hubs.h11
4 files changed, 125 insertions, 8 deletions
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index ab4685a8a570..1e69f63ede26 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1058,6 +1058,8 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
1058 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); 1058 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
1059 int ret; 1059 int ret;
1060 1060
1061 wm_hubs_set_bias_level(codec, level);
1062
1061 switch (level) { 1063 switch (level) {
1062 case SND_SOC_BIAS_ON: 1064 case SND_SOC_BIAS_ON:
1063 case SND_SOC_BIAS_PREPARE: 1065 case SND_SOC_BIAS_PREPARE:
@@ -1078,6 +1080,8 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
1078 regcache_cache_only(wm8993->regmap, false); 1080 regcache_cache_only(wm8993->regmap, false);
1079 regcache_sync(wm8993->regmap); 1081 regcache_sync(wm8993->regmap);
1080 1082
1083 wm_hubs_vmid_ena(codec);
1084
1081 /* Bring up VMID with fast soft start */ 1085 /* Bring up VMID with fast soft start */
1082 snd_soc_update_bits(codec, WM8993_ANTIPOP2, 1086 snd_soc_update_bits(codec, WM8993_ANTIPOP2,
1083 WM8993_STARTUP_BIAS_ENA | 1087 WM8993_STARTUP_BIAS_ENA |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index e6eebf747927..21931a0c7cea 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -787,6 +787,8 @@ static void vmid_reference(struct snd_soc_codec *codec)
787 WM8994_VMID_BUF_ENA | 787 WM8994_VMID_BUF_ENA |
788 (0x3 << WM8994_VMID_RAMP_SHIFT)); 788 (0x3 << WM8994_VMID_RAMP_SHIFT));
789 789
790 wm_hubs_vmid_ena(codec);
791
790 /* Remove discharge for line out */ 792 /* Remove discharge for line out */
791 snd_soc_update_bits(codec, WM8994_ANTIPOP_1, 793 snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
792 WM8994_LINEOUT1_DISCH | 794 WM8994_LINEOUT1_DISCH |
@@ -2074,6 +2076,8 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
2074 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 2076 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
2075 struct wm8994 *control = wm8994->wm8994; 2077 struct wm8994 *control = wm8994->wm8994;
2076 2078
2079 wm_hubs_set_bias_level(codec, level);
2080
2077 switch (level) { 2081 switch (level) {
2078 case SND_SOC_BIAS_ON: 2082 case SND_SOC_BIAS_ON:
2079 break; 2083 break;
@@ -2168,6 +2172,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
2168 wm8994->cur_fw = NULL; 2172 wm8994->cur_fw = NULL;
2169 break; 2173 break;
2170 } 2174 }
2175
2171 codec->dapm.bias_level = level; 2176 codec->dapm.bias_level = level;
2172 2177
2173 return 0; 2178 return 0;
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index a53daf64aa46..f7650c5cc5c2 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -500,6 +500,36 @@ static int earpiece_event(struct snd_soc_dapm_widget *w,
500 return 0; 500 return 0;
501} 501}
502 502
503static int lineout_event(struct snd_soc_dapm_widget *w,
504 struct snd_kcontrol *control, int event)
505{
506 struct snd_soc_codec *codec = w->codec;
507 struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
508 bool *flag;
509
510 switch (w->shift) {
511 case WM8993_LINEOUT1N_ENA_SHIFT:
512 flag = &hubs->lineout1n_ena;
513 break;
514 case WM8993_LINEOUT1P_ENA_SHIFT:
515 flag = &hubs->lineout1p_ena;
516 break;
517 case WM8993_LINEOUT2N_ENA_SHIFT:
518 flag = &hubs->lineout2n_ena;
519 break;
520 case WM8993_LINEOUT2P_ENA_SHIFT:
521 flag = &hubs->lineout2p_ena;
522 break;
523 default:
524 WARN(1, "Unknown line output");
525 return -EINVAL;
526 }
527
528 *flag = SND_SOC_DAPM_EVENT_ON(event);
529
530 return 0;
531}
532
503static const struct snd_kcontrol_new in1l_pga[] = { 533static const struct snd_kcontrol_new in1l_pga[] = {
504SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0), 534SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
505SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0), 535SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
@@ -675,14 +705,18 @@ SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
675SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0, 705SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
676 line2p_mix, ARRAY_SIZE(line2p_mix)), 706 line2p_mix, ARRAY_SIZE(line2p_mix)),
677 707
678SND_SOC_DAPM_OUT_DRV("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0, 708SND_SOC_DAPM_OUT_DRV_E("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
679 NULL, 0), 709 NULL, 0, lineout_event,
680SND_SOC_DAPM_OUT_DRV("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0, 710 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
681 NULL, 0), 711SND_SOC_DAPM_OUT_DRV_E("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
682SND_SOC_DAPM_OUT_DRV("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0, 712 NULL, 0, lineout_event,
683 NULL, 0), 713 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
684SND_SOC_DAPM_OUT_DRV("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0, 714SND_SOC_DAPM_OUT_DRV_E("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
685 NULL, 0), 715 NULL, 0, lineout_event,
716 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
717SND_SOC_DAPM_OUT_DRV_E("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
718 NULL, 0, lineout_event,
719 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
686 720
687SND_SOC_DAPM_OUTPUT("SPKOUTLP"), 721SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
688SND_SOC_DAPM_OUTPUT("SPKOUTLN"), 722SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
@@ -949,6 +983,11 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
949 int jd_scthr, int jd_thr, int micbias1_lvl, 983 int jd_scthr, int jd_thr, int micbias1_lvl,
950 int micbias2_lvl) 984 int micbias2_lvl)
951{ 985{
986 struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
987
988 hubs->lineout1_se = !lineout1_diff;
989 hubs->lineout2_se = !lineout2_diff;
990
952 if (!lineout1_diff) 991 if (!lineout1_diff)
953 snd_soc_update_bits(codec, WM8993_LINE_MIXER1, 992 snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
954 WM8993_LINEOUT1_MODE, 993 WM8993_LINEOUT1_MODE,
@@ -978,6 +1017,64 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
978} 1017}
979EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata); 1018EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata);
980 1019
1020void wm_hubs_vmid_ena(struct snd_soc_codec *codec)
1021{
1022 struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
1023 int val = 0;
1024
1025 if (hubs->lineout1_se)
1026 val |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA;
1027
1028 if (hubs->lineout2_se)
1029 val |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA;
1030
1031 /* Enable the line outputs while we power up */
1032 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3, val, val);
1033}
1034EXPORT_SYMBOL_GPL(wm_hubs_vmid_ena);
1035
1036void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
1037 enum snd_soc_bias_level level)
1038{
1039 struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
1040 int val;
1041
1042 switch (level) {
1043 case SND_SOC_BIAS_ON:
1044 /* Turn off any unneded single ended outputs */
1045 val = 0;
1046
1047 if (hubs->lineout1_se && hubs->lineout1n_ena)
1048 val |= WM8993_LINEOUT1N_ENA;
1049
1050 if (hubs->lineout1_se && hubs->lineout1p_ena)
1051 val |= WM8993_LINEOUT1P_ENA;
1052
1053 if (hubs->lineout2_se && hubs->lineout2n_ena)
1054 val |= WM8993_LINEOUT2N_ENA;
1055
1056 if (hubs->lineout2_se && hubs->lineout2p_ena)
1057 val |= WM8993_LINEOUT2P_ENA;
1058
1059 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3,
1060 WM8993_LINEOUT1N_ENA |
1061 WM8993_LINEOUT1P_ENA |
1062 WM8993_LINEOUT2N_ENA |
1063 WM8993_LINEOUT2P_ENA,
1064 val);
1065
1066 if (!hubs->lineout1n_ena && !hubs->lineout1p_ena &&
1067 !hubs->lineout2n_ena && !hubs->lineout2p_ena)
1068 snd_soc_update_bits(codec, WM8993_ANTIPOP1,
1069 WM8993_LINEOUT_VMID_BUF_ENA, 0);
1070 break;
1071
1072 default:
1073 break;
1074 }
1075}
1076EXPORT_SYMBOL_GPL(wm_hubs_set_bias_level);
1077
981MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); 1078MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
982MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 1079MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
983MODULE_LICENSE("GPL"); 1080MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index c674c7a502a6..4140905c7381 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -33,6 +33,14 @@ struct wm_hubs_data {
33 bool class_w; 33 bool class_w;
34 u16 class_w_dcs; 34 u16 class_w_dcs;
35 35
36 bool lineout1_se;
37 bool lineout1n_ena;
38 bool lineout1p_ena;
39
40 bool lineout2_se;
41 bool lineout2n_ena;
42 bool lineout2p_ena;
43
36 bool dcs_done_irq; 44 bool dcs_done_irq;
37 struct completion dcs_done; 45 struct completion dcs_done;
38}; 46};
@@ -46,5 +54,8 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *,
46 int micbias1_lvl, int micbias2_lvl); 54 int micbias1_lvl, int micbias2_lvl);
47 55
48extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); 56extern irqreturn_t wm_hubs_dcs_done(int irq, void *data);
57extern void wm_hubs_vmid_ena(struct snd_soc_codec *codec);
58extern void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
59 enum snd_soc_bias_level level);
49 60
50#endif 61#endif