diff mbox

[1/2] ASoC: rt5645: Adds push button support for rt5650

Message ID 1429497442-13021-1-git-send-email-bardliao@realtek.com (mailing list archive)
State New, archived
Headers show

Commit Message

Bard Liao April 20, 2015, 2:37 a.m. UTC
rt5650 support headset button detection. Currently, the button
detection is only implemented for rt5650 codec.

Signed-off-by: Bard Liao <bardliao@realtek.com>
---
 sound/soc/codecs/rt5645.c | 262 +++++++++++++++++++++++++++++++++++++++-------
 sound/soc/codecs/rt5645.h |   8 +-
 2 files changed, 231 insertions(+), 39 deletions(-)

Comments

Mark Brown April 20, 2015, 8:41 p.m. UTC | #1
On Mon, Apr 20, 2015 at 10:37:21AM +0800, Bard Liao wrote:

> --- a/sound/soc/codecs/rt5645.c
> +++ b/sound/soc/codecs/rt5645.c
> @@ -198,7 +198,6 @@ static const struct reg_default rt5645_reg[] = {
>  	{ 0xda, 0x0000 },
>  	{ 0xdb, 0x0003 },
>  	{ 0xdc, 0x0049 },
> -	{ 0xdd, 0x001b },
>  	{ 0xdf, 0x0008 },
>  	{ 0xe0, 0x4000 },
>  	{ 0xe6, 0x8000 },

That's a bit weird, why is this in here?

> +	if (rt5645->btn_jack && rt5645->codec_type == CODEC_TYPE_RT5650) {

Can we have a switch statement for the device type so it's easier to add
other devices if there's new derivatives please?

> +			btn_type = rt5645_button_detect(rt5645->codec);
> +			switch (btn_type) {
> +			case 0x8000:
> +			case 0x4000:
> +			case 0x2000:
> +				report |= SND_JACK_BTN_0;
> +				break;

Why do we mash all these values together?
Bard Liao April 21, 2015, 2:08 a.m. UTC | #2
> -----Original Message-----
> From: Mark Brown [mailto:broonie@kernel.org]
> Sent: Tuesday, April 21, 2015 4:41 AM
> To: Bard Liao
> Cc: lgirdwood@gmail.com; alsa-devel@alsa-project.org; lars@metafoo.de;
> Flove; Oder Chiou; John Lin; koro.chen@mediatek.com;
> yang.a.fang@intel.com; zhengxing@rock-chips.com
> Subject: Re: [PATCH 1/2] ASoC: rt5645: Adds push button support for
> rt5650
> 
> On Mon, Apr 20, 2015 at 10:37:21AM +0800, Bard Liao wrote:
> 
> > --- a/sound/soc/codecs/rt5645.c
> > +++ b/sound/soc/codecs/rt5645.c
> > @@ -198,7 +198,6 @@ static const struct reg_default rt5645_reg[] = {
> >  	{ 0xda, 0x0000 },
> >  	{ 0xdb, 0x0003 },
> >  	{ 0xdc, 0x0049 },
> > -	{ 0xdd, 0x001b },
> >  	{ 0xdf, 0x0008 },
> >  	{ 0xe0, 0x4000 },
> >  	{ 0xe6, 0x8000 },
> 
> That's a bit weird, why is this in here?

The default value of register 0xdd is different between rt5645 and rt5650.
And it is for button detection configuration. That's why I put it in this
patch instead of a separate patch.


> 
> > +	if (rt5645->btn_jack && rt5645->codec_type ==
> CODEC_TYPE_RT5650) {
> 
> Can we have a switch statement for the device type so it's easier to add
> other devices if there's new derivatives please?
> 
> > +			btn_type = rt5645_button_detect(rt5645->codec);
> > +			switch (btn_type) {
> > +			case 0x8000:
> > +			case 0x4000:
> > +			case 0x2000:
> > +				report |= SND_JACK_BTN_0;
> > +				break;
> 
> Why do we mash all these values together?

rt5650 can report the action of button (one click, double click or hold).
That is basically for Windows OS. For linux, we only care about whether
the button is pressed or released. So all of the three actions are treated
as button pressed.

> 
> ------Please consider the environment before printing this e-mail.
Mark Brown April 21, 2015, 10:48 a.m. UTC | #3
On Tue, Apr 21, 2015 at 02:08:18AM +0000, Bard Liao wrote:

> > > -	{ 0xdd, 0x001b },

> > That's a bit weird, why is this in here?

> The default value of register 0xdd is different between rt5645 and rt5650.
> And it is for button detection configuration. That's why I put it in this
> patch instead of a separate patch.

OK, you probaly want to move to separate default tables per device.
This is something that should have been called out in the commit log.

> > > +			switch (btn_type) {
> > > +			case 0x8000:
> > > +			case 0x4000:
> > > +			case 0x2000:
> > > +				report |= SND_JACK_BTN_0;
> > > +				break;

> > Why do we mash all these values together?

> rt5650 can report the action of button (one click, double click or hold).
> That is basically for Windows OS. For linux, we only care about whether
> the button is pressed or released. So all of the three actions are treated
> as button pressed.

OK, can we have a comment for that please?  We might want to extend this
in the future as the userspace ABI grows richer (and depending on how
things get reported we may need to synthesize at least a double press
for userspace).
Bard Liao April 21, 2015, 11:41 a.m. UTC | #4
> -----Original Message-----
> From: Mark Brown [mailto:broonie@kernel.org]
> Sent: Tuesday, April 21, 2015 6:48 PM
> To: Bard Liao
> Cc: lgirdwood@gmail.com; alsa-devel@alsa-project.org; lars@metafoo.de;
> Flove; Oder Chiou; John Lin; koro.chen@mediatek.com;
> yang.a.fang@intel.com; zhengxing@rock-chips.com
> Subject: Re: [PATCH 1/2] ASoC: rt5645: Adds push button support for
> rt5650
> 
> On Tue, Apr 21, 2015 at 02:08:18AM +0000, Bard Liao wrote:
> 
> > > > -	{ 0xdd, 0x001b },
> 
> > > That's a bit weird, why is this in here?
> 
> > The default value of register 0xdd is different between rt5645 and
> rt5650.
> > And it is for button detection configuration. That's why I put it in
> > this patch instead of a separate patch.
> 
> OK, you probaly want to move to separate default tables per device.
> This is something that should have been called out in the commit log.

Do you mean we need to write it down in the commit log and send
another patch to use separate default tables for different device?
In fact, there are about 10 different registers which default value
are different between rt5645 and rt5650. We are planning to send
a separate patch for that after this patch is applied.

Regarding the different default tables, do you mean something like:
	case RT5645_DEVICE_ID:
		rt5645->codec_type = CODEC_TYPE_RT5645;
		dev_info(&i2c->dev,	"Codec type is: RT5645\n");
+		rt5645_regmap. reg_defaults = rt5645_reg;
		break;
	case RT5650_DEVICE_ID:
		rt5645->codec_type = CODEC_TYPE_RT5650;
		dev_info(&i2c->dev,	"Codec type is: RT5650\n");
+		rt5645_regmap. reg_defaults = rt5650_reg;
		break;

> 
> > > > +			switch (btn_type) {
> > > > +			case 0x8000:
> > > > +			case 0x4000:
> > > > +			case 0x2000:
> > > > +				report |= SND_JACK_BTN_0;
> > > > +				break;
> 
> > > Why do we mash all these values together?
> 
> > rt5650 can report the action of button (one click, double click or hold).
> > That is basically for Windows OS. For linux, we only care about
> > whether the button is pressed or released. So all of the three actions
> > are treated as button pressed.
> 
> OK, can we have a comment for that please?  We might want to extend
> this in the future as the userspace ABI grows richer (and depending on
> how things get reported we may need to synthesize at least a double press
> for userspace).

Do you mean comment in the source code?

> 
> ------Please consider the environment before printing this e-mail.
Mark Brown April 22, 2015, 11:04 a.m. UTC | #5
On Tue, Apr 21, 2015 at 11:41:48AM +0000, Bard Liao wrote:

> > OK, you probaly want to move to separate default tables per device.
> > This is something that should have been called out in the commit log.

> Do you mean we need to write it down in the commit log and send
> another patch to use separate default tables for different device?

Yes, that's fine.

> Regarding the different default tables, do you mean something like:
> 	case RT5645_DEVICE_ID:
> 		rt5645->codec_type = CODEC_TYPE_RT5645;
> 		dev_info(&i2c->dev,	"Codec type is: RT5645\n");
> +		rt5645_regmap. reg_defaults = rt5645_reg;
> 		break;
> 	case RT5650_DEVICE_ID:
> 		rt5645->codec_type = CODEC_TYPE_RT5650;
> 		dev_info(&i2c->dev,	"Codec type is: RT5650\n");
> +		rt5645_regmap. reg_defaults = rt5650_reg;
> 		break;

It'd be better to have different regmap_config structures rather than
changing the register defaults in the one structure but basically yes.

> > OK, can we have a comment for that please?  We might want to extend
> > this in the future as the userspace ABI grows richer (and depending on
> > how things get reported we may need to synthesize at least a double press
> > for userspace).

> Do you mean comment in the source code?

Yes, please.
diff mbox

Patch

diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 69528ae..7c59f9c 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -198,7 +198,6 @@  static const struct reg_default rt5645_reg[] = {
 	{ 0xda, 0x0000 },
 	{ 0xdb, 0x0003 },
 	{ 0xdc, 0x0049 },
-	{ 0xdd, 0x001b },
 	{ 0xdf, 0x0008 },
 	{ 0xe0, 0x4000 },
 	{ 0xe6, 0x8000 },
@@ -2368,6 +2367,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 +2399,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 +2416,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 +2494,62 @@  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;
 }
 
 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 +2560,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 +2573,120 @@  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);
+			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_MICROPHONE);
+
+	return report;
+}
+
 static int rt5645_probe(struct snd_soc_codec *codec)
 {
 	struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
@@ -2784,8 +2973,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,
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h
index db78e94..4473636 100644
--- a/sound/soc/codecs/rt5645.h
+++ b/sound/soc/codecs/rt5645.h
@@ -2184,6 +2184,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 +2197,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__ */