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();

	if (time_before_eq(jiffies, hi->insert_jiffies + HZ)) {
		HS_LOG("Waiting for HPIN stable");
		if (hi->pdata.driver_flag & DRIVER_HS_MGR_OLD_AJ)
			msleep(HS_DELAY_SEC - HS_DELAY_REMOVE_LONG);
		else
			msleep(HS_DELAY_SEC - HS_DELAY_REMOVE_SHORT);
	}

	if (hi->is_ext_insert) {
		HS_LOG("Headset has been reinserted during debounce time");
		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));
	hi->hs_35mm_type = HEADSET_UNPLUG;

	mutex_lock(&hi->mutex_lock);

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

#if 0
	if (hi->cable_in1 && !gpio_get_value(hi->cable_in1)) {
		state &= ~BIT_35MM_HEADSET;
		switch_set_state(&hi->sdev_h2w, 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_h2w, state);
	}
#else
	state &= ~(MASK_35MM_HEADSET | MASK_FM_ATTRIBUTE);
	switch_set_state(&hi->sdev_h2w, state);
#endif

	HS_LOG_TIME("Remove 3.5mm accessory");

	mutex_unlock(&hi->mutex_lock);

#ifdef HTC_HEADSET_CONFIG_QUICK_BOOT
	if (gpio_event_get_quickboot_status())
		HS_LOG("quick_boot_status = 1");
