Пример #1
0
/*
 * For the NC type headset, a single interrupt is triggered
 * for all the events (insert, remove, press, release).
 * A external GPIO is used to distinguish between diff. states.
 * The GPIO is pulled low when the headset is inserted. Using
 * the current state of the switch, headset and the gpio value we
 * determine which event has occured.
 */
static void othc_process_nc(struct pm8058_othc *dd)
{
	if (!gpio_get_value(dd->othc_nc_gpio)) {
		/* headset plugged in and/or button press/release */
		if (dd->othc_ir_state == false) {
			/* disable irq, this gets enabled in the workqueue */
			disable_irq_nosync(dd->othc_irq_ir);
			/* headset plugged in */
			dd->othc_ir_state = true;
			pm8058_headset_switch(dd->othc_ipd,
					SW_HEADPHONE_INSERT, 1);
		} else if (dd->othc_sw_state == false) {
			/*  Switch has been pressed */
			dd->othc_sw_state = true;
			input_report_key(dd->othc_ipd, KEY_MEDIA, 1);
		} else {
			/* Switch has been released */
			dd->othc_sw_state = false;
			input_report_key(dd->othc_ipd, KEY_MEDIA, 0);
		}
	} else {
		/* disable irq, this gets enabled in the workqueue */
		disable_irq_nosync(dd->othc_irq_ir);
		/* headset has been plugged out */
		dd->othc_ir_state = false;
		pm8058_headset_switch(dd->othc_ipd,
				SW_HEADPHONE_INSERT, 0);
	}
}
Пример #2
0
/*
 * The pm8058_nc_ir detects insert / remove of the headset (for NO and NC),
 * as well as button press / release (for NC type).
 * The current state of the headset is maintained in othc_ir_state variable.
 */
static irqreturn_t pm8058_nc_ir(int irq, void *dev_id)
{
	struct pm8058_othc *dd = dev_id;
	struct othc_hsed_config *hsed_config = dd->othc_pdata->hsed_config;

	if (hsed_config->othc_headset == OTHC_HEADSET_NC)
		othc_process_nc(dd);
	else {
		/* disable irq, this gets enabled in the workqueue */
		disable_irq_nosync(dd->othc_irq_ir);
		/* Processing for NO type headset */
		if (dd->othc_ir_state == false) {
			/*  headset jack inserted */
			dd->othc_ir_state = true;
			pm8058_headset_switch(dd->othc_ipd,
					SW_HEADPHONE_INSERT, 1);
		} else {
			/* headset jack removed */
			dd->othc_ir_state = false;
			pm8058_headset_switch(dd->othc_ipd,
					SW_HEADPHONE_INSERT, 0);
		}
	}
	input_sync(dd->othc_ipd);

	return IRQ_HANDLED;
}
Пример #3
0
/*
 * The pm8058_nc_ir detects insert / remove of the headset (for NO and NC),
 * as well as button press / release (for NC type).
 * The current state of the headset is maintained in othc_ir_state variable.
 * Due to a hardware bug, false switch interrupts are seen during headset
 * insert. This is handled in the software by rejecting the switch interrupts
 * for a small period of time after the headset has been inserted.
 */
static irqreturn_t pm8058_nc_ir(int irq, void *dev_id)
{
	unsigned long flags;
	struct pm8058_othc *dd = dev_id;
	struct othc_hsed_config *hsed_config = dd->othc_pdata->hsed_config;

	spin_lock_irqsave(&dd->lock, flags);
	/* Enable the switch reject flag */
	dd->switch_reject = true;
	spin_unlock_irqrestore(&dd->lock, flags);

	/* Start the HR timer if one is not active */
	if (hrtimer_active(&dd->timer))
		hrtimer_cancel(&dd->timer);

	hrtimer_start(&dd->timer,
		ktime_set((dd->switch_debounce_ms / 1000),
		(dd->switch_debounce_ms % 1000) * 1000000), HRTIMER_MODE_REL);

	if (hsed_config->othc_headset == OTHC_HEADSET_NC)
		othc_process_nc(dd);
	else {
		/* disable irq, this gets enabled in the workqueue */
		disable_irq_nosync(dd->othc_irq_ir);
		/* Processing for NO type headset */
		if (dd->othc_ir_state == false) {
			/*  headset jack inserted */
			dd->othc_ir_state = true;
			pm8058_headset_switch(dd->othc_ipd,
					SW_HEADPHONE_INSERT, 1);
		} else {
			/* headset jack removed */
			dd->othc_ir_state = false;
			pm8058_headset_switch(dd->othc_ipd,
					SW_HEADPHONE_INSERT, 0);
		}
	}
	input_sync(dd->othc_ipd);

	return IRQ_HANDLED;
}