コード例 #1
0
/* 88PM80x gives us an interrupt when ONKEY is held */
static irqreturn_t pm80x_onkey_handler(int irq, void *data)
{
	struct pm80x_onkey_info *info = data;
	int ret = 0;
	unsigned int val;

	ret = regmap_read(info->map, PM800_STATUS_1, &val);
	if (ret < 0) {
		dev_err(info->idev->dev.parent, "failed to read status: %d\n",
			ret);
		return IRQ_NONE;
	}
	val &= PM800_ONKEY_STS1;
	/*
	 * HW workaround: There is bug of LONG_ONKEY_EVENT will be detected wrongly,
	 * then it will trigger  power down/power up cycle unexpectedly.
	 * Sw will reset the LONG_ONKEY timer to avoid this kind of issue.
	 */
	regmap_update_bits(info->map, PM800_WAKEUP1,
			PM800_LONGKEY_RESET, PM800_LONGKEY_RESET);
#ifdef CONFIG_FAKE_SYSTEMOFF
	if (fake_sysoff_block_onkey())
		goto out;
	if (fake_sysoff_status_query()) {
		if (val) { /*down key*/
			if (!atomic_cmpxchg(&longpress_work_state, 0, 1)) {
				schedule_delayed_work(&presscheck_work,
						LONGPRESS_INTERVAL);
				/* Think about following case: onkey down/up->
				 * kernel will awake 5s ->after 4s->
				 * user long down on key -> after 1s, suspend
				 * -> have no chance for 3s timeout*/
				__pm_wakeup_event(&suspend_longkey_lock,
				jiffies_to_msecs(LONGPRESS_INTERVAL + HZ));
			}
		} else { /*up key*/
			if (atomic_cmpxchg(&longpress_work_state, 1, 0)) {
				/* short press */
				cancel_delayed_work_sync(&presscheck_work);
			}
		}
	} else {
#endif
#if defined(CONFIG_KERNEL_DEBUG_SEC) && (defined(CONFIG_MACH_LT02) || defined(CONFIG_MACH_COCOA7))
		key_dbg("%s state = %d\n", __func__, val);
		gpio_keys_setstate(KEY_POWER, val ? true : false);
		if (val && gpio_keys_getstate(KEY_VOLUMEUP) && jack_is_detected)
			gpio_keys_start_upload_modtimer();
#endif
		input_report_key(info->idev, KEY_POWER, val);
		input_sync(info->idev);

#ifdef CONFIG_FAKE_SYSTEMOFF
	}
out:
#endif
	is_power_key_pressed = val;		// AT+KEYSHORT cmd
	return IRQ_HANDLED;
}
コード例 #2
0
/* 88PM822 gives us an interrupt when ONKEY is held */
static irqreturn_t pm822_onkey_handler(int irq, void *data)
{
	struct pm822_onkey_info *info = data;
	int ret = 0;
	unsigned int val;

	ret = regmap_read(info->map, PM822_STATUS1, &val);
	if (ret < 0) {
		dev_err(info->idev->dev.parent, "failed to read status: %d\n",
			ret);
		return IRQ_NONE;
	}
	val &= PM822_ONKEY_STS1;
#ifdef CONFIG_FAKE_SYSTEMOFF
	if (fake_sysoff_block_onkey())
		goto out;
	if (fake_sysoff_status_query()) {
		if (val) { /*down key*/
			if (!atomic_cmpxchg(&longpress_work_state, 0, 1)) {
				schedule_delayed_work(&presscheck_work,
						LONGPRESS_INTERVAL);
				/* Think about following case: onkey down/up->
				 * kernel will awake 5s ->after 4s->
				 * user long down on key -> after 1s, suspend
				 * -> have no chance for 3s timeout*/
				__pm_wakeup_event(&suspend_longkey_lock,
				jiffies_to_msecs(LONGPRESS_INTERVAL + HZ));
			}
		} else { /*up key*/
			if (atomic_cmpxchg(&longpress_work_state, 1, 0)) {
				/* short press */
				cancel_delayed_work_sync(&presscheck_work);
			}
		}
	} else {
#endif
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
	printk("power key val =%d\n",val);
#endif
	input_report_key(info->idev, KEY_POWER, val);
	input_sync(info->idev);
#ifdef CONFIG_FAKE_SYSTEMOFF
	}
out:
#endif
	is_power_key_pressed = val;		// AT+KEYSHORT cmd
	return IRQ_HANDLED;
}