input: HTC: wake-on-volume support
Referenced HTC kernel m7-jb-3.4.10-e22f38b
Patch set 2) ifdef and Kconfig to limit to MACH_HTC
Change-Id: Ifeacaa74bada9985a936b0f5ac29b0550d5a5122
diff --git a/drivers/input/misc/gpio_input.c b/drivers/input/misc/gpio_input.c
index f4b9a5a..975f4d1 100644
--- a/drivers/input/misc/gpio_input.c
+++ b/drivers/input/misc/gpio_input.c
@@ -94,6 +94,51 @@
}
#endif /* CONFIG_TOUCHSCREEN_SYNAPTICS_3K */
+#ifdef CONFIG_HTC_WAKE_ON_VOL
+static DEFINE_MUTEX(wakeup_mutex);
+static unsigned char wakeup_bitmask;
+static unsigned char set_wakeup;
+static unsigned int vol_up_irq;
+static unsigned int vol_down_irq;
+static ssize_t vol_wakeup_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned char bitmask = 0;
+ bitmask = simple_strtoull(buf, NULL, 10);
+ mutex_lock(&wakeup_mutex);
+ if (bitmask) {
+ if (bitmask == 127)
+ wakeup_bitmask &= bitmask;
+ else if (bitmask > 128)
+ wakeup_bitmask &= bitmask;
+ else
+ wakeup_bitmask |= bitmask;
+ }
+
+ if (wakeup_bitmask && (!set_wakeup)) {
+ enable_irq_wake(vol_up_irq);
+ enable_irq_wake(vol_down_irq);
+ set_wakeup = 1;
+ printk(KERN_INFO "%s:change to wake up function(%d, %d)\n", __func__, vol_up_irq, vol_down_irq);
+ } else if ((!wakeup_bitmask) && set_wakeup){
+ disable_irq_wake(vol_up_irq);
+ disable_irq_wake(vol_down_irq);
+ set_wakeup = 0;
+ printk(KERN_INFO "%s:change to non-wake up function(%d, %d)\n", __func__, vol_up_irq, vol_down_irq);
+ }
+ mutex_unlock(&wakeup_mutex);
+ return count;
+}
+static ssize_t vol_wakeup_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%x\n", wakeup_bitmask);
+}
+
+static DEVICE_ATTR(vol_wakeup, 0664, vol_wakeup_show, vol_wakeup_store);
+#endif /* CONFIG_HTC_WAKE_ON_VOL */
+
enum {
DEBOUNCE_UNSTABLE = BIT(0), /* Got irq, while debouncing */
DEBOUNCE_PRESSED = BIT(1),
@@ -303,6 +348,20 @@
ds->info->keymap[i].gpio, irq);
goto err_request_irq_failed;
}
+#ifdef CONFIG_HTC_WAKE_ON_VOL
+ if (ds->info->keymap[i].code == KEY_VOLUMEUP ||
+ ds->info->keymap[i].code == KEY_VOLUMEDOWN) {
+ pr_info("keycode = %d, gpio = %d, irq = %d\n",
+ ds->info->keymap[i].code,
+ ds->info->keymap[i].gpio, irq);
+ if (ds->info->keymap[i].code == KEY_VOLUMEUP)
+ vol_up_irq = irq;
+ else
+ vol_down_irq = irq;
+ } else {
+ enable_irq_wake(irq);
+ }
+#endif
if (ds->info->info.no_suspend) {
err = enable_irq_wake(irq);
if (err) {
@@ -340,6 +399,9 @@
unsigned long irqflags;
struct gpio_event_input_info *di;
struct gpio_input_state *ds = *data;
+#ifdef CONFIG_HTC_WAKE_ON_VOL
+ struct kobject *keyboard_kobj;
+#endif
di = container_of(info, struct gpio_event_input_info, info);
@@ -412,6 +474,20 @@
ret = gpio_event_input_request_irqs(ds);
+#ifdef CONFIG_HTC_WAKE_ON_VOL
+ keyboard_kobj = kobject_create_and_add("keyboard", NULL);
+ if (keyboard_kobj == NULL) {
+ printk(KERN_ERR "KEY_ERR: %s: subsystem_register failed\n", __func__);
+ ret = -ENOMEM;
+ return ret;
+ }
+ if (sysfs_create_file(keyboard_kobj, &dev_attr_vol_wakeup.attr))
+ printk(KERN_ERR "KEY_ERR: %s: sysfs_create_file "
+ "return %d\n", __func__, ret);
+ wakeup_bitmask = 0;
+ set_wakeup = 0;
+#endif
+
spin_lock_irqsave(&ds->irq_lock, irqflags);
ds->use_irq = ret == 0;