diff options
Diffstat (limited to 'sound/soc/codecs/wm8996.c')
-rw-r--r-- | sound/soc/codecs/wm8996.c | 253 |
1 files changed, 110 insertions, 143 deletions
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 61f7daa4d0e6..1fd635494045 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -73,7 +73,6 @@ struct wm8996_priv { | |||
73 | 73 | ||
74 | struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES]; | 74 | struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES]; |
75 | struct notifier_block disable_nb[WM8996_NUM_SUPPLIES]; | 75 | struct notifier_block disable_nb[WM8996_NUM_SUPPLIES]; |
76 | struct regulator *cpvdd; | ||
77 | int bg_ena; | 76 | int bg_ena; |
78 | 77 | ||
79 | struct wm8996_pdata pdata; | 78 | struct wm8996_pdata pdata; |
@@ -90,6 +89,7 @@ struct wm8996_priv { | |||
90 | struct snd_soc_jack *jack; | 89 | struct snd_soc_jack *jack; |
91 | bool detecting; | 90 | bool detecting; |
92 | bool jack_mic; | 91 | bool jack_mic; |
92 | int jack_flips; | ||
93 | wm8996_polarity_fn polarity_cb; | 93 | wm8996_polarity_fn polarity_cb; |
94 | 94 | ||
95 | #ifdef CONFIG_GPIOLIB | 95 | #ifdef CONFIG_GPIOLIB |
@@ -118,7 +118,6 @@ WM8996_REGULATOR_EVENT(1) | |||
118 | WM8996_REGULATOR_EVENT(2) | 118 | WM8996_REGULATOR_EVENT(2) |
119 | 119 | ||
120 | static struct reg_default wm8996_reg[] = { | 120 | static struct reg_default wm8996_reg[] = { |
121 | { WM8996_SOFTWARE_RESET, 0x8996 }, | ||
122 | { WM8996_POWER_MANAGEMENT_1, 0x0 }, | 121 | { WM8996_POWER_MANAGEMENT_1, 0x0 }, |
123 | { WM8996_POWER_MANAGEMENT_2, 0x0 }, | 122 | { WM8996_POWER_MANAGEMENT_2, 0x0 }, |
124 | { WM8996_POWER_MANAGEMENT_3, 0x0 }, | 123 | { WM8996_POWER_MANAGEMENT_3, 0x0 }, |
@@ -153,7 +152,6 @@ static struct reg_default wm8996_reg[] = { | |||
153 | { WM8996_CHARGE_PUMP_1, 0x1f25 }, | 152 | { WM8996_CHARGE_PUMP_1, 0x1f25 }, |
154 | { WM8996_CHARGE_PUMP_2, 0xab19 }, | 153 | { WM8996_CHARGE_PUMP_2, 0xab19 }, |
155 | { WM8996_DC_SERVO_1, 0x0 }, | 154 | { WM8996_DC_SERVO_1, 0x0 }, |
156 | { WM8996_DC_SERVO_2, 0x0 }, | ||
157 | { WM8996_DC_SERVO_3, 0x0 }, | 155 | { WM8996_DC_SERVO_3, 0x0 }, |
158 | { WM8996_DC_SERVO_5, 0x2a2a }, | 156 | { WM8996_DC_SERVO_5, 0x2a2a }, |
159 | { WM8996_DC_SERVO_6, 0x0 }, | 157 | { WM8996_DC_SERVO_6, 0x0 }, |
@@ -716,10 +714,16 @@ SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0), | |||
716 | SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0), | 714 | SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0), |
717 | SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0), | 715 | SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0), |
718 | SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0), | 716 | SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0), |
717 | SND_SOC_BYTES_MASK("DSP1 DRC", WM8996_DSP1_DRC_1, 5, | ||
718 | WM8996_DSP1RX_DRC_ENA | WM8996_DSP1TXL_DRC_ENA | | ||
719 | WM8996_DSP1TXR_DRC_ENA), | ||
719 | 720 | ||
720 | SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0), | 721 | SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0), |
721 | SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0), | 722 | SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0), |
722 | SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0), | 723 | SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0), |
724 | SND_SOC_BYTES_MASK("DSP2 DRC", WM8996_DSP2_DRC_1, 5, | ||
725 | WM8996_DSP2RX_DRC_ENA | WM8996_DSP2TXL_DRC_ENA | | ||
726 | WM8996_DSP2TXR_DRC_ENA), | ||
723 | }; | 727 | }; |
724 | 728 | ||
725 | static const struct snd_kcontrol_new wm8996_eq_controls[] = { | 729 | static const struct snd_kcontrol_new wm8996_eq_controls[] = { |
@@ -792,29 +796,18 @@ static int bg_event(struct snd_soc_dapm_widget *w, | |||
792 | static int cp_event(struct snd_soc_dapm_widget *w, | 796 | static int cp_event(struct snd_soc_dapm_widget *w, |
793 | struct snd_kcontrol *kcontrol, int event) | 797 | struct snd_kcontrol *kcontrol, int event) |
794 | { | 798 | { |
795 | struct snd_soc_codec *codec = w->codec; | ||
796 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
797 | int ret = 0; | 799 | int ret = 0; |
798 | 800 | ||
799 | switch (event) { | 801 | switch (event) { |
800 | case SND_SOC_DAPM_PRE_PMU: | ||
801 | ret = regulator_enable(wm8996->cpvdd); | ||
802 | if (ret != 0) | ||
803 | dev_err(codec->dev, "Failed to enable CPVDD: %d\n", | ||
804 | ret); | ||
805 | break; | ||
806 | case SND_SOC_DAPM_POST_PMU: | 802 | case SND_SOC_DAPM_POST_PMU: |
807 | msleep(5); | 803 | msleep(5); |
808 | break; | 804 | break; |
809 | case SND_SOC_DAPM_POST_PMD: | ||
810 | regulator_disable_deferred(wm8996->cpvdd, 20); | ||
811 | break; | ||
812 | default: | 805 | default: |
813 | BUG(); | 806 | BUG(); |
814 | ret = -EINVAL; | 807 | ret = -EINVAL; |
815 | } | 808 | } |
816 | 809 | ||
817 | return ret; | 810 | return 0; |
818 | } | 811 | } |
819 | 812 | ||
820 | static int rmv_short_event(struct snd_soc_dapm_widget *w, | 813 | static int rmv_short_event(struct snd_soc_dapm_widget *w, |
@@ -897,8 +890,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm, | |||
897 | val = 0; | 890 | val = 0; |
898 | mask = 0; | 891 | mask = 0; |
899 | if (wm8996->hpout_pending & HPOUT1L) { | 892 | if (wm8996->hpout_pending & HPOUT1L) { |
900 | val |= WM8996_HPOUT1L_RMV_SHORT; | 893 | val |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP; |
901 | mask |= WM8996_HPOUT1L_RMV_SHORT; | 894 | mask |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP; |
902 | } else { | 895 | } else { |
903 | mask |= WM8996_HPOUT1L_RMV_SHORT | | 896 | mask |= WM8996_HPOUT1L_RMV_SHORT | |
904 | WM8996_HPOUT1L_OUTP | | 897 | WM8996_HPOUT1L_OUTP | |
@@ -906,8 +899,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm, | |||
906 | } | 899 | } |
907 | 900 | ||
908 | if (wm8996->hpout_pending & HPOUT1R) { | 901 | if (wm8996->hpout_pending & HPOUT1R) { |
909 | val |= WM8996_HPOUT1R_RMV_SHORT; | 902 | val |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP; |
910 | mask |= WM8996_HPOUT1R_RMV_SHORT; | 903 | mask |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP; |
911 | } else { | 904 | } else { |
912 | mask |= WM8996_HPOUT1R_RMV_SHORT | | 905 | mask |= WM8996_HPOUT1R_RMV_SHORT | |
913 | WM8996_HPOUT1R_OUTP | | 906 | WM8996_HPOUT1R_OUTP | |
@@ -919,8 +912,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm, | |||
919 | val = 0; | 912 | val = 0; |
920 | mask = 0; | 913 | mask = 0; |
921 | if (wm8996->hpout_pending & HPOUT2L) { | 914 | if (wm8996->hpout_pending & HPOUT2L) { |
922 | val |= WM8996_HPOUT2L_RMV_SHORT; | 915 | val |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP; |
923 | mask |= WM8996_HPOUT2L_RMV_SHORT; | 916 | mask |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP; |
924 | } else { | 917 | } else { |
925 | mask |= WM8996_HPOUT2L_RMV_SHORT | | 918 | mask |= WM8996_HPOUT2L_RMV_SHORT | |
926 | WM8996_HPOUT2L_OUTP | | 919 | WM8996_HPOUT2L_OUTP | |
@@ -928,8 +921,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm, | |||
928 | } | 921 | } |
929 | 922 | ||
930 | if (wm8996->hpout_pending & HPOUT2R) { | 923 | if (wm8996->hpout_pending & HPOUT2R) { |
931 | val |= WM8996_HPOUT2R_RMV_SHORT; | 924 | val |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP; |
932 | mask |= WM8996_HPOUT2R_RMV_SHORT; | 925 | mask |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP; |
933 | } else { | 926 | } else { |
934 | mask |= WM8996_HPOUT2R_RMV_SHORT | | 927 | mask |= WM8996_HPOUT2R_RMV_SHORT | |
935 | WM8996_HPOUT2R_OUTP | | 928 | WM8996_HPOUT2R_OUTP | |
@@ -1116,12 +1109,12 @@ SND_SOC_DAPM_INPUT("IN2RP"), | |||
1116 | SND_SOC_DAPM_INPUT("DMIC1DAT"), | 1109 | SND_SOC_DAPM_INPUT("DMIC1DAT"), |
1117 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | 1110 | SND_SOC_DAPM_INPUT("DMIC2DAT"), |
1118 | 1111 | ||
1112 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | ||
1119 | SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), | 1113 | SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), |
1120 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), | 1114 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), |
1121 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), | 1115 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), |
1122 | SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, | 1116 | SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, |
1123 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 1117 | SND_SOC_DAPM_POST_PMU), |
1124 | SND_SOC_DAPM_POST_PMD), | ||
1125 | SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event, | 1118 | SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event, |
1126 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | 1119 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1127 | SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), | 1120 | SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), |
@@ -1180,41 +1173,25 @@ SND_SOC_DAPM_DAC("DAC2R", NULL, WM8996_POWER_MANAGEMENT_5, 2, 0), | |||
1180 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0), | 1173 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0), |
1181 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0), | 1174 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0), |
1182 | 1175 | ||
1183 | SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0, | 1176 | SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, WM8996_POWER_MANAGEMENT_4, 9, 0), |
1184 | WM8996_POWER_MANAGEMENT_4, 9, 0), | 1177 | SND_SOC_DAPM_AIF_IN("AIF2RX0", NULL, 1, WM8996_POWER_MANAGEMENT_4, 8, 0), |
1185 | SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 1, | 1178 | |
1186 | WM8996_POWER_MANAGEMENT_4, 8, 0), | 1179 | SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, WM8996_POWER_MANAGEMENT_6, 9, 0), |
1187 | 1180 | SND_SOC_DAPM_AIF_OUT("AIF2TX0", NULL, 1, WM8996_POWER_MANAGEMENT_6, 8, 0), | |
1188 | SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0, | 1181 | |
1189 | WM8996_POWER_MANAGEMENT_6, 9, 0), | 1182 | SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 5, WM8996_POWER_MANAGEMENT_4, 5, 0), |
1190 | SND_SOC_DAPM_AIF_OUT("AIF2TX0", "AIF2 Capture", 1, | 1183 | SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 4, WM8996_POWER_MANAGEMENT_4, 4, 0), |
1191 | WM8996_POWER_MANAGEMENT_6, 8, 0), | 1184 | SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 3, WM8996_POWER_MANAGEMENT_4, 3, 0), |
1192 | 1185 | SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 2, WM8996_POWER_MANAGEMENT_4, 2, 0), | |
1193 | SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5, | 1186 | SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 1, WM8996_POWER_MANAGEMENT_4, 1, 0), |
1194 | WM8996_POWER_MANAGEMENT_4, 5, 0), | 1187 | SND_SOC_DAPM_AIF_IN("AIF1RX0", NULL, 0, WM8996_POWER_MANAGEMENT_4, 0, 0), |
1195 | SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 4, | 1188 | |
1196 | WM8996_POWER_MANAGEMENT_4, 4, 0), | 1189 | SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 5, WM8996_POWER_MANAGEMENT_6, 5, 0), |
1197 | SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 3, | 1190 | SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 4, WM8996_POWER_MANAGEMENT_6, 4, 0), |
1198 | WM8996_POWER_MANAGEMENT_4, 3, 0), | 1191 | SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 3, WM8996_POWER_MANAGEMENT_6, 3, 0), |
1199 | SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 2, | 1192 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 2, WM8996_POWER_MANAGEMENT_6, 2, 0), |
1200 | WM8996_POWER_MANAGEMENT_4, 2, 0), | 1193 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 1, WM8996_POWER_MANAGEMENT_6, 1, 0), |
1201 | SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 1, | 1194 | SND_SOC_DAPM_AIF_OUT("AIF1TX0", NULL, 0, WM8996_POWER_MANAGEMENT_6, 0, 0), |
1202 | WM8996_POWER_MANAGEMENT_4, 1, 0), | ||
1203 | SND_SOC_DAPM_AIF_IN("AIF1RX0", "AIF1 Playback", 0, | ||
1204 | WM8996_POWER_MANAGEMENT_4, 0, 0), | ||
1205 | |||
1206 | SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 5, | ||
1207 | WM8996_POWER_MANAGEMENT_6, 5, 0), | ||
1208 | SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 4, | ||
1209 | WM8996_POWER_MANAGEMENT_6, 4, 0), | ||
1210 | SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 3, | ||
1211 | WM8996_POWER_MANAGEMENT_6, 3, 0), | ||
1212 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 2, | ||
1213 | WM8996_POWER_MANAGEMENT_6, 2, 0), | ||
1214 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 1, | ||
1215 | WM8996_POWER_MANAGEMENT_6, 1, 0), | ||
1216 | SND_SOC_DAPM_AIF_OUT("AIF1TX0", "AIF1 Capture", 0, | ||
1217 | WM8996_POWER_MANAGEMENT_6, 0, 0), | ||
1218 | 1195 | ||
1219 | /* We route as stereo pairs so define some dummy widgets to squash | 1196 | /* We route as stereo pairs so define some dummy widgets to squash |
1220 | * things down for now. RXA = 0,1, RXB = 2,3 and so on */ | 1197 | * things down for now. RXA = 0,1, RXB = 2,3 and so on */ |
@@ -1237,7 +1214,6 @@ SND_SOC_DAPM_PGA_S("HPOUT2L PGA", 0, WM8996_POWER_MANAGEMENT_1, 7, 0, NULL, 0), | |||
1237 | SND_SOC_DAPM_PGA_S("HPOUT2L_DLY", 1, WM8996_ANALOGUE_HP_2, 5, 0, NULL, 0), | 1214 | SND_SOC_DAPM_PGA_S("HPOUT2L_DLY", 1, WM8996_ANALOGUE_HP_2, 5, 0, NULL, 0), |
1238 | SND_SOC_DAPM_PGA_S("HPOUT2L_DCS", 2, WM8996_DC_SERVO_1, 2, 0, dcs_start, | 1215 | SND_SOC_DAPM_PGA_S("HPOUT2L_DCS", 2, WM8996_DC_SERVO_1, 2, 0, dcs_start, |
1239 | SND_SOC_DAPM_POST_PMU), | 1216 | SND_SOC_DAPM_POST_PMU), |
1240 | SND_SOC_DAPM_PGA_S("HPOUT2L_OUTP", 3, WM8996_ANALOGUE_HP_2, 6, 0, NULL, 0), | ||
1241 | SND_SOC_DAPM_PGA_S("HPOUT2L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2L, 0, | 1217 | SND_SOC_DAPM_PGA_S("HPOUT2L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2L, 0, |
1242 | rmv_short_event, | 1218 | rmv_short_event, |
1243 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | 1219 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), |
@@ -1246,7 +1222,6 @@ SND_SOC_DAPM_PGA_S("HPOUT2R PGA", 0, WM8996_POWER_MANAGEMENT_1, 6, 0,NULL, 0), | |||
1246 | SND_SOC_DAPM_PGA_S("HPOUT2R_DLY", 1, WM8996_ANALOGUE_HP_2, 1, 0, NULL, 0), | 1222 | SND_SOC_DAPM_PGA_S("HPOUT2R_DLY", 1, WM8996_ANALOGUE_HP_2, 1, 0, NULL, 0), |
1247 | SND_SOC_DAPM_PGA_S("HPOUT2R_DCS", 2, WM8996_DC_SERVO_1, 3, 0, dcs_start, | 1223 | SND_SOC_DAPM_PGA_S("HPOUT2R_DCS", 2, WM8996_DC_SERVO_1, 3, 0, dcs_start, |
1248 | SND_SOC_DAPM_POST_PMU), | 1224 | SND_SOC_DAPM_POST_PMU), |
1249 | SND_SOC_DAPM_PGA_S("HPOUT2R_OUTP", 3, WM8996_ANALOGUE_HP_2, 2, 0, NULL, 0), | ||
1250 | SND_SOC_DAPM_PGA_S("HPOUT2R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2R, 0, | 1225 | SND_SOC_DAPM_PGA_S("HPOUT2R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2R, 0, |
1251 | rmv_short_event, | 1226 | rmv_short_event, |
1252 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | 1227 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), |
@@ -1255,7 +1230,6 @@ SND_SOC_DAPM_PGA_S("HPOUT1L PGA", 0, WM8996_POWER_MANAGEMENT_1, 5, 0, NULL, 0), | |||
1255 | SND_SOC_DAPM_PGA_S("HPOUT1L_DLY", 1, WM8996_ANALOGUE_HP_1, 5, 0, NULL, 0), | 1230 | SND_SOC_DAPM_PGA_S("HPOUT1L_DLY", 1, WM8996_ANALOGUE_HP_1, 5, 0, NULL, 0), |
1256 | SND_SOC_DAPM_PGA_S("HPOUT1L_DCS", 2, WM8996_DC_SERVO_1, 0, 0, dcs_start, | 1231 | SND_SOC_DAPM_PGA_S("HPOUT1L_DCS", 2, WM8996_DC_SERVO_1, 0, 0, dcs_start, |
1257 | SND_SOC_DAPM_POST_PMU), | 1232 | SND_SOC_DAPM_POST_PMU), |
1258 | SND_SOC_DAPM_PGA_S("HPOUT1L_OUTP", 3, WM8996_ANALOGUE_HP_1, 6, 0, NULL, 0), | ||
1259 | SND_SOC_DAPM_PGA_S("HPOUT1L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1L, 0, | 1233 | SND_SOC_DAPM_PGA_S("HPOUT1L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1L, 0, |
1260 | rmv_short_event, | 1234 | rmv_short_event, |
1261 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | 1235 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), |
@@ -1264,7 +1238,6 @@ SND_SOC_DAPM_PGA_S("HPOUT1R PGA", 0, WM8996_POWER_MANAGEMENT_1, 4, 0, NULL, 0), | |||
1264 | SND_SOC_DAPM_PGA_S("HPOUT1R_DLY", 1, WM8996_ANALOGUE_HP_1, 1, 0, NULL, 0), | 1238 | SND_SOC_DAPM_PGA_S("HPOUT1R_DLY", 1, WM8996_ANALOGUE_HP_1, 1, 0, NULL, 0), |
1265 | SND_SOC_DAPM_PGA_S("HPOUT1R_DCS", 2, WM8996_DC_SERVO_1, 1, 0, dcs_start, | 1239 | SND_SOC_DAPM_PGA_S("HPOUT1R_DCS", 2, WM8996_DC_SERVO_1, 1, 0, dcs_start, |
1266 | SND_SOC_DAPM_POST_PMU), | 1240 | SND_SOC_DAPM_POST_PMU), |
1267 | SND_SOC_DAPM_PGA_S("HPOUT1R_OUTP", 3, WM8996_ANALOGUE_HP_1, 2, 0, NULL, 0), | ||
1268 | SND_SOC_DAPM_PGA_S("HPOUT1R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1R, 0, | 1241 | SND_SOC_DAPM_PGA_S("HPOUT1R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1R, 0, |
1269 | rmv_short_event, | 1242 | rmv_short_event, |
1270 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | 1243 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), |
@@ -1280,6 +1253,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1280 | { "AIFCLK", NULL, "SYSCLK" }, | 1253 | { "AIFCLK", NULL, "SYSCLK" }, |
1281 | { "SYSDSPCLK", NULL, "SYSCLK" }, | 1254 | { "SYSDSPCLK", NULL, "SYSCLK" }, |
1282 | { "Charge Pump", NULL, "SYSCLK" }, | 1255 | { "Charge Pump", NULL, "SYSCLK" }, |
1256 | { "Charge Pump", NULL, "CPVDD" }, | ||
1283 | 1257 | ||
1284 | { "MICB1", NULL, "LDO2" }, | 1258 | { "MICB1", NULL, "LDO2" }, |
1285 | { "MICB1", NULL, "MICB1 Audio" }, | 1259 | { "MICB1", NULL, "MICB1 Audio" }, |
@@ -1288,6 +1262,26 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1288 | { "MICB2", NULL, "MICB2 Audio" }, | 1262 | { "MICB2", NULL, "MICB2 Audio" }, |
1289 | { "MICB2", NULL, "Bandgap" }, | 1263 | { "MICB2", NULL, "Bandgap" }, |
1290 | 1264 | ||
1265 | { "AIF1RX0", NULL, "AIF1 Playback" }, | ||
1266 | { "AIF1RX1", NULL, "AIF1 Playback" }, | ||
1267 | { "AIF1RX2", NULL, "AIF1 Playback" }, | ||
1268 | { "AIF1RX3", NULL, "AIF1 Playback" }, | ||
1269 | { "AIF1RX4", NULL, "AIF1 Playback" }, | ||
1270 | { "AIF1RX5", NULL, "AIF1 Playback" }, | ||
1271 | |||
1272 | { "AIF2RX0", NULL, "AIF2 Playback" }, | ||
1273 | { "AIF2RX1", NULL, "AIF2 Playback" }, | ||
1274 | |||
1275 | { "AIF1 Capture", NULL, "AIF1TX0" }, | ||
1276 | { "AIF1 Capture", NULL, "AIF1TX1" }, | ||
1277 | { "AIF1 Capture", NULL, "AIF1TX2" }, | ||
1278 | { "AIF1 Capture", NULL, "AIF1TX3" }, | ||
1279 | { "AIF1 Capture", NULL, "AIF1TX4" }, | ||
1280 | { "AIF1 Capture", NULL, "AIF1TX5" }, | ||
1281 | |||
1282 | { "AIF2 Capture", NULL, "AIF2TX0" }, | ||
1283 | { "AIF2 Capture", NULL, "AIF2TX1" }, | ||
1284 | |||
1291 | { "IN1L PGA", NULL, "IN2LN" }, | 1285 | { "IN1L PGA", NULL, "IN2LN" }, |
1292 | { "IN1L PGA", NULL, "IN2LP" }, | 1286 | { "IN1L PGA", NULL, "IN2LP" }, |
1293 | { "IN1L PGA", NULL, "IN1LN" }, | 1287 | { "IN1L PGA", NULL, "IN1LN" }, |
@@ -1436,32 +1430,28 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1436 | { "HPOUT2L PGA", NULL, "DAC2L" }, | 1430 | { "HPOUT2L PGA", NULL, "DAC2L" }, |
1437 | { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" }, | 1431 | { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" }, |
1438 | { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" }, | 1432 | { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" }, |
1439 | { "HPOUT2L_OUTP", NULL, "HPOUT2L_DCS" }, | 1433 | { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_DCS" }, |
1440 | { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" }, | ||
1441 | 1434 | ||
1442 | { "HPOUT2R PGA", NULL, "Charge Pump" }, | 1435 | { "HPOUT2R PGA", NULL, "Charge Pump" }, |
1443 | { "HPOUT2R PGA", NULL, "Bandgap" }, | 1436 | { "HPOUT2R PGA", NULL, "Bandgap" }, |
1444 | { "HPOUT2R PGA", NULL, "DAC2R" }, | 1437 | { "HPOUT2R PGA", NULL, "DAC2R" }, |
1445 | { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" }, | 1438 | { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" }, |
1446 | { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" }, | 1439 | { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" }, |
1447 | { "HPOUT2R_OUTP", NULL, "HPOUT2R_DCS" }, | 1440 | { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_DCS" }, |
1448 | { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" }, | ||
1449 | 1441 | ||
1450 | { "HPOUT1L PGA", NULL, "Charge Pump" }, | 1442 | { "HPOUT1L PGA", NULL, "Charge Pump" }, |
1451 | { "HPOUT1L PGA", NULL, "Bandgap" }, | 1443 | { "HPOUT1L PGA", NULL, "Bandgap" }, |
1452 | { "HPOUT1L PGA", NULL, "DAC1L" }, | 1444 | { "HPOUT1L PGA", NULL, "DAC1L" }, |
1453 | { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" }, | 1445 | { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" }, |
1454 | { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" }, | 1446 | { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" }, |
1455 | { "HPOUT1L_OUTP", NULL, "HPOUT1L_DCS" }, | 1447 | { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_DCS" }, |
1456 | { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" }, | ||
1457 | 1448 | ||
1458 | { "HPOUT1R PGA", NULL, "Charge Pump" }, | 1449 | { "HPOUT1R PGA", NULL, "Charge Pump" }, |
1459 | { "HPOUT1R PGA", NULL, "Bandgap" }, | 1450 | { "HPOUT1R PGA", NULL, "Bandgap" }, |
1460 | { "HPOUT1R PGA", NULL, "DAC1R" }, | 1451 | { "HPOUT1R PGA", NULL, "DAC1R" }, |
1461 | { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" }, | 1452 | { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" }, |
1462 | { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" }, | 1453 | { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" }, |
1463 | { "HPOUT1R_OUTP", NULL, "HPOUT1R_DCS" }, | 1454 | { "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_DCS" }, |
1464 | { "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_OUTP" }, | ||
1465 | 1455 | ||
1466 | { "HPOUT2L", NULL, "HPOUT2L_RMV_SHORT" }, | 1456 | { "HPOUT2L", NULL, "HPOUT2L_RMV_SHORT" }, |
1467 | { "HPOUT2R", NULL, "HPOUT2R_RMV_SHORT" }, | 1457 | { "HPOUT2R", NULL, "HPOUT2R_RMV_SHORT" }, |
@@ -1720,6 +1710,7 @@ static int wm8996_reset(struct wm8996_priv *wm8996) | |||
1720 | { | 1710 | { |
1721 | if (wm8996->pdata.ldo_ena > 0) { | 1711 | if (wm8996->pdata.ldo_ena > 0) { |
1722 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 1712 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
1713 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1); | ||
1723 | return 0; | 1714 | return 0; |
1724 | } else { | 1715 | } else { |
1725 | return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET, | 1716 | return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET, |
@@ -1923,7 +1914,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream, | |||
1923 | { | 1914 | { |
1924 | struct snd_soc_codec *codec = dai->codec; | 1915 | struct snd_soc_codec *codec = dai->codec; |
1925 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 1916 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
1926 | int bits, i, bclk_rate; | 1917 | int bits, i, bclk_rate, best; |
1927 | int aifdata = 0; | 1918 | int aifdata = 0; |
1928 | int lrclk = 0; | 1919 | int lrclk = 0; |
1929 | int dsp = 0; | 1920 | int dsp = 0; |
@@ -1972,14 +1963,11 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream, | |||
1972 | return bits; | 1963 | return bits; |
1973 | aifdata |= (bits << WM8996_AIF1TX_WL_SHIFT) | bits; | 1964 | aifdata |= (bits << WM8996_AIF1TX_WL_SHIFT) | bits; |
1974 | 1965 | ||
1966 | best = 0; | ||
1975 | for (i = 0; i < ARRAY_SIZE(dsp_divs); i++) { | 1967 | for (i = 0; i < ARRAY_SIZE(dsp_divs); i++) { |
1976 | if (dsp_divs[i] == params_rate(params)) | 1968 | if (abs(dsp_divs[i] - params_rate(params)) < |
1977 | break; | 1969 | abs(dsp_divs[best] - params_rate(params))) |
1978 | } | 1970 | best = i; |
1979 | if (i == ARRAY_SIZE(dsp_divs)) { | ||
1980 | dev_err(codec->dev, "Unsupported sample rate %dHz\n", | ||
1981 | params_rate(params)); | ||
1982 | return -EINVAL; | ||
1983 | } | 1971 | } |
1984 | dsp |= i << dsp_shift; | 1972 | dsp |= i << dsp_shift; |
1985 | 1973 | ||
@@ -2039,13 +2027,16 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai, | |||
2039 | } | 2027 | } |
2040 | 2028 | ||
2041 | switch (wm8996->sysclk) { | 2029 | switch (wm8996->sysclk) { |
2030 | case 5644800: | ||
2042 | case 6144000: | 2031 | case 6144000: |
2043 | snd_soc_update_bits(codec, WM8996_AIF_RATE, | 2032 | snd_soc_update_bits(codec, WM8996_AIF_RATE, |
2044 | WM8996_SYSCLK_RATE, 0); | 2033 | WM8996_SYSCLK_RATE, 0); |
2045 | break; | 2034 | break; |
2035 | case 22579200: | ||
2046 | case 24576000: | 2036 | case 24576000: |
2047 | ratediv = WM8996_SYSCLK_DIV; | 2037 | ratediv = WM8996_SYSCLK_DIV; |
2048 | wm8996->sysclk /= 2; | 2038 | wm8996->sysclk /= 2; |
2039 | case 11289600: | ||
2049 | case 12288000: | 2040 | case 12288000: |
2050 | snd_soc_update_bits(codec, WM8996_AIF_RATE, | 2041 | snd_soc_update_bits(codec, WM8996_AIF_RATE, |
2051 | WM8996_SYSCLK_RATE, WM8996_SYSCLK_RATE); | 2042 | WM8996_SYSCLK_RATE, WM8996_SYSCLK_RATE); |
@@ -2438,6 +2429,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
2438 | wm8996->jack = jack; | 2429 | wm8996->jack = jack; |
2439 | wm8996->detecting = true; | 2430 | wm8996->detecting = true; |
2440 | wm8996->polarity_cb = polarity_cb; | 2431 | wm8996->polarity_cb = polarity_cb; |
2432 | wm8996->jack_flips = 0; | ||
2441 | 2433 | ||
2442 | if (wm8996->polarity_cb) | 2434 | if (wm8996->polarity_cb) |
2443 | wm8996->polarity_cb(codec, 0); | 2435 | wm8996->polarity_cb(codec, 0); |
@@ -2553,6 +2545,19 @@ static void wm8996_hpdet_start(struct snd_soc_codec *codec) | |||
2553 | WM8996_HP_POLL, WM8996_HP_POLL); | 2545 | WM8996_HP_POLL, WM8996_HP_POLL); |
2554 | } | 2546 | } |
2555 | 2547 | ||
2548 | static void wm8996_report_headphone(struct snd_soc_codec *codec) | ||
2549 | { | ||
2550 | dev_dbg(codec->dev, "Headphone detected\n"); | ||
2551 | wm8996_hpdet_start(codec); | ||
2552 | |||
2553 | /* Increase the detection rate a bit for responsiveness. */ | ||
2554 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, | ||
2555 | WM8996_MICD_RATE_MASK | | ||
2556 | WM8996_MICD_BIAS_STARTTIME_MASK, | ||
2557 | 7 << WM8996_MICD_RATE_SHIFT | | ||
2558 | 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT); | ||
2559 | } | ||
2560 | |||
2556 | static void wm8996_micd(struct snd_soc_codec *codec) | 2561 | static void wm8996_micd(struct snd_soc_codec *codec) |
2557 | { | 2562 | { |
2558 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 2563 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
@@ -2572,6 +2577,7 @@ static void wm8996_micd(struct snd_soc_codec *codec) | |||
2572 | dev_dbg(codec->dev, "Jack removal detected\n"); | 2577 | dev_dbg(codec->dev, "Jack removal detected\n"); |
2573 | wm8996->jack_mic = false; | 2578 | wm8996->jack_mic = false; |
2574 | wm8996->detecting = true; | 2579 | wm8996->detecting = true; |
2580 | wm8996->jack_flips = 0; | ||
2575 | snd_soc_jack_report(wm8996->jack, 0, | 2581 | snd_soc_jack_report(wm8996->jack, 0, |
2576 | SND_JACK_LINEOUT | SND_JACK_HEADSET | | 2582 | SND_JACK_LINEOUT | SND_JACK_HEADSET | |
2577 | SND_JACK_BTN_0); | 2583 | SND_JACK_BTN_0); |
@@ -2612,9 +2618,17 @@ static void wm8996_micd(struct snd_soc_codec *codec) | |||
2612 | /* If we detected a lower impedence during initial startup | 2618 | /* If we detected a lower impedence during initial startup |
2613 | * then we probably have the wrong polarity, flip it. Don't | 2619 | * then we probably have the wrong polarity, flip it. Don't |
2614 | * do this for the lowest impedences to speed up detection of | 2620 | * do this for the lowest impedences to speed up detection of |
2615 | * plain headphones. | 2621 | * plain headphones. If both polarities report a low |
2622 | * impedence then give up and report headphones. | ||
2616 | */ | 2623 | */ |
2617 | if (wm8996->detecting && (val & 0x3f0)) { | 2624 | if (wm8996->detecting && (val & 0x3f0)) { |
2625 | wm8996->jack_flips++; | ||
2626 | |||
2627 | if (wm8996->jack_flips > 1) { | ||
2628 | wm8996_report_headphone(codec); | ||
2629 | return; | ||
2630 | } | ||
2631 | |||
2618 | reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2); | 2632 | reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2); |
2619 | reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC | | 2633 | reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC | |
2620 | WM8996_MICD_BIAS_SRC; | 2634 | WM8996_MICD_BIAS_SRC; |
@@ -2641,17 +2655,7 @@ static void wm8996_micd(struct snd_soc_codec *codec) | |||
2641 | snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0, | 2655 | snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0, |
2642 | SND_JACK_BTN_0); | 2656 | SND_JACK_BTN_0); |
2643 | } else if (wm8996->detecting) { | 2657 | } else if (wm8996->detecting) { |
2644 | dev_dbg(codec->dev, "Headphone detected\n"); | 2658 | wm8996_report_headphone(codec); |
2645 | wm8996_hpdet_start(codec); | ||
2646 | |||
2647 | /* Increase the detection rate a bit for | ||
2648 | * responsiveness. | ||
2649 | */ | ||
2650 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, | ||
2651 | WM8996_MICD_RATE_MASK | | ||
2652 | WM8996_MICD_BIAS_STARTTIME_MASK, | ||
2653 | 7 << WM8996_MICD_RATE_SHIFT | | ||
2654 | 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT); | ||
2655 | } | 2659 | } |
2656 | } | 2660 | } |
2657 | } | 2661 | } |
@@ -2768,7 +2772,7 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec) | |||
2768 | wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts; | 2772 | wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts; |
2769 | wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts; | 2773 | wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts; |
2770 | 2774 | ||
2771 | ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls)); | 2775 | ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls)); |
2772 | if (ret != 0) | 2776 | if (ret != 0) |
2773 | dev_err(codec->dev, | 2777 | dev_err(codec->dev, |
2774 | "Failed to add ReTune Mobile controls: %d\n", ret); | 2778 | "Failed to add ReTune Mobile controls: %d\n", ret); |
@@ -2791,7 +2795,6 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2791 | int ret; | 2795 | int ret; |
2792 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 2796 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
2793 | struct i2c_client *i2c = to_i2c_client(codec->dev); | 2797 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
2794 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
2795 | int i, irq_flags; | 2798 | int i, irq_flags; |
2796 | 2799 | ||
2797 | wm8996->codec = codec; | 2800 | wm8996->codec = codec; |
@@ -2799,8 +2802,6 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2799 | init_completion(&wm8996->dcs_done); | 2802 | init_completion(&wm8996->dcs_done); |
2800 | init_completion(&wm8996->fll_lock); | 2803 | init_completion(&wm8996->fll_lock); |
2801 | 2804 | ||
2802 | dapm->idle_bias_off = true; | ||
2803 | |||
2804 | codec->control_data = wm8996->regmap; | 2805 | codec->control_data = wm8996->regmap; |
2805 | 2806 | ||
2806 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | 2807 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); |
@@ -2966,7 +2967,7 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2966 | if (wm8996->pdata.num_retune_mobile_cfgs) | 2967 | if (wm8996->pdata.num_retune_mobile_cfgs) |
2967 | wm8996_retune_mobile_pdata(codec); | 2968 | wm8996_retune_mobile_pdata(codec); |
2968 | else | 2969 | else |
2969 | snd_soc_add_controls(codec, wm8996_eq_controls, | 2970 | snd_soc_add_codec_controls(codec, wm8996_eq_controls, |
2970 | ARRAY_SIZE(wm8996_eq_controls)); | 2971 | ARRAY_SIZE(wm8996_eq_controls)); |
2971 | 2972 | ||
2972 | /* If the TX LRCLK pins are not in LRCLK mode configure the | 2973 | /* If the TX LRCLK pins are not in LRCLK mode configure the |
@@ -3038,22 +3039,16 @@ static int wm8996_remove(struct snd_soc_codec *codec) | |||
3038 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) | 3039 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) |
3039 | regulator_unregister_notifier(wm8996->supplies[i].consumer, | 3040 | regulator_unregister_notifier(wm8996->supplies[i].consumer, |
3040 | &wm8996->disable_nb[i]); | 3041 | &wm8996->disable_nb[i]); |
3041 | regulator_put(wm8996->cpvdd); | ||
3042 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | 3042 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); |
3043 | 3043 | ||
3044 | return 0; | 3044 | return 0; |
3045 | } | 3045 | } |
3046 | 3046 | ||
3047 | static int wm8996_soc_volatile_register(struct snd_soc_codec *codec, | ||
3048 | unsigned int reg) | ||
3049 | { | ||
3050 | return true; | ||
3051 | } | ||
3052 | |||
3053 | static struct snd_soc_codec_driver soc_codec_dev_wm8996 = { | 3047 | static struct snd_soc_codec_driver soc_codec_dev_wm8996 = { |
3054 | .probe = wm8996_probe, | 3048 | .probe = wm8996_probe, |
3055 | .remove = wm8996_remove, | 3049 | .remove = wm8996_remove, |
3056 | .set_bias_level = wm8996_set_bias_level, | 3050 | .set_bias_level = wm8996_set_bias_level, |
3051 | .idle_bias_off = true, | ||
3057 | .seq_notifier = wm8996_seq_notifier, | 3052 | .seq_notifier = wm8996_seq_notifier, |
3058 | .controls = wm8996_snd_controls, | 3053 | .controls = wm8996_snd_controls, |
3059 | .num_controls = ARRAY_SIZE(wm8996_snd_controls), | 3054 | .num_controls = ARRAY_SIZE(wm8996_snd_controls), |
@@ -3062,12 +3057,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = { | |||
3062 | .dapm_routes = wm8996_dapm_routes, | 3057 | .dapm_routes = wm8996_dapm_routes, |
3063 | .num_dapm_routes = ARRAY_SIZE(wm8996_dapm_routes), | 3058 | .num_dapm_routes = ARRAY_SIZE(wm8996_dapm_routes), |
3064 | .set_pll = wm8996_set_fll, | 3059 | .set_pll = wm8996_set_fll, |
3065 | .reg_cache_size = WM8996_MAX_REGISTER, | ||
3066 | .volatile_register = wm8996_soc_volatile_register, | ||
3067 | }; | 3060 | }; |
3068 | 3061 | ||
3069 | #define WM8996_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ | 3062 | #define WM8996_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ |
3070 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000) | 3063 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ |
3064 | SNDRV_PCM_RATE_48000) | ||
3071 | #define WM8996_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | 3065 | #define WM8996_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ |
3072 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ | 3066 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ |
3073 | SNDRV_PCM_FMTBIT_S32_LE) | 3067 | SNDRV_PCM_FMTBIT_S32_LE) |
@@ -3087,6 +3081,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = { | |||
3087 | .channels_max = 6, | 3081 | .channels_max = 6, |
3088 | .rates = WM8996_RATES, | 3082 | .rates = WM8996_RATES, |
3089 | .formats = WM8996_FORMATS, | 3083 | .formats = WM8996_FORMATS, |
3084 | .sig_bits = 24, | ||
3090 | }, | 3085 | }, |
3091 | .capture = { | 3086 | .capture = { |
3092 | .stream_name = "AIF1 Capture", | 3087 | .stream_name = "AIF1 Capture", |
@@ -3094,6 +3089,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = { | |||
3094 | .channels_max = 6, | 3089 | .channels_max = 6, |
3095 | .rates = WM8996_RATES, | 3090 | .rates = WM8996_RATES, |
3096 | .formats = WM8996_FORMATS, | 3091 | .formats = WM8996_FORMATS, |
3092 | .sig_bits = 24, | ||
3097 | }, | 3093 | }, |
3098 | .ops = &wm8996_dai_ops, | 3094 | .ops = &wm8996_dai_ops, |
3099 | }, | 3095 | }, |
@@ -3105,6 +3101,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = { | |||
3105 | .channels_max = 2, | 3101 | .channels_max = 2, |
3106 | .rates = WM8996_RATES, | 3102 | .rates = WM8996_RATES, |
3107 | .formats = WM8996_FORMATS, | 3103 | .formats = WM8996_FORMATS, |
3104 | .sig_bits = 24, | ||
3108 | }, | 3105 | }, |
3109 | .capture = { | 3106 | .capture = { |
3110 | .stream_name = "AIF2 Capture", | 3107 | .stream_name = "AIF2 Capture", |
@@ -3112,6 +3109,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = { | |||
3112 | .channels_max = 2, | 3109 | .channels_max = 2, |
3113 | .rates = WM8996_RATES, | 3110 | .rates = WM8996_RATES, |
3114 | .formats = WM8996_FORMATS, | 3111 | .formats = WM8996_FORMATS, |
3112 | .sig_bits = 24, | ||
3115 | }, | 3113 | }, |
3116 | .ops = &wm8996_dai_ops, | 3114 | .ops = &wm8996_dai_ops, |
3117 | }, | 3115 | }, |
@@ -3149,25 +3147,18 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, | |||
3149 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) | 3147 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) |
3150 | wm8996->supplies[i].supply = wm8996_supply_names[i]; | 3148 | wm8996->supplies[i].supply = wm8996_supply_names[i]; |
3151 | 3149 | ||
3152 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies), | 3150 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies), |
3153 | wm8996->supplies); | 3151 | wm8996->supplies); |
3154 | if (ret != 0) { | 3152 | if (ret != 0) { |
3155 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | 3153 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); |
3156 | goto err_gpio; | 3154 | goto err_gpio; |
3157 | } | 3155 | } |
3158 | 3156 | ||
3159 | wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD"); | ||
3160 | if (IS_ERR(wm8996->cpvdd)) { | ||
3161 | ret = PTR_ERR(wm8996->cpvdd); | ||
3162 | dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret); | ||
3163 | goto err_get; | ||
3164 | } | ||
3165 | |||
3166 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), | 3157 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies), |
3167 | wm8996->supplies); | 3158 | wm8996->supplies); |
3168 | if (ret != 0) { | 3159 | if (ret != 0) { |
3169 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | 3160 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); |
3170 | goto err_cpvdd; | 3161 | goto err_gpio; |
3171 | } | 3162 | } |
3172 | 3163 | ||
3173 | if (wm8996->pdata.ldo_ena > 0) { | 3164 | if (wm8996->pdata.ldo_ena > 0) { |
@@ -3188,7 +3179,7 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c, | |||
3188 | goto err_regmap; | 3179 | goto err_regmap; |
3189 | } | 3180 | } |
3190 | if (reg != 0x8915) { | 3181 | if (reg != 0x8915) { |
3191 | dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", ret); | 3182 | dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", reg); |
3192 | ret = -EINVAL; | 3183 | ret = -EINVAL; |
3193 | goto err_regmap; | 3184 | goto err_regmap; |
3194 | } | 3185 | } |
@@ -3229,10 +3220,6 @@ err_enable: | |||
3229 | if (wm8996->pdata.ldo_ena > 0) | 3220 | if (wm8996->pdata.ldo_ena > 0) |
3230 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 3221 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
3231 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | 3222 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); |
3232 | err_cpvdd: | ||
3233 | regulator_put(wm8996->cpvdd); | ||
3234 | err_get: | ||
3235 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | ||
3236 | err_gpio: | 3223 | err_gpio: |
3237 | if (wm8996->pdata.ldo_ena > 0) | 3224 | if (wm8996->pdata.ldo_ena > 0) |
3238 | gpio_free(wm8996->pdata.ldo_ena); | 3225 | gpio_free(wm8996->pdata.ldo_ena); |
@@ -3247,8 +3234,6 @@ static __devexit int wm8996_i2c_remove(struct i2c_client *client) | |||
3247 | 3234 | ||
3248 | snd_soc_unregister_codec(&client->dev); | 3235 | snd_soc_unregister_codec(&client->dev); |
3249 | wm8996_free_gpio(wm8996); | 3236 | wm8996_free_gpio(wm8996); |
3250 | regulator_put(wm8996->cpvdd); | ||
3251 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | ||
3252 | regmap_exit(wm8996->regmap); | 3237 | regmap_exit(wm8996->regmap); |
3253 | if (wm8996->pdata.ldo_ena > 0) { | 3238 | if (wm8996->pdata.ldo_ena > 0) { |
3254 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 3239 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
@@ -3273,25 +3258,7 @@ static struct i2c_driver wm8996_i2c_driver = { | |||
3273 | .id_table = wm8996_i2c_id, | 3258 | .id_table = wm8996_i2c_id, |
3274 | }; | 3259 | }; |
3275 | 3260 | ||
3276 | static int __init wm8996_modinit(void) | 3261 | module_i2c_driver(wm8996_i2c_driver); |
3277 | { | ||
3278 | int ret; | ||
3279 | |||
3280 | ret = i2c_add_driver(&wm8996_i2c_driver); | ||
3281 | if (ret != 0) { | ||
3282 | printk(KERN_ERR "Failed to register WM8996 I2C driver: %d\n", | ||
3283 | ret); | ||
3284 | } | ||
3285 | |||
3286 | return ret; | ||
3287 | } | ||
3288 | module_init(wm8996_modinit); | ||
3289 | |||
3290 | static void __exit wm8996_exit(void) | ||
3291 | { | ||
3292 | i2c_del_driver(&wm8996_i2c_driver); | ||
3293 | } | ||
3294 | module_exit(wm8996_exit); | ||
3295 | 3262 | ||
3296 | MODULE_DESCRIPTION("ASoC WM8996 driver"); | 3263 | MODULE_DESCRIPTION("ASoC WM8996 driver"); |
3297 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 3264 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |