未验证 提交 7cc289b9 编写于 作者: M Mark Brown

Merge remote-tracking branches 'asoc/topic/mxs', 'asoc/topic/mxs-sgtl5000',...

Merge remote-tracking branches 'asoc/topic/mxs', 'asoc/topic/mxs-sgtl5000', 'asoc/topic/nau8540', 'asoc/topic/nau8824' and 'asoc/topic/nau8825' into asoc-next
* Freescale MXS audio complex with SGTL5000 codec * Freescale MXS audio complex with SGTL5000 codec
Required properties: Required properties:
- compatible: "fsl,mxs-audio-sgtl5000" - compatible : "fsl,mxs-audio-sgtl5000"
- model: The user-visible name of this sound complex - model : The user-visible name of this sound complex
- saif-controllers: The phandle list of the MXS SAIF controller - saif-controllers : The phandle list of the MXS SAIF controller
- audio-codec: The phandle of the SGTL5000 audio codec - audio-codec : The phandle of the SGTL5000 audio codec
- audio-routing : A list of the connections between audio components.
Each entry is a pair of strings, the first being the
connection's sink, the second being the connection's
source. Valid names could be power supplies, SGTL5000
pins, and the jacks on the board:
Power supplies:
* Mic Bias
SGTL5000 pins:
* MIC_IN
* LINE_IN
* HP_OUT
* LINE_OUT
Board connectors:
* Mic Jack
* Line In Jack
* Headphone Jack
* Line Out Jack
* Ext Spk
Example: Example:
...@@ -14,4 +35,8 @@ sound { ...@@ -14,4 +35,8 @@ sound {
model = "imx28-evk-sgtl5000"; model = "imx28-evk-sgtl5000";
saif-controllers = <&saif0 &saif1>; saif-controllers = <&saif0 &saif1>;
audio-codec = <&sgtl5000>; audio-codec = <&sgtl5000>;
audio-routing =
"MIC_IN", "Mic Jack",
"Mic Jack", "Mic Bias",
"Headphone Jack", "HP_OUT";
}; };
...@@ -69,7 +69,7 @@ Optional properties: ...@@ -69,7 +69,7 @@ Optional properties:
- nuvoton,jack-insert-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms - nuvoton,jack-insert-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms
- nuvoton,jack-eject-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms - nuvoton,jack-eject-debounce: number from 0 to 7 that sets debounce time to 2^(n+2) ms
- nuvoton,crosstalk-bypass: make crosstalk function bypass if set. - nuvoton,crosstalk-enable: make crosstalk function enable if set.
- clocks: list of phandle and clock specifier pairs according to common clock bindings for the - clocks: list of phandle and clock specifier pairs according to common clock bindings for the
clocks described in clock-names clocks described in clock-names
...@@ -98,7 +98,7 @@ Example: ...@@ -98,7 +98,7 @@ Example:
nuvoton,short-key-debounce = <2>; nuvoton,short-key-debounce = <2>;
nuvoton,jack-insert-debounce = <7>; nuvoton,jack-insert-debounce = <7>;
nuvoton,jack-eject-debounce = <7>; nuvoton,jack-eject-debounce = <7>;
nuvoton,crosstalk-bypass; nuvoton,crosstalk-enable;
clock-names = "mclk"; clock-names = "mclk";
clocks = <&tegra_car TEGRA210_CLK_CLK_OUT_2>; clocks = <&tegra_car TEGRA210_CLK_CLK_OUT_2>;
......
...@@ -233,6 +233,41 @@ static SOC_ENUM_SINGLE_DECL( ...@@ -233,6 +233,41 @@ static SOC_ENUM_SINGLE_DECL(
static const struct snd_kcontrol_new digital_ch1_mux = static const struct snd_kcontrol_new digital_ch1_mux =
SOC_DAPM_ENUM("Digital CH1 Select", digital_ch1_enum); SOC_DAPM_ENUM("Digital CH1 Select", digital_ch1_enum);
static int adc_power_control(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct nau8540 *nau8540 = snd_soc_codec_get_drvdata(codec);
if (SND_SOC_DAPM_EVENT_ON(event)) {
msleep(300);
/* DO12 and DO34 pad output enable */
regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL1,
NAU8540_I2S_DO12_TRI, 0);
regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL2,
NAU8540_I2S_DO34_TRI, 0);
} else if (SND_SOC_DAPM_EVENT_OFF(event)) {
regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL1,
NAU8540_I2S_DO12_TRI, NAU8540_I2S_DO12_TRI);
regmap_update_bits(nau8540->regmap, NAU8540_REG_PCM_CTRL2,
NAU8540_I2S_DO34_TRI, NAU8540_I2S_DO34_TRI);
}
return 0;
}
static int aiftx_power_control(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct nau8540 *nau8540 = snd_soc_codec_get_drvdata(codec);
if (SND_SOC_DAPM_EVENT_OFF(event)) {
regmap_write(nau8540->regmap, NAU8540_REG_RST, 0x0001);
regmap_write(nau8540->regmap, NAU8540_REG_RST, 0x0000);
}
return 0;
}
static const struct snd_soc_dapm_widget nau8540_dapm_widgets[] = { static const struct snd_soc_dapm_widget nau8540_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("MICBIAS2", NAU8540_REG_MIC_BIAS, 11, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("MICBIAS2", NAU8540_REG_MIC_BIAS, 11, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS1", NAU8540_REG_MIC_BIAS, 10, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("MICBIAS1", NAU8540_REG_MIC_BIAS, 10, 0, NULL, 0),
...@@ -247,14 +282,18 @@ static const struct snd_soc_dapm_widget nau8540_dapm_widgets[] = { ...@@ -247,14 +282,18 @@ static const struct snd_soc_dapm_widget nau8540_dapm_widgets[] = {
SND_SOC_DAPM_PGA("Frontend PGA3", NAU8540_REG_PWR, 14, 0, NULL, 0), SND_SOC_DAPM_PGA("Frontend PGA3", NAU8540_REG_PWR, 14, 0, NULL, 0),
SND_SOC_DAPM_PGA("Frontend PGA4", NAU8540_REG_PWR, 15, 0, NULL, 0), SND_SOC_DAPM_PGA("Frontend PGA4", NAU8540_REG_PWR, 15, 0, NULL, 0),
SND_SOC_DAPM_ADC("ADC1", NULL, SND_SOC_DAPM_ADC_E("ADC1", NULL,
NAU8540_REG_POWER_MANAGEMENT, 0, 0), NAU8540_REG_POWER_MANAGEMENT, 0, 0, adc_power_control,
SND_SOC_DAPM_ADC("ADC2", NULL, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
NAU8540_REG_POWER_MANAGEMENT, 1, 0), SND_SOC_DAPM_ADC_E("ADC2", NULL,
SND_SOC_DAPM_ADC("ADC3", NULL, NAU8540_REG_POWER_MANAGEMENT, 1, 0, adc_power_control,
NAU8540_REG_POWER_MANAGEMENT, 2, 0), SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_ADC("ADC4", NULL, SND_SOC_DAPM_ADC_E("ADC3", NULL,
NAU8540_REG_POWER_MANAGEMENT, 3, 0), NAU8540_REG_POWER_MANAGEMENT, 2, 0, adc_power_control,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_ADC_E("ADC4", NULL,
NAU8540_REG_POWER_MANAGEMENT, 3, 0, adc_power_control,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PGA("ADC CH1", NAU8540_REG_ANALOG_PWR, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("ADC CH1", NAU8540_REG_ANALOG_PWR, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("ADC CH2", NAU8540_REG_ANALOG_PWR, 1, 0, NULL, 0), SND_SOC_DAPM_PGA("ADC CH2", NAU8540_REG_ANALOG_PWR, 1, 0, NULL, 0),
...@@ -270,7 +309,8 @@ static const struct snd_soc_dapm_widget nau8540_dapm_widgets[] = { ...@@ -270,7 +309,8 @@ static const struct snd_soc_dapm_widget nau8540_dapm_widgets[] = {
SND_SOC_DAPM_MUX("Digital CH1 Mux", SND_SOC_DAPM_MUX("Digital CH1 Mux",
SND_SOC_NOPM, 0, 0, &digital_ch1_mux), SND_SOC_NOPM, 0, 0, &digital_ch1_mux),
SND_SOC_DAPM_AIF_OUT("AIFTX", "Capture", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_AIF_OUT_E("AIFTX", "Capture", 0, SND_SOC_NOPM, 0, 0,
aiftx_power_control, SND_SOC_DAPM_POST_PMD),
}; };
static const struct snd_soc_dapm_route nau8540_dapm_routes[] = { static const struct snd_soc_dapm_route nau8540_dapm_routes[] = {
...@@ -575,7 +615,8 @@ static void nau8540_fll_apply(struct regmap *regmap, ...@@ -575,7 +615,8 @@ static void nau8540_fll_apply(struct regmap *regmap,
NAU8540_CLK_SRC_MASK | NAU8540_CLK_MCLK_SRC_MASK, NAU8540_CLK_SRC_MASK | NAU8540_CLK_MCLK_SRC_MASK,
NAU8540_CLK_SRC_MCLK | fll_param->mclk_src); NAU8540_CLK_SRC_MCLK | fll_param->mclk_src);
regmap_update_bits(regmap, NAU8540_REG_FLL1, regmap_update_bits(regmap, NAU8540_REG_FLL1,
NAU8540_FLL_RATIO_MASK, fll_param->ratio); NAU8540_FLL_RATIO_MASK | NAU8540_ICTRL_LATCH_MASK,
fll_param->ratio | (0x6 << NAU8540_ICTRL_LATCH_SFT));
/* FLL 16-bit fractional input */ /* FLL 16-bit fractional input */
regmap_write(regmap, NAU8540_REG_FLL2, fll_param->fll_frac); regmap_write(regmap, NAU8540_REG_FLL2, fll_param->fll_frac);
/* FLL 10-bit integer input */ /* FLL 10-bit integer input */
...@@ -596,13 +637,14 @@ static void nau8540_fll_apply(struct regmap *regmap, ...@@ -596,13 +637,14 @@ static void nau8540_fll_apply(struct regmap *regmap,
NAU8540_FLL_PDB_DAC_EN | NAU8540_FLL_LOOP_FTR_EN | NAU8540_FLL_PDB_DAC_EN | NAU8540_FLL_LOOP_FTR_EN |
NAU8540_FLL_FTR_SW_FILTER); NAU8540_FLL_FTR_SW_FILTER);
regmap_update_bits(regmap, NAU8540_REG_FLL6, regmap_update_bits(regmap, NAU8540_REG_FLL6,
NAU8540_SDM_EN, NAU8540_SDM_EN); NAU8540_SDM_EN | NAU8540_CUTOFF500,
NAU8540_SDM_EN | NAU8540_CUTOFF500);
} else { } else {
regmap_update_bits(regmap, NAU8540_REG_FLL5, regmap_update_bits(regmap, NAU8540_REG_FLL5,
NAU8540_FLL_PDB_DAC_EN | NAU8540_FLL_LOOP_FTR_EN | NAU8540_FLL_PDB_DAC_EN | NAU8540_FLL_LOOP_FTR_EN |
NAU8540_FLL_FTR_SW_MASK, NAU8540_FLL_FTR_SW_ACCU); NAU8540_FLL_FTR_SW_MASK, NAU8540_FLL_FTR_SW_ACCU);
regmap_update_bits(regmap, regmap_update_bits(regmap, NAU8540_REG_FLL6,
NAU8540_REG_FLL6, NAU8540_SDM_EN, 0); NAU8540_SDM_EN | NAU8540_CUTOFF500, 0);
} }
} }
...@@ -617,17 +659,22 @@ static int nau8540_set_pll(struct snd_soc_codec *codec, int pll_id, int source, ...@@ -617,17 +659,22 @@ static int nau8540_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
switch (pll_id) { switch (pll_id) {
case NAU8540_CLK_FLL_MCLK: case NAU8540_CLK_FLL_MCLK:
regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3, regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3,
NAU8540_FLL_CLK_SRC_MASK, NAU8540_FLL_CLK_SRC_MCLK); NAU8540_FLL_CLK_SRC_MASK | NAU8540_GAIN_ERR_MASK,
NAU8540_FLL_CLK_SRC_MCLK | 0);
break; break;
case NAU8540_CLK_FLL_BLK: case NAU8540_CLK_FLL_BLK:
regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3, regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3,
NAU8540_FLL_CLK_SRC_MASK, NAU8540_FLL_CLK_SRC_BLK); NAU8540_FLL_CLK_SRC_MASK | NAU8540_GAIN_ERR_MASK,
NAU8540_FLL_CLK_SRC_BLK |
(0xf << NAU8540_GAIN_ERR_SFT));
break; break;
case NAU8540_CLK_FLL_FS: case NAU8540_CLK_FLL_FS:
regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3, regmap_update_bits(nau8540->regmap, NAU8540_REG_FLL3,
NAU8540_FLL_CLK_SRC_MASK, NAU8540_FLL_CLK_SRC_FS); NAU8540_FLL_CLK_SRC_MASK | NAU8540_GAIN_ERR_MASK,
NAU8540_FLL_CLK_SRC_FS |
(0xf << NAU8540_GAIN_ERR_SFT));
break; break;
default: default:
...@@ -710,9 +757,24 @@ static void nau8540_init_regs(struct nau8540 *nau8540) ...@@ -710,9 +757,24 @@ static void nau8540_init_regs(struct nau8540 *nau8540)
regmap_update_bits(regmap, NAU8540_REG_CLOCK_CTRL, regmap_update_bits(regmap, NAU8540_REG_CLOCK_CTRL,
NAU8540_CLK_ADC_EN | NAU8540_CLK_I2S_EN, NAU8540_CLK_ADC_EN | NAU8540_CLK_I2S_EN,
NAU8540_CLK_ADC_EN | NAU8540_CLK_I2S_EN); NAU8540_CLK_ADC_EN | NAU8540_CLK_I2S_EN);
/* ADC OSR selection, CLK_ADC = Fs * OSR */ /* ADC OSR selection, CLK_ADC = Fs * OSR;
* Channel time alignment enable.
*/
regmap_update_bits(regmap, NAU8540_REG_ADC_SAMPLE_RATE, regmap_update_bits(regmap, NAU8540_REG_ADC_SAMPLE_RATE,
NAU8540_ADC_OSR_MASK, NAU8540_ADC_OSR_64); NAU8540_CH_SYNC | NAU8540_ADC_OSR_MASK,
NAU8540_CH_SYNC | NAU8540_ADC_OSR_64);
/* PGA input mode selection */
regmap_update_bits(regmap, NAU8540_REG_FEPGA1,
NAU8540_FEPGA1_MODCH2_SHT | NAU8540_FEPGA1_MODCH1_SHT,
NAU8540_FEPGA1_MODCH2_SHT | NAU8540_FEPGA1_MODCH1_SHT);
regmap_update_bits(regmap, NAU8540_REG_FEPGA2,
NAU8540_FEPGA2_MODCH4_SHT | NAU8540_FEPGA2_MODCH3_SHT,
NAU8540_FEPGA2_MODCH4_SHT | NAU8540_FEPGA2_MODCH3_SHT);
/* DO12 and DO34 pad output disable */
regmap_update_bits(regmap, NAU8540_REG_PCM_CTRL1,
NAU8540_I2S_DO12_TRI, NAU8540_I2S_DO12_TRI);
regmap_update_bits(regmap, NAU8540_REG_PCM_CTRL2,
NAU8540_I2S_DO34_TRI, NAU8540_I2S_DO34_TRI);
} }
static int __maybe_unused nau8540_suspend(struct snd_soc_codec *codec) static int __maybe_unused nau8540_suspend(struct snd_soc_codec *codec)
......
...@@ -100,9 +100,13 @@ ...@@ -100,9 +100,13 @@
#define NAU8540_CLK_MCLK_SRC_MASK 0xf #define NAU8540_CLK_MCLK_SRC_MASK 0xf
/* FLL1 (0x04) */ /* FLL1 (0x04) */
#define NAU8540_ICTRL_LATCH_SFT 10
#define NAU8540_ICTRL_LATCH_MASK (0x7 << NAU8540_ICTRL_LATCH_SFT)
#define NAU8540_FLL_RATIO_MASK 0x7f #define NAU8540_FLL_RATIO_MASK 0x7f
/* FLL3 (0x06) */ /* FLL3 (0x06) */
#define NAU8540_GAIN_ERR_SFT 12
#define NAU8540_GAIN_ERR_MASK (0xf << NAU8540_GAIN_ERR_SFT)
#define NAU8540_FLL_CLK_SRC_SFT 10 #define NAU8540_FLL_CLK_SRC_SFT 10
#define NAU8540_FLL_CLK_SRC_MASK (0x3 << NAU8540_FLL_CLK_SRC_SFT) #define NAU8540_FLL_CLK_SRC_MASK (0x3 << NAU8540_FLL_CLK_SRC_SFT)
#define NAU8540_FLL_CLK_SRC_MCLK (0 << NAU8540_FLL_CLK_SRC_SFT) #define NAU8540_FLL_CLK_SRC_MCLK (0 << NAU8540_FLL_CLK_SRC_SFT)
...@@ -127,6 +131,7 @@ ...@@ -127,6 +131,7 @@
/* FLL6 (0x9) */ /* FLL6 (0x9) */
#define NAU8540_DCO_EN (0x1 << 15) #define NAU8540_DCO_EN (0x1 << 15)
#define NAU8540_SDM_EN (0x1 << 14) #define NAU8540_SDM_EN (0x1 << 14)
#define NAU8540_CUTOFF500 (0x1 << 13)
/* PCM_CTRL0 (0x10) */ /* PCM_CTRL0 (0x10) */
#define NAU8540_I2S_BP_SFT 7 #define NAU8540_I2S_BP_SFT 7
...@@ -146,6 +151,7 @@ ...@@ -146,6 +151,7 @@
#define NAU8540_I2S_DF_PCM_AB 0x3 #define NAU8540_I2S_DF_PCM_AB 0x3
/* PCM_CTRL1 (0x11) */ /* PCM_CTRL1 (0x11) */
#define NAU8540_I2S_DO12_TRI (0x1 << 15)
#define NAU8540_I2S_LRC_DIV_SFT 12 #define NAU8540_I2S_LRC_DIV_SFT 12
#define NAU8540_I2S_LRC_DIV_MASK (0x3 << NAU8540_I2S_LRC_DIV_SFT) #define NAU8540_I2S_LRC_DIV_MASK (0x3 << NAU8540_I2S_LRC_DIV_SFT)
#define NAU8540_I2S_DO12_OE (0x1 << 4) #define NAU8540_I2S_DO12_OE (0x1 << 4)
...@@ -156,6 +162,7 @@ ...@@ -156,6 +162,7 @@
#define NAU8540_I2S_BLK_DIV_MASK 0x7 #define NAU8540_I2S_BLK_DIV_MASK 0x7
/* PCM_CTRL1 (0x12) */ /* PCM_CTRL1 (0x12) */
#define NAU8540_I2S_DO34_TRI (0x1 << 15)
#define NAU8540_I2S_DO34_OE (0x1 << 11) #define NAU8540_I2S_DO34_OE (0x1 << 11)
#define NAU8540_I2S_TSLOT_L_MASK 0x3ff #define NAU8540_I2S_TSLOT_L_MASK 0x3ff
...@@ -165,6 +172,7 @@ ...@@ -165,6 +172,7 @@
#define NAU8540_TDM_TX_MASK 0xf #define NAU8540_TDM_TX_MASK 0xf
/* ADC_SAMPLE_RATE (0x3A) */ /* ADC_SAMPLE_RATE (0x3A) */
#define NAU8540_CH_SYNC (0x1 << 14)
#define NAU8540_ADC_OSR_MASK 0x3 #define NAU8540_ADC_OSR_MASK 0x3
#define NAU8540_ADC_OSR_256 0x3 #define NAU8540_ADC_OSR_256 0x3
#define NAU8540_ADC_OSR_128 0x2 #define NAU8540_ADC_OSR_128 0x2
...@@ -183,6 +191,18 @@ ...@@ -183,6 +191,18 @@
#define NAU8540_PRECHARGE_DIS (0x1 << 13) #define NAU8540_PRECHARGE_DIS (0x1 << 13)
#define NAU8540_GLOBAL_BIAS_EN (0x1 << 12) #define NAU8540_GLOBAL_BIAS_EN (0x1 << 12)
/* FEPGA1 (0x69) */
#define NAU8540_FEPGA1_MODCH2_SHT_SFT 7
#define NAU8540_FEPGA1_MODCH2_SHT (0x1 << NAU8540_FEPGA1_MODCH2_SHT_SFT)
#define NAU8540_FEPGA1_MODCH1_SHT_SFT 3
#define NAU8540_FEPGA1_MODCH1_SHT (0x1 << NAU8540_FEPGA1_MODCH1_SHT_SFT)
/* FEPGA2 (0x6A) */
#define NAU8540_FEPGA2_MODCH4_SHT_SFT 7
#define NAU8540_FEPGA2_MODCH4_SHT (0x1 << NAU8540_FEPGA2_MODCH4_SHT_SFT)
#define NAU8540_FEPGA2_MODCH3_SHT_SFT 3
#define NAU8540_FEPGA2_MODCH3_SHT (0x1 << NAU8540_FEPGA2_MODCH3_SHT_SFT)
/* System Clock Source */ /* System Clock Source */
enum { enum {
......
...@@ -43,7 +43,7 @@ static bool nau8824_is_jack_inserted(struct nau8824 *nau8824); ...@@ -43,7 +43,7 @@ static bool nau8824_is_jack_inserted(struct nau8824 *nau8824);
/* the parameter threshold of FLL */ /* the parameter threshold of FLL */
#define NAU_FREF_MAX 13500000 #define NAU_FREF_MAX 13500000
#define NAU_FVCO_MAX 124000000 #define NAU_FVCO_MAX 100000000
#define NAU_FVCO_MIN 90000000 #define NAU_FVCO_MIN 90000000
/* scaling for mclk from sysclk_src output */ /* scaling for mclk from sysclk_src output */
...@@ -811,7 +811,8 @@ static void nau8824_eject_jack(struct nau8824 *nau8824) ...@@ -811,7 +811,8 @@ static void nau8824_eject_jack(struct nau8824 *nau8824)
NAU8824_JD_SLEEP_MODE, NAU8824_JD_SLEEP_MODE); NAU8824_JD_SLEEP_MODE, NAU8824_JD_SLEEP_MODE);
/* Close clock for jack type detection at manual mode */ /* Close clock for jack type detection at manual mode */
nau8824_config_sysclk(nau8824, NAU8824_CLK_DIS, 0); if (dapm->bias_level < SND_SOC_BIAS_PREPARE)
nau8824_config_sysclk(nau8824, NAU8824_CLK_DIS, 0);
} }
static void nau8824_jdet_work(struct work_struct *work) static void nau8824_jdet_work(struct work_struct *work)
...@@ -843,6 +844,11 @@ static void nau8824_jdet_work(struct work_struct *work) ...@@ -843,6 +844,11 @@ static void nau8824_jdet_work(struct work_struct *work)
event_mask |= SND_JACK_HEADSET; event_mask |= SND_JACK_HEADSET;
snd_soc_jack_report(nau8824->jack, event, event_mask); snd_soc_jack_report(nau8824->jack, event, event_mask);
/* Enable short key press and release interruption. */
regmap_update_bits(regmap, NAU8824_REG_INTERRUPT_SETTING,
NAU8824_IRQ_KEY_RELEASE_DIS |
NAU8824_IRQ_KEY_SHORT_PRESS_DIS, 0);
nau8824_sema_release(nau8824); nau8824_sema_release(nau8824);
} }
...@@ -850,15 +856,15 @@ static void nau8824_setup_auto_irq(struct nau8824 *nau8824) ...@@ -850,15 +856,15 @@ static void nau8824_setup_auto_irq(struct nau8824 *nau8824)
{ {
struct regmap *regmap = nau8824->regmap; struct regmap *regmap = nau8824->regmap;
/* Enable jack ejection, short key press and release interruption. */ /* Enable jack ejection interruption. */
regmap_update_bits(regmap, NAU8824_REG_INTERRUPT_SETTING_1, regmap_update_bits(regmap, NAU8824_REG_INTERRUPT_SETTING_1,
NAU8824_IRQ_INSERT_EN | NAU8824_IRQ_EJECT_EN, NAU8824_IRQ_INSERT_EN | NAU8824_IRQ_EJECT_EN,
NAU8824_IRQ_EJECT_EN); NAU8824_IRQ_EJECT_EN);
regmap_update_bits(regmap, NAU8824_REG_INTERRUPT_SETTING, regmap_update_bits(regmap, NAU8824_REG_INTERRUPT_SETTING,
NAU8824_IRQ_EJECT_DIS | NAU8824_IRQ_KEY_RELEASE_DIS | NAU8824_IRQ_EJECT_DIS, 0);
NAU8824_IRQ_KEY_SHORT_PRESS_DIS, 0);
/* Enable internal VCO needed for interruptions */ /* Enable internal VCO needed for interruptions */
nau8824_config_sysclk(nau8824, NAU8824_CLK_INTERNAL, 0); if (nau8824->dapm->bias_level < SND_SOC_BIAS_PREPARE)
nau8824_config_sysclk(nau8824, NAU8824_CLK_INTERNAL, 0);
regmap_update_bits(regmap, NAU8824_REG_ENA_CTRL, regmap_update_bits(regmap, NAU8824_REG_ENA_CTRL,
NAU8824_JD_SLEEP_MODE, 0); NAU8824_JD_SLEEP_MODE, 0);
} }
......
...@@ -194,10 +194,10 @@ static const struct reg_default nau8825_reg_defaults[] = { ...@@ -194,10 +194,10 @@ static const struct reg_default nau8825_reg_defaults[] = {
/* register backup table when cross talk detection */ /* register backup table when cross talk detection */
static struct reg_default nau8825_xtalk_baktab[] = { static struct reg_default nau8825_xtalk_baktab[] = {
{ NAU8825_REG_ADC_DGAIN_CTRL, 0 }, { NAU8825_REG_ADC_DGAIN_CTRL, 0x00cf },
{ NAU8825_REG_HSVOL_CTRL, 0 }, { NAU8825_REG_HSVOL_CTRL, 0 },
{ NAU8825_REG_DACL_CTRL, 0 }, { NAU8825_REG_DACL_CTRL, 0x00cf },
{ NAU8825_REG_DACR_CTRL, 0 }, { NAU8825_REG_DACR_CTRL, 0x02cf },
}; };
static const unsigned short logtable[256] = { static const unsigned short logtable[256] = {
...@@ -245,13 +245,14 @@ static const unsigned short logtable[256] = { ...@@ -245,13 +245,14 @@ static const unsigned short logtable[256] = {
* tasks are allowed to acquire the semaphore, calling this function will * tasks are allowed to acquire the semaphore, calling this function will
* put the task to sleep. If the semaphore is not released within the * put the task to sleep. If the semaphore is not released within the
* specified number of jiffies, this function returns. * specified number of jiffies, this function returns.
* Acquires the semaphore without jiffies. If no more tasks are allowed
* to acquire the semaphore, calling this function will put the task to
* sleep until the semaphore is released.
* If the semaphore is not released within the specified number of jiffies, * If the semaphore is not released within the specified number of jiffies,
* this function returns -ETIME. * this function returns -ETIME. If the sleep is interrupted by a signal,
* If the sleep is interrupted by a signal, this function will return -EINTR. * this function will return -EINTR. It returns 0 if the semaphore was
* It returns 0 if the semaphore was acquired successfully. * acquired successfully.
*
* Acquires the semaphore without jiffies. Try to acquire the semaphore
* atomically. Returns 0 if the semaphore has been acquired successfully
* or 1 if it it cannot be acquired.
*/ */
static int nau8825_sema_acquire(struct nau8825 *nau8825, long timeout) static int nau8825_sema_acquire(struct nau8825 *nau8825, long timeout)
{ {
...@@ -262,8 +263,8 @@ static int nau8825_sema_acquire(struct nau8825 *nau8825, long timeout) ...@@ -262,8 +263,8 @@ static int nau8825_sema_acquire(struct nau8825 *nau8825, long timeout)
if (ret < 0) if (ret < 0)
dev_warn(nau8825->dev, "Acquire semaphore timeout\n"); dev_warn(nau8825->dev, "Acquire semaphore timeout\n");
} else { } else {
ret = down_interruptible(&nau8825->xtalk_sem); ret = down_trylock(&nau8825->xtalk_sem);
if (ret < 0) if (ret)
dev_warn(nau8825->dev, "Acquire semaphore fail\n"); dev_warn(nau8825->dev, "Acquire semaphore fail\n");
} }
...@@ -454,22 +455,32 @@ static void nau8825_xtalk_backup(struct nau8825 *nau8825) ...@@ -454,22 +455,32 @@ static void nau8825_xtalk_backup(struct nau8825 *nau8825)
{ {
int i; int i;
if (nau8825->xtalk_baktab_initialized)
return;
/* Backup some register values to backup table */ /* Backup some register values to backup table */
for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++) for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++)
regmap_read(nau8825->regmap, nau8825_xtalk_baktab[i].reg, regmap_read(nau8825->regmap, nau8825_xtalk_baktab[i].reg,
&nau8825_xtalk_baktab[i].def); &nau8825_xtalk_baktab[i].def);
nau8825->xtalk_baktab_initialized = true;
} }
static void nau8825_xtalk_restore(struct nau8825 *nau8825) static void nau8825_xtalk_restore(struct nau8825 *nau8825, bool cause_cancel)
{ {
int i, volume; int i, volume;
if (!nau8825->xtalk_baktab_initialized)
return;
/* Restore register values from backup table; When the driver restores /* Restore register values from backup table; When the driver restores
* the headphone volumem, it needs recover to original level gradually * the headphone volume in XTALK_DONE state, it needs recover to
* with 3dB per step for less pop noise. * original level gradually with 3dB per step for less pop noise.
* Otherwise, the restore should do ASAP.
*/ */
for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++) { for (i = 0; i < ARRAY_SIZE(nau8825_xtalk_baktab); i++) {
if (nau8825_xtalk_baktab[i].reg == NAU8825_REG_HSVOL_CTRL) { if (!cause_cancel && nau8825_xtalk_baktab[i].reg ==
NAU8825_REG_HSVOL_CTRL) {
/* Ramping up the volume change to reduce pop noise */ /* Ramping up the volume change to reduce pop noise */
volume = nau8825_xtalk_baktab[i].def & volume = nau8825_xtalk_baktab[i].def &
NAU8825_HPR_VOL_MASK; NAU8825_HPR_VOL_MASK;
...@@ -479,6 +490,8 @@ static void nau8825_xtalk_restore(struct nau8825 *nau8825) ...@@ -479,6 +490,8 @@ static void nau8825_xtalk_restore(struct nau8825 *nau8825)
regmap_write(nau8825->regmap, nau8825_xtalk_baktab[i].reg, regmap_write(nau8825->regmap, nau8825_xtalk_baktab[i].reg,
nau8825_xtalk_baktab[i].def); nau8825_xtalk_baktab[i].def);
} }
nau8825->xtalk_baktab_initialized = false;
} }
static void nau8825_xtalk_prepare_dac(struct nau8825 *nau8825) static void nau8825_xtalk_prepare_dac(struct nau8825 *nau8825)
...@@ -644,7 +657,7 @@ static void nau8825_xtalk_clean_adc(struct nau8825 *nau8825) ...@@ -644,7 +657,7 @@ static void nau8825_xtalk_clean_adc(struct nau8825 *nau8825)
NAU8825_POWERUP_ADCL | NAU8825_ADC_VREFSEL_MASK, 0); NAU8825_POWERUP_ADCL | NAU8825_ADC_VREFSEL_MASK, 0);
} }
static void nau8825_xtalk_clean(struct nau8825 *nau8825) static void nau8825_xtalk_clean(struct nau8825 *nau8825, bool cause_cancel)
{ {
/* Enable internal VCO needed for interruptions */ /* Enable internal VCO needed for interruptions */
nau8825_configure_sysclk(nau8825, NAU8825_CLK_INTERNAL, 0); nau8825_configure_sysclk(nau8825, NAU8825_CLK_INTERNAL, 0);
...@@ -660,7 +673,7 @@ static void nau8825_xtalk_clean(struct nau8825 *nau8825) ...@@ -660,7 +673,7 @@ static void nau8825_xtalk_clean(struct nau8825 *nau8825)
NAU8825_I2S_MS_MASK | NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_MS_MASK | NAU8825_I2S_LRC_DIV_MASK |
NAU8825_I2S_BLK_DIV_MASK, NAU8825_I2S_MS_SLAVE); NAU8825_I2S_BLK_DIV_MASK, NAU8825_I2S_MS_SLAVE);
/* Restore value of specific register for cross talk */ /* Restore value of specific register for cross talk */
nau8825_xtalk_restore(nau8825); nau8825_xtalk_restore(nau8825, cause_cancel);
} }
static void nau8825_xtalk_imm_start(struct nau8825 *nau8825, int vol) static void nau8825_xtalk_imm_start(struct nau8825 *nau8825, int vol)
...@@ -779,7 +792,7 @@ static void nau8825_xtalk_measure(struct nau8825 *nau8825) ...@@ -779,7 +792,7 @@ static void nau8825_xtalk_measure(struct nau8825 *nau8825)
dev_dbg(nau8825->dev, "cross talk sidetone: %x\n", sidetone); dev_dbg(nau8825->dev, "cross talk sidetone: %x\n", sidetone);
regmap_write(nau8825->regmap, NAU8825_REG_DAC_DGAIN_CTRL, regmap_write(nau8825->regmap, NAU8825_REG_DAC_DGAIN_CTRL,
(sidetone << 8) | sidetone); (sidetone << 8) | sidetone);
nau8825_xtalk_clean(nau8825); nau8825_xtalk_clean(nau8825, false);
nau8825->xtalk_state = NAU8825_XTALK_DONE; nau8825->xtalk_state = NAU8825_XTALK_DONE;
break; break;
default: default:
...@@ -815,13 +828,14 @@ static void nau8825_xtalk_work(struct work_struct *work) ...@@ -815,13 +828,14 @@ static void nau8825_xtalk_work(struct work_struct *work)
static void nau8825_xtalk_cancel(struct nau8825 *nau8825) static void nau8825_xtalk_cancel(struct nau8825 *nau8825)
{ {
/* If the xtalk_protect is true, that means the process is still /* If the crosstalk is eanbled and the process is on going,
* on going. The driver forces to cancel the cross talk task and * the driver forces to cancel the crosstalk task and
* restores the configuration to original status. * restores the configuration to original status.
*/ */
if (nau8825->xtalk_protect) { if (nau8825->xtalk_enable && nau8825->xtalk_state !=
NAU8825_XTALK_DONE) {
cancel_work_sync(&nau8825->xtalk_work); cancel_work_sync(&nau8825->xtalk_work);
nau8825_xtalk_clean(nau8825); nau8825_xtalk_clean(nau8825, true);
} }
/* Reset parameters for cross talk suppression function */ /* Reset parameters for cross talk suppression function */
nau8825_sema_reset(nau8825); nau8825_sema_reset(nau8825);
...@@ -1246,8 +1260,10 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream, ...@@ -1246,8 +1260,10 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
regmap_read(nau8825->regmap, NAU8825_REG_DAC_CTRL1, &osr); regmap_read(nau8825->regmap, NAU8825_REG_DAC_CTRL1, &osr);
osr &= NAU8825_DAC_OVERSAMPLE_MASK; osr &= NAU8825_DAC_OVERSAMPLE_MASK;
if (nau8825_clock_check(nau8825, substream->stream, if (nau8825_clock_check(nau8825, substream->stream,
params_rate(params), osr)) params_rate(params), osr)) {
nau8825_sema_release(nau8825);
return -EINVAL; return -EINVAL;
}
regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
NAU8825_CLK_DAC_SRC_MASK, NAU8825_CLK_DAC_SRC_MASK,
osr_dac_sel[osr].clk_src << NAU8825_CLK_DAC_SRC_SFT); osr_dac_sel[osr].clk_src << NAU8825_CLK_DAC_SRC_SFT);
...@@ -1255,8 +1271,10 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream, ...@@ -1255,8 +1271,10 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
regmap_read(nau8825->regmap, NAU8825_REG_ADC_RATE, &osr); regmap_read(nau8825->regmap, NAU8825_REG_ADC_RATE, &osr);
osr &= NAU8825_ADC_SYNC_DOWN_MASK; osr &= NAU8825_ADC_SYNC_DOWN_MASK;
if (nau8825_clock_check(nau8825, substream->stream, if (nau8825_clock_check(nau8825, substream->stream,
params_rate(params), osr)) params_rate(params), osr)) {
nau8825_sema_release(nau8825);
return -EINVAL; return -EINVAL;
}
regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER, regmap_update_bits(nau8825->regmap, NAU8825_REG_CLK_DIVIDER,
NAU8825_CLK_ADC_SRC_MASK, NAU8825_CLK_ADC_SRC_MASK,
osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT); osr_adc_sel[osr].clk_src << NAU8825_CLK_ADC_SRC_SFT);
...@@ -1273,8 +1291,10 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream, ...@@ -1273,8 +1291,10 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
bclk_div = 1; bclk_div = 1;
else if (bclk_fs <= 128) else if (bclk_fs <= 128)
bclk_div = 0; bclk_div = 0;
else else {
nau8825_sema_release(nau8825);
return -EINVAL; return -EINVAL;
}
regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2, regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL2,
NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_BLK_DIV_MASK, NAU8825_I2S_LRC_DIV_MASK | NAU8825_I2S_BLK_DIV_MASK,
((bclk_div + 1) << NAU8825_I2S_LRC_DIV_SFT) | bclk_div); ((bclk_div + 1) << NAU8825_I2S_LRC_DIV_SFT) | bclk_div);
...@@ -1294,6 +1314,7 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream, ...@@ -1294,6 +1314,7 @@ static int nau8825_hw_params(struct snd_pcm_substream *substream,
val_len |= NAU8825_I2S_DL_32; val_len |= NAU8825_I2S_DL_32;
break; break;
default: default:
nau8825_sema_release(nau8825);
return -EINVAL; return -EINVAL;
} }
...@@ -1312,8 +1333,6 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) ...@@ -1312,8 +1333,6 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec); struct nau8825 *nau8825 = snd_soc_codec_get_drvdata(codec);
unsigned int ctrl1_val = 0, ctrl2_val = 0; unsigned int ctrl1_val = 0, ctrl2_val = 0;
nau8825_sema_acquire(nau8825, 3 * HZ);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM: case SND_SOC_DAIFMT_CBM_CFM:
ctrl2_val |= NAU8825_I2S_MS_MASTER; ctrl2_val |= NAU8825_I2S_MS_MASTER;
...@@ -1355,6 +1374,8 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) ...@@ -1355,6 +1374,8 @@ static int nau8825_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
return -EINVAL; return -EINVAL;
} }
nau8825_sema_acquire(nau8825, 3 * HZ);
regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1, regmap_update_bits(nau8825->regmap, NAU8825_REG_I2S_PCM_CTRL1,
NAU8825_I2S_DL_MASK | NAU8825_I2S_DF_MASK | NAU8825_I2S_DL_MASK | NAU8825_I2S_DF_MASK |
NAU8825_I2S_BP_MASK | NAU8825_I2S_PCMB_MASK, NAU8825_I2S_BP_MASK | NAU8825_I2S_PCMB_MASK,
...@@ -1687,7 +1708,7 @@ static irqreturn_t nau8825_interrupt(int irq, void *data) ...@@ -1687,7 +1708,7 @@ static irqreturn_t nau8825_interrupt(int irq, void *data)
} else if (active_irq & NAU8825_HEADSET_COMPLETION_IRQ) { } else if (active_irq & NAU8825_HEADSET_COMPLETION_IRQ) {
if (nau8825_is_jack_inserted(regmap)) { if (nau8825_is_jack_inserted(regmap)) {
event |= nau8825_jack_insert(nau8825); event |= nau8825_jack_insert(nau8825);
if (!nau8825->xtalk_bypass && !nau8825->high_imped) { if (nau8825->xtalk_enable && !nau8825->high_imped) {
/* Apply the cross talk suppression in the /* Apply the cross talk suppression in the
* headset without high impedance. * headset without high impedance.
*/ */
...@@ -1701,12 +1722,15 @@ static irqreturn_t nau8825_interrupt(int irq, void *data) ...@@ -1701,12 +1722,15 @@ static irqreturn_t nau8825_interrupt(int irq, void *data)
int ret; int ret;
nau8825->xtalk_protect = true; nau8825->xtalk_protect = true;
ret = nau8825_sema_acquire(nau8825, 0); ret = nau8825_sema_acquire(nau8825, 0);
if (ret < 0) if (ret)
nau8825->xtalk_protect = false; nau8825->xtalk_protect = false;
} }
/* Startup cross talk detection process */ /* Startup cross talk detection process */
nau8825->xtalk_state = NAU8825_XTALK_PREPARE; if (nau8825->xtalk_protect) {
schedule_work(&nau8825->xtalk_work); nau8825->xtalk_state =
NAU8825_XTALK_PREPARE;
schedule_work(&nau8825->xtalk_work);
}
} else { } else {
/* The cross talk suppression shouldn't apply /* The cross talk suppression shouldn't apply
* in the headset with high impedance. Thus, * in the headset with high impedance. Thus,
...@@ -1733,7 +1757,9 @@ static irqreturn_t nau8825_interrupt(int irq, void *data) ...@@ -1733,7 +1757,9 @@ static irqreturn_t nau8825_interrupt(int irq, void *data)
nau8825->xtalk_event_mask = event_mask; nau8825->xtalk_event_mask = event_mask;
} }
} else if (active_irq & NAU8825_IMPEDANCE_MEAS_IRQ) { } else if (active_irq & NAU8825_IMPEDANCE_MEAS_IRQ) {
schedule_work(&nau8825->xtalk_work); /* crosstalk detection enable and process on going */
if (nau8825->xtalk_enable && nau8825->xtalk_protect)
schedule_work(&nau8825->xtalk_work);
clear_irq = NAU8825_IMPEDANCE_MEAS_IRQ; clear_irq = NAU8825_IMPEDANCE_MEAS_IRQ;
} else if ((active_irq & NAU8825_JACK_INSERTION_IRQ_MASK) == } else if ((active_irq & NAU8825_JACK_INSERTION_IRQ_MASK) ==
NAU8825_JACK_INSERTION_DETECTED) { NAU8825_JACK_INSERTION_DETECTED) {
...@@ -2382,7 +2408,7 @@ static int __maybe_unused nau8825_resume(struct snd_soc_codec *codec) ...@@ -2382,7 +2408,7 @@ static int __maybe_unused nau8825_resume(struct snd_soc_codec *codec)
regcache_sync(nau8825->regmap); regcache_sync(nau8825->regmap);
nau8825->xtalk_protect = true; nau8825->xtalk_protect = true;
ret = nau8825_sema_acquire(nau8825, 0); ret = nau8825_sema_acquire(nau8825, 0);
if (ret < 0) if (ret)
nau8825->xtalk_protect = false; nau8825->xtalk_protect = false;
enable_irq(nau8825->irq); enable_irq(nau8825->irq);
...@@ -2441,8 +2467,8 @@ static void nau8825_print_device_properties(struct nau8825 *nau8825) ...@@ -2441,8 +2467,8 @@ static void nau8825_print_device_properties(struct nau8825 *nau8825)
nau8825->jack_insert_debounce); nau8825->jack_insert_debounce);
dev_dbg(dev, "jack-eject-debounce: %d\n", dev_dbg(dev, "jack-eject-debounce: %d\n",
nau8825->jack_eject_debounce); nau8825->jack_eject_debounce);
dev_dbg(dev, "crosstalk-bypass: %d\n", dev_dbg(dev, "crosstalk-enable: %d\n",
nau8825->xtalk_bypass); nau8825->xtalk_enable);
} }
static int nau8825_read_device_properties(struct device *dev, static int nau8825_read_device_properties(struct device *dev,
...@@ -2507,8 +2533,8 @@ static int nau8825_read_device_properties(struct device *dev, ...@@ -2507,8 +2533,8 @@ static int nau8825_read_device_properties(struct device *dev,
&nau8825->jack_eject_debounce); &nau8825->jack_eject_debounce);
if (ret) if (ret)
nau8825->jack_eject_debounce = 0; nau8825->jack_eject_debounce = 0;
nau8825->xtalk_bypass = device_property_read_bool(dev, nau8825->xtalk_enable = device_property_read_bool(dev,
"nuvoton,crosstalk-bypass"); "nuvoton,crosstalk-enable");
nau8825->mclk = devm_clk_get(dev, "mclk"); nau8825->mclk = devm_clk_get(dev, "mclk");
if (PTR_ERR(nau8825->mclk) == -EPROBE_DEFER) { if (PTR_ERR(nau8825->mclk) == -EPROBE_DEFER) {
...@@ -2569,6 +2595,7 @@ static int nau8825_i2c_probe(struct i2c_client *i2c, ...@@ -2569,6 +2595,7 @@ static int nau8825_i2c_probe(struct i2c_client *i2c,
*/ */
nau8825->xtalk_state = NAU8825_XTALK_DONE; nau8825->xtalk_state = NAU8825_XTALK_DONE;
nau8825->xtalk_protect = false; nau8825->xtalk_protect = false;
nau8825->xtalk_baktab_initialized = false;
sema_init(&nau8825->xtalk_sem, 1); sema_init(&nau8825->xtalk_sem, 1);
INIT_WORK(&nau8825->xtalk_work, nau8825_xtalk_work); INIT_WORK(&nau8825->xtalk_work, nau8825_xtalk_work);
......
...@@ -476,7 +476,8 @@ struct nau8825 { ...@@ -476,7 +476,8 @@ struct nau8825 {
int xtalk_event_mask; int xtalk_event_mask;
bool xtalk_protect; bool xtalk_protect;
int imp_rms[NAU8825_XTALK_IMM]; int imp_rms[NAU8825_XTALK_IMM];
int xtalk_bypass; int xtalk_enable;
bool xtalk_baktab_initialized; /* True if initialized. */
}; };
int nau8825_enable_jack_detect(struct snd_soc_codec *codec, int nau8825_enable_jack_detect(struct snd_soc_codec *codec,
......
...@@ -93,6 +93,14 @@ static struct snd_soc_dai_link mxs_sgtl5000_dai[] = { ...@@ -93,6 +93,14 @@ static struct snd_soc_dai_link mxs_sgtl5000_dai[] = {
}, },
}; };
static const struct snd_soc_dapm_widget mxs_sgtl5000_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Mic Jack", NULL),
SND_SOC_DAPM_LINE("Line In Jack", NULL),
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_SPK("Line Out Jack", NULL),
SND_SOC_DAPM_SPK("Ext Spk", NULL),
};
static struct snd_soc_card mxs_sgtl5000 = { static struct snd_soc_card mxs_sgtl5000 = {
.name = "mxs_sgtl5000", .name = "mxs_sgtl5000",
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -141,10 +149,23 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev) ...@@ -141,10 +149,23 @@ static int mxs_sgtl5000_probe(struct platform_device *pdev)
card->dev = &pdev->dev; card->dev = &pdev->dev;
if (of_find_property(np, "audio-routing", NULL)) {
card->dapm_widgets = mxs_sgtl5000_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(mxs_sgtl5000_dapm_widgets);
ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
if (ret) {
dev_err(&pdev->dev, "failed to parse audio-routing (%d)\n",
ret);
return ret;
}
}
ret = devm_snd_soc_register_card(&pdev->dev, card); ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) { if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", if (ret != -EPROBE_DEFER)
ret); dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
ret);
return ret; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册