void hi6402_plug_out_workfunc(struct work_struct *work)
{
	struct hi6402_mbhc_platform_data *pdata = container_of(work,
			struct hi6402_mbhc_platform_data,
			headset_plug_out_delay_work.work);

	pr_info("%s : hs pluged out\n", __FUNCTION__);

	BUG_ON(NULL == pdata);

	wake_lock(&pdata->wake_lock);
	mutex_lock(&pdata->plug_mutex);

	mask_irq(pdata->irq[HI6402_IRQ_BTNDOWN_COMP1], true);
	mask_irq(pdata->irq[HI6402_IRQ_BTNUP_COMP1], true);
	mask_irq(pdata->irq[HI6402_IRQ_BTNDOWN_ECO], true);
	/* todo */
	hi6402_reg_clr_bit(pdata->p_irq, HI6402_MICBIAS_ECO_REG, 0);
	hi6402_reg_set_bit(pdata->p_irq, HI6402_MBHC_VREF_REG, 7);

	mutex_lock(&pdata->status_mutex);
	pdata->hs_status = HISI_JACK_NONE;
	pdata->btn_report = 0;
	mutex_unlock(&pdata->status_mutex);

	hi6402_jack_report(pdata);

	mutex_unlock(&pdata->plug_mutex);
	wake_unlock(&pdata->wake_lock);

	/* unmask plugin interrupt */
	mask_irq(pdata->irq[HI6402_IRQ_PLUGIN], false);
}
void hi6402_plug_in_detect(struct hi6402_mbhc_platform_data *pdata)
{
	if (!check_headset_pluged_in(pdata))
		return;

	wake_lock(&pdata->wake_lock);
	mutex_lock(&pdata->plug_mutex);

	mutex_lock(&pdata->status_mutex);
	/* todo : btn_report 4-pole headset only now */
	pdata->hs_status = HISI_JACK_HEADSET;
	pdata->btn_report = SND_JACK_HEADSET;
	mutex_unlock(&pdata->status_mutex);

	hi6402_jack_report(pdata);

	/* todo */
	hi6402_reg_clr_bit(pdata->p_irq, HI6402_MBHC_VREF_REG, 7);
	hi6402_reg_set_bit(pdata->p_irq, HI6402_MICBIAS_ECO_REG, 0);

	/* unmask btn down irq */
	mask_irq(pdata->irq[HI6402_IRQ_BTNDOWN_COMP1], false);
	mask_irq(pdata->irq[HI6402_IRQ_BTNDOWN_ECO], false);

	mutex_unlock(&pdata->plug_mutex);
	wake_unlock(&pdata->wake_lock);
}
static irqreturn_t hi6402_plugout_handler(int irq, void *data)
{
	struct hi6402_mbhc_platform_data *pdata =
			(struct hi6402_mbhc_platform_data *)data;

	BUG_ON(NULL == pdata);

	if (check_headset_pluged_in(pdata)) {
		pr_info("%s : hs still plugin \n", __FUNCTION__);
		return IRQ_HANDLED;
	}

	mutex_lock(&pdata->plug_mutex);

	hi6402_irq_cancel_delay_work(pdata->p_irq);

	hi6402_irq_mask_btn_irqs(pdata->p_irq);
	//stop charge first
	anc_hs_stop_charge();

	/* eco off */
	hi6402_reg_clr_bit(pdata->p_irq, HI6402_MICBIAS_ECO_REG, HI6402_MICBIAS_ECO_ON_BIT);

	mutex_lock(&pdata->p_irq->hs_micbias_mutex);
	/* hs micbias off */
	pdata->p_irq->mbhc_micbias_work = false;
	pdata->p_irq->dapm_micbias_work = false;
	mutex_unlock(&pdata->p_irq->hs_micbias_mutex);
	hi6402_irq_hs_micbias_enable(pdata->p_irq, false);

	hi6402_irq_clr_btn_irqs(pdata->p_irq);

	hi6402_irq_mask_btn_irqs(pdata->p_irq);

	/* eco off */
	hi6402_reg_clr_bit(pdata->p_irq, HI6402_MICBIAS_ECO_REG, HI6402_MICBIAS_ECO_ON_BIT);
	pr_info("%s : eco disable \n", __FUNCTION__);
	/* vref off */
	hi6402_reg_set_bit(pdata->p_irq, HI6402_MBHC_VREF_REG, HI6402_MBHC_VREF_BIT);
	/* mbhc cmp off */
	hi6402_reg_set_bit(pdata->p_irq, HI6402_ANA_REG60, HI6402_MBHC_ON_BIT);

	mutex_lock(&pdata->status_mutex);
	pdata->hs_status = HISI_JACK_NONE;
	pdata->btn_report = 0;
	mutex_unlock(&pdata->status_mutex);

	hi6402_jack_report(pdata);

	hi6402_mbhc_enable_ldo8(pdata, false);

	mutex_unlock(&pdata->plug_mutex);

	return IRQ_HANDLED;
}
void hi6402_plug_in_detect(struct hi6402_mbhc_platform_data *pdata)
{
	int saradc_value = 0;
	int anc_type = ANC_HS_REVERT_4POLE;

	if (!check_headset_pluged_in(pdata))
		return;

	wake_lock(&pdata->wake_lock);
	mutex_lock(&pdata->plug_mutex);

	if(check_anc_hs_support()) {
		//mask btn irqs while control boost
		hi6402_irq_mask_btn_irqs(pdata->p_irq);
		anc_hs_start_charge();
	}

	/* micbias on */
	hi6402_irq_micbias_mbhc_enable(pdata->p_irq, true);

	/* mbhc on (normal not auto) */
	hi6402_mbhc_on(pdata);
	/* read hs value */
	saradc_value = hi6402_read_saradc_value_detect(pdata);

	mutex_lock(&pdata->status_mutex);

	if (pdata->hs_3_pole_max_voltage >= saradc_value) {
		/* 3-pole headphone */
		pr_info("%s : 3 pole is pluged in\n", __FUNCTION__);
		pdata->hs_status = HISI_JACK_HEADPHONE;
		anc_type = ANC_HS_3POLE;
	} else if (pdata->hs_4_pole_min_voltage <= saradc_value &&
			pdata->hs_4_pole_max_voltage >= saradc_value) {
		/* 4-pole headset */
		pr_info("%s : 4 pole is pluged in\n", __FUNCTION__);
		pdata->hs_status = HISI_JACK_HEADSET;
		anc_type = ANC_HS_4POLE;
	} else {
		/* invert 4-pole headset */
		pr_info("%s : need further detect, report as 3-pole headphone\n", __FUNCTION__);
		pdata->hs_status = HISI_JACK_INVERT;
		anc_type = ANC_HS_REVERT_4POLE;
	}

	mutex_unlock(&pdata->status_mutex);

	if(check_anc_hs_support()) {
		//mask btn irqs while control boost
		hi6402_irq_mask_btn_irqs(pdata->p_irq);
		anc_hs_charge_detect(saradc_value, anc_type);
	}

	hi6402_jack_report(pdata);

	hi6402_mbhc_enable_ldo8(pdata, true);

	/* micbias off */
	hi6402_irq_micbias_mbhc_enable(pdata->p_irq, false);

	mutex_unlock(&pdata->plug_mutex);
	wake_unlock(&pdata->wake_lock);
}