#endif
}
static void insert_detect_work_func(struct work_struct *work)
{
	int state,old_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 (hi->pdata.driver_flag & DRIVER_HS_MGR_FLOAT_DET) {
		HS_LOG("Headset float detect enable");
		if (mic == HEADSET_UNPLUG) {
			mutex_unlock(&hi->mutex_lock);
			update_mic_status(HS_DEF_MIC_DETECT_COUNT);
			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_h2w);
	old_state = state;
	state &= ~MASK_35MM_HEADSET;
	state |= BIT_35MM_HEADSET;

	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;
		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:
		state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_BEATS (UNSTABLE)");
		break;
	case HEADSET_BEATS_SOLO:
		state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_BEATS_SOLO (UNSTABLE)");
		break;
	case HEADSET_INDICATOR:
		HS_LOG_TIME("HEADSET_INDICATOR");
		break;
	}

	if (old_state != state) {
		if (old_state & state & MASK_35MM_HEADSET) {
			if (hi->pdata.driver_flag & DRIVER_HS_MGR_OLD_AJ) {
				state |= old_state;
				HS_LOG("Old audio jack found, use workaround");
			} else {
				switch_set_state(&hi->sdev_h2w, old_state & ~MASK_35MM_HEADSET);
				HS_LOG("Report fake remove event");
			}
		}
		hi->hs_35mm_type = mic;
		HS_LOG_TIME("Send uevent for state change, %d => %d", old_state, state);
		switch_set_state(&hi->sdev_h2w, state);
	} else
		HS_LOG("No state change");

	mutex_unlock(&hi->mutex_lock);

#ifdef HTC_HEADSET_CONFIG_QUICK_BOOT
	if (gpio_event_get_quickboot_status())
		HS_LOG("quick_boot_status = 1");
#endif

	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");
	}
}
static ssize_t headset_simulate_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	unsigned long state = 0;

	HS_DBG();

	state = MASK_35MM_HEADSET | MASK_USB_HEADSET;
	switch_send_event(state, 0);

	if (strncmp(buf, "headset_unplug", count - 1) == 0) {
		HS_LOG("Headset simulation: headset_unplug");
		set_35mm_hw_state(0);
		hi->hs_35mm_type = HEADSET_UNPLUG;
		return count;
	}

	set_35mm_hw_state(1);
	state = BIT_35MM_HEADSET;

	if (strncmp(buf, "headset_no_mic", count - 1) == 0) {
		HS_LOG("Headset simulation: headset_no_mic");
		hi->hs_35mm_type = HEADSET_NO_MIC;
		state |= BIT_HEADSET_NO_MIC;
	} else if (strncmp(buf, "headset_mic", count - 1) == 0) {
		HS_LOG("Headset simulation: headset_mic");
		hi->hs_35mm_type = HEADSET_MIC;
		state |= BIT_HEADSET;
	} else if (strncmp(buf, "headset_metrico", count - 1) == 0) {
		HS_LOG("Headset simulation: headset_metrico");
		hi->hs_35mm_type = HEADSET_METRICO;
		state |= BIT_HEADSET;
	} else if (strncmp(buf, "headset_unknown_mic", count - 1) == 0) {
		HS_LOG("Headset simulation: headset_unknown_mic");
		hi->hs_35mm_type = HEADSET_UNKNOWN_MIC;
		state |= BIT_HEADSET_NO_MIC;
	} else if (strncmp(buf, "headset_tv_out", count - 1) == 0) {
		HS_LOG("Headset simulation: headset_tv_out");
		hi->hs_35mm_type = HEADSET_TV_OUT;
		state |= BIT_TV_OUT;
#if defined(CONFIG_FB_MSM_TVOUT) && defined(CONFIG_ARCH_MSM8X60)
		tvout_enable_detection(1);
#endif
	} else if (strncmp(buf, "headset_indicator", count - 1) == 0) {
		HS_LOG("Headset simulation: headset_indicator");
		hi->hs_35mm_type = HEADSET_INDICATOR;
	} else if (strncmp(buf, "headset_beats", count - 1) == 0) {
		HS_LOG("Headset simulation: headset_beats");
		hi->hs_35mm_type = HEADSET_BEATS;
		state |= BIT_HEADSET;
	} else if (strncmp(buf, "headset_beats_solo", count - 1) == 0) {
		HS_LOG("Headset simulation: headset_beats_solo");
		hi->hs_35mm_type = HEADSET_BEATS_SOLO;
		state |= BIT_HEADSET;
	} else {
		HS_LOG("Invalid parameter");
		return count;
	}

	switch_send_event(state, 1);

	return count;
}
static void mic_detect_work_func(struct work_struct *work)
{
	int mic = HEADSET_NO_MIC;
	int old_state, new_state;

	wake_lock_timeout(&hi->hs_wake_lock, HS_MIC_DETECT_TIMEOUT);

	HS_DBG();

	if (!hi->pdata.headset_config_num && !hs_mgr_notifier.mic_status) {
		HS_LOG("Failed to get MIC status");
		return;
	}

	mutex_lock(&hi->mutex_lock);

	mic = get_mic_status();

	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);

	if (mic == HEADSET_UNKNOWN_MIC || mic == HEADSET_UNPLUG) {
		mutex_unlock(&hi->mutex_lock);
		if (hi->mic_detect_counter--)
			queue_delayed_work(detect_wq, &mic_detect_work,
					   HS_JIFFIES_MIC_DETECT);
		else
			HS_LOG("MIC polling timeout (UNKNOWN/Floating MIC status)");
		return;
	}

	if (hi->hs_35mm_type == HEADSET_UNSTABLE && hi->mic_detect_counter--) {
		mutex_unlock(&hi->mutex_lock);
		queue_delayed_work(detect_wq, &mic_detect_work,
				   HS_JIFFIES_MIC_DETECT);
		return;
	}

	old_state = switch_get_state(&hi->sdev_h2w);
	if (!(old_state & MASK_35MM_HEADSET) && !(hi->is_ext_insert)) {
		HS_LOG("Headset has been removed");
		mutex_unlock(&hi->mutex_lock);
		return;
	}

	new_state = old_state & ~MASK_35MM_HEADSET;
	new_state |= BIT_35MM_HEADSET;

	switch (mic) {
	case HEADSET_UNPLUG:
		new_state &= ~MASK_35MM_HEADSET;
		HS_LOG("HEADSET_UNPLUG (FLOAT)");
		break;
	case HEADSET_NO_MIC:
		new_state |= BIT_HEADSET_NO_MIC;
		HS_LOG("HEADSET_NO_MIC");
		break;
	case HEADSET_MIC:
		new_state |= BIT_HEADSET;
		HS_LOG("HEADSET_MIC");
		break;
	case HEADSET_METRICO:
		new_state |= BIT_HEADSET;
		HS_LOG("HEADSET_METRICO");
		break;
	case HEADSET_TV_OUT:
		new_state |= BIT_TV_OUT;
		HS_LOG("HEADSET_TV_OUT");
#if defined(CONFIG_FB_MSM_TVOUT) && defined(CONFIG_ARCH_MSM8X60)
		tvout_enable_detection(1);
#endif
		break;
	case HEADSET_BEATS:
		new_state |= BIT_HEADSET;
		HS_LOG("HEADSET_BEATS");
		break;
	case HEADSET_BEATS_SOLO:
		new_state |= BIT_HEADSET;
		HS_LOG("HEADSET_BEATS_SOLO");
		break;
	case HEADSET_INDICATOR:
		HS_LOG("HEADSET_INDICATOR");
		break;
	}

	if (old_state != new_state) {
		if (old_state & new_state & MASK_35MM_HEADSET) {
			if (hi->pdata.driver_flag & DRIVER_HS_MGR_OLD_AJ) {
				new_state |= old_state;
				HS_LOG("Old audio jack found, use workaround");
			} else {
				switch_set_state(&hi->sdev_h2w, old_state & ~MASK_35MM_HEADSET);
				HS_LOG("Report fake remove event");
			}
		}
		hi->hs_35mm_type = mic;
		HS_LOG_TIME("Send uevent for state change, %d => %d", old_state, new_state);
		switch_set_state(&hi->sdev_h2w, new_state);
	} else
		HS_LOG("No state change");

	mutex_unlock(&hi->mutex_lock);
}
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();

	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;
	}

	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));
	hi->hs_35mm_type = HEADSET_UNPLUG;

	mutex_lock(&hi->mutex_lock);

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

