diff options
-rw-r--r-- | sound/soc/codecs/wm8993.c | 4 | ||||
-rw-r--r-- | sound/soc/codecs/wm8994.c | 5 | ||||
-rw-r--r-- | sound/soc/codecs/wm_hubs.c | 113 | ||||
-rw-r--r-- | sound/soc/codecs/wm_hubs.h | 11 |
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 | ||
503 | static 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 | |||
503 | static const struct snd_kcontrol_new in1l_pga[] = { | 533 | static const struct snd_kcontrol_new in1l_pga[] = { |
504 | SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0), | 534 | SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0), |
505 | SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0), | 535 | SOC_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, | |||
675 | SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0, | 705 | SND_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 | ||
678 | SND_SOC_DAPM_OUT_DRV("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0, | 708 | SND_SOC_DAPM_OUT_DRV_E("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0, |
679 | NULL, 0), | 709 | NULL, 0, lineout_event, |
680 | SND_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), | 711 | SND_SOC_DAPM_OUT_DRV_E("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0, |
682 | SND_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), |
684 | SND_SOC_DAPM_OUT_DRV("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0, | 714 | SND_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), | ||
717 | SND_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 | ||
687 | SND_SOC_DAPM_OUTPUT("SPKOUTLP"), | 721 | SND_SOC_DAPM_OUTPUT("SPKOUTLP"), |
688 | SND_SOC_DAPM_OUTPUT("SPKOUTLN"), | 722 | SND_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 | } |
979 | EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata); | 1018 | EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata); |
980 | 1019 | ||
1020 | void 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 | } | ||
1034 | EXPORT_SYMBOL_GPL(wm_hubs_vmid_ena); | ||
1035 | |||
1036 | void 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 | } | ||
1076 | EXPORT_SYMBOL_GPL(wm_hubs_set_bias_level); | ||
1077 | |||
981 | MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); | 1078 | MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); |
982 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 1079 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
983 | MODULE_LICENSE("GPL"); | 1080 | MODULE_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 | ||
48 | extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); | 56 | extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); |
57 | extern void wm_hubs_vmid_ena(struct snd_soc_codec *codec); | ||
58 | extern void wm_hubs_set_bias_level(struct snd_soc_codec *codec, | ||
59 | enum snd_soc_bias_level level); | ||
49 | 60 | ||
50 | #endif | 61 | #endif |