X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/ms2-fixes/blobdiff_plain/fc215caab8c37c6e08dfc0d1dd4dd7f8deabd3ac..a6322a6f9aac1788492a6a54b8880dc27fece842:/debounce.c diff --git a/debounce.c b/debounce.c index a5138c3..5694d12 100644 --- a/debounce.c +++ b/debounce.c @@ -2,10 +2,12 @@ #include #include #include +#include -#define PREFIX "debounce: " +/* hardware debounce: (value + 1) * 31us */ +#define GPIO_DEBOUNCE_TIME 0x1 -static int debounce_delay = 15; +#define PREFIX "debounce: " static unsigned old_flags = 0; ktime_t old_debounce_delay; @@ -13,9 +15,6 @@ ktime_t old_settle_time; ktime_t old_poll_time; static struct gpio_event_matrix_info *gpio_evmi = NULL; -module_param(debounce_delay, int, S_IRUSR | S_IRGRP | S_IROTH); -MODULE_PARM_DESC(debounce_delay, "debouncing delay (ms), default: 15"); - static int find_ms2_dev(struct device *dev, void *data) { if (!strncmp((char*)data, dev_name(dev), strlen((char*)data))) { @@ -38,7 +37,6 @@ static void set_debounce_delay(long delay) if (gpio_evmi->debounce_delay.tv.nsec != delay * NSEC_PER_MSEC) { printk(KERN_INFO PREFIX "Changing debounce_delay\n"); gpio_evmi->debounce_delay.tv.nsec = delay * NSEC_PER_MSEC; - debounce_delay = delay; printk(KERN_INFO PREFIX "debounce_delay: %u\n", gpio_evmi->debounce_delay.tv.nsec); } @@ -131,9 +129,6 @@ static ssize_t store_flags(struct device *dev, struct device_attribute *attr, co printk(KERN_INFO PREFIX "flags: 0x%x\n", flags); - if (flags & GPIOKPF_DRIVE_INACTIVE) - return count; - gpio_evmi->flags = flags; return count; @@ -269,6 +264,58 @@ static ssize_t store_print_phantom_keys_flag(struct device *dev, struct device_a return count; } +static ssize_t show_active_high_flag(struct device *dev, struct device_attribute *attr, char *buf) +{ + if (!gpio_evmi) + return -ENODEV; + + return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_ACTIVE_HIGH) ? 1 : 0); +} + +static ssize_t store_active_high_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned flag; + + if (!gpio_evmi) + return -ENODEV; + + sscanf(buf, "%u", &flag); + + if (flag) { + gpio_evmi->flags |= GPIOKPF_ACTIVE_HIGH; + } else { + gpio_evmi->flags &= ~GPIOKPF_ACTIVE_HIGH; + } + + return count; +} + +static ssize_t show_drive_inactive_flag(struct device *dev, struct device_attribute *attr, char *buf) +{ + if (!gpio_evmi) + return -ENODEV; + + return snprintf(buf, PAGE_SIZE, "%u\n", (gpio_evmi->flags & GPIOKPF_DRIVE_INACTIVE) ? 1 : 0); +} + +static ssize_t store_drive_inactive_flag(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned flag; + + if (!gpio_evmi) + return -ENODEV; + + sscanf(buf, "%u", &flag); + + if (flag) { + gpio_evmi->flags |= GPIOKPF_DRIVE_INACTIVE; + } else { + gpio_evmi->flags &= ~GPIOKPF_DRIVE_INACTIVE; + } + + return count; +} + static DEVICE_ATTR(debounce_delay, (S_IRUGO | S_IWUGO), show_debounce_delay, store_debounce_delay); static DEVICE_ATTR(settle_time, (S_IRUGO | S_IWUGO), show_settle_time, store_settle_time); static DEVICE_ATTR(poll_time, (S_IRUGO | S_IWUGO), show_poll_time, store_poll_time); @@ -278,6 +325,8 @@ static DEVICE_ATTR(remove_some_phantom_keys_flag, (S_IRUGO | S_IWUGO), show_remo static DEVICE_ATTR(print_unmapped_keys_flag, (S_IRUGO | S_IWUGO), show_print_unmapped_keys_flag, store_print_unmapped_keys_flag); static DEVICE_ATTR(print_mapped_keys_flag, (S_IRUGO | S_IWUGO), show_print_mapped_keys_flag, store_print_mapped_keys_flag); static DEVICE_ATTR(print_phantom_keys_flag, (S_IRUGO | S_IWUGO), show_print_phantom_keys_flag, store_print_phantom_keys_flag); +static DEVICE_ATTR(active_high_flag, (S_IRUGO), show_active_high_flag, store_active_high_flag); +static DEVICE_ATTR(drive_inactive_flag, (S_IRUGO | S_IWUGO), show_drive_inactive_flag, store_drive_inactive_flag); static void debounce_release(struct device *dev) { @@ -288,6 +337,24 @@ static struct device debounce_device = { .release = debounce_release, }; +static void hw_debounce_pin(int gpio, int enable) { + printk(KERN_INFO PREFIX "%sabling hardware debounce for GPIO %d\n", (enable?"En":"Dis"), gpio); + if (enable) + omap_set_gpio_debounce_time(gpio, GPIO_DEBOUNCE_TIME); + omap_set_gpio_debounce(gpio, enable); +} + +static void hw_debounce(int enable) { + int i; + + if (gpio_evmi == NULL) + return; + + for (i = 0; i < gpio_evmi->ninputs; i++) { + hw_debounce_pin(gpio_evmi->input_gpios[i], enable); + } +} + static int __init debounce_init(void) { struct device *event_dev = NULL; @@ -314,6 +381,8 @@ static int __init debounce_init(void) return err; } + hw_debounce(1); + err = device_create_file(&debounce_device, &dev_attr_debounce_delay); err = device_create_file(&debounce_device, &dev_attr_settle_time); err = device_create_file(&debounce_device, &dev_attr_poll_time); @@ -323,6 +392,8 @@ static int __init debounce_init(void) err = device_create_file(&debounce_device, &dev_attr_print_unmapped_keys_flag); err = device_create_file(&debounce_device, &dev_attr_print_mapped_keys_flag); err = device_create_file(&debounce_device, &dev_attr_print_phantom_keys_flag); + err = device_create_file(&debounce_device, &dev_attr_active_high_flag); + err = device_create_file(&debounce_device, &dev_attr_drive_inactive_flag); printk(KERN_INFO PREFIX "settle_time: %u\n", gpio_evmi->settle_time.tv.nsec); printk(KERN_INFO PREFIX "poll_time: %u\n", gpio_evmi->poll_time.tv.nsec); @@ -334,8 +405,6 @@ static int __init debounce_init(void) old_poll_time = gpio_evmi->poll_time; old_flags = gpio_evmi->flags; - set_debounce_delay(debounce_delay); - printk(KERN_INFO PREFIX "flags: 0x%x\n", gpio_evmi->flags); return 0; @@ -357,6 +426,7 @@ static void __exit debounce_exit(void) gpio_evmi->settle_time = old_settle_time; gpio_evmi->poll_time = old_poll_time; } + hw_debounce(0); device_remove_file(&debounce_device, &dev_attr_debounce_delay); device_remove_file(&debounce_device, &dev_attr_settle_time); device_remove_file(&debounce_device, &dev_attr_poll_time); @@ -366,6 +436,8 @@ static void __exit debounce_exit(void) device_remove_file(&debounce_device, &dev_attr_print_unmapped_keys_flag); device_remove_file(&debounce_device, &dev_attr_print_mapped_keys_flag); device_remove_file(&debounce_device, &dev_attr_print_phantom_keys_flag); + device_remove_file(&debounce_device, &dev_attr_active_high_flag); + device_remove_file(&debounce_device, &dev_attr_drive_inactive_flag); device_unregister(&debounce_device); }