#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

	HS_LOG_TIME("Remove 3.5mm accessory");

	mutex_unlock(&hi->mutex_lock);
}
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_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;

	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:
		state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_METRICO");
		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:
		state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_BEATS");
		break;
	case HEADSET_INDICATOR:
		HS_LOG_TIME("HEADSET_INDICATOR");
		break;
	}

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

	mutex_unlock(&hi->mutex_lock);

	if (mic == HEADSET_UNKNOWN_MIC)
		update_mic_status(HS_DEF_MIC_DETECT_COUNT);
	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");
	}
}
static void mic_detect_work_func(struct work_struct *work)
{
	int mic = HEADSET_NO_MIC;
	int old_state, new_state;

	wake_lock_timeout(&hi->hs_wake_lock, HS_MIC_DETECT_TIMEOUT);

	HS_DBG();

	if (!hi->pdata.headset_config_num && !hs_mgr_notifier.mic_status) {
		HS_LOG("Failed to get MIC status");
		return;
	}

	mutex_lock(&hi->mutex_lock);

	mic = get_mic_status();

	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);

	if (mic == HEADSET_UNKNOWN_MIC) {
		mutex_unlock(&hi->mutex_lock);
		if (hi->mic_detect_counter--)
			queue_delayed_work(detect_wq, &mic_detect_work,
					   HS_JIFFIES_MIC_DETECT);
		else
			HS_LOG("MIC polling timeout (UNKNOWN MIC status)");
		return;
	}

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

	new_state = old_state & ~MASK_35MM_HEADSET;
	new_state |= BIT_35MM_HEADSET;

	switch (mic) {
	case HEADSET_NO_MIC:
		new_state |= BIT_HEADSET_NO_MIC;
		HS_LOG_TIME("HEADSET_NO_MIC");
		break;
	case HEADSET_MIC:
		new_state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_MIC");
		break;
	case HEADSET_METRICO:
		new_state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_METRICO");
		break;
	case HEADSET_TV_OUT:
		new_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:
		new_state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_BEATS");
		break;
	case HEADSET_INDICATOR:
		HS_LOG_TIME("HEADSET_INDICATOR");
		break;
	}

	if (new_state != old_state) {
		hi->hs_35mm_type = mic;
		switch_set_state(&hi->sdev, new_state);
	} else
		HS_LOG("MIC status has not changed");

	mutex_unlock(&hi->mutex_lock);
}
Esempio n. 8
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");
	}
}
Esempio n. 9
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"); */
}
Esempio n. 10
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);

	if (hs_mgr_notifier.mic_status)
		mic = hs_mgr_notifier.mic_status();

	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;

	switch (mic) {
	case HEADSET_TV_OUT:
		state |= BIT_TV_OUT;
		break;
	case HEADSET_METRICO:
	case HEADSET_MIC:
		state |= BIT_HEADSET;
		break;
	default:
		state |= BIT_HEADSET_NO_MIC;
	}

	if (mic == HEADSET_UNKNOWN_MIC) {
		hi->ext_35mm_status = HTC_35MM_UNKNOWN_MIC;
		HS_LOG_TIME("Insert 3.5mm headset with UNKNOWN MIC");
#if defined(CONFIG_FB_MSM_TVOUT) && defined(CONFIG_ARCH_MSM8X60)
	} else if (mic == HEADSET_TV_OUT) {
		hi->ext_35mm_status = HTC_35MM_TV_OUT;
		HS_LOG_TIME("Insert 3.5mm TV OUT cable");
		tvout_enable_detection(1);
#endif
	} else if (state & BIT_HEADSET) {
		hi->ext_35mm_status = HTC_35MM_MIC;
		HS_LOG_TIME("Insert 3.5mm headset with MIC");
	} else {
		hi->ext_35mm_status = HTC_35MM_NO_MIC;
		HS_LOG_TIME("Insert 3.5mm headset without MIC");
	}
	switch_set_state(&hi->sdev, state);

	mutex_unlock(&hi->mutex_lock);

	if (mic == HEADSET_UNKNOWN_MIC) {
		HS_LOG("Start MIC status polling");
		cancel_delayed_work_sync(&mic_detect_work);
		hi->mic_detect_counter = HS_DEF_MIC_DETECT_COUNT;
		queue_delayed_work(detect_wq, &mic_detect_work,
				   HS_JIFFIES_MIC_DETECT);
	}
}
Esempio n. 11
0
static void insert_detect_work_func(struct work_struct *work)
{
	int state,old_state;
	int mic = HEADSET_NO_MIC;
	int adc = 0;

	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;
	}

	HS_LOG("Start 1-wire detecting sequence");
	if (hi->pdata.uart_tx_gpo)
		hi->pdata.uart_tx_gpo(0);
	if (hi->pdata.uart_lv_shift_en)
		hi->pdata.uart_lv_shift_en(0);
	msleep(20);
	if (hi->pdata.uart_lv_shift_en)
		hi->pdata.uart_lv_shift_en(1);
	if (hi->pdata.uart_tx_gpo)
		hi->pdata.uart_tx_gpo(2);

	hi->insert_jiffies = jiffies;
	set_35mm_hw_state(1);
	msleep(150);
	if (hs_mgr_notifier.remote_adc)
		hs_mgr_notifier.remote_adc(&adc);

	mutex_lock(&hi->mutex_lock);

	hi->one_wire_mode = 0;
