Merge branch 'topic/rt5645' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-intel

This commit is contained in:
Mark Brown 2015-05-06 11:58:24 +01:00
Родитель 26f63c692f 177e1e1fbc
Коммит 292d2497cd
3 изменённых файлов: 616 добавлений и 120 удалений

Просмотреть файл

@ -18,6 +18,9 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.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(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(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); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0);
/* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ /* {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), 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[] = { static const struct snd_kcontrol_new rt5645_snd_controls[] = {
/* Speaker Output Volume */ /* Speaker Output Volume */
SOC_DOUBLE("Speaker Channel Switch", RT5645_SPK_VOL, 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, SOC_DOUBLE("DAC2 Playback Switch", RT5645_DAC_CTRL,
RT5645_M_DAC_L2_VOL_SFT, RT5645_M_DAC_R2_VOL_SFT, 1, 1), RT5645_M_DAC_L2_VOL_SFT, RT5645_M_DAC_R2_VOL_SFT, 1, 1),
SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5645_DAC1_DIG_VOL, 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, 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 */ /* IN1/IN2 Control */
SOC_SINGLE_TLV("IN1 Boost", RT5645_IN1_CTRL1, 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, SOC_DOUBLE("ADC Capture Switch", RT5645_STO1_ADC_DIG_VOL,
RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1), RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1),
SOC_DOUBLE_TLV("ADC Capture Volume", RT5645_STO1_ADC_DIG_VOL, 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, SOC_DOUBLE("Mono ADC Capture Switch", RT5645_MONO_ADC_DIG_VOL,
RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1), RT5645_L_MUTE_SFT, RT5645_R_MUTE_SFT, 1, 1),
SOC_DOUBLE_TLV("Mono ADC Capture Volume", RT5645_MONO_ADC_DIG_VOL, 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 */ /* ADC Boost Volume Control */
SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5645_ADC_BST_VOL1, 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 */ /* I2S2 function select */
SOC_SINGLE("I2S2 Func Switch", RT5645_GPIO_CTRL1, RT5645_I2S2_SEL_SFT, SOC_SINGLE("I2S2 Func Switch", RT5645_GPIO_CTRL1, RT5645_I2S2_SEL_SFT,
1, 1), 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] */ /* MX-77 [9:8] */
static const char * const rt5645_if1_adc_in_src[] = { 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( 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 = static const struct snd_kcontrol_new rt5645_if1_adc_in_mux =
SOC_DAPM_ENUM("IF1 ADC IN source", rt5645_if1_adc_in_enum); 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] */ /* MX-2d [3] [2] */
static const char * const rt5650_a_dac1_src[] = { static const char * const rt5650_a_dac1_src[] = {
"DAC1", "Stereo DAC Mixer" "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), SND_SOC_DAPM_PGA("IF1_ADC4", SND_SOC_NOPM, 0, 0, NULL, 0),
/* IF1 2 Mux */ /* 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), 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, SND_SOC_DAPM_MUX("IF2 ADC Mux", SND_SOC_NOPM,
0, 0, &rt5645_if2_adc_in_mux), 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), 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 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 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_MUX("RT5645 IF1 DAC1 L Mux", SND_SOC_NOPM, 0, 0,
SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0), &rt5645_if1_dac0_tdm_sel_mux),
SND_SOC_DAPM_PGA("IF1 DAC2 L", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MUX("RT5645 IF1 DAC1 R Mux", SND_SOC_NOPM, 0, 0,
SND_SOC_DAPM_PGA("IF1 DAC2 R", SND_SOC_NOPM, 0, 0, NULL, 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", 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 L", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("IF1 ADC R", 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" }, { "IF_ADC2", NULL, "Mono ADC MIXR" },
{ "VAD_ADC", NULL, "VAD ADC Mux" }, { "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_ADC1", "IF_ADC1" },
{ "IF2 ADC Mux", "IF_ADC2", "IF_ADC2" }, { "IF2 ADC Mux", "IF_ADC2", "IF_ADC2" },
{ "IF2 ADC Mux", "VAD_ADC", "VAD_ADC" }, { "IF2 ADC Mux", "VAD_ADC", "VAD_ADC" },
{ "IF1 ADC", NULL, "I2S1" }, { "IF1 ADC", NULL, "I2S1" },
{ "IF1 ADC", NULL, "IF1 ADC Mux" },
{ "IF2 ADC", NULL, "I2S2" }, { "IF2 ADC", NULL, "I2S2" },
{ "IF2 ADC", NULL, "IF2 ADC Mux" }, { "IF2 ADC", NULL, "IF2 ADC Mux" },
{ "AIF1TX", NULL, "IF1 ADC" },
{ "AIF1TX", NULL, "IF2 ADC" },
{ "AIF2TX", NULL, "IF2 ADC" }, { "AIF2TX", NULL, "IF2 ADC" },
{ "IF1 DAC0", NULL, "AIF1RX" },
{ "IF1 DAC1", NULL, "AIF1RX" }, { "IF1 DAC1", NULL, "AIF1RX" },
{ "IF1 DAC2", NULL, "AIF1RX" }, { "IF1 DAC2", NULL, "AIF1RX" },
{ "IF1 DAC3", NULL, "AIF1RX" },
{ "IF2 DAC", NULL, "AIF2RX" }, { "IF2 DAC", NULL, "AIF2RX" },
{ "IF1 DAC0", NULL, "I2S1" },
{ "IF1 DAC1", NULL, "I2S1" }, { "IF1 DAC1", NULL, "I2S1" },
{ "IF1 DAC2", NULL, "I2S1" }, { "IF1 DAC2", NULL, "I2S1" },
{ "IF1 DAC3", NULL, "I2S1" },
{ "IF2 DAC", NULL, "I2S2" }, { "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 L", NULL, "IF2 DAC" },
{ "IF2 DAC R", 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 L Mux", "IF2 DAC", "IF2 DAC L" },
{ "DAC1 R Mux", "IF1 DAC", "IF1 DAC1 R" },
{ "DAC1 R Mux", "IF2 DAC", "IF2 DAC R" }, { "DAC1 R Mux", "IF2 DAC", "IF2 DAC R" },
{ "DAC1 MIXL", "Stereo ADC Switch", "Stereo1 ADC MIXL" }, { "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", "DAC1 Switch", "DAC1 R Mux" },
{ "DAC1 MIXR", NULL, "dac stereo1 filter" }, { "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", "IF2 DAC", "IF2 DAC L" },
{ "DAC L2 Mux", "Mono ADC", "Mono ADC MIXL" }, { "DAC L2 Mux", "Mono ADC", "Mono ADC MIXL" },
{ "DAC L2 Mux", "VAD_ADC", "VAD_ADC" }, { "DAC L2 Mux", "VAD_ADC", "VAD_ADC" },
{ "DAC L2 Volume", NULL, "DAC L2 Mux" }, { "DAC L2 Volume", NULL, "DAC L2 Mux" },
{ "DAC L2 Volume", NULL, "dac mono left filter" }, { "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", "IF2 DAC", "IF2 DAC R" },
{ "DAC R2 Mux", "Mono ADC", "Mono ADC MIXR" }, { "DAC R2 Mux", "Mono ADC", "Mono ADC MIXR" },
{ "DAC R2 Mux", "Haptic", "Haptic Generator" }, { "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 R1", NULL, "A DAC1 R Mux" },
{ "DAC L2", NULL, "A DAC2 L Mux" }, { "DAC L2", NULL, "A DAC2 L Mux" },
{ "DAC R2", NULL, "A DAC2 R 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[] = { 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 R1", NULL, "Stereo DAC MIXR" },
{ "DAC L2", NULL, "Mono DAC MIXL" }, { "DAC L2", NULL, "Mono DAC MIXL" },
{ "DAC R2", NULL, "Mono DAC MIXR" }, { "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, 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) { switch (dai->id) {
case RT5645_AIF1: case RT5645_AIF1:
mask_clk = RT5645_I2S_BCLK_MS1_MASK | RT5645_I2S_PD1_MASK; mask_clk = RT5645_I2S_PD1_MASK;
val_clk = bclk_ms << RT5645_I2S_BCLK_MS1_SFT | val_clk = pre_div << RT5645_I2S_PD1_SFT;
pre_div << RT5645_I2S_PD1_SFT;
snd_soc_update_bits(codec, RT5645_I2S1_SDP, snd_soc_update_bits(codec, RT5645_I2S1_SDP,
(0x3 << dl_sft), (val_len << dl_sft)); (0x3 << dl_sft), (val_len << dl_sft));
snd_soc_update_bits(codec, RT5645_ADDA_CLK1, mask_clk, val_clk); 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, static int rt5645_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level) enum snd_soc_bias_level level)
{ {
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
switch (level) { switch (level) {
case SND_SOC_BIAS_PREPARE: case SND_SOC_BIAS_PREPARE:
if (SND_SOC_BIAS_STANDBY == codec->dapm.bias_level) { 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: case SND_SOC_BIAS_OFF:
snd_soc_write(codec, RT5645_DEPOP_M2, 0x1100); snd_soc_write(codec, RT5645_DEPOP_M2, 0x1100);
snd_soc_update_bits(codec, RT5645_GEN_CTRL1, if (!rt5645->en_button_func)
RT5645_DIG_GATE_CTRL, 0); snd_soc_update_bits(codec, RT5645_GEN_CTRL1,
RT5645_DIG_GATE_CTRL, 0);
snd_soc_update_bits(codec, RT5645_PWR_ANLG1, snd_soc_update_bits(codec, RT5645_PWR_ANLG1,
RT5645_PWR_VREF1 | RT5645_PWR_MB | RT5645_PWR_VREF1 | RT5645_PWR_MB |
RT5645_PWR_BG | RT5645_PWR_VREF2 | RT5645_PWR_BG | RT5645_PWR_VREF2 |
@ -2414,28 +2660,71 @@ static int rt5645_set_bias_level(struct snd_soc_codec *codec,
return 0; 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);
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);
}
}
static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert)
{ {
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
int gpio_state, jack_type = 0;
unsigned int val; unsigned int val;
if (!gpio_is_valid(rt5645->pdata.hp_det_gpio)) { if (jack_insert) {
dev_err(codec->dev, "invalid gpio\n"); if (codec->component.card->instantiated) {
return -EINVAL; snd_soc_dapm_force_enable_pin(&codec->dapm,
} "micbias1");
gpio_state = gpio_get_value(rt5645->pdata.hp_det_gpio); snd_soc_dapm_force_enable_pin(&codec->dapm,
"micbias2");
dev_dbg(codec->dev, "gpio = %d(%d)\n", rt5645->pdata.hp_det_gpio, snd_soc_dapm_force_enable_pin(&codec->dapm,
gpio_state); "LDO2");
snd_soc_dapm_force_enable_pin(&codec->dapm,
if ((rt5645->pdata.gpio_hp_det_active_high && gpio_state) || "Mic Det Power");
(!rt5645->pdata.gpio_hp_det_active_high && !gpio_state)) { snd_soc_dapm_sync(&codec->dapm);
snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias1"); } else {
snd_soc_dapm_force_enable_pin(&codec->dapm, "micbias2"); /* Power up necessary bits for JD if dapm is
snd_soc_dapm_force_enable_pin(&codec->dapm, "LDO2"); not ready yet */
snd_soc_dapm_force_enable_pin(&codec->dapm, "Mic Det Power"); snd_soc_update_bits(codec, RT5645_PWR_ANLG2,
snd_soc_dapm_sync(&codec->dapm); 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_IN1_CTRL1, 0x0006);
snd_soc_write(codec, RT5645_JD_CTRL3, 0x00b0); 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; val = snd_soc_read(codec, RT5645_IN1_CTRL3) & 0x7;
dev_dbg(codec->dev, "val = %d\n", val); dev_dbg(codec->dev, "val = %d\n", val);
if (val == 1 || val == 2) if (codec->component.card->instantiated) {
jack_type = SND_JACK_HEADSET; snd_soc_dapm_disable_pin(&codec->dapm, "micbias1");
else snd_soc_dapm_disable_pin(&codec->dapm, "micbias2");
jack_type = SND_JACK_HEADPHONE; 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"); if (val == 1 || val == 2) {
snd_soc_dapm_disable_pin(&codec->dapm, "micbias2"); rt5645->jack_type = SND_JACK_HEADSET;
if (rt5645->pdata.jd_mode == 0) if (rt5645->en_button_func) {
snd_soc_dapm_disable_pin(&codec->dapm, "LDO2"); msleep(100);
snd_soc_dapm_disable_pin(&codec->dapm, "Mic Det Power"); rt5645_enable_push_button_irq(codec, true);
snd_soc_dapm_sync(&codec->dapm); }
} 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); return rt5645->jack_type;
snd_soc_jack_report(rt5645->mic_jack, jack_type, SND_JACK_MICROPHONE);
return 0;
} }
static int rt5645_irq_detection(struct rt5645_priv *rt5645);
int rt5645_set_jack_detect(struct snd_soc_codec *codec, 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); struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
rt5645->hp_jack = hp_jack; rt5645->hp_jack = hp_jack;
rt5645->mic_jack = mic_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; return 0;
} }
@ -2485,7 +2806,7 @@ static void rt5645_jack_detect_work(struct work_struct *work)
struct rt5645_priv *rt5645 = struct rt5645_priv *rt5645 =
container_of(work, struct rt5645_priv, jack_detect_work.work); 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) 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; 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) static int rt5645_probe(struct snd_soc_codec *codec)
{ {
struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(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); 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, static int rt5645_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
@ -2663,6 +3141,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
struct rt5645_priv *rt5645; struct rt5645_priv *rt5645;
int ret; int ret;
unsigned int val; unsigned int val;
struct gpio_desc *gpiod;
rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv), rt5645 = devm_kzalloc(&i2c->dev, sizeof(struct rt5645_priv),
GFP_KERNEL); GFP_KERNEL);
@ -2672,8 +3151,23 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
rt5645->i2c = i2c; rt5645->i2c = i2c;
i2c_set_clientdata(i2c, rt5645); i2c_set_clientdata(i2c, rt5645);
if (pdata) if (pdata) {
rt5645->pdata = *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); rt5645->regmap = devm_regmap_init_i2c(i2c, &rt5645_regmap);
if (IS_ERR(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: case RT5645_DMIC_DATA_GPIO12:
regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1, 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, regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
RT5645_GP12_PIN_MASK, RT5645_GP12_PIN_MASK,
RT5645_GP12_PIN_DMIC2_SDA); RT5645_GP12_PIN_DMIC2_SDA);
@ -2784,8 +3278,7 @@ static int rt5645_i2c_probe(struct i2c_client *i2c,
if (rt5645->pdata.en_jd_func) { if (rt5645->pdata.en_jd_func) {
regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3, regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL3,
RT5645_IRQ_CLK_GATE_CTRL | RT5645_MICINDET_MANU, RT5645_IRQ_CLK_GATE_CTRL, RT5645_IRQ_CLK_GATE_CTRL);
RT5645_IRQ_CLK_GATE_CTRL | RT5645_MICINDET_MANU);
regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1, regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1,
RT5645_CBJ_BST1_EN, RT5645_CBJ_BST1_EN); RT5645_CBJ_BST1_EN, RT5645_CBJ_BST1_EN);
regmap_update_bits(rt5645->regmap, RT5645_JD_CTRL3, regmap_update_bits(rt5645->regmap, RT5645_JD_CTRL3,
@ -2872,6 +3365,7 @@ static struct i2c_driver rt5645_i2c_driver = {
.driver = { .driver = {
.name = "rt5645", .name = "rt5645",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.acpi_match_table = ACPI_PTR(rt5645_acpi_match),
}, },
.probe = rt5645_i2c_probe, .probe = rt5645_i2c_probe,
.remove = rt5645_i2c_remove, .remove = rt5645_i2c_remove,

Просмотреть файл

@ -105,6 +105,7 @@
#define RT5645_TDM_CTRL_1 0x77 #define RT5645_TDM_CTRL_1 0x77
#define RT5645_TDM_CTRL_2 0x78 #define RT5645_TDM_CTRL_2 0x78
#define RT5645_TDM_CTRL_3 0x79 #define RT5645_TDM_CTRL_3 0x79
#define RT5650_TDM_CTRL_4 0x7a
/* Function - Analog */ /* Function - Analog */
#define RT5645_GLB_CLK 0x80 #define RT5645_GLB_CLK 0x80
@ -942,10 +943,6 @@
#define RT5645_I2S2_SDI_I2S2 (0x1 << 6) #define RT5645_I2S2_SDI_I2S2 (0x1 << 6)
/* ADC/DAC Clock Control 1 (0x73) */ /* 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_MASK (0x7 << 12)
#define RT5645_I2S_PD1_SFT 12 #define RT5645_I2S_PD1_SFT 12
#define RT5645_I2S_PD1_1 (0x0 << 12) #define RT5645_I2S_PD1_1 (0x0 << 12)
@ -1067,13 +1064,14 @@
#define RT5645_SCLK_SRC_SFT 14 #define RT5645_SCLK_SRC_SFT 14
#define RT5645_SCLK_SRC_MCLK (0x0 << 14) #define RT5645_SCLK_SRC_MCLK (0x0 << 14)
#define RT5645_SCLK_SRC_PLL1 (0x1 << 14) #define RT5645_SCLK_SRC_PLL1 (0x1 << 14)
#define RT5645_SCLK_SRC_RCCLK (0x2 << 14) /* 15MHz */ #define RT5645_SCLK_SRC_RCCLK (0x2 << 14)
#define RT5645_PLL1_SRC_MASK (0x3 << 12) #define RT5645_PLL1_SRC_MASK (0x7 << 11)
#define RT5645_PLL1_SRC_SFT 12 #define RT5645_PLL1_SRC_SFT 11
#define RT5645_PLL1_SRC_MCLK (0x0 << 12) #define RT5645_PLL1_SRC_MCLK (0x0 << 11)
#define RT5645_PLL1_SRC_BCLK1 (0x1 << 12) #define RT5645_PLL1_SRC_BCLK1 (0x1 << 11)
#define RT5645_PLL1_SRC_BCLK2 (0x2 << 12) #define RT5645_PLL1_SRC_BCLK2 (0x2 << 11)
#define RT5645_PLL1_SRC_BCLK3 (0x3 << 12) #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_MASK (0x1 << 3)
#define RT5645_PLL1_PD_SFT 3 #define RT5645_PLL1_PD_SFT 3
#define RT5645_PLL1_PD_1 (0x0 << 3) #define RT5645_PLL1_PD_1 (0x0 << 3)
@ -2184,6 +2182,7 @@ struct rt5645_priv {
struct i2c_client *i2c; struct i2c_client *i2c;
struct snd_soc_jack *hp_jack; struct snd_soc_jack *hp_jack;
struct snd_soc_jack *mic_jack; struct snd_soc_jack *mic_jack;
struct snd_soc_jack *btn_jack;
struct delayed_work jack_detect_work; struct delayed_work jack_detect_work;
int codec_type; int codec_type;
@ -2196,9 +2195,12 @@ struct rt5645_priv {
int pll_src; int pll_src;
int pll_in; int pll_in;
int pll_out; int pll_out;
int jack_type;
bool en_button_func;
}; };
int rt5645_set_jack_detect(struct snd_soc_codec *codec, 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__ */ #endif /* __RT5645_H__ */

Просмотреть файл

@ -214,7 +214,7 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
return ret; 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; return ret;
} }