diff options
author | Mark Brown <broonie@kernel.org> | 2015-05-06 11:58:24 +0100 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-05-06 11:58:24 +0100 |
commit | 292d2497cd8f551642a38f7a55b1b7965049c75d (patch) | |
tree | 1332204457623c47341dffbcd4ff33bf83599d47 /sound | |
parent | 26f63c692f012ff665a8fd085a36549fe734f59f (diff) | |
parent | 177e1e1fbc63f6e4ac0fab56dcb61bb8c8597681 (diff) | |
download | linux-292d2497cd8f551642a38f7a55b1b7965049c75d.tar.gz linux-292d2497cd8f551642a38f7a55b1b7965049c75d.tar.bz2 linux-292d2497cd8f551642a38f7a55b1b7965049c75d.zip |
Merge branch 'topic/rt5645' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-intel
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/rt5645.c | 702 | ||||
-rw-r--r-- | sound/soc/codecs/rt5645.h | 28 | ||||
-rw-r--r-- | sound/soc/intel/boards/cht_bsw_rt5645.c | 2 |
3 files changed, 614 insertions, 118 deletions
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 69528ae5410c..7996c9ceff5c 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -18,6 +18,9 @@ #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/gpio.h> +#include <linux/gpio/consumer.h> +#include <linux/acpi.h> +#include <linux/dmi.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -414,9 +417,9 @@ static bool rt5645_readable_register(struct device *dev, unsigned int reg) } static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6525, 75, 0); static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1725, 75, 0); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ @@ -431,30 +434,6 @@ static unsigned int bst_tlv[] = { 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0), }; -static const char * const rt5645_tdm_data_swap_select[] = { - "L/R", "R/L", "L/L", "R/R" -}; - -static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot0_1_enum, - RT5645_TDM_CTRL_1, 6, rt5645_tdm_data_swap_select); - -static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot2_3_enum, - RT5645_TDM_CTRL_1, 4, rt5645_tdm_data_swap_select); - -static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot4_5_enum, - RT5645_TDM_CTRL_1, 2, rt5645_tdm_data_swap_select); - -static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot6_7_enum, - RT5645_TDM_CTRL_1, 0, rt5645_tdm_data_swap_select); - -static const char * const rt5645_tdm_adc_data_select[] = { - "1/2/R", "2/1/R", "R/1/2", "R/2/1" -}; - -static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_sel_enum, - RT5645_TDM_CTRL_1, 8, - rt5645_tdm_adc_data_select); - static const struct snd_kcontrol_new rt5645_snd_controls[] = { /* Speaker Output Volume */ SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL, @@ -480,9 +459,9 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = { SOC_DOUBLE("DAC2 Playback Switch", RT5645_DAC_CTRL, RT5645_M_DAC_L2_VOL_SFT, RT5645_M_DAC_R2_VOL_SFT, 1, 1), SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5645_DAC1_DIG_VOL, - RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 175, 0, dac_vol_tlv), + RT5645_L_VOL_SFT + 1, RT5645_R_VOL_SFT + 1, 87, 0, dac_vol_tlv), SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5645_DAC2_DIG_VOL, - RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 175, 0, dac_vol_tlv), + RT5645_L_VOL_SFT + 1, RT5645_R_VOL_SFT + 1, 87, 0, dac_vol_tlv), /* IN1/IN2 Control */ SOC_SINGLE_TLV("IN1 Boost", RT5645_IN1_CTRL1, @@ -498,11 +477,11 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = { SOC_DOUBLE("ADC Capture Switch", RT5645_STO1_ADC_DIG_VOL, RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1), SOC_DOUBLE_TLV("ADC Capture Volume", RT5645_STO1_ADC_DIG_VOL, - RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 127, 0, adc_vol_tlv), + RT5645_L_VOL_SFT + 1, RT5645_R_VOL_SFT + 1, 63, 0, adc_vol_tlv), SOC_DOUBLE("Mono ADC Capture Switch", RT5645_MONO_ADC_DIG_VOL, RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1), SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5645_MONO_ADC_DIG_VOL, - RT5645_L_VOL_SFT, RT5645_R_VOL_SFT, 127, 0, adc_vol_tlv), + RT5645_L_VOL_SFT + 1, RT5645_R_VOL_SFT + 1, 63, 0, adc_vol_tlv), /* ADC Boost Volume Control */ SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5645_ADC_BST_VOL1, @@ -515,17 +494,6 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = { /* I2S2 function select */ SOC_SINGLE("I2S2 Func Switch", RT5645_GPIO_CTRL1, RT5645_I2S2_SEL_SFT, 1, 1), - - /* TDM */ - SOC_ENUM("TDM Adc Slot0 1 Data", rt5645_tdm_adc_slot0_1_enum), - SOC_ENUM("TDM Adc Slot2 3 Data", rt5645_tdm_adc_slot2_3_enum), - SOC_ENUM("TDM Adc Slot4 5 Data", rt5645_tdm_adc_slot4_5_enum), - SOC_ENUM("TDM Adc Slot6 7 Data", rt5645_tdm_adc_slot6_7_enum), - SOC_ENUM("TDM IF1 ADC DATA Sel", rt5645_tdm_adc_sel_enum), - SOC_SINGLE("TDM IF1_DAC1_L Sel", RT5645_TDM_CTRL_3, 12, 7, 0), - SOC_SINGLE("TDM IF1_DAC1_R Sel", RT5645_TDM_CTRL_3, 8, 7, 0), - SOC_SINGLE("TDM IF1_DAC2_L Sel", RT5645_TDM_CTRL_3, 4, 7, 0), - SOC_SINGLE("TDM IF1_DAC2_R Sel", RT5645_TDM_CTRL_3, 0, 7, 0), }; /** @@ -1092,7 +1060,8 @@ static const struct snd_kcontrol_new rt5645_mono_adc_r2_mux = /* MX-77 [9:8] */ static const char * const rt5645_if1_adc_in_src[] = { - "IF_ADC1", "IF_ADC2", "VAD_ADC" + "IF_ADC1/IF_ADC2/VAD_ADC", "IF_ADC2/IF_ADC1/VAD_ADC", + "VAD_ADC/IF_ADC1/IF_ADC2", "VAD_ADC/IF_ADC2/IF_ADC1" }; static SOC_ENUM_SINGLE_DECL( @@ -1102,6 +1071,140 @@ static SOC_ENUM_SINGLE_DECL( static const struct snd_kcontrol_new rt5645_if1_adc_in_mux = SOC_DAPM_ENUM("IF1 ADC IN source", rt5645_if1_adc_in_enum); +/* MX-78 [4:0] */ +static const char * const rt5650_if1_adc_in_src[] = { + "IF_ADC1/IF_ADC2/DAC_REF/Null", + "IF_ADC1/IF_ADC2/Null/DAC_REF", + "IF_ADC1/DAC_REF/IF_ADC2/Null", + "IF_ADC1/DAC_REF/Null/IF_ADC2", + "IF_ADC1/Null/DAC_REF/IF_ADC2", + "IF_ADC1/Null/IF_ADC2/DAC_REF", + + "IF_ADC2/IF_ADC1/DAC_REF/Null", + "IF_ADC2/IF_ADC1/Null/DAC_REF", + "IF_ADC2/DAC_REF/IF_ADC1/Null", + "IF_ADC2/DAC_REF/Null/IF_ADC1", + "IF_ADC2/Null/DAC_REF/IF_ADC1", + "IF_ADC2/Null/IF_ADC1/DAC_REF", + + "DAC_REF/IF_ADC1/IF_ADC2/Null", + "DAC_REF/IF_ADC1/Null/IF_ADC2", + "DAC_REF/IF_ADC2/IF_ADC1/Null", + "DAC_REF/IF_ADC2/Null/IF_ADC1", + "DAC_REF/Null/IF_ADC1/IF_ADC2", + "DAC_REF/Null/IF_ADC2/IF_ADC1", + + "Null/IF_ADC1/IF_ADC2/DAC_REF", + "Null/IF_ADC1/DAC_REF/IF_ADC2", + "Null/IF_ADC2/IF_ADC1/DAC_REF", + "Null/IF_ADC2/DAC_REF/IF_ADC1", + "Null/DAC_REF/IF_ADC1/IF_ADC2", + "Null/DAC_REF/IF_ADC2/IF_ADC1", +}; + +static SOC_ENUM_SINGLE_DECL( + rt5650_if1_adc_in_enum, RT5645_TDM_CTRL_2, + 0, rt5650_if1_adc_in_src); + +static const struct snd_kcontrol_new rt5650_if1_adc_in_mux = + SOC_DAPM_ENUM("IF1 ADC IN source", rt5650_if1_adc_in_enum); + +/* MX-78 [15:14][13:12][11:10] */ +static const char * const rt5645_tdm_adc_swap_select[] = { + "L/R", "R/L", "L/L", "R/R" +}; + +static SOC_ENUM_SINGLE_DECL(rt5650_tdm_adc_slot0_1_enum, + RT5645_TDM_CTRL_2, 14, rt5645_tdm_adc_swap_select); + +static const struct snd_kcontrol_new rt5650_if1_adc1_in_mux = + SOC_DAPM_ENUM("IF1 ADC1 IN source", rt5650_tdm_adc_slot0_1_enum); + +static SOC_ENUM_SINGLE_DECL(rt5650_tdm_adc_slot2_3_enum, + RT5645_TDM_CTRL_2, 12, rt5645_tdm_adc_swap_select); + +static const struct snd_kcontrol_new rt5650_if1_adc2_in_mux = + SOC_DAPM_ENUM("IF1 ADC2 IN source", rt5650_tdm_adc_slot2_3_enum); + +static SOC_ENUM_SINGLE_DECL(rt5650_tdm_adc_slot4_5_enum, + RT5645_TDM_CTRL_2, 10, rt5645_tdm_adc_swap_select); + +static const struct snd_kcontrol_new rt5650_if1_adc3_in_mux = + SOC_DAPM_ENUM("IF1 ADC3 IN source", rt5650_tdm_adc_slot4_5_enum); + +/* MX-77 [7:6][5:4][3:2] */ +static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot0_1_enum, + RT5645_TDM_CTRL_1, 6, rt5645_tdm_adc_swap_select); + +static const struct snd_kcontrol_new rt5645_if1_adc1_in_mux = + SOC_DAPM_ENUM("IF1 ADC1 IN source", rt5645_tdm_adc_slot0_1_enum); + +static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot2_3_enum, + RT5645_TDM_CTRL_1, 4, rt5645_tdm_adc_swap_select); + +static const struct snd_kcontrol_new rt5645_if1_adc2_in_mux = + SOC_DAPM_ENUM("IF1 ADC2 IN source", rt5645_tdm_adc_slot2_3_enum); + +static SOC_ENUM_SINGLE_DECL(rt5645_tdm_adc_slot4_5_enum, + RT5645_TDM_CTRL_1, 2, rt5645_tdm_adc_swap_select); + +static const struct snd_kcontrol_new rt5645_if1_adc3_in_mux = + SOC_DAPM_ENUM("IF1 ADC3 IN source", rt5645_tdm_adc_slot4_5_enum); + +/* MX-79 [14:12][10:8][6:4][2:0] */ +static const char * const rt5645_tdm_dac_swap_select[] = { + "Slot0", "Slot1", "Slot2", "Slot3" +}; + +static SOC_ENUM_SINGLE_DECL(rt5645_tdm_dac0_enum, + RT5645_TDM_CTRL_3, 12, rt5645_tdm_dac_swap_select); + +static const struct snd_kcontrol_new rt5645_if1_dac0_tdm_sel_mux = + SOC_DAPM_ENUM("IF1 DAC0 source", rt5645_tdm_dac0_enum); + +static SOC_ENUM_SINGLE_DECL(rt5645_tdm_dac1_enum, + RT5645_TDM_CTRL_3, 8, rt5645_tdm_dac_swap_select); + +static const struct snd_kcontrol_new rt5645_if1_dac1_tdm_sel_mux = + SOC_DAPM_ENUM("IF1 DAC1 source", rt5645_tdm_dac1_enum); + +static SOC_ENUM_SINGLE_DECL(rt5645_tdm_dac2_enum, + RT5645_TDM_CTRL_3, 4, rt5645_tdm_dac_swap_select); + +static const struct snd_kcontrol_new rt5645_if1_dac2_tdm_sel_mux = + SOC_DAPM_ENUM("IF1 DAC2 source", rt5645_tdm_dac2_enum); + +static SOC_ENUM_SINGLE_DECL(rt5645_tdm_dac3_enum, + RT5645_TDM_CTRL_3, 0, rt5645_tdm_dac_swap_select); + +static const struct snd_kcontrol_new rt5645_if1_dac3_tdm_sel_mux = + SOC_DAPM_ENUM("IF1 DAC3 source", rt5645_tdm_dac3_enum); + +/* MX-7a [14:12][10:8][6:4][2:0] */ +static SOC_ENUM_SINGLE_DECL(rt5650_tdm_dac0_enum, + RT5650_TDM_CTRL_4, 12, rt5645_tdm_dac_swap_select); + +static const struct snd_kcontrol_new rt5650_if1_dac0_tdm_sel_mux = + SOC_DAPM_ENUM("IF1 DAC0 source", rt5650_tdm_dac0_enum); + +static SOC_ENUM_SINGLE_DECL(rt5650_tdm_dac1_enum, + RT5650_TDM_CTRL_4, 8, rt5645_tdm_dac_swap_select); + +static const struct snd_kcontrol_new rt5650_if1_dac1_tdm_sel_mux = + SOC_DAPM_ENUM("IF1 DAC1 source", rt5650_tdm_dac1_enum); + +static SOC_ENUM_SINGLE_DECL(rt5650_tdm_dac2_enum, + RT5650_TDM_CTRL_4, 4, rt5645_tdm_dac_swap_select); + +static const struct snd_kcontrol_new rt5650_if1_dac2_tdm_sel_mux = + SOC_DAPM_ENUM("IF1 DAC2 source", rt5650_tdm_dac2_enum); + +static SOC_ENUM_SINGLE_DECL(rt5650_tdm_dac3_enum, + RT5650_TDM_CTRL_4, 0, rt5645_tdm_dac_swap_select); + +static const struct snd_kcontrol_new rt5650_if1_dac3_tdm_sel_mux = + SOC_DAPM_ENUM("IF1 DAC3 source", rt5650_tdm_dac3_enum); + /* MX-2d [3] [2] */ static const char * const rt5650_a_dac1_src[] = { "DAC1", "Stereo DAC Mixer" @@ -1570,8 +1673,24 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0), /* IF1 2 Mux */ - SND_SOC_DAPM_MUX("IF1 ADC Mux", SND_SOC_NOPM, + SND_SOC_DAPM_MUX("RT5645 IF1 ADC1 Swap Mux", SND_SOC_NOPM, + 0, 0, &rt5645_if1_adc1_in_mux), + SND_SOC_DAPM_MUX("RT5645 IF1 ADC2 Swap Mux", SND_SOC_NOPM, + 0, 0, &rt5645_if1_adc2_in_mux), + SND_SOC_DAPM_MUX("RT5645 IF1 ADC3 Swap Mux", SND_SOC_NOPM, + 0, 0, &rt5645_if1_adc3_in_mux), + SND_SOC_DAPM_MUX("RT5645 IF1 ADC Mux", SND_SOC_NOPM, 0, 0, &rt5645_if1_adc_in_mux), + + SND_SOC_DAPM_MUX("RT5650 IF1 ADC1 Swap Mux", SND_SOC_NOPM, + 0, 0, &rt5650_if1_adc1_in_mux), + SND_SOC_DAPM_MUX("RT5650 IF1 ADC2 Swap Mux", SND_SOC_NOPM, + 0, 0, &rt5650_if1_adc2_in_mux), + SND_SOC_DAPM_MUX("RT5650 IF1 ADC3 Swap Mux", SND_SOC_NOPM, + 0, 0, &rt5650_if1_adc3_in_mux), + SND_SOC_DAPM_MUX("RT5650 IF1 ADC Mux", SND_SOC_NOPM, + 0, 0, &rt5650_if1_adc_in_mux), + SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM, 0, 0, &rt5645_if2_adc_in_mux), @@ -1580,10 +1699,22 @@ static const struct snd_soc_dapm_widget rt5645_dapm_widgets[] = { RT5645_PWR_I2S1_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1 DAC1", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1 DAC2", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("IF1 DAC2 L", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("IF1 DAC2 R", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 L Mux", SND_SOC_NOPM, 0, 0, + &rt5645_if1_dac0_tdm_sel_mux), + SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 R Mux", SND_SOC_NOPM, 0, 0, + &rt5645_if1_dac1_tdm_sel_mux), + SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 L Mux", SND_SOC_NOPM, 0, 0, + &rt5645_if1_dac2_tdm_sel_mux), + SND_SOC_DAPM_MUX("RT5645 IF1 DAC2 R Mux", SND_SOC_NOPM, 0, 0, + &rt5645_if1_dac3_tdm_sel_mux), + SND_SOC_DAPM_MUX("RT5650 IF1 DAC1 L Mux", SND_SOC_NOPM, 0, 0, + &rt5650_if1_dac0_tdm_sel_mux), + SND_SOC_DAPM_MUX("RT5650 IF1 DAC1 R Mux", SND_SOC_NOPM, 0, 0, + &rt5650_if1_dac1_tdm_sel_mux), + SND_SOC_DAPM_MUX("RT5650 IF1 DAC2 L Mux", SND_SOC_NOPM, 0, 0, + &rt5650_if1_dac2_tdm_sel_mux), + SND_SOC_DAPM_MUX("RT5650 IF1 DAC2 R Mux", SND_SOC_NOPM, 0, 0, + &rt5650_if1_dac3_tdm_sel_mux), SND_SOC_DAPM_PGA("IF1 ADC", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1 ADC L", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1 ADC R", SND_SOC_NOPM, 0, 0, NULL, 0), @@ -1847,42 +1978,32 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { { "IF_ADC2", NULL, "Mono ADC MIXR" }, { "VAD_ADC", NULL, "VAD ADC Mux" }, - { "IF1 ADC Mux", "IF_ADC1", "IF_ADC1" }, - { "IF1 ADC Mux", "IF_ADC2", "IF_ADC2" }, - { "IF1 ADC Mux", "VAD_ADC", "VAD_ADC" }, - { "IF2 ADC Mux", "IF_ADC1", "IF_ADC1" }, { "IF2 ADC Mux", "IF_ADC2", "IF_ADC2" }, { "IF2 ADC Mux", "VAD_ADC", "VAD_ADC" }, { "IF1 ADC", NULL, "I2S1" }, - { "IF1 ADC", NULL, "IF1 ADC Mux" }, { "IF2 ADC", NULL, "I2S2" }, { "IF2 ADC", NULL, "IF2 ADC Mux" }, - { "AIF1TX", NULL, "IF1 ADC" }, - { "AIF1TX", NULL, "IF2 ADC" }, { "AIF2TX", NULL, "IF2 ADC" }, + { "IF1 DAC0", NULL, "AIF1RX" }, { "IF1 DAC1", NULL, "AIF1RX" }, { "IF1 DAC2", NULL, "AIF1RX" }, + { "IF1 DAC3", NULL, "AIF1RX" }, { "IF2 DAC", NULL, "AIF2RX" }, + { "IF1 DAC0", NULL, "I2S1" }, { "IF1 DAC1", NULL, "I2S1" }, { "IF1 DAC2", NULL, "I2S1" }, + { "IF1 DAC3", NULL, "I2S1" }, { "IF2 DAC", NULL, "I2S2" }, - { "IF1 DAC2 L", NULL, "IF1 DAC2" }, - { "IF1 DAC2 R", NULL, "IF1 DAC2" }, - { "IF1 DAC1 L", NULL, "IF1 DAC1" }, - { "IF1 DAC1 R", NULL, "IF1 DAC1" }, { "IF2 DAC L", NULL, "IF2 DAC" }, { "IF2 DAC R", NULL, "IF2 DAC" }, - { "DAC1 L Mux", "IF1 DAC", "IF1 DAC1 L" }, { "DAC1 L Mux", "IF2 DAC", "IF2 DAC L" }, - - { "DAC1 R Mux", "IF1 DAC", "IF1 DAC1 R" }, { "DAC1 R Mux", "IF2 DAC", "IF2 DAC R" }, { "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" }, @@ -1892,14 +2013,12 @@ static const struct snd_soc_dapm_route rt5645_dapm_routes[] = { { "DAC1 MIXR", "DAC1 Switch", "DAC1 R Mux" }, { "DAC1 MIXR", NULL, "dac stereo1 filter" }, - { "DAC L2 Mux", "IF1 DAC", "IF1 DAC2 L" }, { "DAC L2 Mux", "IF2 DAC", "IF2 DAC L" }, { "DAC L2 Mux", "Mono ADC", "Mono ADC MIXL" }, { "DAC L2 Mux", "VAD_ADC", "VAD_ADC" }, { "DAC L2 Volume", NULL, "DAC L2 Mux" }, { "DAC L2 Volume", NULL, "dac mono left filter" }, - { "DAC R2 Mux", "IF1 DAC", "IF1 DAC2 R" }, { "DAC R2 Mux", "IF2 DAC", "IF2 DAC R" }, { "DAC R2 Mux", "Mono ADC", "Mono ADC MIXR" }, { "DAC R2 Mux", "Haptic", "Haptic Generator" }, @@ -2037,6 +2156,80 @@ static const struct snd_soc_dapm_route rt5650_specific_dapm_routes[] = { { "DAC R1", NULL, "A DAC1 R Mux" }, { "DAC L2", NULL, "A DAC2 L Mux" }, { "DAC R2", NULL, "A DAC2 R Mux" }, + + { "RT5650 IF1 ADC1 Swap Mux", "L/R", "IF_ADC1" }, + { "RT5650 IF1 ADC1 Swap Mux", "R/L", "IF_ADC1" }, + { "RT5650 IF1 ADC1 Swap Mux", "L/L", "IF_ADC1" }, + { "RT5650 IF1 ADC1 Swap Mux", "R/R", "IF_ADC1" }, + + { "RT5650 IF1 ADC2 Swap Mux", "L/R", "IF_ADC2" }, + { "RT5650 IF1 ADC2 Swap Mux", "R/L", "IF_ADC2" }, + { "RT5650 IF1 ADC2 Swap Mux", "L/L", "IF_ADC2" }, + { "RT5650 IF1 ADC2 Swap Mux", "R/R", "IF_ADC2" }, + + { "RT5650 IF1 ADC3 Swap Mux", "L/R", "VAD_ADC" }, + { "RT5650 IF1 ADC3 Swap Mux", "R/L", "VAD_ADC" }, + { "RT5650 IF1 ADC3 Swap Mux", "L/L", "VAD_ADC" }, + { "RT5650 IF1 ADC3 Swap Mux", "R/R", "VAD_ADC" }, + + { "IF1 ADC", NULL, "RT5650 IF1 ADC1 Swap Mux" }, + { "IF1 ADC", NULL, "RT5650 IF1 ADC2 Swap Mux" }, + { "IF1 ADC", NULL, "RT5650 IF1 ADC3 Swap Mux" }, + + { "RT5650 IF1 ADC Mux", "IF_ADC1/IF_ADC2/DAC_REF/Null", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "IF_ADC1/IF_ADC2/Null/DAC_REF", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "IF_ADC1/DAC_REF/IF_ADC2/Null", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "IF_ADC1/DAC_REF/Null/IF_ADC2", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "IF_ADC1/Null/DAC_REF/IF_ADC2", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "IF_ADC1/Null/IF_ADC2/DAC_REF", "IF1 ADC" }, + + { "RT5650 IF1 ADC Mux", "IF_ADC2/IF_ADC1/DAC_REF/Null", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "IF_ADC2/IF_ADC1/Null/DAC_REF", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "IF_ADC2/DAC_REF/IF_ADC1/Null", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "IF_ADC2/DAC_REF/Null/IF_ADC1", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "IF_ADC2/Null/DAC_REF/IF_ADC1", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "IF_ADC2/Null/IF_ADC1/DAC_REF", "IF1 ADC" }, + + { "RT5650 IF1 ADC Mux", "DAC_REF/IF_ADC1/IF_ADC2/Null", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "DAC_REF/IF_ADC1/Null/IF_ADC2", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "DAC_REF/IF_ADC2/IF_ADC1/Null", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "DAC_REF/IF_ADC2/Null/IF_ADC1", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "DAC_REF/Null/IF_ADC1/IF_ADC2", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "DAC_REF/Null/IF_ADC2/IF_ADC1", "IF1 ADC" }, + + { "RT5650 IF1 ADC Mux", "Null/IF_ADC1/IF_ADC2/DAC_REF", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "Null/IF_ADC1/DAC_REF/IF_ADC2", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "Null/IF_ADC2/IF_ADC1/DAC_REF", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "Null/IF_ADC2/DAC_REF/IF_ADC1", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "Null/DAC_REF/IF_ADC1/IF_ADC2", "IF1 ADC" }, + { "RT5650 IF1 ADC Mux", "Null/DAC_REF/IF_ADC2/IF_ADC1", "IF1 ADC" }, + { "AIF1TX", NULL, "RT5650 IF1 ADC Mux" }, + + { "RT5650 IF1 DAC1 L Mux", "Slot0", "IF1 DAC0" }, + { "RT5650 IF1 DAC1 L Mux", "Slot1", "IF1 DAC1" }, + { "RT5650 IF1 DAC1 L Mux", "Slot2", "IF1 DAC2" }, + { "RT5650 IF1 DAC1 L Mux", "Slot3", "IF1 DAC3" }, + + { "RT5650 IF1 DAC1 R Mux", "Slot0", "IF1 DAC0" }, + { "RT5650 IF1 DAC1 R Mux", "Slot1", "IF1 DAC1" }, + { "RT5650 IF1 DAC1 R Mux", "Slot2", "IF1 DAC2" }, + { "RT5650 IF1 DAC1 R Mux", "Slot3", "IF1 DAC3" }, + + { "RT5650 IF1 DAC2 L Mux", "Slot0", "IF1 DAC0" }, + { "RT5650 IF1 DAC2 L Mux", "Slot1", "IF1 DAC1" }, + { "RT5650 IF1 DAC2 L Mux", "Slot2", "IF1 DAC2" }, + { "RT5650 IF1 DAC2 L Mux", "Slot3", "IF1 DAC3" }, + + { "RT5650 IF1 DAC2 R Mux", "Slot0", "IF1 DAC0" }, + { "RT5650 IF1 DAC2 R Mux", "Slot1", "IF1 DAC1" }, + { "RT5650 IF1 DAC2 R Mux", "Slot2", "IF1 DAC2" }, + { "RT5650 IF1 DAC2 R Mux", "Slot3", "IF1 DAC3" }, + + { "DAC1 L Mux", "IF1 DAC", "RT5650 IF1 DAC1 L Mux" }, + { "DAC1 R Mux", "IF1 DAC", "RT5650 IF1 DAC1 R Mux" }, + + { "DAC L2 Mux", "IF1 DAC", "RT5650 IF1 DAC2 L Mux" }, + { "DAC R2 Mux", "IF1 DAC", "RT5650 IF1 DAC2 R Mux" }, }; static const struct snd_soc_dapm_route rt5645_specific_dapm_routes[] = { @@ -2044,6 +2237,57 @@ static const struct snd_soc_dapm_route rt5645_specific_dapm_routes[] = { { "DAC R1", NULL, "Stereo DAC MIXR" }, { "DAC L2", NULL, "Mono DAC MIXL" }, { "DAC R2", NULL, "Mono DAC MIXR" }, + + { "RT5645 IF1 ADC1 Swap Mux", "L/R", "IF_ADC1" }, + { "RT5645 IF1 ADC1 Swap Mux", "R/L", "IF_ADC1" }, + { "RT5645 IF1 ADC1 Swap Mux", "L/L", "IF_ADC1" }, + { "RT5645 IF1 ADC1 Swap Mux", "R/R", "IF_ADC1" }, + + { "RT5645 IF1 ADC2 Swap Mux", "L/R", "IF_ADC2" }, + { "RT5645 IF1 ADC2 Swap Mux", "R/L", "IF_ADC2" }, + { "RT5645 IF1 ADC2 Swap Mux", "L/L", "IF_ADC2" }, + { "RT5645 IF1 ADC2 Swap Mux", "R/R", "IF_ADC2" }, + + { "RT5645 IF1 ADC3 Swap Mux", "L/R", "VAD_ADC" }, + { "RT5645 IF1 ADC3 Swap Mux", "R/L", "VAD_ADC" }, + { "RT5645 IF1 ADC3 Swap Mux", "L/L", "VAD_ADC" }, + { "RT5645 IF1 ADC3 Swap Mux", "R/R", "VAD_ADC" }, + + { "IF1 ADC", NULL, "RT5645 IF1 ADC1 Swap Mux" }, + { "IF1 ADC", NULL, "RT5645 IF1 ADC2 Swap Mux" }, + { "IF1 ADC", NULL, "RT5645 IF1 ADC3 Swap Mux" }, + + { "RT5645 IF1 ADC Mux", "IF_ADC1/IF_ADC2/VAD_ADC", "IF1 ADC" }, + { "RT5645 IF1 ADC Mux", "IF_ADC2/IF_ADC1/VAD_ADC", "IF1 ADC" }, + { "RT5645 IF1 ADC Mux", "VAD_ADC/IF_ADC1/IF_ADC2", "IF1 ADC" }, + { "RT5645 IF1 ADC Mux", "VAD_ADC/IF_ADC2/IF_ADC1", "IF1 ADC" }, + { "AIF1TX", NULL, "RT5645 IF1 ADC Mux" }, + + { "RT5645 IF1 DAC1 L Mux", "Slot0", "IF1 DAC0" }, + { "RT5645 IF1 DAC1 L Mux", "Slot1", "IF1 DAC1" }, + { "RT5645 IF1 DAC1 L Mux", "Slot2", "IF1 DAC2" }, + { "RT5645 IF1 DAC1 L Mux", "Slot3", "IF1 DAC3" }, + + { "RT5645 IF1 DAC1 R Mux", "Slot0", "IF1 DAC0" }, + { "RT5645 IF1 DAC1 R Mux", "Slot1", "IF1 DAC1" }, + { "RT5645 IF1 DAC1 R Mux", "Slot2", "IF1 DAC2" }, + { "RT5645 IF1 DAC1 R Mux", "Slot3", "IF1 DAC3" }, + + { "RT5645 IF1 DAC2 L Mux", "Slot0", "IF1 DAC0" }, + { "RT5645 IF1 DAC2 L Mux", "Slot1", "IF1 DAC1" }, + { "RT5645 IF1 DAC2 L Mux", "Slot2", "IF1 DAC2" }, + { "RT5645 IF1 DAC2 L Mux", "Slot3", "IF1 DAC3" }, + + { "RT5645 IF1 DAC2 R Mux", "Slot0", "IF1 DAC0" }, + { "RT5645 IF1 DAC2 R Mux", "Slot1", "IF1 DAC1" }, + { "RT5645 IF1 DAC2 R Mux", "Slot2", "IF1 DAC2" }, + { "RT5645 IF1 DAC2 R Mux", "Slot3", "IF1 DAC3" }, + + { "DAC1 L Mux", "IF1 DAC", "RT5645 IF1 DAC1 L Mux" }, + { "DAC1 R Mux", "IF1 DAC", "RT5645 IF1 DAC1 R Mux" }, + + { "DAC L2 Mux", "IF1 DAC", "RT5645 IF1 DAC2 L Mux" }, + { "DAC R2 Mux", "IF1 DAC", "RT5645 IF1 DAC2 R Mux" }, }; static int rt5645_hw_params(struct snd_pcm_substream *substream, @@ -2101,9 +2345,8 @@ static int rt5645_hw_params(struct snd_pcm_substream *substream, switch (dai->id) { case RT5645_AIF1: - mask_clk = RT5645_I2S_BCLK_MS1_MASK | RT5645_I2S_PD1_MASK; - val_clk = bclk_ms << RT5645_I2S_BCLK_MS1_SFT | - pre_div << RT5645_I2S_PD1_SFT; + mask_clk = RT5645_I2S_PD1_MASK; + val_clk = pre_div << RT5645_I2S_PD1_SFT; snd_soc_update_bits(codec, RT5645_I2S1_SDP, (0x3 << dl_sft), (val_len << dl_sft)); snd_soc_update_bits(codec, RT5645_ADDA_CLK1, mask_clk, val_clk); @@ -2368,6 +2611,8 @@ static int rt5645_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, static int rt5645_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); + switch (level) { case SND_SOC_BIAS_PREPARE: if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { @@ -2398,8 +2643,9 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_OFF: snd_soc_write(codec, RT5645_DEPOP_M2, 0x1100); - snd_soc_update_bits(codec, RT5645_GEN_CTRL1, - RT5645_DIG_GATE_CTRL, 0); + if (!rt5645->en_button_func) + snd_soc_update_bits(codec, RT5645_GEN_CTRL1, + RT5645_DIG_GATE_CTRL, 0); snd_soc_update_bits(codec, RT5645_PWR_ANLG1, RT5645_PWR_VREF1 | RT5645_PWR_MB | RT5645_PWR_BG | RT5645_PWR_VREF2 | @@ -2414,28 +2660,71 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec, return 0; } -static int rt5645_jack_detect(struct snd_soc_codec *codec) +static void rt5645_enable_push_button_irq(struct snd_soc_codec *codec, + bool enable) { struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); - int gpio_state, jack_type = 0; - unsigned int val; - if (!gpio_is_valid(rt5645->pdata.hp_det_gpio)) { - dev_err(codec->dev, "invalid gpio\n"); - return -EINVAL; + if (enable) { + snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, + "ADC L power"); + snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, + "ADC R power"); + snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, + "LDO2"); + snd_soc_dapm_force_enable_pin_unlocked(&codec->dapm, + "Mic Det Power"); + snd_soc_dapm_sync_unlocked(&codec->dapm); + snd_soc_update_bits(codec, + RT5645_INT_IRQ_ST, 0x8, 0x8); + snd_soc_update_bits(codec, + RT5650_4BTN_IL_CMD2, 0x8000, 0x8000); + snd_soc_read(codec, RT5650_4BTN_IL_CMD1); + pr_debug("%s read %x = %x\n", __func__, RT5650_4BTN_IL_CMD1, + snd_soc_read(codec, RT5650_4BTN_IL_CMD1)); + } else { + snd_soc_update_bits(codec, RT5650_4BTN_IL_CMD2, 0x8000, 0x0); + snd_soc_update_bits(codec, RT5645_INT_IRQ_ST, 0x8, 0x0); + snd_soc_dapm_disable_pin_unlocked(&codec->dapm, + "ADC L power"); + snd_soc_dapm_disable_pin_unlocked(&codec->dapm, + "ADC R power"); + if (rt5645->pdata.jd_mode == 0) + snd_soc_dapm_disable_pin_unlocked(&codec->dapm, + "LDO2"); + snd_soc_dapm_disable_pin_unlocked(&codec->dapm, + "Mic Det Power"); + snd_soc_dapm_sync_unlocked(&codec->dapm); } - gpio_state = gpio_get_value(rt5645->pdata.hp_det_gpio); +} - dev_dbg(codec->dev, "gpio = %d(%d)\n", rt5645->pdata.hp_det_gpio, - gpio_state); +static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert) +{ + struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); + unsigned int val; - if ((rt5645->pdata.gpio_hp_det_active_high && gpio_state) || - (!rt5645->pdata.gpio_hp_det_active_high && !gpio_state)) { - snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias1"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias2"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); - snd_soc_dapm_force_enable_pin(&codec->dapm, "Mic Det Power"); - snd_soc_dapm_sync(&codec->dapm); + if (jack_insert) { + if (codec->component.card->instantiated) { + snd_soc_dapm_force_enable_pin(&codec->dapm, + "micbias1"); + snd_soc_dapm_force_enable_pin(&codec->dapm, + "micbias2"); + snd_soc_dapm_force_enable_pin(&codec->dapm, + "LDO2"); + snd_soc_dapm_force_enable_pin(&codec->dapm, + "Mic Det Power"); + snd_soc_dapm_sync(&codec->dapm); + } else { + /* Power up necessary bits for JD if dapm is + not ready yet */ + snd_soc_update_bits(codec, RT5645_PWR_ANLG2, + RT5645_PWR_MB1 | RT5645_PWR_MB2, + RT5645_PWR_MB1 | RT5645_PWR_MB2); + snd_soc_update_bits(codec, RT5645_PWR_MIXER, + RT5645_PWR_LDO2, RT5645_PWR_LDO2); + snd_soc_update_bits(codec, RT5645_PWR_VOL, + RT5645_PWR_MIC_DET, RT5645_PWR_MIC_DET); + } snd_soc_write(codec, RT5645_IN1_CTRL1, 0x0006); snd_soc_write(codec, RT5645_JD_CTRL3, 0x00b0); @@ -2449,32 +2738,64 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec) val = snd_soc_read(codec, RT5645_IN1_CTRL3) & 0x7; dev_dbg(codec->dev, "val = %d\n", val); - if (val == 1 || val == 2) - jack_type = SND_JACK_HEADSET; - else - jack_type = SND_JACK_HEADPHONE; + if (codec->component.card->instantiated) { + snd_soc_dapm_disable_pin(&codec->dapm, "micbias1"); + snd_soc_dapm_disable_pin(&codec->dapm, "micbias2"); + if (rt5645->pdata.jd_mode == 0) + snd_soc_dapm_disable_pin(&codec->dapm, "LDO2"); + snd_soc_dapm_disable_pin(&codec->dapm, + "Mic Det Power"); + snd_soc_dapm_sync(&codec->dapm); + } else { + snd_soc_update_bits(codec, RT5645_PWR_ANLG2, + RT5645_PWR_MB1 | RT5645_PWR_MB2, 0); + if (rt5645->pdata.jd_mode == 0) + snd_soc_update_bits(codec, RT5645_PWR_MIXER, + RT5645_PWR_LDO2, 0); + snd_soc_update_bits(codec, RT5645_PWR_VOL, + RT5645_PWR_MIC_DET, 0); + } - snd_soc_dapm_disable_pin(&codec->dapm, "micbias1"); - snd_soc_dapm_disable_pin(&codec->dapm, "micbias2"); - if (rt5645->pdata.jd_mode == 0) - snd_soc_dapm_disable_pin(&codec->dapm, "LDO2"); - snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); - snd_soc_dapm_sync(&codec->dapm); + if (val == 1 || val == 2) { + rt5645->jack_type = SND_JACK_HEADSET; + if (rt5645->en_button_func) { + msleep(100); + rt5645_enable_push_button_irq(codec, true); + } + } else { + rt5645->jack_type = SND_JACK_HEADPHONE; + } + + } else { /* jack out */ + rt5645->jack_type = 0; + if (rt5645->en_button_func) + rt5645_enable_push_button_irq(codec, false); } - snd_soc_jack_report(rt5645->hp_jack, jack_type, SND_JACK_HEADPHONE); - snd_soc_jack_report(rt5645->mic_jack, jack_type, SND_JACK_MICROPHONE); - return 0; + return rt5645->jack_type; } +static int rt5645_irq_detection(struct rt5645_priv *rt5645); + int rt5645_set_jack_detect(struct snd_soc_codec *codec, - struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack) + struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack, + struct snd_soc_jack *btn_jack) { struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); rt5645->hp_jack = hp_jack; rt5645->mic_jack = mic_jack; - rt5645_jack_detect(codec); + rt5645->btn_jack = btn_jack; + if (rt5645->btn_jack && rt5645->codec_type == CODEC_TYPE_RT5650) { + rt5645->en_button_func = true; + regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, + RT5645_GP1_PIN_IRQ, RT5645_GP1_PIN_IRQ); + regmap_update_bits(rt5645->regmap, RT5645_DEPOP_M1, + RT5645_HP_CB_MASK, RT5645_HP_CB_PU); + regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL1, + RT5645_DIG_GATE_CTRL, RT5645_DIG_GATE_CTRL); + } + rt5645_irq_detection(rt5645); return 0; } @@ -2485,7 +2806,7 @@ static void rt5645_jack_detect_work(struct work_struct *work) struct rt5645_priv *rt5645 = container_of(work, struct rt5645_priv, jack_detect_work.work); - rt5645_jack_detect(rt5645->codec); + rt5645_irq_detection(rt5645); } static irqreturn_t rt5645_irq(int irq, void *data) @@ -2498,6 +2819,126 @@ static irqreturn_t rt5645_irq(int irq, void *data) return IRQ_HANDLED; } +static int rt5645_button_detect(struct snd_soc_codec *codec) +{ + int btn_type, val; + + val = snd_soc_read(codec, RT5650_4BTN_IL_CMD1); + pr_debug("val=0x%x\n", val); + btn_type = val & 0xfff0; + snd_soc_write(codec, RT5650_4BTN_IL_CMD1, val); + + return btn_type; +} + +static int rt5645_irq_detection(struct rt5645_priv *rt5645) +{ + int val, btn_type, gpio_state = 0, report = 0; + + switch (rt5645->pdata.jd_mode) { + case 0: /* Not using rt5645 JD */ + if (gpio_is_valid(rt5645->pdata.hp_det_gpio)) { + gpio_state = gpio_get_value(rt5645->pdata.hp_det_gpio); + dev_dbg(rt5645->codec->dev, "gpio = %d(%d)\n", + rt5645->pdata.hp_det_gpio, gpio_state); + } + if ((rt5645->pdata.gpio_hp_det_active_high && gpio_state) || + (!rt5645->pdata.gpio_hp_det_active_high && + !gpio_state)) { + report = rt5645_jack_detect(rt5645->codec, 1); + } else { + report = rt5645_jack_detect(rt5645->codec, 0); + } + snd_soc_jack_report(rt5645->hp_jack, + report, SND_JACK_HEADPHONE); + snd_soc_jack_report(rt5645->mic_jack, + report, SND_JACK_MICROPHONE); + return report; + case 1: /* 2 port */ + val = snd_soc_read(rt5645->codec, RT5645_A_JD_CTRL1) & 0x0070; + break; + default: /* 1 port */ + val = snd_soc_read(rt5645->codec, RT5645_A_JD_CTRL1) & 0x0020; + break; + + } + + switch (val) { + /* jack in */ + case 0x30: /* 2 port */ + case 0x0: /* 1 port or 2 port */ + if (rt5645->jack_type == 0) { + report = rt5645_jack_detect(rt5645->codec, 1); + /* for push button and jack out */ + break; + } + btn_type = 0; + if (snd_soc_read(rt5645->codec, RT5645_INT_IRQ_ST) & 0x4) { + /* button pressed */ + report = SND_JACK_HEADSET; + btn_type = rt5645_button_detect(rt5645->codec); + /* rt5650 can report three kinds of button behavior, + one click, double click and hold. However, + currently we will report button pressed/released + event. So all the three button behaviors are + treated as button pressed. */ + switch (btn_type) { + case 0x8000: + case 0x4000: + case 0x2000: + report |= SND_JACK_BTN_0; + break; + case 0x1000: + case 0x0800: + case 0x0400: + report |= SND_JACK_BTN_1; + break; + case 0x0200: + case 0x0100: + case 0x0080: + report |= SND_JACK_BTN_2; + break; + case 0x0040: + case 0x0020: + case 0x0010: + report |= SND_JACK_BTN_3; + break; + case 0x0000: /* unpressed */ + break; + default: + dev_err(rt5645->codec->dev, + "Unexpected button code 0x%04x\n", + btn_type); + break; + } + } + if (btn_type == 0)/* button release */ + report = rt5645->jack_type; + + break; + /* jack out */ + case 0x70: /* 2 port */ + case 0x10: /* 2 port */ + case 0x20: /* 1 port */ + report = 0; + snd_soc_update_bits(rt5645->codec, + RT5645_INT_IRQ_ST, 0x1, 0x0); + rt5645_jack_detect(rt5645->codec, 0); + break; + default: + break; + } + + snd_soc_jack_report(rt5645->hp_jack, report, SND_JACK_HEADPHONE); + snd_soc_jack_report(rt5645->mic_jack, report, SND_JACK_MICROPHONE); + if (rt5645->en_button_func) + snd_soc_jack_report(rt5645->btn_jack, + report, SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + + return report; +} + static int rt5645_probe(struct snd_soc_codec *codec) { struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); @@ -2656,6 +3097,43 @@ static const struct i2c_device_id rt5645_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id); +#ifdef CONFIG_ACPI +static struct acpi_device_id rt5645_acpi_match[] = { + { "10EC5645", 0 }, + { "10EC5650", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, rt5645_acpi_match); +#endif + +static struct rt5645_platform_data *rt5645_pdata; + +static struct rt5645_platform_data strago_platform_data = { + .dmic_en = true, + .dmic1_data_pin = -1, + .dmic2_data_pin = RT5645_DMIC_DATA_IN2P, + .en_jd_func = true, + .jd_mode = 3, +}; + +static int strago_quirk_cb(const struct dmi_system_id *id) +{ + rt5645_pdata = &strago_platform_data; + + return 1; +} + +static struct dmi_system_id dmi_platform_intel_braswell[] = { + { + .ident = "Intel Strago", + .callback = strago_quirk_cb, + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Strago"), + }, + }, + { } +}; + static int rt5645_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -2663,6 +3141,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, struct rt5645_priv *rt5645; int ret; unsigned int val; + struct gpio_desc *gpiod; rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv), GFP_KERNEL); @@ -2672,8 +3151,23 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, rt5645->i2c = i2c; i2c_set_clientdata(i2c, rt5645); - if (pdata) + if (pdata) { rt5645->pdata = *pdata; + } else { + if (dmi_check_system(dmi_platform_intel_braswell)) { + rt5645->pdata = *rt5645_pdata; + gpiod = devm_gpiod_get_index(&i2c->dev, "rt5645", 0); + + if (IS_ERR(gpiod) || gpiod_direction_input(gpiod)) { + rt5645->pdata.hp_det_gpio = -1; + dev_err(&i2c->dev, "failed to initialize gpiod\n"); + } else { + rt5645->pdata.hp_det_gpio = desc_to_gpio(gpiod); + rt5645->pdata.gpio_hp_det_active_high + = !gpiod_is_active_low(gpiod); + } + } + } rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap); if (IS_ERR(rt5645->regmap)) { @@ -2770,7 +3264,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, case RT5645_DMIC_DATA_GPIO12: regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, - RT5645_DMIC_1_DP_MASK, RT5645_DMIC_2_DP_GPIO12); + RT5645_DMIC_2_DP_MASK, RT5645_DMIC_2_DP_GPIO12); regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1, RT5645_GP12_PIN_MASK, RT5645_GP12_PIN_DMIC2_SDA); @@ -2784,8 +3278,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, if (rt5645->pdata.en_jd_func) { regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, - RT5645_IRQ_CLK_GATE_CTRL | RT5645_MICINDET_MANU, - RT5645_IRQ_CLK_GATE_CTRL | RT5645_MICINDET_MANU); + RT5645_IRQ_CLK_GATE_CTRL, RT5645_IRQ_CLK_GATE_CTRL); regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, RT5645_CBJ_BST1_EN, RT5645_CBJ_BST1_EN); regmap_update_bits(rt5645->regmap, RT5645_JD_CTRL3, @@ -2872,6 +3365,7 @@ static struct i2c_driver rt5645_i2c_driver = { .driver = { .name = "rt5645", .owner = THIS_MODULE, + .acpi_match_table = ACPI_PTR(rt5645_acpi_match), }, .probe = rt5645_i2c_probe, .remove = rt5645_i2c_remove, diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index db78e9462876..c204861d31d9 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h @@ -105,6 +105,7 @@ #define RT5645_TDM_CTRL_1 0x77 #define RT5645_TDM_CTRL_2 0x78 #define RT5645_TDM_CTRL_3 0x79 +#define RT5650_TDM_CTRL_4 0x7a /* Function - Analog */ #define RT5645_GLB_CLK 0x80 @@ -942,10 +943,6 @@ #define RT5645_I2S2_SDI_I2S2 (0x1 << 6) /* ADC/DAC Clock Control 1 (0x73) */ -#define RT5645_I2S_BCLK_MS1_MASK (0x1 << 15) -#define RT5645_I2S_BCLK_MS1_SFT 15 -#define RT5645_I2S_BCLK_MS1_32 (0x0 << 15) -#define RT5645_I2S_BCLK_MS1_64 (0x1 << 15) #define RT5645_I2S_PD1_MASK (0x7 << 12) #define RT5645_I2S_PD1_SFT 12 #define RT5645_I2S_PD1_1 (0x0 << 12) @@ -1067,13 +1064,14 @@ #define RT5645_SCLK_SRC_SFT 14 #define RT5645_SCLK_SRC_MCLK (0x0 << 14) #define RT5645_SCLK_SRC_PLL1 (0x1 << 14) -#define RT5645_SCLK_SRC_RCCLK (0x2 << 14) /* 15MHz */ -#define RT5645_PLL1_SRC_MASK (0x3 << 12) -#define RT5645_PLL1_SRC_SFT 12 -#define RT5645_PLL1_SRC_MCLK (0x0 << 12) -#define RT5645_PLL1_SRC_BCLK1 (0x1 << 12) -#define RT5645_PLL1_SRC_BCLK2 (0x2 << 12) -#define RT5645_PLL1_SRC_BCLK3 (0x3 << 12) +#define RT5645_SCLK_SRC_RCCLK (0x2 << 14) +#define RT5645_PLL1_SRC_MASK (0x7 << 11) +#define RT5645_PLL1_SRC_SFT 11 +#define RT5645_PLL1_SRC_MCLK (0x0 << 11) +#define RT5645_PLL1_SRC_BCLK1 (0x1 << 11) +#define RT5645_PLL1_SRC_BCLK2 (0x2 << 11) +#define RT5645_PLL1_SRC_BCLK3 (0x3 << 11) +#define RT5645_PLL1_SRC_RCCLK (0x4 << 11) #define RT5645_PLL1_PD_MASK (0x1 << 3) #define RT5645_PLL1_PD_SFT 3 #define RT5645_PLL1_PD_1 (0x0 << 3) @@ -2184,6 +2182,7 @@ struct rt5645_priv { struct i2c_client *i2c; struct snd_soc_jack *hp_jack; struct snd_soc_jack *mic_jack; + struct snd_soc_jack *btn_jack; struct delayed_work jack_detect_work; int codec_type; @@ -2196,9 +2195,12 @@ struct rt5645_priv { int pll_src; int pll_in; int pll_out; + + int jack_type; + bool en_button_func; }; int rt5645_set_jack_detect(struct snd_soc_codec *codec, - struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack); - + struct snd_soc_jack *hp_jack, struct snd_soc_jack *mic_jack, + struct snd_soc_jack *btn_jack); #endif /* __RT5645_H__ */ diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 7d23ead3fd40..8f96c21fef4f 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -214,7 +214,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) return ret; } - rt5645_set_jack_detect(codec, &ctx->hp_jack, &ctx->mic_jack); + rt5645_set_jack_detect(codec, &ctx->hp_jack, &ctx->mic_jack, NULL); return ret; } |