aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-03-19 13:32:06 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-03-19 15:08:17 -0400
commit22f8d055350066b4a87de4adea8c5213cac54534 (patch)
tree229a761bb0e5c4a9ee27db3d327bbd11905b9c96 /sound
parent6f8270cc9a43d767676c97df5773fdcede312a88 (diff)
ASoC: wm8994: Provide VMID mode control and fix default sequence
The optimal management of VMID depends on a number of factors which vary dynamically at runtime, for example the connection to a system docking station. In some circumstances it is desirable to keep VMID enabled all the time, in others it is desirable to aggressively power it up and down. Provide a callback allowing machine driver to configure either the normal power up/down mode (WM8994_VMID_MODE_NORMAL) or to maintain VMID even when idle (WM8994_VMID_MODE_FORCE). This callback, wm8994_vmid_mode(), should be called with the CODEC lock. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/wm8994.c186
-rw-r--r--sound/soc/codecs/wm8994.h8
2 files changed, 155 insertions, 39 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index b7f3cfc74e98..9685dff44dd8 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -777,36 +777,68 @@ static void vmid_reference(struct snd_soc_codec *codec)
777 777
778 if (wm8994->vmid_refcount == 1) { 778 if (wm8994->vmid_refcount == 1) {
779 snd_soc_update_bits(codec, WM8994_ANTIPOP_1, 779 snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
780 WM8994_LINEOUT_VMID_BUF_ENA |
781 WM8994_LINEOUT1_DISCH | 780 WM8994_LINEOUT1_DISCH |
782 WM8994_LINEOUT2_DISCH, 781 WM8994_LINEOUT2_DISCH, 0);
783 WM8994_LINEOUT_VMID_BUF_ENA);
784 782
785 wm_hubs_vmid_ena(codec); 783 wm_hubs_vmid_ena(codec);
786 784
787 /* Startup bias, VMID ramp & buffer */ 785 switch (wm8994->vmid_mode) {
788 snd_soc_update_bits(codec, WM8994_ANTIPOP_2, 786 default:
789 WM8994_BIAS_SRC | 787 WARN_ON(0 == "Invalid VMID mode");
790 WM8994_VMID_DISCH | 788 case WM8994_VMID_NORMAL:
791 WM8994_STARTUP_BIAS_ENA | 789 /* Startup bias, VMID ramp & buffer */
792 WM8994_VMID_BUF_ENA | 790 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
793 WM8994_VMID_RAMP_MASK, 791 WM8994_BIAS_SRC |
794 WM8994_BIAS_SRC | 792 WM8994_VMID_DISCH |
795 WM8994_STARTUP_BIAS_ENA | 793 WM8994_STARTUP_BIAS_ENA |
796 WM8994_VMID_BUF_ENA | 794 WM8994_VMID_BUF_ENA |
797 (0x2 << WM8994_VMID_RAMP_SHIFT)); 795 WM8994_VMID_RAMP_MASK,
796 WM8994_BIAS_SRC |
797 WM8994_STARTUP_BIAS_ENA |
798 WM8994_VMID_BUF_ENA |
799 (0x3 << WM8994_VMID_RAMP_SHIFT));
800
801 /* Main bias enable, VMID=2x40k */
802 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
803 WM8994_BIAS_ENA |
804 WM8994_VMID_SEL_MASK,
805 WM8994_BIAS_ENA | 0x2);
806
807 msleep(50);
798 808
799 /* Main bias enable, VMID=2x40k */ 809 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
800 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, 810 WM8994_VMID_RAMP_MASK |
801 WM8994_BIAS_ENA | 811 WM8994_BIAS_SRC,
802 WM8994_VMID_SEL_MASK, 812 0);
803 WM8994_BIAS_ENA | 0x2); 813 break;
804 814
805 msleep(50); 815 case WM8994_VMID_FORCE:
816 /* Startup bias, slow VMID ramp & buffer */
817 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
818 WM8994_BIAS_SRC |
819 WM8994_VMID_DISCH |
820 WM8994_STARTUP_BIAS_ENA |
821 WM8994_VMID_BUF_ENA |
822 WM8994_VMID_RAMP_MASK,
823 WM8994_BIAS_SRC |
824 WM8994_STARTUP_BIAS_ENA |
825 WM8994_VMID_BUF_ENA |
826 (0x2 << WM8994_VMID_RAMP_SHIFT));
827
828 /* Main bias enable, VMID=2x40k */
829 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
830 WM8994_BIAS_ENA |
831 WM8994_VMID_SEL_MASK,
832 WM8994_BIAS_ENA | 0x2);
833
834 msleep(400);
806 835
807 snd_soc_update_bits(codec, WM8994_ANTIPOP_2, 836 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
808 WM8994_VMID_RAMP_MASK | WM8994_BIAS_SRC, 837 WM8994_VMID_RAMP_MASK |
809 0); 838 WM8994_BIAS_SRC,
839 0);
840 break;
841 }
810 } 842 }
811} 843}
812 844
@@ -820,34 +852,55 @@ static void vmid_dereference(struct snd_soc_codec *codec)
820 wm8994->vmid_refcount); 852 wm8994->vmid_refcount);
821 853
822 if (wm8994->vmid_refcount == 0) { 854 if (wm8994->vmid_refcount == 0) {
823 /* Switch over to startup biases */ 855 if (wm8994->hubs.lineout1_se)
856 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
857 WM8994_LINEOUT1N_ENA |
858 WM8994_LINEOUT1P_ENA,
859 WM8994_LINEOUT1N_ENA |
860 WM8994_LINEOUT1P_ENA);
861
862 if (wm8994->hubs.lineout2_se)
863 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
864 WM8994_LINEOUT2N_ENA |
865 WM8994_LINEOUT2P_ENA,
866 WM8994_LINEOUT2N_ENA |
867 WM8994_LINEOUT2P_ENA);
868
869 /* Start discharging VMID */
824 snd_soc_update_bits(codec, WM8994_ANTIPOP_2, 870 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
825 WM8994_BIAS_SRC | 871 WM8994_BIAS_SRC |
826 WM8994_STARTUP_BIAS_ENA | 872 WM8994_VMID_DISCH,
827 WM8994_VMID_BUF_ENA |
828 WM8994_VMID_RAMP_MASK,
829 WM8994_BIAS_SRC | 873 WM8994_BIAS_SRC |
830 WM8994_STARTUP_BIAS_ENA | 874 WM8994_VMID_DISCH);
831 WM8994_VMID_BUF_ENA |
832 (1 << WM8994_VMID_RAMP_SHIFT));
833 875
834 /* Disable main biases */ 876 switch (wm8994->vmid_mode) {
835 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, 877 case WM8994_VMID_FORCE:
836 WM8994_BIAS_ENA | 878 msleep(350);
837 WM8994_VMID_SEL_MASK, 0); 879 break;
880 default:
881 break;
882 }
838 883
839 /* Discharge VMID */ 884 snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
840 snd_soc_update_bits(codec, WM8994_ANTIPOP_2, 885 WM8994_VROI, WM8994_VROI);
841 WM8994_VMID_DISCH, WM8994_VMID_DISCH);
842 886
843 /* Discharge line */ 887 /* Active discharge */
844 snd_soc_update_bits(codec, WM8994_ANTIPOP_1, 888 snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
845 WM8994_LINEOUT1_DISCH | 889 WM8994_LINEOUT1_DISCH |
846 WM8994_LINEOUT2_DISCH, 890 WM8994_LINEOUT2_DISCH,
847 WM8994_LINEOUT1_DISCH | 891 WM8994_LINEOUT1_DISCH |
848 WM8994_LINEOUT2_DISCH); 892 WM8994_LINEOUT2_DISCH);
849 893
850 msleep(5); 894 msleep(150);
895
896 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
897 WM8994_LINEOUT1N_ENA |
898 WM8994_LINEOUT1P_ENA |
899 WM8994_LINEOUT2N_ENA |
900 WM8994_LINEOUT2P_ENA, 0);
901
902 snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
903 WM8994_VROI, 0);
851 904
852 /* Switch off startup biases */ 905 /* Switch off startup biases */
853 snd_soc_update_bits(codec, WM8994_ANTIPOP_2, 906 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
@@ -855,6 +908,12 @@ static void vmid_dereference(struct snd_soc_codec *codec)
855 WM8994_STARTUP_BIAS_ENA | 908 WM8994_STARTUP_BIAS_ENA |
856 WM8994_VMID_BUF_ENA | 909 WM8994_VMID_BUF_ENA |
857 WM8994_VMID_RAMP_MASK, 0); 910 WM8994_VMID_RAMP_MASK, 0);
911
912 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
913 WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
914
915 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
916 WM8994_VMID_RAMP_MASK, 0);
858 } 917 }
859 918
860 pm_runtime_put(codec->dev); 919 pm_runtime_put(codec->dev);
@@ -2197,6 +2256,55 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
2197 return 0; 2256 return 0;
2198} 2257}
2199 2258
2259int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode)
2260{
2261 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
2262
2263 switch (mode) {
2264 case WM8994_VMID_NORMAL:
2265 if (wm8994->hubs.lineout1_se) {
2266 snd_soc_dapm_disable_pin(&codec->dapm,
2267 "LINEOUT1N Driver");
2268 snd_soc_dapm_disable_pin(&codec->dapm,
2269 "LINEOUT1P Driver");
2270 }
2271 if (wm8994->hubs.lineout2_se) {
2272 snd_soc_dapm_disable_pin(&codec->dapm,
2273 "LINEOUT2N Driver");
2274 snd_soc_dapm_disable_pin(&codec->dapm,
2275 "LINEOUT2P Driver");
2276 }
2277
2278 /* Do the sync with the old mode to allow it to clean up */
2279 snd_soc_dapm_sync(&codec->dapm);
2280 wm8994->vmid_mode = mode;
2281 break;
2282
2283 case WM8994_VMID_FORCE:
2284 if (wm8994->hubs.lineout1_se) {
2285 snd_soc_dapm_force_enable_pin(&codec->dapm,
2286 "LINEOUT1N Driver");
2287 snd_soc_dapm_force_enable_pin(&codec->dapm,
2288 "LINEOUT1P Driver");
2289 }
2290 if (wm8994->hubs.lineout2_se) {
2291 snd_soc_dapm_force_enable_pin(&codec->dapm,
2292 "LINEOUT2N Driver");
2293 snd_soc_dapm_force_enable_pin(&codec->dapm,
2294 "LINEOUT2P Driver");
2295 }
2296
2297 wm8994->vmid_mode = mode;
2298 snd_soc_dapm_sync(&codec->dapm);
2299 break;
2300
2301 default:
2302 return -EINVAL;
2303 }
2304
2305 return 0;
2306}
2307
2200static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) 2308static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2201{ 2309{
2202 struct snd_soc_codec *codec = dai->codec; 2310 struct snd_soc_codec *codec = dai->codec;
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 2f4d2d12a452..c724112998d8 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -32,6 +32,11 @@
32#define WM8994_FLL_SRC_LRCLK 3 32#define WM8994_FLL_SRC_LRCLK 3
33#define WM8994_FLL_SRC_BCLK 4 33#define WM8994_FLL_SRC_BCLK 4
34 34
35enum wm8994_vmid_mode {
36 WM8994_VMID_NORMAL,
37 WM8994_VMID_FORCE,
38};
39
35typedef void (*wm8958_micdet_cb)(u16 status, void *data); 40typedef void (*wm8958_micdet_cb)(u16 status, void *data);
36 41
37int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, 42int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
@@ -39,6 +44,8 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
39int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, 44int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
40 wm8958_micdet_cb cb, void *cb_data); 45 wm8958_micdet_cb cb, void *cb_data);
41 46
47int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode);
48
42int wm8958_aif_ev(struct snd_soc_dapm_widget *w, 49int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
43 struct snd_kcontrol *kcontrol, int event); 50 struct snd_kcontrol *kcontrol, int event);
44 51
@@ -75,6 +82,7 @@ struct wm8994_priv {
75 82
76 int vmid_refcount; 83 int vmid_refcount;
77 int active_refcount; 84 int active_refcount;
85 enum wm8994_vmid_mode vmid_mode;
78 86
79 int dac_rates[2]; 87 int dac_rates[2];
80 int lrclk_shared[2]; 88 int lrclk_shared[2];