static irqreturn_t detect_irq_handler(int irq, void *dev_id)
{
	int value1, value2;
	int retry_limit = 10;
	int state = BIT_HEADSET | BIT_HEADSET_NO_MIC;
	H2W_DBG("");
	set_irq_type(hi->irq_btn, IRQF_TRIGGER_LOW);
	do {
		value1 = gpio_get_value(hi->cable_in1);
		set_irq_type(hi->irq, value1 ?
				IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
		value2 = gpio_get_value(hi->cable_in1);
	} while (value1 != value2 && retry_limit-- > 0);

	H2WI("value2 = %d (%d retries), device=%d", value2,
		(10-retry_limit), switch_get_state(&hi->sdev));

	if ((hi->h2w_dev_type == 0) ^ value2) {
		if ((switch_get_state(&hi->sdev) & state) &&
		    !hi->is_ext_insert)
			hi->ignore_btn = 1;
		if (hi->is_wake_lock_ready)
			wake_lock_timeout(&hi->headset_wake_lock, 2.5*HZ);
		queue_delayed_work(detect_wq,
			&detect_h2w_work, H2W_DETECT_DELAY);
	}
	return IRQ_HANDLED;
}
Ejemplo n.º 2
0
static void remove_35mm_do_work(struct work_struct *work)
{
	wake_lock_timeout(&hi->headset_wake_lock, 2.5*HZ);

	H2W_DBG("");
	/*To solve the insert, remove, insert headset problem*/
	if (time_before_eq(jiffies, hi->insert_jiffies))
		msleep(800);

	if (hi->is_ext_insert) {
		H2WI("Skip 3.5mm headset plug out!!!");
		if (hi->is_hpin_stable)
			*(hi->is_hpin_stable) = 1;
		return;
	}

	pr_info("3.5mm_headset plug out\n");

	if (pd->key_event_disable != NULL)
		pd->key_event_disable();

	if (hi->mic_bias_state) {
		turn_mic_bias_on(0);
		hi->mic_bias_state = 0;
	}
	hi->ext_35mm_status = 0;
	if (hi->is_hpin_stable)
		*(hi->is_hpin_stable) = 0;

	/* Notify framework via switch class */
	mutex_lock(&hi->mutex_lock);
	switch_set_state(&hi->hs_change, hi->ext_35mm_status);
	mutex_unlock(&hi->mutex_lock);
}
static void remove_35mm_do_work(struct work_struct *work)
{
	int state;

	if (hi->is_wake_lock_ready)
		wake_lock_timeout(&hi->headset_wake_lock, 2.5*HZ);

	H2W_DBG("");
	/*To solve the insert, remove, insert headset problem*/
	if (time_before_eq(jiffies, hi->insert_jiffies))
		msleep(800);
	if (hi->is_ext_insert) {
		H2WI("Skip 3.5mm headset plug out!!!");
		return;
	}

	printk(KERN_INFO "3.5mm_headset plug out\n");
	mutex_lock(&hi->mutex_lock);
	state = switch_get_state(&hi->sdev);

	if (hi->mic_bias_state) {
		turn_mic_bias_on(0);
		hi->mic_bias_state = 0;
	}

	/* For HW Metrico lab test */
	if (hi->metrico_status)
		enable_metrico_headset(0);

	microp_notify_unplug_mic();

	if (atomic_read(&hi->btn_state))
		button_released(atomic_read(&hi->btn_state));
	hi->ext_35mm_status = HTC_35MM_UNPLUG;

	if (hi->key_int_shutdown_gpio)
		gpio_set_value(hi->key_int_shutdown_gpio, 0);

	if (hi->ext_mic_sel)
		gpio_direction_output(hi->ext_mic_sel, 0);

	if (hi->h2w_dev_type == H2W_TVOUT) {
		state &= ~(BIT_HEADSET | BIT_35MM_HEADSET);
		state |= BIT_HEADSET_NO_MIC;
		switch_set_state(&hi->sdev, state);
	} else 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, H2W_NO_DELAY);
	} else {
		state &= ~(BIT_HEADSET | BIT_HEADSET_NO_MIC |
			BIT_35MM_HEADSET);
		switch_set_state(&hi->sdev, state);
	}

	mutex_unlock(&hi->mutex_lock);
}
Ejemplo n.º 4
0
static void button_35mm_do_work(struct work_struct *work)
{
	int key = 0;
	int pressed = 0;

	if (!hi->is_ext_insert) {
		/* no headset ignor key event */
		H2WI("3.5mm headset is plugged out, skip report key event");
		return;
	}

	switch (hi->key_code) {
	case 0x1: /* Play/Pause */
		H2WI("3.5mm RC: Play Pressed");
		key = KEY_MEDIA;
		pressed = 1;
		break;
	case 0x2:
		H2WI("3.5mm RC: BACKWARD Pressed");
		key = KEY_PREVIOUSSONG;
		pressed = 1;
		break;
	case 0x3:
		H2WI("3.5mm RC: FORWARD Pressed");
		key = KEY_NEXTSONG;
		pressed = 1;
		break;
	case 0x81: /* Play/Pause */
		H2WI("3.5mm RC: Play Released");
		key = KEY_MEDIA;
		pressed = 0;
		break;
	case 0x82:
		H2WI("3.5mm RC: BACKWARD Released");
		key = KEY_PREVIOUSSONG;
		pressed = 0;
		break;
	case 0x83:
		H2WI("3.5mm RC: FORWARD Released");
		key = KEY_NEXTSONG;
		pressed = 0;
		break;
	default:
		H2WI("3.5mm RC: Unknown Button (0x%x) Pressed", hi->key_code);
		return;
	}
	input_report_key(hi->input, key, pressed);
	input_sync(hi->input);

	wake_lock_timeout(&hi->headset_wake_lock, 1.5*HZ);
}
int htc_35mm_remote_notify_insert_ext_headset(int insert)
{
	if (hi) {
		mutex_lock(&hi->mutex_lock);
		hi->is_ext_insert = insert;
		mutex_unlock(&hi->mutex_lock);

		H2WI(" %d", hi->is_ext_insert);
		if (!hi->is_ext_insert)
			queue_work(detect_wq, &remove_35mm_work);
		else
			queue_work(detect_wq, &insert_35mm_work);
	}
	return 1;
}
Ejemplo n.º 6
0
int htc_35mm_jack_plug_event(int insert, int *hpin_stable)
{
	if (!hi) {
		pr_err("Plug event before driver init\n");
		return -1;
	}

	mutex_lock(&hi->mutex_lock);
	hi->is_ext_insert = insert;
	hi->is_hpin_stable = hpin_stable;
	mutex_unlock(&hi->mutex_lock);

	H2WI(" %d", hi->is_ext_insert);
	if (!hi->is_ext_insert)
		queue_work(detect_wq, &remove_35mm_work);
	else
		queue_work(detect_wq, &insert_35mm_work);
	return 1;
}
static void button_35mm_do_work(struct work_struct *w)
{
	int key;

	if (!hi->is_ext_insert && !hi->h2w_35mm_status) {
		H2WI("3.5mm headset is plugged out, skip report key event");
		return;
	}

	if (hi->key_level_flag) {
		switch (hi->key_level_flag) {
		case 1:
			H2WI("3.5mm RC: Play Pressed");
			key = KEY_MEDIA;
			break;
		case 2:
			H2WI("3.5mm RC: BACKWARD Pressed");
			key = KEY_PREVIOUSSONG;
			break;
		case 3:
			H2WI("3.5mm RC: FORWARD Pressed");
			key = KEY_NEXTSONG;
			break;
		default:
			H2WI("3.5mm RC: WRONG Button Pressed");
			return;
		}
		headset_button_event(1, key);
	} else { /* key release */
		if (atomic_read(&hi->btn_state))
			headset_button_event(0, atomic_read(&hi->btn_state));
		else
			H2WI("3.5mm RC: WRONG Button Release");
	}

	if (hi->is_wake_lock_ready)
		wake_lock_timeout(&hi->headset_wake_lock, 1.5*HZ);
}