/*Check one wire accessory for every plug event*/
	if (hi->driver_one_wire_exist && adc > 915) {
		HS_LOG("[HS_1wire]1wire driver exists, starting init");
		if (hs_mgr_notifier.key_int_enable)
			hs_mgr_notifier.key_int_enable(0);
		if (hs_mgr_notifier.hs_1wire_init() == 0) {
			hi->one_wire_mode = 1;
		/*Report as normal headset with MIC*/
			state = switch_get_state(&hi->sdev_h2w);
			state |= BIT_HEADSET;
			switch_set_state(&hi->sdev_h2w, state);
			hi->hs_35mm_type = HEADSET_BEATS;
			mutex_unlock(&hi->mutex_lock);
		if (hs_mgr_notifier.key_int_enable)
			hs_mgr_notifier.key_int_enable(1);
			return;
		}
		else {
			hi->one_wire_mode = 0;
			HS_LOG("Lagacy mode");
			if (hi->pdata.uart_tx_gpo)
				hi->pdata.uart_tx_gpo(2);
			if (hs_mgr_notifier.key_int_enable)
				hs_mgr_notifier.key_int_enable(1);
		}
	}

	mic = get_mic_status();
	if (hi->pdata.driver_flag & DRIVER_HS_MGR_FLOAT_DET) {
		HS_LOG("Headset float detect enable");
		if (mic == HEADSET_UNPLUG) {
			mutex_unlock(&hi->mutex_lock);
			update_mic_status(HS_DEF_MIC_DETECT_COUNT);
			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_h2w);
	old_state = state;
	state &= ~MASK_35MM_HEADSET;
	state |= BIT_35MM_HEADSET;

	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;
		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:
		state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_BEATS (UNSTABLE)");
		break;
	case HEADSET_BEATS_SOLO:
		state |= BIT_HEADSET;
		HS_LOG_TIME("HEADSET_BEATS_SOLO (UNSTABLE)");
		break;
	case HEADSET_INDICATOR:
		HS_LOG_TIME("HEADSET_INDICATOR");
		break;
	}

	if (old_state != state) {
		if (old_state & state & MASK_35MM_HEADSET) {
			if (hi->pdata.driver_flag & DRIVER_HS_MGR_OLD_AJ) {
				state |= old_state;
				HS_LOG("Old audio jack found, use workaround");
			} else {
				switch_set_state(&hi->sdev_h2w, old_state & ~MASK_35MM_HEADSET);
				HS_LOG("Report fake remove event");
			}
		}
		hi->hs_35mm_type = mic;
		HS_LOG_TIME("Send uevent for state change, %d => %d", old_state, state);
		switch_set_state(&hi->sdev_h2w, state);
		hpin_report++;
	} else
		HS_LOG("No state change");

	mutex_unlock(&hi->mutex_lock);

#ifdef HTC_HEADSET_CONFIG_QUICK_BOOT
	if (gpio_event_get_quickboot_status())
		HS_LOG("quick_boot_status = 1");
#endif

	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");
	}
}