Commit 246693ba7b0b824a970f9431486ad88c18e0ce2d
Committed by
Mark Brown
1 parent
54ac045026
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
ASoC: rt5640: change widget sequence for depop
Signed-off-by: Bard Liao <bardliao@realtek.com> Tested-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Showing 2 changed files with 175 additions and 54 deletions Side-by-side Diff
sound/soc/codecs/rt5640.c
... | ... | @@ -50,8 +50,6 @@ |
50 | 50 | |
51 | 51 | static struct reg_default init_list[] = { |
52 | 52 | {RT5640_PR_BASE + 0x3d, 0x3600}, |
53 | - {RT5640_PR_BASE + 0x1c, 0x0D21}, | |
54 | - {RT5640_PR_BASE + 0x1b, 0x0000}, | |
55 | 53 | {RT5640_PR_BASE + 0x12, 0x0aa8}, |
56 | 54 | {RT5640_PR_BASE + 0x14, 0x0aaa}, |
57 | 55 | {RT5640_PR_BASE + 0x20, 0x6110}, |
58 | 56 | |
... | ... | @@ -384,15 +382,11 @@ |
384 | 382 | |
385 | 383 | static const struct snd_kcontrol_new rt5640_snd_controls[] = { |
386 | 384 | /* Speaker Output Volume */ |
387 | - SOC_DOUBLE("Speaker Playback Switch", RT5640_SPK_VOL, | |
388 | - RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1), | |
389 | 385 | SOC_DOUBLE("Speaker Channel Switch", RT5640_SPK_VOL, |
390 | 386 | RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1), |
391 | 387 | SOC_DOUBLE_TLV("Speaker Playback Volume", RT5640_SPK_VOL, |
392 | 388 | RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 39, 1, out_vol_tlv), |
393 | 389 | /* Headphone Output Volume */ |
394 | - SOC_DOUBLE("HP Playback Switch", RT5640_HP_VOL, | |
395 | - RT5640_L_MUTE_SFT, RT5640_R_MUTE_SFT, 1, 1), | |
396 | 390 | SOC_DOUBLE("HP Channel Switch", RT5640_HP_VOL, |
397 | 391 | RT5640_VOL_L_SFT, RT5640_VOL_R_SFT, 1, 1), |
398 | 392 | SOC_DOUBLE_TLV("HP Playback Volume", RT5640_HP_VOL, |
... | ... | @@ -737,6 +731,22 @@ |
737 | 731 | RT5640_M_BST1_MM_SFT, 1, 1), |
738 | 732 | }; |
739 | 733 | |
734 | +static const struct snd_kcontrol_new spk_l_enable_control = | |
735 | + SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL, | |
736 | + RT5640_L_MUTE_SFT, 1, 1); | |
737 | + | |
738 | +static const struct snd_kcontrol_new spk_r_enable_control = | |
739 | + SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_SPK_VOL, | |
740 | + RT5640_R_MUTE_SFT, 1, 1); | |
741 | + | |
742 | +static const struct snd_kcontrol_new hp_l_enable_control = | |
743 | + SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_HP_VOL, | |
744 | + RT5640_L_MUTE_SFT, 1, 1); | |
745 | + | |
746 | +static const struct snd_kcontrol_new hp_r_enable_control = | |
747 | + SOC_DAPM_SINGLE_AUTODISABLE("Switch", RT5640_HP_VOL, | |
748 | + RT5640_R_MUTE_SFT, 1, 1); | |
749 | + | |
740 | 750 | /* Stereo ADC source */ |
741 | 751 | static const char * const rt5640_stereo_adc1_src[] = { |
742 | 752 | "DIG MIX", "ADC" |
... | ... | @@ -868,33 +878,6 @@ |
868 | 878 | static const struct snd_kcontrol_new rt5640_sdi_mux = |
869 | 879 | SOC_DAPM_ENUM("SDI select", rt5640_sdi_sel_enum); |
870 | 880 | |
871 | -static int spk_event(struct snd_soc_dapm_widget *w, | |
872 | - struct snd_kcontrol *kcontrol, int event) | |
873 | -{ | |
874 | - struct snd_soc_codec *codec = w->codec; | |
875 | - struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | |
876 | - | |
877 | - switch (event) { | |
878 | - case SND_SOC_DAPM_POST_PMU: | |
879 | - regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1, | |
880 | - 0x0001, 0x0001); | |
881 | - regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c, | |
882 | - 0xf000, 0xf000); | |
883 | - break; | |
884 | - | |
885 | - case SND_SOC_DAPM_PRE_PMD: | |
886 | - regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + 0x1c, | |
887 | - 0xf000, 0x0000); | |
888 | - regmap_update_bits(rt5640->regmap, RT5640_PWR_DIG1, | |
889 | - 0x0001, 0x0000); | |
890 | - break; | |
891 | - | |
892 | - default: | |
893 | - return 0; | |
894 | - } | |
895 | - return 0; | |
896 | -} | |
897 | - | |
898 | 881 | static int rt5640_set_dmic1_event(struct snd_soc_dapm_widget *w, |
899 | 882 | struct snd_kcontrol *kcontrol, int event) |
900 | 883 | { |
... | ... | @@ -943,6 +926,117 @@ |
943 | 926 | return 0; |
944 | 927 | } |
945 | 928 | |
929 | +void hp_amp_power_on(struct snd_soc_codec *codec) | |
930 | +{ | |
931 | + struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | |
932 | + | |
933 | + /* depop parameters */ | |
934 | + regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + | |
935 | + RT5640_CHPUMP_INT_REG1, 0x0700, 0x0200); | |
936 | + regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M2, | |
937 | + RT5640_DEPOP_MASK, RT5640_DEPOP_MAN); | |
938 | + regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1, | |
939 | + RT5640_HP_CP_MASK | RT5640_HP_SG_MASK | RT5640_HP_CB_MASK, | |
940 | + RT5640_HP_CP_PU | RT5640_HP_SG_DIS | RT5640_HP_CB_PU); | |
941 | + regmap_write(rt5640->regmap, RT5640_PR_BASE + RT5640_HP_DCC_INT1, | |
942 | + 0x9f00); | |
943 | + /* headphone amp power on */ | |
944 | + regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1, | |
945 | + RT5640_PWR_FV1 | RT5640_PWR_FV2, 0); | |
946 | + regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1, | |
947 | + RT5640_PWR_HA, | |
948 | + RT5640_PWR_HA); | |
949 | + usleep_range(10000, 15000); | |
950 | + regmap_update_bits(rt5640->regmap, RT5640_PWR_ANLG1, | |
951 | + RT5640_PWR_FV1 | RT5640_PWR_FV2 , | |
952 | + RT5640_PWR_FV1 | RT5640_PWR_FV2); | |
953 | +} | |
954 | + | |
955 | +static void rt5640_pmu_depop(struct snd_soc_codec *codec) | |
956 | +{ | |
957 | + struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | |
958 | + | |
959 | + regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M2, | |
960 | + RT5640_DEPOP_MASK | RT5640_DIG_DP_MASK, | |
961 | + RT5640_DEPOP_AUTO | RT5640_DIG_DP_EN); | |
962 | + regmap_update_bits(rt5640->regmap, RT5640_CHARGE_PUMP, | |
963 | + RT5640_PM_HP_MASK, RT5640_PM_HP_HV); | |
964 | + | |
965 | + regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M3, | |
966 | + RT5640_CP_FQ1_MASK | RT5640_CP_FQ2_MASK | RT5640_CP_FQ3_MASK, | |
967 | + (RT5640_CP_FQ_192_KHZ << RT5640_CP_FQ1_SFT) | | |
968 | + (RT5640_CP_FQ_12_KHZ << RT5640_CP_FQ2_SFT) | | |
969 | + (RT5640_CP_FQ_192_KHZ << RT5640_CP_FQ3_SFT)); | |
970 | + | |
971 | + regmap_write(rt5640->regmap, RT5640_PR_BASE + | |
972 | + RT5640_MAMP_INT_REG2, 0x1c00); | |
973 | + regmap_update_bits(rt5640->regmap, RT5640_DEPOP_M1, | |
974 | + RT5640_HP_CP_MASK | RT5640_HP_SG_MASK, | |
975 | + RT5640_HP_CP_PD | RT5640_HP_SG_EN); | |
976 | + regmap_update_bits(rt5640->regmap, RT5640_PR_BASE + | |
977 | + RT5640_CHPUMP_INT_REG1, 0x0700, 0x0400); | |
978 | +} | |
979 | + | |
980 | +static int rt5640_hp_event(struct snd_soc_dapm_widget *w, | |
981 | + struct snd_kcontrol *kcontrol, int event) | |
982 | +{ | |
983 | + struct snd_soc_codec *codec = w->codec; | |
984 | + struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | |
985 | + | |
986 | + switch (event) { | |
987 | + case SND_SOC_DAPM_POST_PMU: | |
988 | + rt5640_pmu_depop(codec); | |
989 | + rt5640->hp_mute = 0; | |
990 | + break; | |
991 | + | |
992 | + case SND_SOC_DAPM_PRE_PMD: | |
993 | + rt5640->hp_mute = 1; | |
994 | + usleep_range(70000, 75000); | |
995 | + break; | |
996 | + | |
997 | + default: | |
998 | + return 0; | |
999 | + } | |
1000 | + | |
1001 | + return 0; | |
1002 | +} | |
1003 | + | |
1004 | +static int rt5640_hp_power_event(struct snd_soc_dapm_widget *w, | |
1005 | + struct snd_kcontrol *kcontrol, int event) | |
1006 | +{ | |
1007 | + struct snd_soc_codec *codec = w->codec; | |
1008 | + | |
1009 | + switch (event) { | |
1010 | + case SND_SOC_DAPM_POST_PMU: | |
1011 | + hp_amp_power_on(codec); | |
1012 | + break; | |
1013 | + default: | |
1014 | + return 0; | |
1015 | + } | |
1016 | + | |
1017 | + return 0; | |
1018 | +} | |
1019 | + | |
1020 | +static int rt5640_hp_post_event(struct snd_soc_dapm_widget *w, | |
1021 | + struct snd_kcontrol *kcontrol, int event) | |
1022 | +{ | |
1023 | + struct snd_soc_codec *codec = w->codec; | |
1024 | + struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); | |
1025 | + | |
1026 | + switch (event) { | |
1027 | + case SND_SOC_DAPM_POST_PMU: | |
1028 | + if (!rt5640->hp_mute) | |
1029 | + usleep_range(80000, 85000); | |
1030 | + | |
1031 | + break; | |
1032 | + | |
1033 | + default: | |
1034 | + return 0; | |
1035 | + } | |
1036 | + | |
1037 | + return 0; | |
1038 | +} | |
1039 | + | |
946 | 1040 | static const struct snd_soc_dapm_widget rt5640_dapm_widgets[] = { |
947 | 1041 | SND_SOC_DAPM_SUPPLY("PLL1", RT5640_PWR_ANLG2, |
948 | 1042 | RT5640_PWR_PLL_BIT, 0, NULL, 0), |
949 | 1043 | |
950 | 1044 | |
... | ... | @@ -1132,15 +1226,28 @@ |
1132 | 1226 | rt5640_mono_mix, ARRAY_SIZE(rt5640_mono_mix)), |
1133 | 1227 | SND_SOC_DAPM_SUPPLY("Improve MONO Amp Drv", RT5640_PWR_ANLG1, |
1134 | 1228 | RT5640_PWR_MA_BIT, 0, NULL, 0), |
1135 | - SND_SOC_DAPM_SUPPLY("Improve HP Amp Drv", RT5640_PWR_ANLG1, | |
1136 | - SND_SOC_NOPM, 0, NULL, 0), | |
1137 | - SND_SOC_DAPM_PGA("HP L Amp", RT5640_PWR_ANLG1, | |
1229 | + SND_SOC_DAPM_SUPPLY_S("Improve HP Amp Drv", 1, SND_SOC_NOPM, | |
1230 | + 0, 0, rt5640_hp_power_event, SND_SOC_DAPM_POST_PMU), | |
1231 | + SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, | |
1232 | + rt5640_hp_event, | |
1233 | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
1234 | + SND_SOC_DAPM_SUPPLY("HP L Amp", RT5640_PWR_ANLG1, | |
1138 | 1235 | RT5640_PWR_HP_L_BIT, 0, NULL, 0), |
1139 | - SND_SOC_DAPM_PGA("HP R Amp", RT5640_PWR_ANLG1, | |
1236 | + SND_SOC_DAPM_SUPPLY("HP R Amp", RT5640_PWR_ANLG1, | |
1140 | 1237 | RT5640_PWR_HP_R_BIT, 0, NULL, 0), |
1141 | 1238 | SND_SOC_DAPM_SUPPLY("Improve SPK Amp Drv", RT5640_PWR_DIG1, |
1142 | - SND_SOC_NOPM, 0, spk_event, | |
1143 | - SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | |
1239 | + RT5640_PWR_CLS_D_BIT, 0, NULL, 0), | |
1240 | + | |
1241 | + /* Output Switch */ | |
1242 | + SND_SOC_DAPM_SWITCH("Speaker L Playback", SND_SOC_NOPM, 0, 0, | |
1243 | + &spk_l_enable_control), | |
1244 | + SND_SOC_DAPM_SWITCH("Speaker R Playback", SND_SOC_NOPM, 0, 0, | |
1245 | + &spk_r_enable_control), | |
1246 | + SND_SOC_DAPM_SWITCH("HP L Playback", SND_SOC_NOPM, 0, 0, | |
1247 | + &hp_l_enable_control), | |
1248 | + SND_SOC_DAPM_SWITCH("HP R Playback", SND_SOC_NOPM, 0, 0, | |
1249 | + &hp_r_enable_control), | |
1250 | + SND_SOC_DAPM_POST("HP Post", rt5640_hp_post_event), | |
1144 | 1251 | /* Output Lines */ |
1145 | 1252 | SND_SOC_DAPM_OUTPUT("SPOLP"), |
1146 | 1253 | SND_SOC_DAPM_OUTPUT("SPOLN"), |
1147 | 1254 | |
... | ... | @@ -1381,9 +1488,11 @@ |
1381 | 1488 | {"HPO MIX L", "HPO MIX DAC2 Switch", "DAC L2"}, |
1382 | 1489 | {"HPO MIX L", "HPO MIX DAC1 Switch", "DAC L1"}, |
1383 | 1490 | {"HPO MIX L", "HPO MIX HPVOL Switch", "HPOVOL L"}, |
1491 | + {"HPO MIX L", NULL, "HP L Amp"}, | |
1384 | 1492 | {"HPO MIX R", "HPO MIX DAC2 Switch", "DAC R2"}, |
1385 | 1493 | {"HPO MIX R", "HPO MIX DAC1 Switch", "DAC R1"}, |
1386 | 1494 | {"HPO MIX R", "HPO MIX HPVOL Switch", "HPOVOL R"}, |
1495 | + {"HPO MIX R", NULL, "HP R Amp"}, | |
1387 | 1496 | |
1388 | 1497 | {"LOUT MIX", "DAC L1 Switch", "DAC L1"}, |
1389 | 1498 | {"LOUT MIX", "DAC R1 Switch", "DAC R1"}, |
1390 | 1499 | |
... | ... | @@ -1396,13 +1505,15 @@ |
1396 | 1505 | {"Mono MIX", "OUTVOL L Switch", "OUTVOL L"}, |
1397 | 1506 | {"Mono MIX", "BST1 Switch", "BST1"}, |
1398 | 1507 | |
1399 | - {"HP L Amp", NULL, "HPO MIX L"}, | |
1400 | - {"HP R Amp", NULL, "HPO MIX R"}, | |
1508 | + {"HP Amp", NULL, "HPO MIX L"}, | |
1509 | + {"HP Amp", NULL, "HPO MIX R"}, | |
1401 | 1510 | |
1402 | - {"SPOLP", NULL, "SPOL MIX"}, | |
1403 | - {"SPOLN", NULL, "SPOL MIX"}, | |
1404 | - {"SPORP", NULL, "SPOR MIX"}, | |
1405 | - {"SPORN", NULL, "SPOR MIX"}, | |
1511 | + {"Speaker L Playback", "Switch", "SPOL MIX"}, | |
1512 | + {"Speaker R Playback", "Switch", "SPOR MIX"}, | |
1513 | + {"SPOLP", NULL, "Speaker L Playback"}, | |
1514 | + {"SPOLN", NULL, "Speaker L Playback"}, | |
1515 | + {"SPORP", NULL, "Speaker R Playback"}, | |
1516 | + {"SPORN", NULL, "Speaker R Playback"}, | |
1406 | 1517 | |
1407 | 1518 | {"SPOLP", NULL, "Improve SPK Amp Drv"}, |
1408 | 1519 | {"SPOLN", NULL, "Improve SPK Amp Drv"}, |
... | ... | @@ -1412,8 +1523,10 @@ |
1412 | 1523 | {"HPOL", NULL, "Improve HP Amp Drv"}, |
1413 | 1524 | {"HPOR", NULL, "Improve HP Amp Drv"}, |
1414 | 1525 | |
1415 | - {"HPOL", NULL, "HP L Amp"}, | |
1416 | - {"HPOR", NULL, "HP R Amp"}, | |
1526 | + {"HP L Playback", "Switch", "HP Amp"}, | |
1527 | + {"HP R Playback", "Switch", "HP Amp"}, | |
1528 | + {"HPOL", NULL, "HP L Playback"}, | |
1529 | + {"HPOR", NULL, "HP R Playback"}, | |
1417 | 1530 | {"LOUTL", NULL, "LOUT MIX"}, |
1418 | 1531 | {"LOUTR", NULL, "LOUT MIX"}, |
1419 | 1532 | {"MONOP", NULL, "Mono MIX"}, |
1420 | 1533 | |
... | ... | @@ -1792,17 +1905,13 @@ |
1792 | 1905 | RT5640_PWR_BG | RT5640_PWR_VREF2, |
1793 | 1906 | RT5640_PWR_VREF1 | RT5640_PWR_MB | |
1794 | 1907 | RT5640_PWR_BG | RT5640_PWR_VREF2); |
1795 | - mdelay(10); | |
1908 | + usleep_range(10000, 15000); | |
1796 | 1909 | snd_soc_update_bits(codec, RT5640_PWR_ANLG1, |
1797 | 1910 | RT5640_PWR_FV1 | RT5640_PWR_FV2, |
1798 | 1911 | RT5640_PWR_FV1 | RT5640_PWR_FV2); |
1799 | 1912 | regcache_sync(rt5640->regmap); |
1800 | 1913 | snd_soc_update_bits(codec, RT5640_DUMMY1, |
1801 | 1914 | 0x0301, 0x0301); |
1802 | - snd_soc_update_bits(codec, RT5640_DEPOP_M1, | |
1803 | - 0x001d, 0x0019); | |
1804 | - snd_soc_update_bits(codec, RT5640_DEPOP_M2, | |
1805 | - 0x2000, 0x2000); | |
1806 | 1915 | snd_soc_update_bits(codec, RT5640_MICBIAS, |
1807 | 1916 | 0x0030, 0x0030); |
1808 | 1917 | } |
... | ... | @@ -1846,8 +1955,6 @@ |
1846 | 1955 | rt5640_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1847 | 1956 | |
1848 | 1957 | snd_soc_update_bits(codec, RT5640_DUMMY1, 0x0301, 0x0301); |
1849 | - snd_soc_update_bits(codec, RT5640_DEPOP_M1, 0x001d, 0x0019); | |
1850 | - snd_soc_update_bits(codec, RT5640_DEPOP_M2, 0x2000, 0x2000); | |
1851 | 1958 | snd_soc_update_bits(codec, RT5640_MICBIAS, 0x0030, 0x0030); |
1852 | 1959 | snd_soc_update_bits(codec, RT5640_DSP_PATH2, 0xfc00, 0x0c00); |
1853 | 1960 | |
... | ... | @@ -2068,6 +2175,8 @@ |
2068 | 2175 | if (rt5640->pdata.in2_diff) |
2069 | 2176 | regmap_update_bits(rt5640->regmap, RT5640_IN3_IN4, |
2070 | 2177 | RT5640_IN_DF2, RT5640_IN_DF2); |
2178 | + | |
2179 | + rt5640->hp_mute = 1; | |
2071 | 2180 | |
2072 | 2181 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5640, |
2073 | 2182 | rt5640_dai, ARRAY_SIZE(rt5640_dai)); |
sound/soc/codecs/rt5640.h
... | ... | @@ -145,6 +145,8 @@ |
145 | 145 | |
146 | 146 | |
147 | 147 | /* Index of Codec Private Register definition */ |
148 | +#define RT5640_CHPUMP_INT_REG1 0x24 | |
149 | +#define RT5640_MAMP_INT_REG2 0x37 | |
148 | 150 | #define RT5640_3D_SPK 0x63 |
149 | 151 | #define RT5640_WND_1 0x6c |
150 | 152 | #define RT5640_WND_2 0x6d |
... | ... | @@ -153,6 +155,7 @@ |
153 | 155 | #define RT5640_WND_5 0x70 |
154 | 156 | #define RT5640_WND_8 0x73 |
155 | 157 | #define RT5640_DIP_SPK_INF 0x75 |
158 | +#define RT5640_HP_DCC_INT1 0x77 | |
156 | 159 | #define RT5640_EQ_BW_LOP 0xa0 |
157 | 160 | #define RT5640_EQ_GN_LOP 0xa1 |
158 | 161 | #define RT5640_EQ_FC_BP1 0xa2 |
... | ... | @@ -1201,6 +1204,14 @@ |
1201 | 1204 | #define RT5640_CP_FQ2_SFT 4 |
1202 | 1205 | #define RT5640_CP_FQ3_MASK (0x7) |
1203 | 1206 | #define RT5640_CP_FQ3_SFT 0 |
1207 | +#define RT5640_CP_FQ_1_5_KHZ 0 | |
1208 | +#define RT5640_CP_FQ_3_KHZ 1 | |
1209 | +#define RT5640_CP_FQ_6_KHZ 2 | |
1210 | +#define RT5640_CP_FQ_12_KHZ 3 | |
1211 | +#define RT5640_CP_FQ_24_KHZ 4 | |
1212 | +#define RT5640_CP_FQ_48_KHZ 5 | |
1213 | +#define RT5640_CP_FQ_96_KHZ 6 | |
1214 | +#define RT5640_CP_FQ_192_KHZ 7 | |
1204 | 1215 | |
1205 | 1216 | /* HPOUT charge pump (0x91) */ |
1206 | 1217 | #define RT5640_OSW_L_MASK (0x1 << 11) |
... | ... | @@ -2087,6 +2098,7 @@ |
2087 | 2098 | int pll_out; |
2088 | 2099 | |
2089 | 2100 | int dmic_en; |
2101 | + bool hp_mute; | |
2090 | 2102 | }; |
2091 | 2103 | |
2092 | 2104 | #endif |