diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/keyboard/bf54x-keys.c | 2 | ||||
-rw-r--r-- | drivers/input/mouse/bcm5974.c | 74 | ||||
-rw-r--r-- | drivers/input/serio/i8042-x86ia64io.h | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 68 |
4 files changed, 113 insertions, 33 deletions
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 6f227d3dbda..e348cfccc17 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -43,7 +43,7 @@ #include <linux/input.h> #include <asm/portmux.h> -#include <asm/mach/bf54x_keys.h> +#include <mach/bf54x_keys.h> #define DRV_NAME "bf54x-keys" #define TIME_SCALE 100 /* 100 ns */ diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2ec921bf3c6..18f4d7f6ce6 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -63,7 +63,7 @@ } /* table of devices that work with this driver */ -static const struct usb_device_id bcm5974_table [] = { +static const struct usb_device_id bcm5974_table[] = { /* MacbookAir1.1 */ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING_ISO), @@ -105,7 +105,7 @@ struct tp_header { /* trackpad finger structure */ struct tp_finger { - __le16 origin; /* left/right origin? */ + __le16 origin; /* zero when switching track finger */ __le16 abs_x; /* absolute x coodinate */ __le16 abs_y; /* absolute y coodinate */ __le16 rel_x; /* relative x coodinate */ @@ -159,6 +159,7 @@ struct bcm5974 { struct bt_data *bt_data; /* button transferred data */ struct urb *tp_urb; /* trackpad usb request block */ struct tp_data *tp_data; /* trackpad transferred data */ + int fingers; /* number of fingers on trackpad */ }; /* logical dimensions */ @@ -172,6 +173,10 @@ struct bcm5974 { #define SN_WIDTH 100 /* width signal-to-noise ratio */ #define SN_COORD 250 /* coordinate signal-to-noise ratio */ +/* pressure thresholds */ +#define PRESSURE_LOW (2 * DIM_PRESSURE / SN_PRESSURE) +#define PRESSURE_HIGH (3 * PRESSURE_LOW) + /* device constants */ static const struct bcm5974_config bcm5974_config_table[] = { { @@ -248,6 +253,7 @@ static void setup_events_to_report(struct input_dev *input_dev, 0, cfg->y.dim, cfg->y.fuzz, 0); __set_bit(EV_KEY, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(BTN_TOOL_FINGER, input_dev->keybit); __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); @@ -273,32 +279,66 @@ static int report_tp_state(struct bcm5974 *dev, int size) const struct tp_finger *f = dev->tp_data->finger; struct input_dev *input = dev->input; const int fingers = (size - 26) / 28; - int p = 0, w, x, y, n = 0; + int raw_p, raw_w, raw_x, raw_y; + int ptest = 0, origin = 0, nmin = 0, nmax = 0; + int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; if (size < 26 || (size - 26) % 28 != 0) return -EIO; + /* always track the first finger; when detached, start over */ if (fingers) { - p = raw2int(f->force_major); - w = raw2int(f->size_major); - x = raw2int(f->abs_x); - y = raw2int(f->abs_y); - n = p > 0 ? fingers : 0; + raw_p = raw2int(f->force_major); + raw_w = raw2int(f->size_major); + raw_x = raw2int(f->abs_x); + raw_y = raw2int(f->abs_y); dprintk(9, - "bcm5974: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", - p, w, x, y, n); + "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n", + raw_p, raw_w, raw_x, raw_y); + + ptest = int2bound(&c->p, raw_p); + origin = raw2int(f->origin); + } - input_report_abs(input, ABS_TOOL_WIDTH, int2bound(&c->w, w)); - input_report_abs(input, ABS_X, int2bound(&c->x, x - c->x.devmin)); - input_report_abs(input, ABS_Y, int2bound(&c->y, c->y.devmax - y)); + /* while tracking finger still valid, count all fingers */ + if (ptest > PRESSURE_LOW && origin) { + abs_p = ptest; + abs_w = int2bound(&c->w, raw_w); + abs_x = int2bound(&c->x, raw_x - c->x.devmin); + abs_y = int2bound(&c->y, c->y.devmax - raw_y); + for (; f != dev->tp_data->finger + fingers; f++) { + ptest = int2bound(&c->p, raw2int(f->force_major)); + if (ptest > PRESSURE_LOW) + nmax++; + if (ptest > PRESSURE_HIGH) + nmin++; + } } - input_report_abs(input, ABS_PRESSURE, int2bound(&c->p, p)); + if (dev->fingers < nmin) + dev->fingers = nmin; + if (dev->fingers > nmax) + dev->fingers = nmax; + + input_report_key(input, BTN_TOUCH, dev->fingers > 0); + input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); + input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); + input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2); - input_report_key(input, BTN_TOOL_FINGER, n == 1); - input_report_key(input, BTN_TOOL_DOUBLETAP, n == 2); - input_report_key(input, BTN_TOOL_TRIPLETAP, n > 2); + input_report_abs(input, ABS_PRESSURE, abs_p); + input_report_abs(input, ABS_TOOL_WIDTH, abs_w); + + if (abs_p) { + input_report_abs(input, ABS_X, abs_x); + input_report_abs(input, ABS_Y, abs_y); + + dprintk(8, + "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " + "nmin: %d nmax: %d n: %d\n", + abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers); + + } input_sync(input); diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 3282b741e24..5aafe24984c 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -305,7 +305,7 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { .ident = "Lenovo 3000 n100", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"), + DMI_MATCH(DMI_PRODUCT_NAME, "076804U"), }, }, { diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index ce6f48c695f..8583c766d56 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -24,6 +24,7 @@ #include <linux/input.h> #include <linux/interrupt.h> #include <linux/slab.h> +#include <linux/gpio.h> #include <linux/spi/spi.h> #include <linux/spi/ads7846.h> #include <asm/irq.h> @@ -116,6 +117,7 @@ struct ads7846 { void *filter_data; void (*filter_cleanup)(void *data); int (*get_pendown_state)(void); + int gpio_pendown; }; /* leave chip selected when we're done, for quicker re-select? */ @@ -491,6 +493,14 @@ static struct attribute_group ads784x_attr_group = { /*--------------------------------------------------------------------------*/ +static int get_pendown_state(struct ads7846 *ts) +{ + if (ts->get_pendown_state) + return ts->get_pendown_state(); + + return !gpio_get_value(ts->gpio_pendown); +} + /* * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, * to retrieve touchscreen status. @@ -550,7 +560,7 @@ static void ads7846_rx(void *ads) */ if (ts->penirq_recheck_delay_usecs) { udelay(ts->penirq_recheck_delay_usecs); - if (!ts->get_pendown_state()) + if (!get_pendown_state(ts)) Rt = 0; } @@ -677,7 +687,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) spin_lock_irq(&ts->lock); - if (unlikely(!ts->get_pendown_state() || + if (unlikely(!get_pendown_state(ts) || device_suspended(&ts->spi->dev))) { if (ts->pendown) { struct input_dev *input = ts->input; @@ -716,7 +726,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle) unsigned long flags; spin_lock_irqsave(&ts->lock, flags); - if (likely(ts->get_pendown_state())) { + if (likely(get_pendown_state(ts))) { if (!ts->irq_disabled) { /* The ARM do_simple_IRQ() dispatcher doesn't act * like the other dispatchers: it will report IRQs @@ -806,6 +816,36 @@ static int ads7846_resume(struct spi_device *spi) return 0; } +static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts) +{ + struct ads7846_platform_data *pdata = spi->dev.platform_data; + int err; + + /* REVISIT when the irq can be triggered active-low, or if for some + * reason the touchscreen isn't hooked up, we don't need to access + * the pendown state. + */ + if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) { + dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); + return -EINVAL; + } + + if (pdata->get_pendown_state) { + ts->get_pendown_state = pdata->get_pendown_state; + return 0; + } + + err = gpio_request(pdata->gpio_pendown, "ads7846_pendown"); + if (err) { + dev_err(&spi->dev, "failed to request pendown GPIO%d\n", + pdata->gpio_pendown); + return err; + } + + ts->gpio_pendown = pdata->gpio_pendown; + return 0; +} + static int __devinit ads7846_probe(struct spi_device *spi) { struct ads7846 *ts; @@ -833,15 +873,6 @@ static int __devinit ads7846_probe(struct spi_device *spi) return -EINVAL; } - /* REVISIT when the irq can be triggered active-low, or if for some - * reason the touchscreen isn't hooked up, we don't need to access - * the pendown state. - */ - if (pdata->get_pendown_state == NULL) { - dev_dbg(&spi->dev, "no get_pendown_state function?\n"); - return -EINVAL; - } - /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except * that even if the hardware can do that, the SPI controller driver * may not. So we stick to very-portable 8 bit words, both RX and TX. @@ -893,7 +924,10 @@ static int __devinit ads7846_probe(struct spi_device *spi) ts->filter_data = ts; } else ts->filter = ads7846_no_filter; - ts->get_pendown_state = pdata->get_pendown_state; + + err = setup_pendown(spi, ts); + if (err) + goto err_cleanup_filter; if (pdata->penirq_recheck_delay_usecs) ts->penirq_recheck_delay_usecs = @@ -1085,7 +1119,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) spi->dev.driver->name, ts)) { dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); err = -EBUSY; - goto err_cleanup_filter; + goto err_free_gpio; } err = ads784x_hwmon_register(spi, ts); @@ -1116,6 +1150,9 @@ static int __devinit ads7846_probe(struct spi_device *spi) ads784x_hwmon_unregister(spi, ts); err_free_irq: free_irq(spi->irq, ts); + err_free_gpio: + if (ts->gpio_pendown != -1) + gpio_free(ts->gpio_pendown); err_cleanup_filter: if (ts->filter_cleanup) ts->filter_cleanup(ts->filter_data); @@ -1140,6 +1177,9 @@ static int __devexit ads7846_remove(struct spi_device *spi) /* suspend left the IRQ disabled */ enable_irq(ts->spi->irq); + if (ts->gpio_pendown != -1) + gpio_free(ts->gpio_pendown); + if (ts->filter_cleanup) ts->filter_cleanup(ts->filter_data); |