static void detect_gpio_work_func(struct work_struct *work)
{
	int insert = 0;
	int ret = 0;

	HS_DBG();
	if ((hi->pdata.eng_cfg == HS_EDE_U) || (hi->pdata.eng_cfg == HS_EDE_TD) || (hi->pdata.eng_cfg == HS_BLE))
	{
		aic3008_set_mic_bias(1);
	}
	if ((hi->pdata.eng_cfg == HS_QUO_F_U))
	{
		regulator = regulator_get(NULL, "v_aud_2v85");
		if (IS_ERR_OR_NULL(regulator)) {
			pr_err("htc_headset_gpio_probe:Couldn't get regulator v_aud_2v85\n");
			regulator = NULL;
			return;
		}
		regulator_enable(regulator);
	}

	insert = gpio_get_value(hi->pdata.hpin_gpio) ? 0 : 1;

	if (hi->headset_state == insert)
		return;

	hi->headset_state = insert;
	hs_notify_plug_event(insert);

	if (hi->pdata.key_gpio){
		if(!hi->key_irq){
			ret = gpio_to_irq(hi->pdata.key_gpio);
			if (ret < 0)
				HS_ERR("gpio_to_irq");
			hi->key_irq = (unsigned int) ret;

			ret = request_irq(hi->key_irq, button_irq_handler,
				hi->key_irq_type, "HS_GPIO_BUTTON", NULL);
			if (ret < 0)
				HS_ERR("request irq error;");
			disable_irq_nosync(hi->key_irq);
		}

		if (hi->key_irq){
			if (hi->headset_state == 1){
				ret = irq_set_irq_wake(hi->key_irq, 1);
				if (ret < 0)
					HS_ERR("set irq wake error");
				enable_irq(hi->key_irq);
			}else{
				ret = irq_set_irq_wake(hi->key_irq, 0);
				if (ret < 0)
					HS_ERR("set irq wake error");
				disable_irq_nosync(hi->key_irq);
			}
		}
	}
}
예제 #2
0
static void insert_detect_work_func(struct work_struct *work)
{
	int state;
	int mic = HEADSET_NO_MIC;

	wake_lock_timeout(&hi->hs_wake_lock, HS_WAKE_LOCK_TIMEOUT);

	HS_DBG();

	if (!hi->is_ext_insert) {
		HS_LOG("Headset has been removed");
		return;
	}

	hi->insert_jiffies = jiffies;
	set_35mm_hw_state(1);

	mutex_lock(&hi->mutex_lock);

	mic = get_mic_status();

	if(mic == HEADSET_UNPLUG){
		mdelay(1000);
		mic = get_mic_status();
	if(mic == HEADSET_UNPLUG){
		HS_LOG("Headset unplug.");
		hi->hs_35mm_type = mic;
		mutex_unlock(&hi->mutex_lock);
		if ((hi->pdata.eng_cfg == HS_EDE_U) || (hi->pdata.eng_cfg == HS_EDE_TD) || (hi->pdata.eng_cfg == HS_BLE)){
			aic3008_set_mic_bias(0);
		}
		if ((hi->pdata.eng_cfg == HS_QUO_F_U)){
			regulator = regulator_get(NULL, "v_aud_2v85");
			if (IS_ERR_OR_NULL(regulator)) {
				pr_err("htc_headset_gpio_probe:Couldn't get regulator v_aud_2v85\n");
				regulator = NULL;
				return;
			}
			regulator_disable(regulator);
		}
		return;
	}
	}

	if (mic == HEADSET_NO_MIC)
		mic = tv_out_detect();

	if (mic == HEADSET_TV_OUT && hi->pdata.hptv_sel_gpio)
		gpio_set_value(hi->pdata.hptv_sel_gpio, 1);

	if (mic == HEADSET_METRICO && !hi->metrico_status)
		enable_metrico_headset(1);

	state = switch_get_state(&hi->sdev);
	state &= ~MASK_35MM_HEADSET;
	state |= BIT_35MM_HEADSET;

/*run one-wire detect work function if one-wire detection is enable*/
	if (hi->pdata.enable_1wire)
		{
		int wire = 0;
		wire = insert_1wire_work_func();
		if (wire > 0)
			{
			HS_LOG("Enable one-wire detection");
			mic = wire;
			}
		}

	switch (mic) {
	case HEADSET_NO_MIC:
		state |= BIT_HEADSET_NO_MIC;
		HS_LOG_TIME("HEADSET_NO_MIC");
		break;
	case HEADSET_MIC:
		state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_MIC");
		break;
	case HEADSET_METRICO:
		mic = HEADSET_UNSTABLE;
		state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_METRICO (UNSTABLE)");
		break;
	case HEADSET_UNKNOWN_MIC:
		state |= BIT_HEADSET_NO_MIC;
		HS_LOG_TIME("HEADSET_UNKNOWN_MIC");
		break;
	case HEADSET_TV_OUT:
		state |= BIT_TV_OUT;
		HS_LOG_TIME("HEADSET_TV_OUT");
#if defined(CONFIG_FB_MSM_TVOUT) && defined(CONFIG_ARCH_MSM8X60)
		tvout_enable_detection(1);
#endif
		break;
	case HEADSET_BEATS:
//		mic = HEADSET_UNSTABLE;
		state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_BEATS (UNSTABLE)");
		break;
	case HEADSET_BEATS_SOLO:
//		mic = HEADSET_UNSTABLE;
		state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_BEATS_SOLO (UNSTABLE)");
		break;
	case HEADSET_INDICATOR:
		HS_LOG_TIME("HEADSET_INDICATOR");
		break;
	}

	hi->hs_35mm_type = mic;
	switch_set_state(&hi->sdev, state);
	hpin_report++;

	mutex_unlock(&hi->mutex_lock);

	/* FIXME */
/*	if (gpio_event_get_quickboot_status())
		HS_LOG("quick_boot_status = 1"); */

	if (mic == HEADSET_UNKNOWN_MIC)
		update_mic_status(HS_DEF_MIC_DETECT_COUNT);
	else if (mic == HEADSET_UNSTABLE)
		update_mic_status(0);
	else if (mic == HEADSET_INDICATOR) {
		if (headset_get_type_sync(3, HS_DELAY_SEC) == HEADSET_INDICATOR)
			HS_LOG("Delay check: HEADSET_INDICATOR");
		else
			HS_LOG("Delay check: HEADSET_UNKNOWN_MIC");
	}
}
예제 #3
0
static void remove_detect_work_func(struct work_struct *work)
{
	int state;

	wake_lock_timeout(&hi->hs_wake_lock, HS_WAKE_LOCK_TIMEOUT);

	HS_DBG();

/*remove one-wire detection setting if the project support one-wire detection*/
	if(hi->detect_type == HEADSET_1WIRE && hi->pdata.enable_1wire){
		HS_LOG("Disable one-wire detection.");
		closeFile(fp);
		disable_1wire();
		hi->detect_type = HEADSET_ADC;
	}

	if (time_before_eq(jiffies, hi->insert_jiffies + HZ)) {
		HS_LOG("Waiting for HPIN stable");
		msleep(HS_DELAY_SEC - HS_DELAY_REMOVE);
	}

	if (hi->is_ext_insert) {
		HS_LOG("Headset has been inserted");
		return;
	}

	if (hi->hs_35mm_type == HEADSET_INDICATOR &&
	    hs_mgr_notifier.indicator_enable)
		hs_mgr_notifier.indicator_enable(0);

	set_35mm_hw_state(0);
#if defined(CONFIG_FB_MSM_TVOUT) && defined(CONFIG_ARCH_MSM8X60)
	if (hi->hs_35mm_type == HEADSET_TV_OUT && hi->pdata.hptv_sel_gpio) {
		HS_LOG_TIME("Remove 3.5mm TVOUT cable");
		tvout_enable_detection(0);
		gpio_set_value(hi->pdata.hptv_sel_gpio, 0);
	}
#endif
	if (hi->metrico_status)
		enable_metrico_headset(0);

	if (atomic_read(&hi->btn_state))
		button_released(atomic_read(&hi->btn_state));

	mutex_lock(&hi->mutex_lock);

	state = switch_get_state(&hi->sdev);
	if (!(state & MASK_35MM_HEADSET)||hi->hs_35mm_type == HEADSET_UNPLUG) {
		HS_LOG("Headset has been removed");
		mutex_unlock(&hi->mutex_lock);
		return;
	}
	hi->hs_35mm_type = HEADSET_UNPLUG;

#if 0
	if (hi->cable_in1 && !gpio_get_value(hi->cable_in1)) {
		state &= ~BIT_35MM_HEADSET;
		switch_set_state(&hi->sdev, state);
		queue_delayed_work(detect_wq, &detect_h2w_work,
				   HS_DELAY_ZERO_JIFFIES);
	} else {
		state &= ~(MASK_35MM_HEADSET | MASK_FM_ATTRIBUTE);
		switch_set_state(&hi->sdev, state);
	}
#else
	state &= ~(MASK_35MM_HEADSET | MASK_FM_ATTRIBUTE);
	switch_set_state(&hi->sdev, state);
#endif
	hpin_report++;
	HS_LOG_TIME("Remove 3.5mm accessory");

	mutex_unlock(&hi->mutex_lock);
	if ((hi->pdata.eng_cfg == HS_EDE_U) || (hi->pdata.eng_cfg == HS_EDE_TD) || (hi->pdata.eng_cfg == HS_BLE))
	{
		aic3008_set_mic_bias(0);
	}

	if ((hi->pdata.eng_cfg == HS_QUO_F_U))
	{
		regulator = regulator_get(NULL, "v_aud_2v85");
		if (IS_ERR_OR_NULL(regulator)) {
			pr_err("htc_headset_gpio_probe:Couldn't get regulator v_aud_2v85\n");
			regulator = NULL;
			return;
		}
		regulator_disable(regulator);
	}

	/* FIXME */
/*	if (gpio_event_get_quickboot_status())
		HS_LOG("quick_boot_status = 1"); */
}