]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 31 Dec 2014 00:59:59 +0000 (16:59 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 31 Dec 2014 00:59:59 +0000 (16:59 -0800)
Pull input layer fixes from Dmitry Torokhov:
 "Fixes for v7 protocol for ALPS devices and few other driver fixes.

  Also users can request input events to be stamped with boot time
  timestamps, in addition to real and monotonic timestamps"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: hil_kbd - fix incorrect use of init_completion
  Input: alps - v7: document the v7 touchpad packet protocol
  Input: alps - v7: fix finger counting for > 2 fingers on clickpads
  Input: alps - v7: sometimes a single touch is reported in mt[1]
  Input: alps - v7: ignore new packets
  Input: evdev - add CLOCK_BOOTTIME support
  Input: psmouse - expose drift duration for IBM trackpoints
  Input: stmpe - bias keypad columns properly
  Input: stmpe - enforce device tree only mode
  mfd: stmpe: add pull up/down register offsets for STMPE
  Input: optimize events_per_packet count calculation
  Input: edt-ft5x06 - fixed a macro coding style issue
  Input: gpio_keys - replace timer and workqueue with delayed workqueue
  Input: gpio_keys - allow separating gpio and irq in device tree

1  2 
drivers/input/evdev.c
drivers/input/keyboard/gpio_keys.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/mfd/stmpe.c
drivers/mfd/stmpe.h

diff --combined drivers/input/evdev.c
index 8afa28e4570ed099bb3fb9fc4b2d7e1c1a5ba9d6,b1a52abc58df89d866f4fc39ee747346f4e02403..18d4b2c8fe55092aa8e31c411faf051d968fb49d
  #include <linux/cdev.h>
  #include "input-compat.h"
  
+ enum evdev_clock_type {
+       EV_CLK_REAL = 0,
+       EV_CLK_MONO,
+       EV_CLK_BOOT,
+       EV_CLK_MAX
+ };
  struct evdev {
        int open;
        struct input_handle handle;
@@@ -49,12 -56,32 +56,32 @@@ struct evdev_client 
        struct fasync_struct *fasync;
        struct evdev *evdev;
        struct list_head node;
-       int clkid;
+       int clk_type;
        bool revoked;
        unsigned int bufsize;
        struct input_event buffer[];
  };
  
+ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
+ {
+       switch (clkid) {
+       case CLOCK_REALTIME:
+               client->clk_type = EV_CLK_REAL;
+               break;
+       case CLOCK_MONOTONIC:
+               client->clk_type = EV_CLK_MONO;
+               break;
+       case CLOCK_BOOTTIME:
+               client->clk_type = EV_CLK_BOOT;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+ }
  /* flush queued events of type @type, caller must hold client->buffer_lock */
  static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
  {
@@@ -108,8 -135,11 +135,11 @@@ static void evdev_queue_syn_dropped(str
        struct input_event ev;
        ktime_t time;
  
-       time = (client->clkid == CLOCK_MONOTONIC) ?
-               ktime_get() : ktime_get_real();
+       time = client->clk_type == EV_CLK_REAL ?
+                       ktime_get_real() :
+                       client->clk_type == EV_CLK_MONO ?
+                               ktime_get() :
+                               ktime_get_boottime();
  
        ev.time = ktime_to_timeval(time);
        ev.type = EV_SYN;
@@@ -159,7 -189,7 +189,7 @@@ static void __pass_event(struct evdev_c
  
  static void evdev_pass_values(struct evdev_client *client,
                        const struct input_value *vals, unsigned int count,
-                       ktime_t mono, ktime_t real)
+                       ktime_t *ev_time)
  {
        struct evdev *evdev = client->evdev;
        const struct input_value *v;
        if (client->revoked)
                return;
  
-       event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
-                                     mono : real);
+       event.time = ktime_to_timeval(ev_time[client->clk_type]);
  
        /* Interrupts are disabled, just acquire the lock. */
        spin_lock(&client->buffer_lock);
@@@ -198,21 -227,22 +227,22 @@@ static void evdev_events(struct input_h
  {
        struct evdev *evdev = handle->private;
        struct evdev_client *client;
-       ktime_t time_mono, time_real;
+       ktime_t ev_time[EV_CLK_MAX];
  
-       time_mono = ktime_get();
-       time_real = ktime_mono_to_real(time_mono);
+       ev_time[EV_CLK_MONO] = ktime_get();
+       ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]);
+       ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO],
+                                                TK_OFFS_BOOT);
  
        rcu_read_lock();
  
        client = rcu_dereference(evdev->grab);
  
        if (client)
-               evdev_pass_values(client, vals, count, time_mono, time_real);
+               evdev_pass_values(client, vals, count, ev_time);
        else
                list_for_each_entry_rcu(client, &evdev->client_list, node)
-                       evdev_pass_values(client, vals, count,
-                                         time_mono, time_real);
+                       evdev_pass_values(client, vals, count, ev_time);
  
        rcu_read_unlock();
  }
@@@ -421,7 -451,7 +451,7 @@@ static int evdev_open(struct inode *ino
  
   err_free_client:
        evdev_detach_client(evdev, client);
 -      kfree(client);
 +      kvfree(client);
        return error;
  }
  
@@@ -877,10 -907,8 +907,8 @@@ static long evdev_do_ioctl(struct file 
        case EVIOCSCLOCKID:
                if (copy_from_user(&i, p, sizeof(unsigned int)))
                        return -EFAULT;
-               if (i != CLOCK_MONOTONIC && i != CLOCK_REALTIME)
-                       return -EINVAL;
-               client->clkid = i;
-               return 0;
+               return evdev_set_clk_type(client, i);
  
        case EVIOCGKEYCODE:
                return evdev_handle_get_keycode(dev, p);
index d4dd78a7d56b5b1bf3dbe8865025bd5559a82ce2,eefd976ab4ebe68e1f1a6d0269bdf566a1a765f8..883d6aed5b9ac12f47bc3a137bbf8e61c0bd1ec2
  struct gpio_button_data {
        const struct gpio_keys_button *button;
        struct input_dev *input;
-       struct timer_list timer;
-       struct work_struct work;
-       unsigned int timer_debounce;    /* in msecs */
+       struct timer_list release_timer;
+       unsigned int release_delay;     /* in msecs, for IRQ-only buttons */
+       struct delayed_work work;
+       unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
        unsigned int irq;
        spinlock_t lock;
        bool disabled;
@@@ -116,11 -120,14 +120,14 @@@ static void gpio_keys_disable_button(st
  {
        if (!bdata->disabled) {
                /*
-                * Disable IRQ and possible debouncing timer.
+                * Disable IRQ and associated timer/work structure.
                 */
                disable_irq(bdata->irq);
-               if (bdata->timer_debounce)
-                       del_timer_sync(&bdata->timer);
+               if (gpio_is_valid(bdata->button->gpio))
+                       cancel_delayed_work_sync(&bdata->work);
+               else
+                       del_timer_sync(&bdata->release_timer);
  
                bdata->disabled = true;
        }
@@@ -343,7 -350,7 +350,7 @@@ static void gpio_keys_gpio_report_event
  static void gpio_keys_gpio_work_func(struct work_struct *work)
  {
        struct gpio_button_data *bdata =
-               container_of(work, struct gpio_button_data, work);
+               container_of(work, struct gpio_button_data, work.work);
  
        gpio_keys_gpio_report_event(bdata);
  
                pm_relax(bdata->input->dev.parent);
  }
  
- static void gpio_keys_gpio_timer(unsigned long _data)
- {
-       struct gpio_button_data *bdata = (struct gpio_button_data *)_data;
-       schedule_work(&bdata->work);
- }
  static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
  {
        struct gpio_button_data *bdata = dev_id;
  
        if (bdata->button->wakeup)
                pm_stay_awake(bdata->input->dev.parent);
-       if (bdata->timer_debounce)
-               mod_timer(&bdata->timer,
-                       jiffies + msecs_to_jiffies(bdata->timer_debounce));
-       else
-               schedule_work(&bdata->work);
+       mod_delayed_work(system_wq,
+                        &bdata->work,
+                        msecs_to_jiffies(bdata->software_debounce));
  
        return IRQ_HANDLED;
  }
@@@ -408,7 -407,7 +407,7 @@@ static irqreturn_t gpio_keys_irq_isr(in
                input_event(input, EV_KEY, button->code, 1);
                input_sync(input);
  
-               if (!bdata->timer_debounce) {
+               if (!bdata->release_delay) {
                        input_event(input, EV_KEY, button->code, 0);
                        input_sync(input);
                        goto out;
                bdata->key_pressed = true;
        }
  
-       if (bdata->timer_debounce)
-               mod_timer(&bdata->timer,
-                       jiffies + msecs_to_jiffies(bdata->timer_debounce));
+       if (bdata->release_delay)
+               mod_timer(&bdata->release_timer,
+                       jiffies + msecs_to_jiffies(bdata->release_delay));
  out:
        spin_unlock_irqrestore(&bdata->lock, flags);
        return IRQ_HANDLED;
@@@ -429,10 -428,10 +428,10 @@@ static void gpio_keys_quiesce_key(void 
  {
        struct gpio_button_data *bdata = data;
  
-       if (bdata->timer_debounce)
-               del_timer_sync(&bdata->timer);
-       cancel_work_sync(&bdata->work);
+       if (gpio_is_valid(bdata->button->gpio))
+               cancel_delayed_work_sync(&bdata->work);
+       else
+               del_timer_sync(&bdata->release_timer);
  }
  
  static int gpio_keys_setup_key(struct platform_device *pdev,
                                        button->debounce_interval * 1000);
                        /* use timer if gpiolib doesn't provide debounce */
                        if (error < 0)
-                               bdata->timer_debounce =
+                               bdata->software_debounce =
                                                button->debounce_interval;
                }
  
-               irq = gpio_to_irq(button->gpio);
-               if (irq < 0) {
-                       error = irq;
-                       dev_err(dev,
-                               "Unable to get irq number for GPIO %d, error %d\n",
-                               button->gpio, error);
-                       return error;
+               if (button->irq) {
+                       bdata->irq = button->irq;
+               } else {
+                       irq = gpio_to_irq(button->gpio);
+                       if (irq < 0) {
+                               error = irq;
+                               dev_err(dev,
+                                       "Unable to get irq number for GPIO %d, error %d\n",
+                                       button->gpio, error);
+                               return error;
+                       }
+                       bdata->irq = irq;
                }
-               bdata->irq = irq;
  
-               INIT_WORK(&bdata->work, gpio_keys_gpio_work_func);
-               setup_timer(&bdata->timer,
-                           gpio_keys_gpio_timer, (unsigned long)bdata);
+               INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func);
  
                isr = gpio_keys_gpio_isr;
                irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
                        return -EINVAL;
                }
  
-               bdata->timer_debounce = button->debounce_interval;
-               setup_timer(&bdata->timer,
+               bdata->release_delay = button->debounce_interval;
+               setup_timer(&bdata->release_timer,
                            gpio_keys_irq_timer, (unsigned long)bdata);
  
                isr = gpio_keys_irq_isr;
        input_set_capability(input, button->type ?: EV_KEY, button->code);
  
        /*
-        * Install custom action to cancel debounce timer and
+        * Install custom action to cancel release timer and
         * workqueue item.
         */
        error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata);
@@@ -618,33 -619,30 +619,30 @@@ gpio_keys_get_devtree_pdata(struct devi
  
        i = 0;
        for_each_child_of_node(node, pp) {
-               int gpio = -1;
                enum of_gpio_flags flags;
  
                button = &pdata->buttons[i++];
  
-               if (!of_find_property(pp, "gpios", NULL)) {
-                       button->irq = irq_of_parse_and_map(pp, 0);
-                       if (button->irq == 0) {
-                               i--;
-                               pdata->nbuttons--;
-                               dev_warn(dev, "Found button without gpios or irqs\n");
-                               continue;
-                       }
-               } else {
-                       gpio = of_get_gpio_flags(pp, 0, &flags);
-                       if (gpio < 0) {
-                               error = gpio;
+               button->gpio = of_get_gpio_flags(pp, 0, &flags);
+               if (button->gpio < 0) {
+                       error = button->gpio;
+                       if (error != -ENOENT) {
                                if (error != -EPROBE_DEFER)
                                        dev_err(dev,
                                                "Failed to get gpio flags, error: %d\n",
                                                error);
                                return ERR_PTR(error);
                        }
+               } else {
+                       button->active_low = flags & OF_GPIO_ACTIVE_LOW;
                }
  
-               button->gpio = gpio;
-               button->active_low = flags & OF_GPIO_ACTIVE_LOW;
+               button->irq = irq_of_parse_and_map(pp, 0);
+               if (!gpio_is_valid(button->gpio) && !button->irq) {
+                       dev_err(dev, "Found button without gpios or irqs\n");
+                       return ERR_PTR(-EINVAL);
+               }
  
                if (of_property_read_u32(pp, "linux,code", &button->code)) {
                        dev_err(dev, "Button without keycode: 0x%x\n",
  
                button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
  
+               button->can_disable = !!of_get_property(pp, "linux,can-disable", NULL);
                if (of_property_read_u32(pp, "debounce-interval",
                                         &button->debounce_interval))
                        button->debounce_interval = 5;
@@@ -840,6 -840,7 +840,6 @@@ static struct platform_driver gpio_keys
        .remove         = gpio_keys_remove,
        .driver         = {
                .name   = "gpio-keys",
 -              .owner  = THIS_MODULE,
                .pm     = &gpio_keys_pm_ops,
                .of_match_table = of_match_ptr(gpio_keys_of_match),
        }
index 3793fcc7e5db31117404e819272da27f4fd15d90,dcc68efd0d7fa26d934ebfebc5ee39d176cd9733..d4c24fb7704f5e2d87f299ac01e2aa2ba5866521
@@@ -812,7 -812,7 +812,7 @@@ static int edt_ft5x06_ts_identify(struc
        /* if we find something consistent, stay with that assumption
         * at least M09 won't send 3 bytes here
         */
 -      if (!(strnicmp(rdbuf + 1, "EP0", 3))) {
 +      if (!(strncasecmp(rdbuf + 1, "EP0", 3))) {
                tsdata->version = M06;
  
                /* remove last '$' end marker */
  }
  
  #define EDT_ATTR_CHECKSET(name, reg) \
+ do {                                                          \
        if (pdata->name >= edt_ft5x06_attr_##name.limit_low &&          \
            pdata->name <= edt_ft5x06_attr_##name.limit_high)           \
-               edt_ft5x06_register_write(tsdata, reg, pdata->name)
+               edt_ft5x06_register_write(tsdata, reg, pdata->name);    \
+ } while (0)
  
  #define EDT_GET_PROP(name, reg) {                             \
        u32 val;                                                \
diff --combined drivers/mfd/stmpe.c
index e2f9df1c0c361f0d0e66bf782817af6170e49dc5,2d29d17518c4614c102c1b7ad3df1a0d5935f411..2d7fae94c861013c594463705e05ea413275e4d0
@@@ -249,7 -249,7 +249,7 @@@ int stmpe_set_altfunc(struct stmpe *stm
        int af_bits = variant->af_bits;
        int numregs = DIV_ROUND_UP(stmpe->num_gpios * af_bits, 8);
        int mask = (1 << af_bits) - 1;
 -      u8 regs[numregs];
 +      u8 regs[8];
        int af, afperreg, ret;
  
        if (!variant->get_altfunc)
@@@ -519,6 -519,7 +519,7 @@@ static const u8 stmpe1601_regs[] = 
        [STMPE_IDX_GPDR_LSB]    = STMPE1601_REG_GPIO_SET_DIR_LSB,
        [STMPE_IDX_GPRER_LSB]   = STMPE1601_REG_GPIO_RE_LSB,
        [STMPE_IDX_GPFER_LSB]   = STMPE1601_REG_GPIO_FE_LSB,
+       [STMPE_IDX_GPPUR_LSB]   = STMPE1601_REG_GPIO_PU_LSB,
        [STMPE_IDX_GPAFR_U_MSB] = STMPE1601_REG_GPIO_AF_U_MSB,
        [STMPE_IDX_IEGPIOR_LSB] = STMPE1601_REG_INT_EN_GPIO_MASK_LSB,
        [STMPE_IDX_ISGPIOR_MSB] = STMPE1601_REG_INT_STA_GPIO_MSB,
@@@ -667,6 -668,7 +668,7 @@@ static const u8 stmpe1801_regs[] = 
        [STMPE_IDX_GPDR_LSB]    = STMPE1801_REG_GPIO_SET_DIR_LOW,
        [STMPE_IDX_GPRER_LSB]   = STMPE1801_REG_GPIO_RE_LOW,
        [STMPE_IDX_GPFER_LSB]   = STMPE1801_REG_GPIO_FE_LOW,
+       [STMPE_IDX_GPPUR_LSB]   = STMPE1801_REG_GPIO_PULL_UP_LOW,
        [STMPE_IDX_IEGPIOR_LSB] = STMPE1801_REG_INT_EN_GPIO_MASK_LOW,
        [STMPE_IDX_ISGPIOR_LSB] = STMPE1801_REG_INT_STA_GPIO_LOW,
  };
@@@ -750,6 -752,8 +752,8 @@@ static const u8 stmpe24xx_regs[] = 
        [STMPE_IDX_GPDR_LSB]    = STMPE24XX_REG_GPDR_LSB,
        [STMPE_IDX_GPRER_LSB]   = STMPE24XX_REG_GPRER_LSB,
        [STMPE_IDX_GPFER_LSB]   = STMPE24XX_REG_GPFER_LSB,
+       [STMPE_IDX_GPPUR_LSB]   = STMPE24XX_REG_GPPUR_LSB,
+       [STMPE_IDX_GPPDR_LSB]   = STMPE24XX_REG_GPPDR_LSB,
        [STMPE_IDX_GPAFR_U_MSB] = STMPE24XX_REG_GPAFR_U_MSB,
        [STMPE_IDX_IEGPIOR_LSB] = STMPE24XX_REG_IEGPIOR_LSB,
        [STMPE_IDX_ISGPIOR_MSB] = STMPE24XX_REG_ISGPIOR_MSB,
@@@ -854,7 -858,7 +858,7 @@@ static irqreturn_t stmpe_irq(int irq, v
        struct stmpe_variant_info *variant = stmpe->variant;
        int num = DIV_ROUND_UP(variant->num_irqs, 8);
        u8 israddr;
 -      u8 isr[num];
 +      u8 isr[3];
        int ret;
        int i;
  
@@@ -1122,12 -1126,7 +1126,12 @@@ static void stmpe_of_probe(struct stmpe
        if (pdata->id < 0)
                pdata->id = -1;
  
 -      pdata->irq_trigger = IRQF_TRIGGER_NONE;
 +      pdata->irq_gpio = of_get_named_gpio_flags(np, "irq-gpio", 0,
 +                              &pdata->irq_trigger);
 +      if (gpio_is_valid(pdata->irq_gpio))
 +              pdata->irq_over_gpio = 1;
 +      else
 +              pdata->irq_trigger = IRQF_TRIGGER_NONE;
  
        of_property_read_u32(np, "st,autosleep-timeout",
                        &pdata->autosleep_timeout);
diff --combined drivers/mfd/stmpe.h
index bee0abf82040001664c07e82c646e0e3e5afc259,e00710b6393225c111f04a96b8d5dd3c5f559f2f..84adb46b3e2fea599f069072f2f48190602092e9
@@@ -188,6 -188,7 +188,7 @@@ int stmpe_remove(struct stmpe *stmpe)
  #define STMPE1601_REG_GPIO_ED_MSB             0x8A
  #define STMPE1601_REG_GPIO_RE_LSB             0x8D
  #define STMPE1601_REG_GPIO_FE_LSB             0x8F
+ #define STMPE1601_REG_GPIO_PU_LSB             0x91
  #define STMPE1601_REG_GPIO_AF_U_MSB           0x92
  
  #define STMPE1601_SYS_CTRL_ENABLE_GPIO                (1 << 3)
  #define STMPE24XX_REG_CHIP_ID         0x80
  #define STMPE24XX_REG_IEGPIOR_LSB     0x18
  #define STMPE24XX_REG_ISGPIOR_MSB     0x19
 -#define STMPE24XX_REG_GPMR_LSB                0xA5
 +#define STMPE24XX_REG_GPMR_LSB                0xA4
  #define STMPE24XX_REG_GPSR_LSB                0x85
  #define STMPE24XX_REG_GPCR_LSB                0x88
  #define STMPE24XX_REG_GPDR_LSB                0x8B
  #define STMPE24XX_REG_GPEDR_MSB               0x8C
  #define STMPE24XX_REG_GPRER_LSB               0x91
  #define STMPE24XX_REG_GPFER_LSB               0x94
+ #define STMPE24XX_REG_GPPUR_LSB               0x97
+ #define STMPE24XX_REG_GPPDR_LSB               0x9a
  #define STMPE24XX_REG_GPAFR_U_MSB     0x9B
  
  #define STMPE24XX_SYS_CTRL_ENABLE_GPIO                (1 << 3)