diff options
Diffstat (limited to 'sound/soc/codecs/wm5100.c')
-rw-r--r-- | sound/soc/codecs/wm5100.c | 643 |
1 files changed, 276 insertions, 367 deletions
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 89f2af77b1c3..b9c185ce64e4 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/gcd.h> | 18 | #include <linux/gcd.h> |
19 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/pm_runtime.h> | ||
21 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
22 | #include <linux/regulator/fixed.h> | 23 | #include <linux/regulator/fixed.h> |
23 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
@@ -50,13 +51,11 @@ struct wm5100_fll { | |||
50 | 51 | ||
51 | /* codec private data */ | 52 | /* codec private data */ |
52 | struct wm5100_priv { | 53 | struct wm5100_priv { |
54 | struct device *dev; | ||
53 | struct regmap *regmap; | 55 | struct regmap *regmap; |
54 | struct snd_soc_codec *codec; | 56 | struct snd_soc_codec *codec; |
55 | 57 | ||
56 | struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES]; | 58 | struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES]; |
57 | struct regulator *cpvdd; | ||
58 | struct regulator *dbvdd2; | ||
59 | struct regulator *dbvdd3; | ||
60 | 59 | ||
61 | int rev; | 60 | int rev; |
62 | 61 | ||
@@ -73,6 +72,7 @@ struct wm5100_priv { | |||
73 | bool jack_detecting; | 72 | bool jack_detecting; |
74 | bool jack_mic; | 73 | bool jack_mic; |
75 | int jack_mode; | 74 | int jack_mode; |
75 | int jack_flips; | ||
76 | 76 | ||
77 | struct wm5100_fll fll[2]; | 77 | struct wm5100_fll fll[2]; |
78 | 78 | ||
@@ -709,6 +709,8 @@ WM5100_MIXER_CONTROLS("EQ4", WM5100_EQ4MIX_INPUT_1_SOURCE), | |||
709 | 709 | ||
710 | WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE), | 710 | WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE), |
711 | WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE), | 711 | WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE), |
712 | SND_SOC_BYTES_MASK("DRC", WM5100_DRC1_CTRL1, 5, | ||
713 | WM5100_DRCL_ENA | WM5100_DRCR_ENA), | ||
712 | 714 | ||
713 | WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE), | 715 | WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE), |
714 | WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE), | 716 | WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE), |
@@ -776,127 +778,48 @@ static int wm5100_out_ev(struct snd_soc_dapm_widget *w, | |||
776 | return 0; | 778 | return 0; |
777 | } | 779 | } |
778 | 780 | ||
779 | static int wm5100_cp_ev(struct snd_soc_dapm_widget *w, | 781 | static void wm5100_log_status3(struct wm5100_priv *wm5100, int val) |
780 | struct snd_kcontrol *kcontrol, | ||
781 | int event) | ||
782 | { | ||
783 | struct snd_soc_codec *codec = w->codec; | ||
784 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | ||
785 | int ret; | ||
786 | |||
787 | switch (event) { | ||
788 | case SND_SOC_DAPM_PRE_PMU: | ||
789 | ret = regulator_enable(wm5100->cpvdd); | ||
790 | if (ret != 0) { | ||
791 | dev_err(codec->dev, "Failed to enable CPVDD: %d\n", | ||
792 | ret); | ||
793 | return ret; | ||
794 | } | ||
795 | return ret; | ||
796 | |||
797 | case SND_SOC_DAPM_POST_PMD: | ||
798 | ret = regulator_disable_deferred(wm5100->cpvdd, 20); | ||
799 | if (ret != 0) { | ||
800 | dev_err(codec->dev, "Failed to disable CPVDD: %d\n", | ||
801 | ret); | ||
802 | return ret; | ||
803 | } | ||
804 | return ret; | ||
805 | |||
806 | default: | ||
807 | BUG(); | ||
808 | return 0; | ||
809 | } | ||
810 | } | ||
811 | |||
812 | static int wm5100_dbvdd_ev(struct snd_soc_dapm_widget *w, | ||
813 | struct snd_kcontrol *kcontrol, | ||
814 | int event) | ||
815 | { | ||
816 | struct snd_soc_codec *codec = w->codec; | ||
817 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | ||
818 | struct regulator *regulator; | ||
819 | int ret; | ||
820 | |||
821 | switch (w->shift) { | ||
822 | case 2: | ||
823 | regulator = wm5100->dbvdd2; | ||
824 | break; | ||
825 | case 3: | ||
826 | regulator = wm5100->dbvdd3; | ||
827 | break; | ||
828 | default: | ||
829 | BUG(); | ||
830 | return 0; | ||
831 | } | ||
832 | |||
833 | switch (event) { | ||
834 | case SND_SOC_DAPM_PRE_PMU: | ||
835 | ret = regulator_enable(regulator); | ||
836 | if (ret != 0) { | ||
837 | dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n", | ||
838 | w->shift, ret); | ||
839 | return ret; | ||
840 | } | ||
841 | return ret; | ||
842 | |||
843 | case SND_SOC_DAPM_POST_PMD: | ||
844 | ret = regulator_disable(regulator); | ||
845 | if (ret != 0) { | ||
846 | dev_err(codec->dev, "Failed to enable DBVDD%d: %d\n", | ||
847 | w->shift, ret); | ||
848 | return ret; | ||
849 | } | ||
850 | return ret; | ||
851 | |||
852 | default: | ||
853 | BUG(); | ||
854 | return 0; | ||
855 | } | ||
856 | } | ||
857 | |||
858 | static void wm5100_log_status3(struct snd_soc_codec *codec, int val) | ||
859 | { | 782 | { |
860 | if (val & WM5100_SPK_SHUTDOWN_WARN_EINT) | 783 | if (val & WM5100_SPK_SHUTDOWN_WARN_EINT) |
861 | dev_crit(codec->dev, "Speaker shutdown warning\n"); | 784 | dev_crit(wm5100->dev, "Speaker shutdown warning\n"); |
862 | if (val & WM5100_SPK_SHUTDOWN_EINT) | 785 | if (val & WM5100_SPK_SHUTDOWN_EINT) |
863 | dev_crit(codec->dev, "Speaker shutdown\n"); | 786 | dev_crit(wm5100->dev, "Speaker shutdown\n"); |
864 | if (val & WM5100_CLKGEN_ERR_EINT) | 787 | if (val & WM5100_CLKGEN_ERR_EINT) |
865 | dev_crit(codec->dev, "SYSCLK underclocked\n"); | 788 | dev_crit(wm5100->dev, "SYSCLK underclocked\n"); |
866 | if (val & WM5100_CLKGEN_ERR_ASYNC_EINT) | 789 | if (val & WM5100_CLKGEN_ERR_ASYNC_EINT) |
867 | dev_crit(codec->dev, "ASYNCCLK underclocked\n"); | 790 | dev_crit(wm5100->dev, "ASYNCCLK underclocked\n"); |
868 | } | 791 | } |
869 | 792 | ||
870 | static void wm5100_log_status4(struct snd_soc_codec *codec, int val) | 793 | static void wm5100_log_status4(struct wm5100_priv *wm5100, int val) |
871 | { | 794 | { |
872 | if (val & WM5100_AIF3_ERR_EINT) | 795 | if (val & WM5100_AIF3_ERR_EINT) |
873 | dev_err(codec->dev, "AIF3 configuration error\n"); | 796 | dev_err(wm5100->dev, "AIF3 configuration error\n"); |
874 | if (val & WM5100_AIF2_ERR_EINT) | 797 | if (val & WM5100_AIF2_ERR_EINT) |
875 | dev_err(codec->dev, "AIF2 configuration error\n"); | 798 | dev_err(wm5100->dev, "AIF2 configuration error\n"); |
876 | if (val & WM5100_AIF1_ERR_EINT) | 799 | if (val & WM5100_AIF1_ERR_EINT) |
877 | dev_err(codec->dev, "AIF1 configuration error\n"); | 800 | dev_err(wm5100->dev, "AIF1 configuration error\n"); |
878 | if (val & WM5100_CTRLIF_ERR_EINT) | 801 | if (val & WM5100_CTRLIF_ERR_EINT) |
879 | dev_err(codec->dev, "Control interface error\n"); | 802 | dev_err(wm5100->dev, "Control interface error\n"); |
880 | if (val & WM5100_ISRC2_UNDERCLOCKED_EINT) | 803 | if (val & WM5100_ISRC2_UNDERCLOCKED_EINT) |
881 | dev_err(codec->dev, "ISRC2 underclocked\n"); | 804 | dev_err(wm5100->dev, "ISRC2 underclocked\n"); |
882 | if (val & WM5100_ISRC1_UNDERCLOCKED_EINT) | 805 | if (val & WM5100_ISRC1_UNDERCLOCKED_EINT) |
883 | dev_err(codec->dev, "ISRC1 underclocked\n"); | 806 | dev_err(wm5100->dev, "ISRC1 underclocked\n"); |
884 | if (val & WM5100_FX_UNDERCLOCKED_EINT) | 807 | if (val & WM5100_FX_UNDERCLOCKED_EINT) |
885 | dev_err(codec->dev, "FX underclocked\n"); | 808 | dev_err(wm5100->dev, "FX underclocked\n"); |
886 | if (val & WM5100_AIF3_UNDERCLOCKED_EINT) | 809 | if (val & WM5100_AIF3_UNDERCLOCKED_EINT) |
887 | dev_err(codec->dev, "AIF3 underclocked\n"); | 810 | dev_err(wm5100->dev, "AIF3 underclocked\n"); |
888 | if (val & WM5100_AIF2_UNDERCLOCKED_EINT) | 811 | if (val & WM5100_AIF2_UNDERCLOCKED_EINT) |
889 | dev_err(codec->dev, "AIF2 underclocked\n"); | 812 | dev_err(wm5100->dev, "AIF2 underclocked\n"); |
890 | if (val & WM5100_AIF1_UNDERCLOCKED_EINT) | 813 | if (val & WM5100_AIF1_UNDERCLOCKED_EINT) |
891 | dev_err(codec->dev, "AIF1 underclocked\n"); | 814 | dev_err(wm5100->dev, "AIF1 underclocked\n"); |
892 | if (val & WM5100_ASRC_UNDERCLOCKED_EINT) | 815 | if (val & WM5100_ASRC_UNDERCLOCKED_EINT) |
893 | dev_err(codec->dev, "ASRC underclocked\n"); | 816 | dev_err(wm5100->dev, "ASRC underclocked\n"); |
894 | if (val & WM5100_DAC_UNDERCLOCKED_EINT) | 817 | if (val & WM5100_DAC_UNDERCLOCKED_EINT) |
895 | dev_err(codec->dev, "DAC underclocked\n"); | 818 | dev_err(wm5100->dev, "DAC underclocked\n"); |
896 | if (val & WM5100_ADC_UNDERCLOCKED_EINT) | 819 | if (val & WM5100_ADC_UNDERCLOCKED_EINT) |
897 | dev_err(codec->dev, "ADC underclocked\n"); | 820 | dev_err(wm5100->dev, "ADC underclocked\n"); |
898 | if (val & WM5100_MIXER_UNDERCLOCKED_EINT) | 821 | if (val & WM5100_MIXER_UNDERCLOCKED_EINT) |
899 | dev_err(codec->dev, "Mixer underclocked\n"); | 822 | dev_err(wm5100->dev, "Mixer underclocked\n"); |
900 | } | 823 | } |
901 | 824 | ||
902 | static int wm5100_post_ev(struct snd_soc_dapm_widget *w, | 825 | static int wm5100_post_ev(struct snd_soc_dapm_widget *w, |
@@ -904,16 +827,17 @@ static int wm5100_post_ev(struct snd_soc_dapm_widget *w, | |||
904 | int event) | 827 | int event) |
905 | { | 828 | { |
906 | struct snd_soc_codec *codec = w->codec; | 829 | struct snd_soc_codec *codec = w->codec; |
830 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | ||
907 | int ret; | 831 | int ret; |
908 | 832 | ||
909 | ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3); | 833 | ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3); |
910 | ret &= WM5100_SPK_SHUTDOWN_WARN_STS | | 834 | ret &= WM5100_SPK_SHUTDOWN_WARN_STS | |
911 | WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS | | 835 | WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS | |
912 | WM5100_CLKGEN_ERR_ASYNC_STS; | 836 | WM5100_CLKGEN_ERR_ASYNC_STS; |
913 | wm5100_log_status3(codec, ret); | 837 | wm5100_log_status3(wm5100, ret); |
914 | 838 | ||
915 | ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4); | 839 | ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4); |
916 | wm5100_log_status4(codec, ret); | 840 | wm5100_log_status4(wm5100, ret); |
917 | 841 | ||
918 | return 0; | 842 | return 0; |
919 | } | 843 | } |
@@ -924,18 +848,16 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0, | |||
924 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT, | 848 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT, |
925 | 0, NULL, 0), | 849 | 0, NULL, 0), |
926 | 850 | ||
851 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | ||
852 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | ||
853 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | ||
854 | |||
927 | SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0, | 855 | SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0, |
928 | wm5100_cp_ev, | 856 | NULL, 0), |
929 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
930 | SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0, | 857 | SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0, |
931 | NULL, 0), | 858 | NULL, 0), |
932 | SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1, | 859 | SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1, |
933 | WM5100_CP2_BYPASS_SHIFT, 1, wm5100_cp_ev, | 860 | WM5100_CP2_BYPASS_SHIFT, 1, NULL, 0), |
934 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
935 | SND_SOC_DAPM_SUPPLY("DBVDD2", SND_SOC_NOPM, 2, 0, wm5100_dbvdd_ev, | ||
936 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
937 | SND_SOC_DAPM_SUPPLY("DBVDD3", SND_SOC_NOPM, 3, 0, wm5100_dbvdd_ev, | ||
938 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
939 | 861 | ||
940 | SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT, | 862 | SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT, |
941 | 0, NULL, 0), | 863 | 0, NULL, 0), |
@@ -1146,6 +1068,9 @@ SND_SOC_DAPM_POST("Post", wm5100_post_ev), | |||
1146 | }; | 1068 | }; |
1147 | 1069 | ||
1148 | static const struct snd_soc_dapm_route wm5100_dapm_routes[] = { | 1070 | static const struct snd_soc_dapm_route wm5100_dapm_routes[] = { |
1071 | { "CP1", NULL, "CPVDD" }, | ||
1072 | { "CP2 Active", NULL, "CPVDD" }, | ||
1073 | |||
1149 | { "IN1L", NULL, "SYSCLK" }, | 1074 | { "IN1L", NULL, "SYSCLK" }, |
1150 | { "IN1R", NULL, "SYSCLK" }, | 1075 | { "IN1R", NULL, "SYSCLK" }, |
1151 | { "IN2L", NULL, "SYSCLK" }, | 1076 | { "IN2L", NULL, "SYSCLK" }, |
@@ -1308,10 +1233,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = { | |||
1308 | { "PWM2", NULL, "PWM2 Driver" }, | 1233 | { "PWM2", NULL, "PWM2 Driver" }, |
1309 | }; | 1234 | }; |
1310 | 1235 | ||
1311 | static struct { | 1236 | static const __devinitdata struct reg_default wm5100_reva_patches[] = { |
1312 | int reg; | ||
1313 | int val; | ||
1314 | } wm5100_reva_patches[] = { | ||
1315 | { WM5100_AUDIO_IF_1_10, 0 }, | 1237 | { WM5100_AUDIO_IF_1_10, 0 }, |
1316 | { WM5100_AUDIO_IF_1_11, 1 }, | 1238 | { WM5100_AUDIO_IF_1_11, 1 }, |
1317 | { WM5100_AUDIO_IF_1_12, 2 }, | 1239 | { WM5100_AUDIO_IF_1_12, 2 }, |
@@ -1343,80 +1265,6 @@ static struct { | |||
1343 | { WM5100_AUDIO_IF_3_19, 1 }, | 1265 | { WM5100_AUDIO_IF_3_19, 1 }, |
1344 | }; | 1266 | }; |
1345 | 1267 | ||
1346 | static int wm5100_set_bias_level(struct snd_soc_codec *codec, | ||
1347 | enum snd_soc_bias_level level) | ||
1348 | { | ||
1349 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | ||
1350 | int ret, i; | ||
1351 | |||
1352 | switch (level) { | ||
1353 | case SND_SOC_BIAS_ON: | ||
1354 | break; | ||
1355 | |||
1356 | case SND_SOC_BIAS_PREPARE: | ||
1357 | break; | ||
1358 | |||
1359 | case SND_SOC_BIAS_STANDBY: | ||
1360 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
1361 | ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies), | ||
1362 | wm5100->core_supplies); | ||
1363 | if (ret != 0) { | ||
1364 | dev_err(codec->dev, | ||
1365 | "Failed to enable supplies: %d\n", | ||
1366 | ret); | ||
1367 | return ret; | ||
1368 | } | ||
1369 | |||
1370 | if (wm5100->pdata.ldo_ena) { | ||
1371 | gpio_set_value_cansleep(wm5100->pdata.ldo_ena, | ||
1372 | 1); | ||
1373 | msleep(2); | ||
1374 | } | ||
1375 | |||
1376 | regcache_cache_only(wm5100->regmap, false); | ||
1377 | |||
1378 | switch (wm5100->rev) { | ||
1379 | case 0: | ||
1380 | regcache_cache_bypass(wm5100->regmap, true); | ||
1381 | snd_soc_write(codec, 0x11, 0x3); | ||
1382 | snd_soc_write(codec, 0x203, 0xc); | ||
1383 | snd_soc_write(codec, 0x206, 0); | ||
1384 | snd_soc_write(codec, 0x207, 0xf0); | ||
1385 | snd_soc_write(codec, 0x208, 0x3c); | ||
1386 | snd_soc_write(codec, 0x209, 0); | ||
1387 | snd_soc_write(codec, 0x211, 0x20d8); | ||
1388 | snd_soc_write(codec, 0x11, 0); | ||
1389 | |||
1390 | for (i = 0; | ||
1391 | i < ARRAY_SIZE(wm5100_reva_patches); | ||
1392 | i++) | ||
1393 | snd_soc_write(codec, | ||
1394 | wm5100_reva_patches[i].reg, | ||
1395 | wm5100_reva_patches[i].val); | ||
1396 | regcache_cache_bypass(wm5100->regmap, false); | ||
1397 | break; | ||
1398 | default: | ||
1399 | break; | ||
1400 | } | ||
1401 | |||
1402 | regcache_sync(wm5100->regmap); | ||
1403 | } | ||
1404 | break; | ||
1405 | |||
1406 | case SND_SOC_BIAS_OFF: | ||
1407 | regcache_cache_only(wm5100->regmap, true); | ||
1408 | regcache_mark_dirty(wm5100->regmap); | ||
1409 | if (wm5100->pdata.ldo_ena) | ||
1410 | gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); | ||
1411 | regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), | ||
1412 | wm5100->core_supplies); | ||
1413 | break; | ||
1414 | } | ||
1415 | codec->dapm.bias_level = level; | ||
1416 | |||
1417 | return 0; | ||
1418 | } | ||
1419 | |||
1420 | static int wm5100_dai_to_base(struct snd_soc_dai *dai) | 1268 | static int wm5100_dai_to_base(struct snd_soc_dai *dai) |
1421 | { | 1269 | { |
1422 | switch (dai->id) { | 1270 | switch (dai->id) { |
@@ -1944,6 +1792,8 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
1944 | 1792 | ||
1945 | if (!Fout) { | 1793 | if (!Fout) { |
1946 | dev_dbg(codec->dev, "FLL%d disabled", fll_id); | 1794 | dev_dbg(codec->dev, "FLL%d disabled", fll_id); |
1795 | if (fll->fout) | ||
1796 | pm_runtime_put(codec->dev); | ||
1947 | fll->fout = 0; | 1797 | fll->fout = 0; |
1948 | snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0); | 1798 | snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0); |
1949 | return 0; | 1799 | return 0; |
@@ -1988,6 +1838,8 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
1988 | /* Clear any pending completions */ | 1838 | /* Clear any pending completions */ |
1989 | try_wait_for_completion(&fll->lock); | 1839 | try_wait_for_completion(&fll->lock); |
1990 | 1840 | ||
1841 | pm_runtime_get_sync(codec->dev); | ||
1842 | |||
1991 | snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA); | 1843 | snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA); |
1992 | 1844 | ||
1993 | if (i2c->irq) | 1845 | if (i2c->irq) |
@@ -2022,6 +1874,7 @@ static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2022 | } | 1874 | } |
2023 | if (i == timeout) { | 1875 | if (i == timeout) { |
2024 | dev_err(codec->dev, "FLL%d lock timed out\n", fll_id); | 1876 | dev_err(codec->dev, "FLL%d lock timed out\n", fll_id); |
1877 | pm_runtime_put(codec->dev); | ||
2025 | return -ETIMEDOUT; | 1878 | return -ETIMEDOUT; |
2026 | } | 1879 | } |
2027 | 1880 | ||
@@ -2124,55 +1977,73 @@ static int wm5100_dig_vu[] = { | |||
2124 | WM5100_DAC_DIGITAL_VOLUME_6R, | 1977 | WM5100_DAC_DIGITAL_VOLUME_6R, |
2125 | }; | 1978 | }; |
2126 | 1979 | ||
2127 | static void wm5100_set_detect_mode(struct snd_soc_codec *codec, int the_mode) | 1980 | static void wm5100_set_detect_mode(struct wm5100_priv *wm5100, int the_mode) |
2128 | { | 1981 | { |
2129 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | ||
2130 | struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode]; | 1982 | struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode]; |
2131 | 1983 | ||
2132 | BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes)); | 1984 | BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes)); |
2133 | 1985 | ||
2134 | gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol); | 1986 | gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol); |
2135 | snd_soc_update_bits(codec, WM5100_ACCESSORY_DETECT_MODE_1, | 1987 | regmap_update_bits(wm5100->regmap, WM5100_ACCESSORY_DETECT_MODE_1, |
2136 | WM5100_ACCDET_BIAS_SRC_MASK | | 1988 | WM5100_ACCDET_BIAS_SRC_MASK | |
2137 | WM5100_ACCDET_SRC, | 1989 | WM5100_ACCDET_SRC, |
2138 | (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) | | 1990 | (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) | |
2139 | mode->micd_src << WM5100_ACCDET_SRC_SHIFT); | 1991 | mode->micd_src << WM5100_ACCDET_SRC_SHIFT); |
2140 | snd_soc_update_bits(codec, WM5100_MISC_CONTROL, | 1992 | regmap_update_bits(wm5100->regmap, WM5100_MISC_CONTROL, |
2141 | WM5100_HPCOM_SRC, | 1993 | WM5100_HPCOM_SRC, |
2142 | mode->micd_src << WM5100_HPCOM_SRC_SHIFT); | 1994 | mode->micd_src << WM5100_HPCOM_SRC_SHIFT); |
2143 | 1995 | ||
2144 | wm5100->jack_mode = the_mode; | 1996 | wm5100->jack_mode = the_mode; |
2145 | 1997 | ||
2146 | dev_dbg(codec->dev, "Set microphone polarity to %d\n", | 1998 | dev_dbg(wm5100->dev, "Set microphone polarity to %d\n", |
2147 | wm5100->jack_mode); | 1999 | wm5100->jack_mode); |
2148 | } | 2000 | } |
2149 | 2001 | ||
2150 | static void wm5100_micd_irq(struct snd_soc_codec *codec) | 2002 | static void wm5100_report_headphone(struct wm5100_priv *wm5100) |
2151 | { | 2003 | { |
2152 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | 2004 | dev_dbg(wm5100->dev, "Headphone detected\n"); |
2153 | int val; | 2005 | wm5100->jack_detecting = false; |
2006 | snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE, | ||
2007 | SND_JACK_HEADPHONE); | ||
2008 | |||
2009 | /* Increase the detection rate a bit for responsiveness. */ | ||
2010 | regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1, | ||
2011 | WM5100_ACCDET_RATE_MASK, | ||
2012 | 7 << WM5100_ACCDET_RATE_SHIFT); | ||
2013 | } | ||
2154 | 2014 | ||
2155 | val = snd_soc_read(codec, WM5100_MIC_DETECT_3); | 2015 | static void wm5100_micd_irq(struct wm5100_priv *wm5100) |
2016 | { | ||
2017 | unsigned int val; | ||
2018 | int ret; | ||
2156 | 2019 | ||
2157 | dev_dbg(codec->dev, "Microphone event: %x\n", val); | 2020 | ret = regmap_read(wm5100->regmap, WM5100_MIC_DETECT_3, &val); |
2021 | if (ret != 0) { | ||
2022 | dev_err(wm5100->dev, "Failed to read micropone status: %d\n", | ||
2023 | ret); | ||
2024 | return; | ||
2025 | } | ||
2026 | |||
2027 | dev_dbg(wm5100->dev, "Microphone event: %x\n", val); | ||
2158 | 2028 | ||
2159 | if (!(val & WM5100_ACCDET_VALID)) { | 2029 | if (!(val & WM5100_ACCDET_VALID)) { |
2160 | dev_warn(codec->dev, "Microphone detection state invalid\n"); | 2030 | dev_warn(wm5100->dev, "Microphone detection state invalid\n"); |
2161 | return; | 2031 | return; |
2162 | } | 2032 | } |
2163 | 2033 | ||
2164 | /* No accessory, reset everything and report removal */ | 2034 | /* No accessory, reset everything and report removal */ |
2165 | if (!(val & WM5100_ACCDET_STS)) { | 2035 | if (!(val & WM5100_ACCDET_STS)) { |
2166 | dev_dbg(codec->dev, "Jack removal detected\n"); | 2036 | dev_dbg(wm5100->dev, "Jack removal detected\n"); |
2167 | wm5100->jack_mic = false; | 2037 | wm5100->jack_mic = false; |
2168 | wm5100->jack_detecting = true; | 2038 | wm5100->jack_detecting = true; |
2039 | wm5100->jack_flips = 0; | ||
2169 | snd_soc_jack_report(wm5100->jack, 0, | 2040 | snd_soc_jack_report(wm5100->jack, 0, |
2170 | SND_JACK_LINEOUT | SND_JACK_HEADSET | | 2041 | SND_JACK_LINEOUT | SND_JACK_HEADSET | |
2171 | SND_JACK_BTN_0); | 2042 | SND_JACK_BTN_0); |
2172 | 2043 | ||
2173 | snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, | 2044 | regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1, |
2174 | WM5100_ACCDET_RATE_MASK, | 2045 | WM5100_ACCDET_RATE_MASK, |
2175 | WM5100_ACCDET_RATE_MASK); | 2046 | WM5100_ACCDET_RATE_MASK); |
2176 | return; | 2047 | return; |
2177 | } | 2048 | } |
2178 | 2049 | ||
@@ -2182,7 +2053,7 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec) | |||
2182 | */ | 2053 | */ |
2183 | if (val & 0x400) { | 2054 | if (val & 0x400) { |
2184 | if (wm5100->jack_detecting) { | 2055 | if (wm5100->jack_detecting) { |
2185 | dev_dbg(codec->dev, "Microphone detected\n"); | 2056 | dev_dbg(wm5100->dev, "Microphone detected\n"); |
2186 | wm5100->jack_mic = true; | 2057 | wm5100->jack_mic = true; |
2187 | wm5100->jack_detecting = false; | 2058 | wm5100->jack_detecting = false; |
2188 | snd_soc_jack_report(wm5100->jack, | 2059 | snd_soc_jack_report(wm5100->jack, |
@@ -2191,11 +2062,11 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec) | |||
2191 | 2062 | ||
2192 | /* Increase poll rate to give better responsiveness | 2063 | /* Increase poll rate to give better responsiveness |
2193 | * for buttons */ | 2064 | * for buttons */ |
2194 | snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, | 2065 | regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1, |
2195 | WM5100_ACCDET_RATE_MASK, | 2066 | WM5100_ACCDET_RATE_MASK, |
2196 | 5 << WM5100_ACCDET_RATE_SHIFT); | 2067 | 5 << WM5100_ACCDET_RATE_SHIFT); |
2197 | } else { | 2068 | } else { |
2198 | dev_dbg(codec->dev, "Mic button up\n"); | 2069 | dev_dbg(wm5100->dev, "Mic button up\n"); |
2199 | snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0); | 2070 | snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0); |
2200 | } | 2071 | } |
2201 | 2072 | ||
@@ -2205,10 +2076,16 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec) | |||
2205 | /* If we detected a lower impedence during initial startup | 2076 | /* If we detected a lower impedence during initial startup |
2206 | * then we probably have the wrong polarity, flip it. Don't | 2077 | * then we probably have the wrong polarity, flip it. Don't |
2207 | * do this for the lowest impedences to speed up detection of | 2078 | * do this for the lowest impedences to speed up detection of |
2208 | * plain headphones. | 2079 | * plain headphones and give up if neither polarity looks |
2080 | * sensible. | ||
2209 | */ | 2081 | */ |
2210 | if (wm5100->jack_detecting && (val & 0x3f8)) { | 2082 | if (wm5100->jack_detecting && (val & 0x3f8)) { |
2211 | wm5100_set_detect_mode(codec, !wm5100->jack_mode); | 2083 | wm5100->jack_flips++; |
2084 | |||
2085 | if (wm5100->jack_flips > 1) | ||
2086 | wm5100_report_headphone(wm5100); | ||
2087 | else | ||
2088 | wm5100_set_detect_mode(wm5100, !wm5100->jack_mode); | ||
2212 | 2089 | ||
2213 | return; | 2090 | return; |
2214 | } | 2091 | } |
@@ -2218,21 +2095,11 @@ static void wm5100_micd_irq(struct snd_soc_codec *codec) | |||
2218 | */ | 2095 | */ |
2219 | if (val & 0x3fc) { | 2096 | if (val & 0x3fc) { |
2220 | if (wm5100->jack_mic) { | 2097 | if (wm5100->jack_mic) { |
2221 | dev_dbg(codec->dev, "Mic button detected\n"); | 2098 | dev_dbg(wm5100->dev, "Mic button detected\n"); |
2222 | snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0, | 2099 | snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0, |
2223 | SND_JACK_BTN_0); | 2100 | SND_JACK_BTN_0); |
2224 | } else if (wm5100->jack_detecting) { | 2101 | } else if (wm5100->jack_detecting) { |
2225 | dev_dbg(codec->dev, "Headphone detected\n"); | 2102 | wm5100_report_headphone(wm5100); |
2226 | wm5100->jack_detecting = false; | ||
2227 | snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE, | ||
2228 | SND_JACK_HEADPHONE); | ||
2229 | |||
2230 | /* Increase the detection rate a bit for | ||
2231 | * responsiveness. | ||
2232 | */ | ||
2233 | snd_soc_update_bits(codec, WM5100_MIC_DETECT_1, | ||
2234 | WM5100_ACCDET_RATE_MASK, | ||
2235 | 7 << WM5100_ACCDET_RATE_SHIFT); | ||
2236 | } | 2103 | } |
2237 | } | 2104 | } |
2238 | } | 2105 | } |
@@ -2244,8 +2111,9 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
2244 | if (jack) { | 2111 | if (jack) { |
2245 | wm5100->jack = jack; | 2112 | wm5100->jack = jack; |
2246 | wm5100->jack_detecting = true; | 2113 | wm5100->jack_detecting = true; |
2114 | wm5100->jack_flips = 0; | ||
2247 | 2115 | ||
2248 | wm5100_set_detect_mode(codec, 0); | 2116 | wm5100_set_detect_mode(wm5100, 0); |
2249 | 2117 | ||
2250 | /* Slowest detection rate, gives debounce for initial | 2118 | /* Slowest detection rate, gives debounce for initial |
2251 | * detection */ | 2119 | * detection */ |
@@ -2284,52 +2152,70 @@ int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
2284 | 2152 | ||
2285 | static irqreturn_t wm5100_irq(int irq, void *data) | 2153 | static irqreturn_t wm5100_irq(int irq, void *data) |
2286 | { | 2154 | { |
2287 | struct snd_soc_codec *codec = data; | 2155 | struct wm5100_priv *wm5100 = data; |
2288 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | ||
2289 | irqreturn_t status = IRQ_NONE; | 2156 | irqreturn_t status = IRQ_NONE; |
2290 | int irq_val; | 2157 | unsigned int irq_val, mask_val; |
2158 | int ret; | ||
2291 | 2159 | ||
2292 | irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3); | 2160 | ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, &irq_val); |
2293 | if (irq_val < 0) { | 2161 | if (ret < 0) { |
2294 | dev_err(codec->dev, "Failed to read IRQ status 3: %d\n", | 2162 | dev_err(wm5100->dev, "Failed to read IRQ status 3: %d\n", |
2295 | irq_val); | 2163 | ret); |
2296 | irq_val = 0; | 2164 | irq_val = 0; |
2297 | } | 2165 | } |
2298 | irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_3_MASK); | ||
2299 | 2166 | ||
2300 | snd_soc_write(codec, WM5100_INTERRUPT_STATUS_3, irq_val); | 2167 | ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3_MASK, |
2168 | &mask_val); | ||
2169 | if (ret < 0) { | ||
2170 | dev_err(wm5100->dev, "Failed to read IRQ mask 3: %d\n", | ||
2171 | ret); | ||
2172 | mask_val = 0xffff; | ||
2173 | } | ||
2174 | |||
2175 | irq_val &= ~mask_val; | ||
2176 | |||
2177 | regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, irq_val); | ||
2301 | 2178 | ||
2302 | if (irq_val) | 2179 | if (irq_val) |
2303 | status = IRQ_HANDLED; | 2180 | status = IRQ_HANDLED; |
2304 | 2181 | ||
2305 | wm5100_log_status3(codec, irq_val); | 2182 | wm5100_log_status3(wm5100, irq_val); |
2306 | 2183 | ||
2307 | if (irq_val & WM5100_FLL1_LOCK_EINT) { | 2184 | if (irq_val & WM5100_FLL1_LOCK_EINT) { |
2308 | dev_dbg(codec->dev, "FLL1 locked\n"); | 2185 | dev_dbg(wm5100->dev, "FLL1 locked\n"); |
2309 | complete(&wm5100->fll[0].lock); | 2186 | complete(&wm5100->fll[0].lock); |
2310 | } | 2187 | } |
2311 | if (irq_val & WM5100_FLL2_LOCK_EINT) { | 2188 | if (irq_val & WM5100_FLL2_LOCK_EINT) { |
2312 | dev_dbg(codec->dev, "FLL2 locked\n"); | 2189 | dev_dbg(wm5100->dev, "FLL2 locked\n"); |
2313 | complete(&wm5100->fll[1].lock); | 2190 | complete(&wm5100->fll[1].lock); |
2314 | } | 2191 | } |
2315 | 2192 | ||
2316 | if (irq_val & WM5100_ACCDET_EINT) | 2193 | if (irq_val & WM5100_ACCDET_EINT) |
2317 | wm5100_micd_irq(codec); | 2194 | wm5100_micd_irq(wm5100); |
2318 | 2195 | ||
2319 | irq_val = snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4); | 2196 | ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, &irq_val); |
2320 | if (irq_val < 0) { | 2197 | if (ret < 0) { |
2321 | dev_err(codec->dev, "Failed to read IRQ status 4: %d\n", | 2198 | dev_err(wm5100->dev, "Failed to read IRQ status 4: %d\n", |
2322 | irq_val); | 2199 | ret); |
2323 | irq_val = 0; | 2200 | irq_val = 0; |
2324 | } | 2201 | } |
2325 | irq_val &= ~snd_soc_read(codec, WM5100_INTERRUPT_STATUS_4_MASK); | 2202 | |
2203 | ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4_MASK, | ||
2204 | &mask_val); | ||
2205 | if (ret < 0) { | ||
2206 | dev_err(wm5100->dev, "Failed to read IRQ mask 4: %d\n", | ||
2207 | ret); | ||
2208 | mask_val = 0xffff; | ||
2209 | } | ||
2210 | |||
2211 | irq_val &= ~mask_val; | ||
2326 | 2212 | ||
2327 | if (irq_val) | 2213 | if (irq_val) |
2328 | status = IRQ_HANDLED; | 2214 | status = IRQ_HANDLED; |
2329 | 2215 | ||
2330 | snd_soc_write(codec, WM5100_INTERRUPT_STATUS_4, irq_val); | 2216 | regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, irq_val); |
2331 | 2217 | ||
2332 | wm5100_log_status4(codec, irq_val); | 2218 | wm5100_log_status4(wm5100, irq_val); |
2333 | 2219 | ||
2334 | return status; | 2220 | return status; |
2335 | } | 2221 | } |
@@ -2454,7 +2340,7 @@ static int wm5100_probe(struct snd_soc_codec *codec) | |||
2454 | { | 2340 | { |
2455 | struct i2c_client *i2c = to_i2c_client(codec->dev); | 2341 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
2456 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | 2342 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); |
2457 | int ret, i, irq_flags; | 2343 | int ret, i; |
2458 | 2344 | ||
2459 | wm5100->codec = codec; | 2345 | wm5100->codec = codec; |
2460 | codec->control_data = wm5100->regmap; | 2346 | codec->control_data = wm5100->regmap; |
@@ -2465,9 +2351,6 @@ static int wm5100_probe(struct snd_soc_codec *codec) | |||
2465 | return ret; | 2351 | return ret; |
2466 | } | 2352 | } |
2467 | 2353 | ||
2468 | regcache_cache_only(wm5100->regmap, true); | ||
2469 | |||
2470 | |||
2471 | for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++) | 2354 | for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++) |
2472 | snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU, | 2355 | snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU, |
2473 | WM5100_OUT_VU); | 2356 | WM5100_OUT_VU); |
@@ -2478,60 +2361,10 @@ static int wm5100_probe(struct snd_soc_codec *codec) | |||
2478 | 2361 | ||
2479 | /* TODO: check if we're symmetric */ | 2362 | /* TODO: check if we're symmetric */ |
2480 | 2363 | ||
2481 | if (i2c->irq) { | 2364 | if (i2c->irq) |
2482 | if (wm5100->pdata.irq_flags) | ||
2483 | irq_flags = wm5100->pdata.irq_flags; | ||
2484 | else | ||
2485 | irq_flags = IRQF_TRIGGER_LOW; | ||
2486 | |||
2487 | irq_flags |= IRQF_ONESHOT; | ||
2488 | |||
2489 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) | ||
2490 | ret = request_threaded_irq(i2c->irq, NULL, | ||
2491 | wm5100_edge_irq, | ||
2492 | irq_flags, "wm5100", codec); | ||
2493 | else | ||
2494 | ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq, | ||
2495 | irq_flags, "wm5100", codec); | ||
2496 | |||
2497 | if (ret != 0) { | ||
2498 | dev_err(codec->dev, "Failed to request IRQ %d: %d\n", | ||
2499 | i2c->irq, ret); | ||
2500 | } else { | ||
2501 | /* Enable default interrupts */ | ||
2502 | snd_soc_update_bits(codec, | ||
2503 | WM5100_INTERRUPT_STATUS_3_MASK, | ||
2504 | WM5100_IM_SPK_SHUTDOWN_WARN_EINT | | ||
2505 | WM5100_IM_SPK_SHUTDOWN_EINT | | ||
2506 | WM5100_IM_ASRC2_LOCK_EINT | | ||
2507 | WM5100_IM_ASRC1_LOCK_EINT | | ||
2508 | WM5100_IM_FLL2_LOCK_EINT | | ||
2509 | WM5100_IM_FLL1_LOCK_EINT | | ||
2510 | WM5100_CLKGEN_ERR_EINT | | ||
2511 | WM5100_CLKGEN_ERR_ASYNC_EINT, 0); | ||
2512 | |||
2513 | snd_soc_update_bits(codec, | ||
2514 | WM5100_INTERRUPT_STATUS_4_MASK, | ||
2515 | WM5100_AIF3_ERR_EINT | | ||
2516 | WM5100_AIF2_ERR_EINT | | ||
2517 | WM5100_AIF1_ERR_EINT | | ||
2518 | WM5100_CTRLIF_ERR_EINT | | ||
2519 | WM5100_ISRC2_UNDERCLOCKED_EINT | | ||
2520 | WM5100_ISRC1_UNDERCLOCKED_EINT | | ||
2521 | WM5100_FX_UNDERCLOCKED_EINT | | ||
2522 | WM5100_AIF3_UNDERCLOCKED_EINT | | ||
2523 | WM5100_AIF2_UNDERCLOCKED_EINT | | ||
2524 | WM5100_AIF1_UNDERCLOCKED_EINT | | ||
2525 | WM5100_ASRC_UNDERCLOCKED_EINT | | ||
2526 | WM5100_DAC_UNDERCLOCKED_EINT | | ||
2527 | WM5100_ADC_UNDERCLOCKED_EINT | | ||
2528 | WM5100_MIXER_UNDERCLOCKED_EINT, 0); | ||
2529 | } | ||
2530 | } else { | ||
2531 | snd_soc_dapm_new_controls(&codec->dapm, | 2365 | snd_soc_dapm_new_controls(&codec->dapm, |
2532 | wm5100_dapm_widgets_noirq, | 2366 | wm5100_dapm_widgets_noirq, |
2533 | ARRAY_SIZE(wm5100_dapm_widgets_noirq)); | 2367 | ARRAY_SIZE(wm5100_dapm_widgets_noirq)); |
2534 | } | ||
2535 | 2368 | ||
2536 | if (wm5100->pdata.hp_pol) { | 2369 | if (wm5100->pdata.hp_pol) { |
2537 | ret = gpio_request_one(wm5100->pdata.hp_pol, | 2370 | ret = gpio_request_one(wm5100->pdata.hp_pol, |
@@ -2543,19 +2376,9 @@ static int wm5100_probe(struct snd_soc_codec *codec) | |||
2543 | } | 2376 | } |
2544 | } | 2377 | } |
2545 | 2378 | ||
2546 | /* We'll get woken up again when the system has something useful | ||
2547 | * for us to do. | ||
2548 | */ | ||
2549 | if (wm5100->pdata.ldo_ena) | ||
2550 | gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); | ||
2551 | regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), | ||
2552 | wm5100->core_supplies); | ||
2553 | |||
2554 | return 0; | 2379 | return 0; |
2555 | 2380 | ||
2556 | err_gpio: | 2381 | err_gpio: |
2557 | if (i2c->irq) | ||
2558 | free_irq(i2c->irq, codec); | ||
2559 | 2382 | ||
2560 | return ret; | 2383 | return ret; |
2561 | } | 2384 | } |
@@ -2563,14 +2386,11 @@ err_gpio: | |||
2563 | static int wm5100_remove(struct snd_soc_codec *codec) | 2386 | static int wm5100_remove(struct snd_soc_codec *codec) |
2564 | { | 2387 | { |
2565 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); | 2388 | struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec); |
2566 | struct i2c_client *i2c = to_i2c_client(codec->dev); | ||
2567 | 2389 | ||
2568 | wm5100_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
2569 | if (wm5100->pdata.hp_pol) { | 2390 | if (wm5100->pdata.hp_pol) { |
2570 | gpio_free(wm5100->pdata.hp_pol); | 2391 | gpio_free(wm5100->pdata.hp_pol); |
2571 | } | 2392 | } |
2572 | if (i2c->irq) | 2393 | |
2573 | free_irq(i2c->irq, codec); | ||
2574 | return 0; | 2394 | return 0; |
2575 | } | 2395 | } |
2576 | 2396 | ||
@@ -2587,7 +2407,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5100 = { | |||
2587 | 2407 | ||
2588 | .set_sysclk = wm5100_set_sysclk, | 2408 | .set_sysclk = wm5100_set_sysclk, |
2589 | .set_pll = wm5100_set_fll, | 2409 | .set_pll = wm5100_set_fll, |
2590 | .set_bias_level = wm5100_set_bias_level, | ||
2591 | .idle_bias_off = 1, | 2410 | .idle_bias_off = 1, |
2592 | .reg_cache_size = WM5100_MAX_REGISTER, | 2411 | .reg_cache_size = WM5100_MAX_REGISTER, |
2593 | .volatile_register = wm5100_soc_volatile, | 2412 | .volatile_register = wm5100_soc_volatile, |
@@ -2626,13 +2445,15 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, | |||
2626 | struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev); | 2445 | struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev); |
2627 | struct wm5100_priv *wm5100; | 2446 | struct wm5100_priv *wm5100; |
2628 | unsigned int reg; | 2447 | unsigned int reg; |
2629 | int ret, i; | 2448 | int ret, i, irq_flags; |
2630 | 2449 | ||
2631 | wm5100 = devm_kzalloc(&i2c->dev, sizeof(struct wm5100_priv), | 2450 | wm5100 = devm_kzalloc(&i2c->dev, sizeof(struct wm5100_priv), |
2632 | GFP_KERNEL); | 2451 | GFP_KERNEL); |
2633 | if (wm5100 == NULL) | 2452 | if (wm5100 == NULL) |
2634 | return -ENOMEM; | 2453 | return -ENOMEM; |
2635 | 2454 | ||
2455 | wm5100->dev = &i2c->dev; | ||
2456 | |||
2636 | wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap); | 2457 | wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap); |
2637 | if (IS_ERR(wm5100->regmap)) { | 2458 | if (IS_ERR(wm5100->regmap)) { |
2638 | ret = PTR_ERR(wm5100->regmap); | 2459 | ret = PTR_ERR(wm5100->regmap); |
@@ -2652,41 +2473,21 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, | |||
2652 | for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++) | 2473 | for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++) |
2653 | wm5100->core_supplies[i].supply = wm5100_core_supply_names[i]; | 2474 | wm5100->core_supplies[i].supply = wm5100_core_supply_names[i]; |
2654 | 2475 | ||
2655 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm5100->core_supplies), | 2476 | ret = devm_regulator_bulk_get(&i2c->dev, |
2656 | wm5100->core_supplies); | 2477 | ARRAY_SIZE(wm5100->core_supplies), |
2478 | wm5100->core_supplies); | ||
2657 | if (ret != 0) { | 2479 | if (ret != 0) { |
2658 | dev_err(&i2c->dev, "Failed to request core supplies: %d\n", | 2480 | dev_err(&i2c->dev, "Failed to request core supplies: %d\n", |
2659 | ret); | 2481 | ret); |
2660 | goto err_regmap; | 2482 | goto err_regmap; |
2661 | } | 2483 | } |
2662 | 2484 | ||
2663 | wm5100->cpvdd = regulator_get(&i2c->dev, "CPVDD"); | ||
2664 | if (IS_ERR(wm5100->cpvdd)) { | ||
2665 | ret = PTR_ERR(wm5100->cpvdd); | ||
2666 | dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret); | ||
2667 | goto err_core; | ||
2668 | } | ||
2669 | |||
2670 | wm5100->dbvdd2 = regulator_get(&i2c->dev, "DBVDD2"); | ||
2671 | if (IS_ERR(wm5100->dbvdd2)) { | ||
2672 | ret = PTR_ERR(wm5100->dbvdd2); | ||
2673 | dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret); | ||
2674 | goto err_cpvdd; | ||
2675 | } | ||
2676 | |||
2677 | wm5100->dbvdd3 = regulator_get(&i2c->dev, "DBVDD3"); | ||
2678 | if (IS_ERR(wm5100->dbvdd3)) { | ||
2679 | ret = PTR_ERR(wm5100->dbvdd3); | ||
2680 | dev_err(&i2c->dev, "Failed to get DBVDD2: %d\n", ret); | ||
2681 | goto err_dbvdd2; | ||
2682 | } | ||
2683 | |||
2684 | ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies), | 2485 | ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies), |
2685 | wm5100->core_supplies); | 2486 | wm5100->core_supplies); |
2686 | if (ret != 0) { | 2487 | if (ret != 0) { |
2687 | dev_err(&i2c->dev, "Failed to enable core supplies: %d\n", | 2488 | dev_err(&i2c->dev, "Failed to enable core supplies: %d\n", |
2688 | ret); | 2489 | ret); |
2689 | goto err_dbvdd3; | 2490 | goto err_regmap; |
2690 | } | 2491 | } |
2691 | 2492 | ||
2692 | if (wm5100->pdata.ldo_ena) { | 2493 | if (wm5100->pdata.ldo_ena) { |
@@ -2712,7 +2513,7 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, | |||
2712 | 2513 | ||
2713 | ret = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, ®); | 2514 | ret = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, ®); |
2714 | if (ret < 0) { | 2515 | if (ret < 0) { |
2715 | dev_err(&i2c->dev, "Failed to read ID register\n"); | 2516 | dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret); |
2716 | goto err_reset; | 2517 | goto err_reset; |
2717 | } | 2518 | } |
2718 | switch (reg) { | 2519 | switch (reg) { |
@@ -2741,6 +2542,22 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, | |||
2741 | goto err_reset; | 2542 | goto err_reset; |
2742 | } | 2543 | } |
2743 | 2544 | ||
2545 | switch (wm5100->rev) { | ||
2546 | case 0: | ||
2547 | ret = regmap_register_patch(wm5100->regmap, | ||
2548 | wm5100_reva_patches, | ||
2549 | ARRAY_SIZE(wm5100_reva_patches)); | ||
2550 | if (ret != 0) { | ||
2551 | dev_err(&i2c->dev, "Failed to register patches: %d\n", | ||
2552 | ret); | ||
2553 | goto err_reset; | ||
2554 | } | ||
2555 | break; | ||
2556 | default: | ||
2557 | break; | ||
2558 | } | ||
2559 | |||
2560 | |||
2744 | wm5100_init_gpio(i2c); | 2561 | wm5100_init_gpio(i2c); |
2745 | 2562 | ||
2746 | for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) { | 2563 | for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) { |
@@ -2761,6 +2578,62 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, | |||
2761 | WM5100_IN1_DMIC_SUP_SHIFT)); | 2578 | WM5100_IN1_DMIC_SUP_SHIFT)); |
2762 | } | 2579 | } |
2763 | 2580 | ||
2581 | if (i2c->irq) { | ||
2582 | if (wm5100->pdata.irq_flags) | ||
2583 | irq_flags = wm5100->pdata.irq_flags; | ||
2584 | else | ||
2585 | irq_flags = IRQF_TRIGGER_LOW; | ||
2586 | |||
2587 | irq_flags |= IRQF_ONESHOT; | ||
2588 | |||
2589 | if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) | ||
2590 | ret = request_threaded_irq(i2c->irq, NULL, | ||
2591 | wm5100_edge_irq, irq_flags, | ||
2592 | "wm5100", wm5100); | ||
2593 | else | ||
2594 | ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq, | ||
2595 | irq_flags, "wm5100", | ||
2596 | wm5100); | ||
2597 | |||
2598 | if (ret != 0) { | ||
2599 | dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n", | ||
2600 | i2c->irq, ret); | ||
2601 | } else { | ||
2602 | /* Enable default interrupts */ | ||
2603 | regmap_update_bits(wm5100->regmap, | ||
2604 | WM5100_INTERRUPT_STATUS_3_MASK, | ||
2605 | WM5100_IM_SPK_SHUTDOWN_WARN_EINT | | ||
2606 | WM5100_IM_SPK_SHUTDOWN_EINT | | ||
2607 | WM5100_IM_ASRC2_LOCK_EINT | | ||
2608 | WM5100_IM_ASRC1_LOCK_EINT | | ||
2609 | WM5100_IM_FLL2_LOCK_EINT | | ||
2610 | WM5100_IM_FLL1_LOCK_EINT | | ||
2611 | WM5100_CLKGEN_ERR_EINT | | ||
2612 | WM5100_CLKGEN_ERR_ASYNC_EINT, 0); | ||
2613 | |||
2614 | regmap_update_bits(wm5100->regmap, | ||
2615 | WM5100_INTERRUPT_STATUS_4_MASK, | ||
2616 | WM5100_AIF3_ERR_EINT | | ||
2617 | WM5100_AIF2_ERR_EINT | | ||
2618 | WM5100_AIF1_ERR_EINT | | ||
2619 | WM5100_CTRLIF_ERR_EINT | | ||
2620 | WM5100_ISRC2_UNDERCLOCKED_EINT | | ||
2621 | WM5100_ISRC1_UNDERCLOCKED_EINT | | ||
2622 | WM5100_FX_UNDERCLOCKED_EINT | | ||
2623 | WM5100_AIF3_UNDERCLOCKED_EINT | | ||
2624 | WM5100_AIF2_UNDERCLOCKED_EINT | | ||
2625 | WM5100_AIF1_UNDERCLOCKED_EINT | | ||
2626 | WM5100_ASRC_UNDERCLOCKED_EINT | | ||
2627 | WM5100_DAC_UNDERCLOCKED_EINT | | ||
2628 | WM5100_ADC_UNDERCLOCKED_EINT | | ||
2629 | WM5100_MIXER_UNDERCLOCKED_EINT, 0); | ||
2630 | } | ||
2631 | } | ||
2632 | |||
2633 | pm_runtime_set_active(&i2c->dev); | ||
2634 | pm_runtime_enable(&i2c->dev); | ||
2635 | pm_request_idle(&i2c->dev); | ||
2636 | |||
2764 | ret = snd_soc_register_codec(&i2c->dev, | 2637 | ret = snd_soc_register_codec(&i2c->dev, |
2765 | &soc_codec_dev_wm5100, wm5100_dai, | 2638 | &soc_codec_dev_wm5100, wm5100_dai, |
2766 | ARRAY_SIZE(wm5100_dai)); | 2639 | ARRAY_SIZE(wm5100_dai)); |
@@ -2772,9 +2645,11 @@ static __devinit int wm5100_i2c_probe(struct i2c_client *i2c, | |||
2772 | return ret; | 2645 | return ret; |
2773 | 2646 | ||
2774 | err_reset: | 2647 | err_reset: |
2648 | if (i2c->irq) | ||
2649 | free_irq(i2c->irq, wm5100); | ||
2775 | wm5100_free_gpio(i2c); | 2650 | wm5100_free_gpio(i2c); |
2776 | if (wm5100->pdata.reset) { | 2651 | if (wm5100->pdata.reset) { |
2777 | gpio_set_value_cansleep(wm5100->pdata.reset, 1); | 2652 | gpio_set_value_cansleep(wm5100->pdata.reset, 0); |
2778 | gpio_free(wm5100->pdata.reset); | 2653 | gpio_free(wm5100->pdata.reset); |
2779 | } | 2654 | } |
2780 | err_ldo: | 2655 | err_ldo: |
@@ -2785,45 +2660,78 @@ err_ldo: | |||
2785 | err_enable: | 2660 | err_enable: |
2786 | regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), | 2661 | regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), |
2787 | wm5100->core_supplies); | 2662 | wm5100->core_supplies); |
2788 | err_dbvdd3: | ||
2789 | regulator_put(wm5100->dbvdd3); | ||
2790 | err_dbvdd2: | ||
2791 | regulator_put(wm5100->dbvdd2); | ||
2792 | err_cpvdd: | ||
2793 | regulator_put(wm5100->cpvdd); | ||
2794 | err_core: | ||
2795 | regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies), | ||
2796 | wm5100->core_supplies); | ||
2797 | err_regmap: | 2663 | err_regmap: |
2798 | regmap_exit(wm5100->regmap); | 2664 | regmap_exit(wm5100->regmap); |
2799 | err: | 2665 | err: |
2800 | return ret; | 2666 | return ret; |
2801 | } | 2667 | } |
2802 | 2668 | ||
2803 | static __devexit int wm5100_i2c_remove(struct i2c_client *client) | 2669 | static __devexit int wm5100_i2c_remove(struct i2c_client *i2c) |
2804 | { | 2670 | { |
2805 | struct wm5100_priv *wm5100 = i2c_get_clientdata(client); | 2671 | struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c); |
2806 | 2672 | ||
2807 | snd_soc_unregister_codec(&client->dev); | 2673 | snd_soc_unregister_codec(&i2c->dev); |
2808 | wm5100_free_gpio(client); | 2674 | if (i2c->irq) |
2675 | free_irq(i2c->irq, wm5100); | ||
2676 | wm5100_free_gpio(i2c); | ||
2809 | if (wm5100->pdata.reset) { | 2677 | if (wm5100->pdata.reset) { |
2810 | gpio_set_value_cansleep(wm5100->pdata.reset, 1); | 2678 | gpio_set_value_cansleep(wm5100->pdata.reset, 0); |
2811 | gpio_free(wm5100->pdata.reset); | 2679 | gpio_free(wm5100->pdata.reset); |
2812 | } | 2680 | } |
2813 | if (wm5100->pdata.ldo_ena) { | 2681 | if (wm5100->pdata.ldo_ena) { |
2814 | gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); | 2682 | gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); |
2815 | gpio_free(wm5100->pdata.ldo_ena); | 2683 | gpio_free(wm5100->pdata.ldo_ena); |
2816 | } | 2684 | } |
2817 | regulator_put(wm5100->dbvdd3); | ||
2818 | regulator_put(wm5100->dbvdd2); | ||
2819 | regulator_put(wm5100->cpvdd); | ||
2820 | regulator_bulk_free(ARRAY_SIZE(wm5100->core_supplies), | ||
2821 | wm5100->core_supplies); | ||
2822 | regmap_exit(wm5100->regmap); | 2685 | regmap_exit(wm5100->regmap); |
2823 | 2686 | ||
2824 | return 0; | 2687 | return 0; |
2825 | } | 2688 | } |
2826 | 2689 | ||
2690 | #ifdef CONFIG_PM_RUNTIME | ||
2691 | static int wm5100_runtime_suspend(struct device *dev) | ||
2692 | { | ||
2693 | struct wm5100_priv *wm5100 = dev_get_drvdata(dev); | ||
2694 | |||
2695 | regcache_cache_only(wm5100->regmap, true); | ||
2696 | regcache_mark_dirty(wm5100->regmap); | ||
2697 | if (wm5100->pdata.ldo_ena) | ||
2698 | gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); | ||
2699 | regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies), | ||
2700 | wm5100->core_supplies); | ||
2701 | |||
2702 | return 0; | ||
2703 | } | ||
2704 | |||
2705 | static int wm5100_runtime_resume(struct device *dev) | ||
2706 | { | ||
2707 | struct wm5100_priv *wm5100 = dev_get_drvdata(dev); | ||
2708 | int ret; | ||
2709 | |||
2710 | ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies), | ||
2711 | wm5100->core_supplies); | ||
2712 | if (ret != 0) { | ||
2713 | dev_err(dev, "Failed to enable supplies: %d\n", | ||
2714 | ret); | ||
2715 | return ret; | ||
2716 | } | ||
2717 | |||
2718 | if (wm5100->pdata.ldo_ena) { | ||
2719 | gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 1); | ||
2720 | msleep(2); | ||
2721 | } | ||
2722 | |||
2723 | regcache_cache_only(wm5100->regmap, false); | ||
2724 | regcache_sync(wm5100->regmap); | ||
2725 | |||
2726 | return 0; | ||
2727 | } | ||
2728 | #endif | ||
2729 | |||
2730 | static struct dev_pm_ops wm5100_pm = { | ||
2731 | SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume, | ||
2732 | NULL) | ||
2733 | }; | ||
2734 | |||
2827 | static const struct i2c_device_id wm5100_i2c_id[] = { | 2735 | static const struct i2c_device_id wm5100_i2c_id[] = { |
2828 | { "wm5100", 0 }, | 2736 | { "wm5100", 0 }, |
2829 | { } | 2737 | { } |
@@ -2834,6 +2742,7 @@ static struct i2c_driver wm5100_i2c_driver = { | |||
2834 | .driver = { | 2742 | .driver = { |
2835 | .name = "wm5100", | 2743 | .name = "wm5100", |
2836 | .owner = THIS_MODULE, | 2744 | .owner = THIS_MODULE, |
2745 | .pm = &wm5100_pm, | ||
2837 | }, | 2746 | }, |
2838 | .probe = wm5100_i2c_probe, | 2747 | .probe = wm5100_i2c_probe, |
2839 | .remove = __devexit_p(wm5100_i2c_remove), | 2748 | .remove = __devexit_p(wm5100_i2c_remove), |