From fef95faeae9fa5f605fbad8693e2d6e2171f5ad4 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 21 Jun 2011 04:20:57 -0700 Subject: Input: qt1070 - remove obsolete cleanup for clientdata A few new i2c-drivers came into the kernel which clear the clientdata pointer on exit or error. This is not required anymore since the core will do it for us. Signed-off-by: Wolfram Sang Acked-by: Jean Delvare Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/qt1070.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c index ca7b891..b21bf5b 100644 --- a/drivers/input/keyboard/qt1070.c +++ b/drivers/input/keyboard/qt1070.c @@ -239,8 +239,6 @@ static int __devexit qt1070_remove(struct i2c_client *client) input_unregister_device(data->input); kfree(data); - i2c_set_clientdata(client, NULL); - return 0; } -- cgit v1.1 From 61cf3813d32411b23d5df8a650bbd2aa89b4618c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 21 Jun 2011 04:20:57 -0700 Subject: Input: lm8323 - convert to threaded IRQ There's no need for that workqueue anymore. Get rid of it and move to threaded IRQs instead. Signed-off-by: Felipe Balbi Tested-by: Leigh Brown Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/lm8323.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 71f744a8..3b21f42 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -146,7 +146,6 @@ struct lm8323_chip { /* device lock */ struct mutex lock; struct i2c_client *client; - struct work_struct work; struct input_dev *idev; bool kp_enabled; bool pm_suspend; @@ -162,7 +161,6 @@ struct lm8323_chip { #define client_to_lm8323(c) container_of(c, struct lm8323_chip, client) #define dev_to_lm8323(d) container_of(d, struct lm8323_chip, client->dev) -#define work_to_lm8323(w) container_of(w, struct lm8323_chip, work) #define cdev_to_pwm(c) container_of(c, struct lm8323_pwm, cdev) #define work_to_pwm(w) container_of(w, struct lm8323_pwm, work) @@ -375,9 +373,9 @@ static void pwm_done(struct lm8323_pwm *pwm) * Bottom half: handle the interrupt by posting key events, or dealing with * errors appropriately. */ -static void lm8323_work(struct work_struct *work) +static irqreturn_t lm8323_irq(int irq, void *_lm) { - struct lm8323_chip *lm = work_to_lm8323(work); + struct lm8323_chip *lm = _lm; u8 ints; int i; @@ -409,16 +407,6 @@ static void lm8323_work(struct work_struct *work) } mutex_unlock(&lm->lock); -} - -/* - * We cannot use I2C in interrupt context, so we just schedule work. - */ -static irqreturn_t lm8323_irq(int irq, void *data) -{ - struct lm8323_chip *lm = data; - - schedule_work(&lm->work); return IRQ_HANDLED; } @@ -675,7 +663,6 @@ static int __devinit lm8323_probe(struct i2c_client *client, lm->client = client; lm->idev = idev; mutex_init(&lm->lock); - INIT_WORK(&lm->work, lm8323_work); lm->size_x = pdata->size_x; lm->size_y = pdata->size_y; @@ -746,9 +733,8 @@ static int __devinit lm8323_probe(struct i2c_client *client, goto fail3; } - err = request_irq(client->irq, lm8323_irq, - IRQF_TRIGGER_FALLING | IRQF_DISABLED, - "lm8323", lm); + err = request_threaded_irq(client->irq, NULL, lm8323_irq, + IRQF_TRIGGER_FALLING, "lm8323", lm); if (err) { dev_err(&client->dev, "could not get IRQ %d\n", client->irq); goto fail4; @@ -783,7 +769,6 @@ static int __devexit lm8323_remove(struct i2c_client *client) disable_irq_wake(client->irq); free_irq(client->irq, lm); - cancel_work_sync(&lm->work); input_unregister_device(lm->idev); -- cgit v1.1 From eaa499aebf6265f18ffc836ead30059031c6d7a7 Mon Sep 17 00:00:00 2001 From: Leigh Brown Date: Tue, 21 Jun 2011 04:25:21 -0700 Subject: Input: lm8323 - use oneshot level triggered interrupts According to the data sheet the interrupt should be level rather than edge triggered. This fixes the issue of the Nokia N810 keypad stopping responding if multiple key events occur in quick succession. Signed-off-by: Leigh Brown Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/lm8323.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 3b21f42..ab0acaf 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -734,7 +734,7 @@ static int __devinit lm8323_probe(struct i2c_client *client, } err = request_threaded_irq(client->irq, NULL, lm8323_irq, - IRQF_TRIGGER_FALLING, "lm8323", lm); + IRQF_TRIGGER_LOW|IRQF_ONESHOT, "lm8323", lm); if (err) { dev_err(&client->dev, "could not get IRQ %d\n", client->irq); goto fail4; -- cgit v1.1 From 7e2ecdf438bb479e2b4667fc16b1a84d6348da04 Mon Sep 17 00:00:00 2001 From: David Jander Date: Tue, 21 Jun 2011 14:26:18 -0700 Subject: Input: gpio_keys - switch to using threaded IRQs Use a threaded interrupt handler in order to permit the handler to use a GPIO driver that causes things like I2C transactions being done inside the handler context. Signed-off-by: David Jander Acked-by: Grant Likely Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 6e6145b..6d0e2f6 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -415,7 +415,7 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev, if (!button->can_disable) irqflags |= IRQF_SHARED; - error = request_any_context_irq(irq, gpio_keys_isr, irqflags, desc, bdata); + error = request_threaded_irq(irq, NULL, gpio_keys_isr, irqflags, desc, bdata); if (error < 0) { dev_err(dev, "Unable to claim irq %d; error %d\n", irq, error); @@ -649,5 +649,5 @@ module_exit(gpio_keys_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Phil Blundell "); -MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs"); +MODULE_DESCRIPTION("Keyboard driver for GPIOs"); MODULE_ALIAS("platform:gpio-keys"); -- cgit v1.1 From fabadbc754cf461e8d68e5f8ff53f287dcee41b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20H=C3=B6rlin?= Date: Tue, 21 Jun 2011 14:40:30 -0700 Subject: Input: xpad - add support for two more dance pads and a guitar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Magnus Hörlin Reviewed-by: Christoph Fritz Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 56abf3d..e91838c 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -154,10 +154,13 @@ static const struct xpad_device { { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, + { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 }, { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, + { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, @@ -236,9 +239,10 @@ static struct usb_device_id xpad_table [] = { XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ + XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ - XPAD_XBOX360_VENDOR(0x1bad), /* Rock Band Drums */ + XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ { } }; -- cgit v1.1 From 71c86ce59791bcd67af937bbea719a508079d7c2 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Wed, 22 Jun 2011 01:02:51 -0700 Subject: Input: wacom - Cintiq 21UX2 does not have menu strips So don't set ABS_RX/ABS_RY for them. Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 08ba5ad..cc6c917 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1129,8 +1129,11 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(BTN_0 + i, input_dev->keybit); __set_bit(BTN_TOOL_FINGER, input_dev->keybit); - input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); - input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); + if (wacom_wac->features.type != WACOM_21UX2) { + input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); + input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); + } + input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); wacom_setup_cintiq(wacom_wac); break; -- cgit v1.1 From 1483f5513b2d215216ad56c618b42454c5bc1e4d Mon Sep 17 00:00:00 2001 From: Aristeu Rozanski Date: Wed, 22 Jun 2011 01:17:17 -0700 Subject: Input: wacom - use only one interface with DTU-2231 The Wacom DTU-2231 tablet has two interfaces on its default configuration and both have HID class, leading to the creation of two input devices instead of one. Only the first one is used, so filter out the second. Signed-off-by: Aristeu Rozanski Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index cc6c917..2ea0d2e 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -15,6 +15,7 @@ #include "wacom_wac.h" #include "wacom.h" #include +#include /* resolution for penabled devices */ #define WACOM_PL_RES 20 @@ -1486,6 +1487,11 @@ static const struct wacom_features wacom_features_0x6004 = USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ .driver_info = (kernel_ulong_t)&wacom_features_##prod +#define USB_DEVICE_DETAILED(prod, class, sub, proto) \ + USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_WACOM, prod, class, \ + sub, proto), \ + .driver_info = (kernel_ulong_t)&wacom_features_##prod + #define USB_DEVICE_LENOVO(prod) \ USB_DEVICE(USB_VENDOR_ID_LENOVO, prod), \ .driver_info = (kernel_ulong_t)&wacom_features_##prod @@ -1548,7 +1554,13 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xC5) }, { USB_DEVICE_WACOM(0xC6) }, { USB_DEVICE_WACOM(0xC7) }, - { USB_DEVICE_WACOM(0xCE) }, + /* + * DTU-2231 has two interfaces on the same configuration, + * only one is used. + */ + { USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID, + USB_INTERFACE_SUBCLASS_BOOT, + USB_INTERFACE_PROTOCOL_MOUSE) }, { USB_DEVICE_WACOM(0xD0) }, { USB_DEVICE_WACOM(0xD1) }, { USB_DEVICE_WACOM(0xD2) }, -- cgit v1.1 From 3ead8b5ddbe6ca8e79b24535f4119c9d4ffd91e3 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 22 Jun 2011 01:02:50 -0700 Subject: Input: add support for mma8450 accelerometer Signed-off-by: Sammy He Signed-off-by: Eric Miao Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 11 ++ drivers/input/misc/Makefile | 2 +- drivers/input/misc/mma8450.c | 256 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 drivers/input/misc/mma8450.c (limited to 'drivers') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 45dc6aa..0f22918 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -100,6 +100,17 @@ config INPUT_MAX8925_ONKEY To compile this driver as a module, choose M here: the module will be called max8925_onkey. +config INPUT_MMA8450 + tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer" + depends on I2C + select INPUT_POLLDEV + help + Say Y here if you want to support Freescale's MMA8450 Accelerometer + through I2C interface. + + To compile this driver as a module, choose M here: the + module will be called mma8450. + config INPUT_APANEL tristate "Fujitsu Lifebook Application Panel buttons" depends on X86 && I2C && LEDS_CLASS diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 38efb2c..99953c3 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o +obj-$(CONFIG_INPUT_MMA8450) += mma8450.o obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o @@ -45,4 +46,3 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o obj-$(CONFIG_INPUT_YEALINK) += yealink.o - diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c new file mode 100644 index 0000000..20f8f92 --- /dev/null +++ b/drivers/input/misc/mma8450.c @@ -0,0 +1,256 @@ +/* + * Driver for Freescale's 3-Axis Accelerometer MMA8450 + * + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#define MMA8450_DRV_NAME "mma8450" + +#define MODE_CHANGE_DELAY_MS 100 +#define POLL_INTERVAL 100 +#define POLL_INTERVAL_MAX 500 + +/* register definitions */ +#define MMA8450_STATUS 0x00 +#define MMA8450_STATUS_ZXYDR 0x08 + +#define MMA8450_OUT_X8 0x01 +#define MMA8450_OUT_Y8 0x02 +#define MMA8450_OUT_Z8 0x03 + +#define MMA8450_OUT_X_LSB 0x05 +#define MMA8450_OUT_X_MSB 0x06 +#define MMA8450_OUT_Y_LSB 0x07 +#define MMA8450_OUT_Y_MSB 0x08 +#define MMA8450_OUT_Z_LSB 0x09 +#define MMA8450_OUT_Z_MSB 0x0a + +#define MMA8450_XYZ_DATA_CFG 0x16 + +#define MMA8450_CTRL_REG1 0x38 +#define MMA8450_CTRL_REG2 0x39 + +/* mma8450 status */ +struct mma8450 { + struct i2c_client *client; + struct input_polled_dev *idev; +}; + +static int mma8450_read(struct mma8450 *m, unsigned off) +{ + struct i2c_client *c = m->client; + int ret; + + ret = i2c_smbus_read_byte_data(c, off); + if (ret < 0) + dev_err(&c->dev, + "failed to read register 0x%02x, error %d\n", + off, ret); + + return ret; +} + +static int mma8450_write(struct mma8450 *m, unsigned off, u8 v) +{ + struct i2c_client *c = m->client; + int error; + + error = i2c_smbus_write_byte_data(c, off, v); + if (error < 0) { + dev_err(&c->dev, + "failed to write to register 0x%02x, error %d\n", + off, error); + return error; + } + + return 0; +} + +static int mma8450_read_xyz(struct mma8450 *m, int *x, int *y, int *z) +{ + struct i2c_client *c = m->client; + u8 buff[6]; + int err; + + err = i2c_smbus_read_i2c_block_data(c, MMA8450_OUT_X_LSB, 6, buff); + if (err < 0) { + dev_err(&c->dev, + "failed to read block data at 0x%02x, error %d\n", + MMA8450_OUT_X_LSB, err); + return err; + } + + *x = ((buff[1] << 4) & 0xff0) | (buff[0] & 0xf); + *y = ((buff[3] << 4) & 0xff0) | (buff[2] & 0xf); + *z = ((buff[5] << 4) & 0xff0) | (buff[4] & 0xf); + + return 0; +} + +static void mma8450_poll(struct input_polled_dev *dev) +{ + struct mma8450 *m = dev->private; + int x, y, z; + int ret; + int err; + + ret = mma8450_read(m, MMA8450_STATUS); + if (ret < 0) + return; + + if (!(ret & MMA8450_STATUS_ZXYDR)) + return; + + err = mma8450_read_xyz(m, &x, &y, &z); + if (err) + return; + + input_report_abs(dev->input, ABS_X, x); + input_report_abs(dev->input, ABS_Y, y); + input_report_abs(dev->input, ABS_Z, z); + input_sync(dev->input); +} + +/* Initialize the MMA8450 chip */ +static void mma8450_open(struct input_polled_dev *dev) +{ + struct mma8450 *m = dev->private; + int err; + + /* enable all events from X/Y/Z, no FIFO */ + err = mma8450_write(m, MMA8450_XYZ_DATA_CFG, 0x07); + if (err) + return; + + /* + * Sleep mode poll rate - 50Hz + * System output data rate - 400Hz + * Full scale selection - Active, +/- 2G + */ + err = mma8450_write(m, MMA8450_CTRL_REG1, 0x01); + if (err < 0) + return; + + msleep(MODE_CHANGE_DELAY_MS); +} + +static void mma8450_close(struct input_polled_dev *dev) +{ + struct mma8450 *m = dev->private; + + mma8450_write(m, MMA8450_CTRL_REG1, 0x00); + mma8450_write(m, MMA8450_CTRL_REG2, 0x01); +} + +/* + * I2C init/probing/exit functions + */ +static int __devinit mma8450_probe(struct i2c_client *c, + const struct i2c_device_id *id) +{ + struct input_polled_dev *idev; + struct mma8450 *m; + int err; + + m = kzalloc(sizeof(struct mma8450), GFP_KERNEL); + idev = input_allocate_polled_device(); + if (!m || !idev) { + err = -ENOMEM; + goto err_free_mem; + } + + m->client = c; + m->idev = idev; + + idev->private = m; + idev->input->name = MMA8450_DRV_NAME; + idev->input->id.bustype = BUS_I2C; + idev->poll = mma8450_poll; + idev->poll_interval = POLL_INTERVAL; + idev->poll_interval_max = POLL_INTERVAL_MAX; + idev->open = mma8450_open; + idev->close = mma8450_close; + + __set_bit(EV_ABS, idev->input->evbit); + input_set_abs_params(idev->input, ABS_X, -2048, 2047, 32, 32); + input_set_abs_params(idev->input, ABS_Y, -2048, 2047, 32, 32); + input_set_abs_params(idev->input, ABS_Z, -2048, 2047, 32, 32); + + err = input_register_polled_device(idev); + if (err) { + dev_err(&c->dev, "failed to register polled input device\n"); + goto err_free_mem; + } + + return 0; + +err_free_mem: + input_free_polled_device(idev); + kfree(m); + return err; +} + +static int __devexit mma8450_remove(struct i2c_client *c) +{ + struct mma8450 *m = i2c_get_clientdata(c); + struct input_polled_dev *idev = m->idev; + + input_unregister_polled_device(idev); + input_free_polled_device(idev); + kfree(m); + + return 0; +} + +static const struct i2c_device_id mma8450_id[] = { + { MMA8450_DRV_NAME, 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, mma8450_id); + +static struct i2c_driver mma8450_driver = { + .driver = { + .name = MMA8450_DRV_NAME, + .owner = THIS_MODULE, + }, + .probe = mma8450_probe, + .remove = __devexit_p(mma8450_remove), + .id_table = mma8450_id, +}; + +static int __init mma8450_init(void) +{ + return i2c_add_driver(&mma8450_driver); +} +module_init(mma8450_init); + +static void __exit mma8450_exit(void) +{ + i2c_del_driver(&mma8450_driver); +} +module_exit(mma8450_exit); + +MODULE_AUTHOR("Freescale Semiconductor, Inc."); +MODULE_DESCRIPTION("MMA8450 3-Axis Accelerometer Driver"); +MODULE_LICENSE("GPL"); -- cgit v1.1 From 5993548725ba3f3deb2b90a681a62dbb7bd17961 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 27 Jun 2011 11:59:43 -0700 Subject: Input: remove unneeded version.h includes It was pointed out by 'make versioncheck' that some includes of linux/version.h are not needed in drivers/input/. This patch removes them. Signed-off-by: Jesper Juhl Acked-by: Mike Frysinger Acked-by: Michael Hennerich Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/adp5588-keys.c | 1 - drivers/input/keyboard/adp5589-keys.c | 1 - drivers/input/misc/bfin_rotary.c | 1 - drivers/input/mouse/pxa930_trkball.c | 1 - drivers/input/mouse/sentelic.c | 1 - 5 files changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index af45d27..7b404e5 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -9,7 +9,6 @@ */ #include -#include #include #include #include diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 6315986..c770826 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -8,7 +8,6 @@ */ #include -#include #include #include #include diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c index 4f72bdd..d00edc9 100644 --- a/drivers/input/misc/bfin_rotary.c +++ b/drivers/input/misc/bfin_rotary.c @@ -6,7 +6,6 @@ */ #include -#include #include #include #include diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index 943cfec..6c5d84f 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 1242775..2fc887a 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -20,7 +20,6 @@ */ #include -#include #include #include #include -- cgit v1.1 From 51a3db41e18254b938279cb4b160310e11a13d4f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 27 Jun 2011 12:38:43 -0700 Subject: Input: tnetv107x-keypad - fix MODULE_ALIAS Remove the space between "platform:" prefix and the driver name. Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tnetv107x-keypad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index c8f097a..1c58681 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -337,5 +337,5 @@ module_exit(keypad_exit); MODULE_AUTHOR("Cyril Chemparathy"); MODULE_DESCRIPTION("TNETV107X Keypad Driver"); -MODULE_ALIAS("platform: tnetv107x-keypad"); +MODULE_ALIAS("platform:tnetv107x-keypad"); MODULE_LICENSE("GPL"); -- cgit v1.1 From 6a592a7f4514cd744e154a146db1ab7af06a7ee7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 27 Jun 2011 12:42:12 -0700 Subject: Input: tnetv107x-ts - fix MODULE_ALIAS Remove the space between "platform:" prefix and the driver name. Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tnetv107x-ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c index 22a3411..089b0a0 100644 --- a/drivers/input/touchscreen/tnetv107x-ts.c +++ b/drivers/input/touchscreen/tnetv107x-ts.c @@ -393,5 +393,5 @@ module_exit(tsc_exit); MODULE_AUTHOR("Cyril Chemparathy"); MODULE_DESCRIPTION("TNETV107X Touchscreen Driver"); -MODULE_ALIAS("platform: tnetv107x-ts"); +MODULE_ALIAS("platform:tnetv107x-ts"); MODULE_LICENSE("GPL"); -- cgit v1.1 From b23302052d96a3945e4c72aca77b5fd28884c353 Mon Sep 17 00:00:00 2001 From: David Jander Date: Thu, 23 Jun 2011 01:30:09 -0700 Subject: Input: gpio_keys - move to late_initcall Initialize gpio_keys driver at late_initcall level, to give it a chance to work with GPIO expanders that might not be ready yet if we initialize the driver at module_init time. This is strictly a band-aid until there is a better way to specify inter-device dependencies. Signed-off-by: David Jander Acked-by: Grant Likely Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 6d0e2f6..320b59a 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -644,7 +644,7 @@ static void __exit gpio_keys_exit(void) platform_driver_unregister(&gpio_keys_device_driver); } -module_init(gpio_keys_init); +late_initcall(gpio_keys_init); module_exit(gpio_keys_exit); MODULE_LICENSE("GPL"); -- cgit v1.1 From a001a8f3cedb0e3cb92ff3abdb3170df7da92d47 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Mon, 27 Jun 2011 12:57:58 -0700 Subject: Input: wacom - Wacom Bamboo Pen D4 has 1024 pressure levels D4 has 1024, not 512, pressure levels. Reported-by: David Foley Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 2ea0d2e..1cbb9a8 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1462,7 +1462,7 @@ static const struct wacom_features wacom_features_0xD3 = { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xD4 = - { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 255, + { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xD6 = { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, -- cgit v1.1 From 11d0cf8859451d6336959204b2d4cc173dd1aa4e Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Mon, 27 Jun 2011 12:57:58 -0700 Subject: Input: wacom - add 3 new models - 6A, 6B, and 97 Tested-by: Alex Tervoort for 6A Signed-off-by: David Foley Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 1cbb9a8..0c302c9 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1299,6 +1299,12 @@ static const struct wacom_features wacom_features_0x65 = static const struct wacom_features wacom_features_0x69 = { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; +static const struct wacom_features wacom_features_0x6A = + { "Wacom Bamboo1 4x6", WACOM_PKGLEN_GRAPHIRE, 14760, 9225, 1023, + 63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x6B = + { "Wacom Bamboo1 5x8", WACOM_PKGLEN_GRAPHIRE, 21648, 13530, 1023, + 63, GRAPHIRE, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x20 = { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -1431,6 +1437,9 @@ static const struct wacom_features wacom_features_0x90 = static const struct wacom_features wacom_features_0x93 = { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x97 = + { "Wacom ISDv4 97", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 511, + 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x9A = { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -1515,6 +1524,8 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x64) }, { USB_DEVICE_WACOM(0x65) }, { USB_DEVICE_WACOM(0x69) }, + { USB_DEVICE_WACOM(0x6A) }, + { USB_DEVICE_WACOM(0x6B) }, { USB_DEVICE_WACOM(0x20) }, { USB_DEVICE_WACOM(0x21) }, { USB_DEVICE_WACOM(0x22) }, @@ -1575,6 +1586,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xCC) }, { USB_DEVICE_WACOM(0x90) }, { USB_DEVICE_WACOM(0x93) }, + { USB_DEVICE_WACOM(0x97) }, { USB_DEVICE_WACOM(0x9A) }, { USB_DEVICE_WACOM(0x9F) }, { USB_DEVICE_WACOM(0xE2) }, -- cgit v1.1 From 58c244009ef6ca450f0d787828a7f2f27651db5b Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Mon, 27 Jun 2011 13:06:27 -0700 Subject: Input: ads7846 - cleanup GPIO initialization Use gpio_request_one() instead of multiple gpiolib calls. This also simplifies error handling a bit. Signed-off-by: Igor Grinberg Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 5196861..d507b9b 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -967,17 +967,12 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784 ts->get_pendown_state = pdata->get_pendown_state; } else if (gpio_is_valid(pdata->gpio_pendown)) { - err = gpio_request(pdata->gpio_pendown, "ads7846_pendown"); + err = gpio_request_one(pdata->gpio_pendown, GPIOF_IN, + "ads7846_pendown"); if (err) { - dev_err(&spi->dev, "failed to request pendown GPIO%d\n", - pdata->gpio_pendown); - return err; - } - err = gpio_direction_input(pdata->gpio_pendown); - if (err) { - dev_err(&spi->dev, "failed to setup pendown GPIO%d\n", - pdata->gpio_pendown); - gpio_free(pdata->gpio_pendown); + dev_err(&spi->dev, + "failed to request/setup pendown GPIO%d: %d\n", + pdata->gpio_pendown, err); return err; } -- cgit v1.1 From 1638207910019368253fc4c4a930c49ce2e98432 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 28 Jun 2011 14:23:30 -0700 Subject: Input: gpio_keys - fix a memory leak Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 320b59a..97bada4 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -569,6 +569,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) } input_unregister_device(input); + kfree(ddata); return 0; } -- cgit v1.1 From 7c40952295db64867a45938b860a217b622cc3ed Mon Sep 17 00:00:00 2001 From: Hans-Christian Egtvedt Date: Wed, 29 Jun 2011 00:13:26 -0700 Subject: Input: update author email for gpio_mouse, at32psif, and atmel-wm97xx This patch updates the email address of the gpio_mouse, at32psif, and atmel-wm97xx drivers supported by me to an email account I will use on a more regular basis in the future. Signed-off-by: Hans-Christian Egtvedt Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/gpio_mouse.c | 2 +- drivers/input/serio/at32psif.c | 2 +- drivers/input/touchscreen/atmel-wm97xx.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 7b6ce17..58902fb 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -191,7 +191,7 @@ static void __exit gpio_mouse_exit(void) } module_exit(gpio_mouse_exit); -MODULE_AUTHOR("Hans-Christian Egtvedt "); +MODULE_AUTHOR("Hans-Christian Egtvedt "); MODULE_DESCRIPTION("GPIO mouse driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */ diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index 6ee8f0d..95280f9 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c @@ -372,6 +372,6 @@ static void __exit psif_exit(void) module_init(psif_init); module_exit(psif_exit); -MODULE_AUTHOR("Hans-Christian Egtvedt "); +MODULE_AUTHOR("Hans-Christian Egtvedt "); MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c index fa8e56b..c804189 100644 --- a/drivers/input/touchscreen/atmel-wm97xx.c +++ b/drivers/input/touchscreen/atmel-wm97xx.c @@ -442,6 +442,6 @@ static void __exit atmel_wm97xx_exit(void) } module_exit(atmel_wm97xx_exit); -MODULE_AUTHOR("Hans-Christian Egtvedt "); +MODULE_AUTHOR("Hans-Christian Egtvedt "); MODULE_DESCRIPTION("wm97xx continuous touch driver for Atmel AT91 and AVR32"); MODULE_LICENSE("GPL"); -- cgit v1.1 From 631b16e81eab82e2894425a94c3fc14bf21adb26 Mon Sep 17 00:00:00 2001 From: Joseph Lai Date: Mon, 27 Jun 2011 13:26:53 -0700 Subject: Input: add a driver to support InvenSense mpu3050 gyroscope chip This driver is registered as an input device. An IRQ is required in this basic driver configuration. Signed-off-by: Joseph Lai [Cleaned up PM_RUNTIME defines] Signed-off-by: Alan Cox [dtor@mail.ru: consolidated PM methods, some code rearrangement] Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 10 ++ drivers/input/misc/Makefile | 1 + drivers/input/misc/mpu3050.c | 376 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 387 insertions(+) create mode 100644 drivers/input/misc/mpu3050.c (limited to 'drivers') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 0f22918..6fdce4b 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -111,6 +111,16 @@ config INPUT_MMA8450 To compile this driver as a module, choose M here: the module will be called mma8450. +config INPUT_MPU3050 + tristate "MPU3050 Triaxial gyroscope sensor" + depends on I2C + help + Say Y here if you want to support InvenSense MPU3050 + connected via an I2C bus. + + To compile this driver as a module, choose M here: the + module will be called mpu3050. + config INPUT_APANEL tristate "Fujitsu Lifebook Application Panel buttons" depends on X86 && I2C && LEDS_CLASS diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 99953c3..b7e227a 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o obj-$(CONFIG_INPUT_MMA8450) += mma8450.o +obj-$(CONFIG_INPUT_MPU3050) += mpu3050.o obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c new file mode 100644 index 0000000..b95fac1 --- /dev/null +++ b/drivers/input/misc/mpu3050.c @@ -0,0 +1,376 @@ +/* + * MPU3050 Tri-axis gyroscope driver + * + * Copyright (C) 2011 Wistron Co.Ltd + * Joseph Lai + * + * Trimmed down by Alan Cox to produce this version + * + * This is a 'lite' version of the driver, while we consider the right way + * to present the other features to user space. In particular it requires the + * device has an IRQ, and it only provides an input interface, so is not much + * use for device orientation. A fuller version is available from the Meego + * tree. + * + * This program is based on bma023.c. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MPU3050_CHIP_ID_REG 0x00 +#define MPU3050_CHIP_ID 0x69 +#define MPU3050_XOUT_H 0x1D +#define MPU3050_PWR_MGM 0x3E +#define MPU3050_PWR_MGM_POS 6 +#define MPU3050_PWR_MGM_MASK 0x40 + +#define MPU3050_AUTO_DELAY 1000 + +#define MPU3050_MIN_VALUE -32768 +#define MPU3050_MAX_VALUE 32767 + +struct axis_data { + s16 x; + s16 y; + s16 z; +}; + +struct mpu3050_sensor { + struct i2c_client *client; + struct device *dev; + struct input_dev *idev; +}; + +/** + * mpu3050_xyz_read_reg - read the axes values + * @buffer: provide register addr and get register + * @length: length of register + * + * Reads the register values in one transaction or returns a negative + * error code on failure. + */ +static int mpu3050_xyz_read_reg(struct i2c_client *client, + u8 *buffer, int length) +{ + /* + * Annoying we can't make this const because the i2c layer doesn't + * declare input buffers const. + */ + char cmd = MPU3050_XOUT_H; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &cmd, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = length, + .buf = buffer, + }, + }; + + return i2c_transfer(client->adapter, msg, 2); +} + +/** + * mpu3050_read_xyz - get co-ordinates from device + * @client: i2c address of sensor + * @coords: co-ordinates to update + * + * Return the converted X Y and Z co-ordinates from the sensor device + */ +static void mpu3050_read_xyz(struct i2c_client *client, + struct axis_data *coords) +{ + u16 buffer[3]; + + mpu3050_xyz_read_reg(client, (u8 *)buffer, 6); + coords->x = be16_to_cpu(buffer[0]); + coords->y = be16_to_cpu(buffer[1]); + coords->z = be16_to_cpu(buffer[2]); + dev_dbg(&client->dev, "%s: x %d, y %d, z %d\n", __func__, + coords->x, coords->y, coords->z); +} + +/** + * mpu3050_set_power_mode - set the power mode + * @client: i2c client for the sensor + * @val: value to switch on/off of power, 1: normal power, 0: low power + * + * Put device to normal-power mode or low-power mode. + */ +static void mpu3050_set_power_mode(struct i2c_client *client, u8 val) +{ + u8 value; + + value = i2c_smbus_read_byte_data(client, MPU3050_PWR_MGM); + value = (value & ~MPU3050_PWR_MGM_MASK) | + (((val << MPU3050_PWR_MGM_POS) & MPU3050_PWR_MGM_MASK) ^ + MPU3050_PWR_MGM_MASK); + i2c_smbus_write_byte_data(client, MPU3050_PWR_MGM, value); +} + +/** + * mpu3050_input_open - called on input event open + * @input: input dev of opened device + * + * The input layer calls this function when input event is opened. The + * function will push the device to resume. Then, the device is ready + * to provide data. + */ +static int mpu3050_input_open(struct input_dev *input) +{ + struct mpu3050_sensor *sensor = input_get_drvdata(input); + + pm_runtime_get(sensor->dev); + + return 0; +} + +/** + * mpu3050_input_close - called on input event close + * @input: input dev of closed device + * + * The input layer calls this function when input event is closed. The + * function will push the device to suspend. + */ +static void mpu3050_input_close(struct input_dev *input) +{ + struct mpu3050_sensor *sensor = input_get_drvdata(input); + + pm_runtime_put(sensor->dev); +} + +/** + * mpu3050_interrupt_thread - handle an IRQ + * @irq: interrupt numner + * @data: the sensor + * + * Called by the kernel single threaded after an interrupt occurs. Read + * the sensor data and generate an input event for it. + */ +static irqreturn_t mpu3050_interrupt_thread(int irq, void *data) +{ + struct mpu3050_sensor *sensor = data; + struct axis_data axis; + + mpu3050_read_xyz(sensor->client, &axis); + + input_report_abs(sensor->idev, ABS_X, axis.x); + input_report_abs(sensor->idev, ABS_Y, axis.y); + input_report_abs(sensor->idev, ABS_Z, axis.z); + input_sync(sensor->idev); + + return IRQ_HANDLED; +} + +/** + * mpu3050_probe - device detection callback + * @client: i2c client of found device + * @id: id match information + * + * The I2C layer calls us when it believes a sensor is present at this + * address. Probe to see if this is correct and to validate the device. + * + * If present install the relevant sysfs interfaces and input device. + */ +static int __devinit mpu3050_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct mpu3050_sensor *sensor; + struct input_dev *idev; + int ret; + int error; + + sensor = kzalloc(sizeof(struct mpu3050_sensor), GFP_KERNEL); + idev = input_allocate_device(); + if (!sensor || !idev) { + dev_err(&client->dev, "failed to allocate driver data\n"); + error = -ENOMEM; + goto err_free_mem; + } + + sensor->client = client; + sensor->dev = &client->dev; + sensor->idev = idev; + + mpu3050_set_power_mode(client, 1); + msleep(10); + + ret = i2c_smbus_read_byte_data(client, MPU3050_CHIP_ID_REG); + if (ret < 0) { + dev_err(&client->dev, "failed to detect device\n"); + error = -ENXIO; + goto err_free_mem; + } + + if (ret != MPU3050_CHIP_ID) { + dev_err(&client->dev, "unsupported chip id\n"); + error = -ENXIO; + goto err_free_mem; + } + + idev->name = "MPU3050"; + idev->id.bustype = BUS_I2C; + idev->dev.parent = &client->dev; + + idev->open = mpu3050_input_open; + idev->close = mpu3050_input_close; + + __set_bit(EV_ABS, idev->evbit); + input_set_abs_params(idev, ABS_X, + MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0); + input_set_abs_params(idev, ABS_Y, + MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0); + input_set_abs_params(idev, ABS_Z, + MPU3050_MIN_VALUE, MPU3050_MAX_VALUE, 0, 0); + + input_set_drvdata(idev, sensor); + + pm_runtime_set_active(&client->dev); + + error = request_threaded_irq(client->irq, + NULL, mpu3050_interrupt_thread, + IRQF_TRIGGER_RISING, + "mpu_int", sensor); + if (error) { + dev_err(&client->dev, + "can't get IRQ %d, error %d\n", client->irq, error); + goto err_pm_set_suspended; + } + + error = input_register_device(idev); + if (error) { + dev_err(&client->dev, "failed to register input device\n"); + goto err_free_irq; + } + + pm_runtime_enable(&client->dev); + pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY); + + return 0; + +err_free_irq: + free_irq(client->irq, sensor); +err_pm_set_suspended: + pm_runtime_set_suspended(&client->dev); +err_free_mem: + input_unregister_device(idev); + kfree(sensor); + return error; +} + +/** + * mpu3050_remove - remove a sensor + * @client: i2c client of sensor being removed + * + * Our sensor is going away, clean up the resources. + */ +static int __devexit mpu3050_remove(struct i2c_client *client) +{ + struct mpu3050_sensor *sensor = i2c_get_clientdata(client); + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + + free_irq(client->irq, sensor); + input_unregister_device(sensor->idev); + kfree(sensor); + + return 0; +} + +#ifdef CONFIG_PM +/** + * mpu3050_suspend - called on device suspend + * @dev: device being suspended + * + * Put the device into sleep mode before we suspend the machine. + */ +static int mpu3050_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + mpu3050_set_power_mode(client, 0); + + return 0; +} + +/** + * mpu3050_resume - called on device resume + * @dev: device being resumed + * + * Put the device into powered mode on resume. + */ +static int mpu3050_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + mpu3050_set_power_mode(client, 1); + msleep(100); /* wait for gyro chip resume */ + + return 0; +} +#endif + +static UNIVERSAL_DEV_PM_OPS(mpu3050_pm, mpu3050_suspend, mpu3050_resume, NULL); + +static const struct i2c_device_id mpu3050_ids[] = { + { "mpu3050", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mpu3050_ids); + +static struct i2c_driver mpu3050_i2c_driver = { + .driver = { + .name = "mpu3050", + .owner = THIS_MODULE, + .pm = &mpu3050_pm, + }, + .probe = mpu3050_probe, + .remove = __devexit_p(mpu3050_remove), + .id_table = mpu3050_ids, +}; + +static int __init mpu3050_init(void) +{ + return i2c_add_driver(&mpu3050_i2c_driver); +} +module_init(mpu3050_init); + +static void __exit mpu3050_exit(void) +{ + i2c_del_driver(&mpu3050_i2c_driver); +} +module_exit(mpu3050_exit); + +MODULE_AUTHOR("Wistron Corp."); +MODULE_DESCRIPTION("MPU3050 Tri-axis gyroscope driver"); +MODULE_LICENSE("GPL"); -- cgit v1.1 From c7b4a5d58bffdf3aa7f923319643af0ebf925515 Mon Sep 17 00:00:00 2001 From: Jiejing Zhang Date: Wed, 29 Jun 2011 01:28:21 -0700 Subject: Input: mpr121 - improve sensibility of touch key The Quick Charge bit in Electrode conf register should be set in init function. This bit was missed in chip's document, which may cause touch controller charge too slow to generate an interrupt. Also, adjust the default vlaue of touch and release threshold to make touch key more sensitive, this fix touch may not sensitive after setup with plastic case. Signed-off-by: Jiejing Zhang Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/mpr121_touchkey.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index 0a9e811..1c1615d 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -43,14 +43,15 @@ * enabled capacitance sensing inputs and its run/suspend mode. */ #define ELECTRODE_CONF_ADDR 0x5e +#define ELECTRODE_CONF_QUICK_CHARGE 0x80 #define AUTO_CONFIG_CTRL_ADDR 0x7b #define AUTO_CONFIG_USL_ADDR 0x7d #define AUTO_CONFIG_LSL_ADDR 0x7e #define AUTO_CONFIG_TL_ADDR 0x7f /* Threshold of touch/release trigger */ -#define TOUCH_THRESHOLD 0x0f -#define RELEASE_THRESHOLD 0x0a +#define TOUCH_THRESHOLD 0x08 +#define RELEASE_THRESHOLD 0x05 /* Masks for touch and release triggers */ #define TOUCH_STATUS_MASK 0xfff /* MPR121 has 12 keys */ @@ -127,7 +128,7 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata, struct i2c_client *client) { const struct mpr121_init_register *reg; - unsigned char usl, lsl, tl; + unsigned char usl, lsl, tl, eleconf; int i, t, vdd, ret; /* Set up touch/release threshold for ele0-ele11 */ @@ -163,8 +164,15 @@ static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata, ret = i2c_smbus_write_byte_data(client, AUTO_CONFIG_USL_ADDR, usl); ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_LSL_ADDR, lsl); ret |= i2c_smbus_write_byte_data(client, AUTO_CONFIG_TL_ADDR, tl); + + /* + * Quick charge bit will let the capacitive charge to ready + * state quickly, or the buttons may not function after system + * boot. + */ + eleconf = mpr121->keycount | ELECTRODE_CONF_QUICK_CHARGE; ret |= i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR, - mpr121->keycount); + eleconf); if (ret != 0) goto err_i2c_write; -- cgit v1.1 From 81c88a711aef5552375c4296bb473fdf9b12273c Mon Sep 17 00:00:00 2001 From: Iiro Valkonen Date: Mon, 4 Jul 2011 03:08:25 -0700 Subject: Input: atmel_mxt_ts - update object list Update the object list to include new objects, and add unique identifiers so we can distinguish between old & new generation of the same object. Signed-off-by: Iiro Valkonen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 184 +++++++++++++++++-------------- 1 file changed, 102 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 1e61387..5d71e44 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -48,41 +48,47 @@ #define MXT_OBJECT_SIZE 6 /* Object types */ -#define MXT_DEBUG_DIAGNOSTIC 37 -#define MXT_GEN_MESSAGE 5 -#define MXT_GEN_COMMAND 6 -#define MXT_GEN_POWER 7 -#define MXT_GEN_ACQUIRE 8 -#define MXT_TOUCH_MULTI 9 -#define MXT_TOUCH_KEYARRAY 15 -#define MXT_TOUCH_PROXIMITY 23 -#define MXT_PROCI_GRIPFACE 20 -#define MXT_PROCG_NOISE 22 -#define MXT_PROCI_ONETOUCH 24 -#define MXT_PROCI_TWOTOUCH 27 -#define MXT_PROCI_GRIP 40 -#define MXT_PROCI_PALM 41 -#define MXT_SPT_COMMSCONFIG 18 -#define MXT_SPT_GPIOPWM 19 -#define MXT_SPT_SELFTEST 25 -#define MXT_SPT_CTECONFIG 28 -#define MXT_SPT_USERDATA 38 -#define MXT_SPT_DIGITIZER 43 -#define MXT_SPT_MESSAGECOUNT 44 - -/* MXT_GEN_COMMAND field */ +#define MXT_DEBUG_DIAGNOSTIC_T37 37 +#define MXT_GEN_MESSAGE_T5 5 +#define MXT_GEN_COMMAND_T6 6 +#define MXT_GEN_POWER_T7 7 +#define MXT_GEN_ACQUIRE_T8 8 +#define MXT_GEN_DATASOURCE_T53 53 +#define MXT_TOUCH_MULTI_T9 9 +#define MXT_TOUCH_KEYARRAY_T15 15 +#define MXT_TOUCH_PROXIMITY_T23 23 +#define MXT_TOUCH_PROXKEY_T52 52 +#define MXT_PROCI_GRIPFACE_T20 20 +#define MXT_PROCG_NOISE_T22 22 +#define MXT_PROCI_ONETOUCH_T24 24 +#define MXT_PROCI_TWOTOUCH_T27 27 +#define MXT_PROCI_GRIP_T40 40 +#define MXT_PROCI_PALM_T41 41 +#define MXT_PROCI_TOUCHSUPPRESSION_T42 42 +#define MXT_PROCI_STYLUS_T47 47 +#define MXT_PROCG_NOISESUPPRESSION_T48 48 +#define MXT_SPT_COMMSCONFIG_T18 18 +#define MXT_SPT_GPIOPWM_T19 19 +#define MXT_SPT_SELFTEST_T25 25 +#define MXT_SPT_CTECONFIG_T28 28 +#define MXT_SPT_USERDATA_T38 38 +#define MXT_SPT_DIGITIZER_T43 43 +#define MXT_SPT_MESSAGECOUNT_T44 44 +#define MXT_SPT_CTECONFIG_T46 46 + +/* MXT_GEN_COMMAND_T6 field */ #define MXT_COMMAND_RESET 0 #define MXT_COMMAND_BACKUPNV 1 #define MXT_COMMAND_CALIBRATE 2 #define MXT_COMMAND_REPORTALL 3 #define MXT_COMMAND_DIAGNOSTIC 5 -/* MXT_GEN_POWER field */ +/* MXT_GEN_POWER_T7 field */ #define MXT_POWER_IDLEACQINT 0 #define MXT_POWER_ACTVACQINT 1 #define MXT_POWER_ACTV2IDLETO 2 -/* MXT_GEN_ACQUIRE field */ +/* MXT_GEN_ACQUIRE_T8 field */ #define MXT_ACQUIRE_CHRGTIME 0 #define MXT_ACQUIRE_TCHDRIFT 2 #define MXT_ACQUIRE_DRIFTST 3 @@ -91,7 +97,7 @@ #define MXT_ACQUIRE_ATCHCALST 6 #define MXT_ACQUIRE_ATCHCALSTHR 7 -/* MXT_TOUCH_MULTI field */ +/* MXT_TOUCH_MULTI_T9 field */ #define MXT_TOUCH_CTRL 0 #define MXT_TOUCH_XORIGIN 1 #define MXT_TOUCH_YORIGIN 2 @@ -121,7 +127,7 @@ #define MXT_TOUCH_YEDGEDIST 29 #define MXT_TOUCH_JUMPLIMIT 30 -/* MXT_PROCI_GRIPFACE field */ +/* MXT_PROCI_GRIPFACE_T20 field */ #define MXT_GRIPFACE_CTRL 0 #define MXT_GRIPFACE_XLOGRIP 1 #define MXT_GRIPFACE_XHIGRIP 2 @@ -151,11 +157,11 @@ #define MXT_NOISE_FREQ4 15 #define MXT_NOISE_IDLEGCAFVALID 16 -/* MXT_SPT_COMMSCONFIG */ +/* MXT_SPT_COMMSCONFIG_T18 */ #define MXT_COMMS_CTRL 0 #define MXT_COMMS_CMD 1 -/* MXT_SPT_CTECONFIG field */ +/* MXT_SPT_CTECONFIG_T28 field */ #define MXT_CTE_CTRL 0 #define MXT_CTE_CMD 1 #define MXT_CTE_MODE 2 @@ -166,7 +172,7 @@ #define MXT_VOLTAGE_DEFAULT 2700000 #define MXT_VOLTAGE_STEP 10000 -/* Define for MXT_GEN_COMMAND */ +/* Define for MXT_GEN_COMMAND_T6 */ #define MXT_BOOT_VALUE 0xa5 #define MXT_BACKUP_VALUE 0x55 #define MXT_BACKUP_TIME 25 /* msec */ @@ -256,24 +262,31 @@ struct mxt_data { static bool mxt_object_readable(unsigned int type) { switch (type) { - case MXT_GEN_MESSAGE: - case MXT_GEN_COMMAND: - case MXT_GEN_POWER: - case MXT_GEN_ACQUIRE: - case MXT_TOUCH_MULTI: - case MXT_TOUCH_KEYARRAY: - case MXT_TOUCH_PROXIMITY: - case MXT_PROCI_GRIPFACE: - case MXT_PROCG_NOISE: - case MXT_PROCI_ONETOUCH: - case MXT_PROCI_TWOTOUCH: - case MXT_PROCI_GRIP: - case MXT_PROCI_PALM: - case MXT_SPT_COMMSCONFIG: - case MXT_SPT_GPIOPWM: - case MXT_SPT_SELFTEST: - case MXT_SPT_CTECONFIG: - case MXT_SPT_USERDATA: + case MXT_GEN_MESSAGE_T5: + case MXT_GEN_COMMAND_T6: + case MXT_GEN_POWER_T7: + case MXT_GEN_ACQUIRE_T8: + case MXT_GEN_DATASOURCE_T53: + case MXT_TOUCH_MULTI_T9: + case MXT_TOUCH_KEYARRAY_T15: + case MXT_TOUCH_PROXIMITY_T23: + case MXT_TOUCH_PROXKEY_T52: + case MXT_PROCI_GRIPFACE_T20: + case MXT_PROCG_NOISE_T22: + case MXT_PROCI_ONETOUCH_T24: + case MXT_PROCI_TWOTOUCH_T27: + case MXT_PROCI_GRIP_T40: + case MXT_PROCI_PALM_T41: + case MXT_PROCI_TOUCHSUPPRESSION_T42: + case MXT_PROCI_STYLUS_T47: + case MXT_PROCG_NOISESUPPRESSION_T48: + case MXT_SPT_COMMSCONFIG_T18: + case MXT_SPT_GPIOPWM_T19: + case MXT_SPT_SELFTEST_T25: + case MXT_SPT_CTECONFIG_T28: + case MXT_SPT_USERDATA_T38: + case MXT_SPT_DIGITIZER_T43: + case MXT_SPT_CTECONFIG_T46: return true; default: return false; @@ -283,21 +296,28 @@ static bool mxt_object_readable(unsigned int type) static bool mxt_object_writable(unsigned int type) { switch (type) { - case MXT_GEN_COMMAND: - case MXT_GEN_POWER: - case MXT_GEN_ACQUIRE: - case MXT_TOUCH_MULTI: - case MXT_TOUCH_KEYARRAY: - case MXT_TOUCH_PROXIMITY: - case MXT_PROCI_GRIPFACE: - case MXT_PROCG_NOISE: - case MXT_PROCI_ONETOUCH: - case MXT_PROCI_TWOTOUCH: - case MXT_PROCI_GRIP: - case MXT_PROCI_PALM: - case MXT_SPT_GPIOPWM: - case MXT_SPT_SELFTEST: - case MXT_SPT_CTECONFIG: + case MXT_GEN_COMMAND_T6: + case MXT_GEN_POWER_T7: + case MXT_GEN_ACQUIRE_T8: + case MXT_TOUCH_MULTI_T9: + case MXT_TOUCH_KEYARRAY_T15: + case MXT_TOUCH_PROXIMITY_T23: + case MXT_TOUCH_PROXKEY_T52: + case MXT_PROCI_GRIPFACE_T20: + case MXT_PROCG_NOISE_T22: + case MXT_PROCI_ONETOUCH_T24: + case MXT_PROCI_TWOTOUCH_T27: + case MXT_PROCI_GRIP_T40: + case MXT_PROCI_PALM_T41: + case MXT_PROCI_TOUCHSUPPRESSION_T42: + case MXT_PROCI_STYLUS_T47: + case MXT_PROCG_NOISESUPPRESSION_T48: + case MXT_SPT_COMMSCONFIG_T18: + case MXT_SPT_GPIOPWM_T19: + case MXT_SPT_SELFTEST_T25: + case MXT_SPT_CTECONFIG_T28: + case MXT_SPT_DIGITIZER_T43: + case MXT_SPT_CTECONFIG_T46: return true; default: return false; @@ -455,7 +475,7 @@ static int mxt_read_message(struct mxt_data *data, struct mxt_object *object; u16 reg; - object = mxt_get_object(data, MXT_GEN_MESSAGE); + object = mxt_get_object(data, MXT_GEN_MESSAGE_T5); if (!object) return -EINVAL; @@ -597,8 +617,8 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) reportid = message.reportid; - /* whether reportid is thing of MXT_TOUCH_MULTI */ - object = mxt_get_object(data, MXT_TOUCH_MULTI); + /* whether reportid is thing of MXT_TOUCH_MULTI_T9 */ + object = mxt_get_object(data, MXT_TOUCH_MULTI_T9); if (!object) goto end; @@ -678,31 +698,31 @@ static void mxt_handle_pdata(struct mxt_data *data) u8 voltage; /* Set touchscreen lines */ - mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE, + mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_XSIZE, pdata->x_line); - mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE, + mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_YSIZE, pdata->y_line); /* Set touchscreen orient */ - mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT, + mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_ORIENT, pdata->orient); /* Set touchscreen burst length */ - mxt_write_object(data, MXT_TOUCH_MULTI, + mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_BLEN, pdata->blen); /* Set touchscreen threshold */ - mxt_write_object(data, MXT_TOUCH_MULTI, + mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_TCHTHR, pdata->threshold); /* Set touchscreen resolution */ - mxt_write_object(data, MXT_TOUCH_MULTI, + mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff); - mxt_write_object(data, MXT_TOUCH_MULTI, + mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8); - mxt_write_object(data, MXT_TOUCH_MULTI, + mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff); - mxt_write_object(data, MXT_TOUCH_MULTI, + mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8); /* Set touchscreen voltage */ @@ -715,7 +735,7 @@ static void mxt_handle_pdata(struct mxt_data *data) voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) / MXT_VOLTAGE_STEP; - mxt_write_object(data, MXT_SPT_CTECONFIG, + mxt_write_object(data, MXT_SPT_CTECONFIG_T28, MXT_CTE_VOLTAGE, voltage); } } @@ -819,13 +839,13 @@ static int mxt_initialize(struct mxt_data *data) mxt_handle_pdata(data); /* Backup to memory */ - mxt_write_object(data, MXT_GEN_COMMAND, + mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE); msleep(MXT_BACKUP_TIME); /* Soft reset */ - mxt_write_object(data, MXT_GEN_COMMAND, + mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1); msleep(MXT_RESET_TIME); @@ -921,7 +941,7 @@ static int mxt_load_fw(struct device *dev, const char *fn) } /* Change to the bootloader mode */ - mxt_write_object(data, MXT_GEN_COMMAND, + mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, MXT_BOOT_VALUE); msleep(MXT_RESET_TIME); @@ -1027,14 +1047,14 @@ static void mxt_start(struct mxt_data *data) { /* Touch enable */ mxt_write_object(data, - MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0x83); + MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83); } static void mxt_stop(struct mxt_data *data) { /* Touch disable */ mxt_write_object(data, - MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0); + MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0); } static int mxt_input_open(struct input_dev *dev) @@ -1182,7 +1202,7 @@ static int mxt_resume(struct device *dev) struct input_dev *input_dev = data->input_dev; /* Soft reset */ - mxt_write_object(data, MXT_GEN_COMMAND, + mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1); msleep(MXT_RESET_TIME); -- cgit v1.1 From a93d4f2d023ea5e84c0104d4e479243c6ac77d17 Mon Sep 17 00:00:00 2001 From: Iiro Valkonen Date: Mon, 4 Jul 2011 03:16:25 -0700 Subject: Input: atmel_mxt_ts - handle objects with multiple instances correctly Handle the objects with multiple instances correctly when the configuration data is loaded. Signed-off-by: Iiro Valkonen Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 5d71e44..ae00604 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -655,7 +655,9 @@ static int mxt_check_reg_init(struct mxt_data *data) if (!mxt_object_writable(object->type)) continue; - for (j = 0; j < object->size + 1; j++) { + for (j = 0; + j < (object->size + 1) * (object->instances + 1); + j++) { config_offset = index + j; if (config_offset > pdata->config_length) { dev_err(dev, "Not enough config data!\n"); @@ -664,7 +666,7 @@ static int mxt_check_reg_init(struct mxt_data *data) mxt_write_object(data, object->type, j, pdata->config[config_offset]); } - index += object->size + 1; + index += (object->size + 1) * (object->instances + 1); } return 0; -- cgit v1.1 From cca8edfd2ec2a34d9f50f593bc753bb11e1bc1f5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 4 Jul 2011 06:34:48 -0700 Subject: Input: sh_keysc - fix compile warning The "#if" above should really be an "#ifdef" to avoid this warning: CC drivers/input/keyboard/sh_keysc.o drivers/input/keyboard/sh_keysc.c:294:5: warning: "CONFIG_PM_SLEEP" is not defined Reported-by: Magnus Damm Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/sh_keysc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 6876700..934aeb583 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -291,7 +291,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) return 0; } -#if CONFIG_PM_SLEEP +#ifdef CONFIG_PM_SLEEP static int sh_keysc_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); -- cgit v1.1 From b514d4f7c6506b696d7de6a4426d0886753e43c9 Mon Sep 17 00:00:00 2001 From: Chris Moeller Date: Mon, 4 Jul 2011 19:21:59 -0700 Subject: Input: xpad - enable rumble support for XBox360 Wireless Controllers This patch implements rumble support for XBox360 Wireless Controllers. Signed-off-by: Chris Moeller Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index e91838c..d728875 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -549,7 +549,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) struct usb_endpoint_descriptor *ep_irq_out; int error; - if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) + if (xpad->xtype == XTYPE_UNKNOWN) return 0; xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN, @@ -583,13 +583,13 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) static void xpad_stop_output(struct usb_xpad *xpad) { - if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) + if (xpad->xtype != XTYPE_UNKNOWN) usb_kill_urb(xpad->irq_out); } static void xpad_deinit_output(struct usb_xpad *xpad) { - if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) { + if (xpad->xtype != XTYPE_UNKNOWN) { usb_free_urb(xpad->irq_out); usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); @@ -636,6 +636,23 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); + case XTYPE_XBOX360W: + xpad->odata[0] = 0x00; + xpad->odata[1] = 0x01; + xpad->odata[2] = 0x0F; + xpad->odata[3] = 0xC0; + xpad->odata[4] = 0x00; + xpad->odata[5] = strong / 256; + xpad->odata[6] = weak / 256; + xpad->odata[7] = 0x00; + xpad->odata[8] = 0x00; + xpad->odata[9] = 0x00; + xpad->odata[10] = 0x00; + xpad->odata[11] = 0x00; + xpad->irq_out->transfer_buffer_length = 12; + + return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); + default: dbg("%s - rumble command sent to unsupported xpad type: %d", __func__, xpad->xtype); @@ -648,7 +665,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect static int xpad_init_ff(struct usb_xpad *xpad) { - if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) + if (xpad->xtype == XTYPE_UNKNOWN) return 0; input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); -- cgit v1.1 From 5f098ecd4288333d87e2293239fab1c13ec90dae Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Mon, 4 Jul 2011 19:22:00 -0700 Subject: Input: xen-kbdfront - enable driver for HVM guests Signed-off-by: Stefano Stabellini Acked-by: Konrad Rzeszutek Wilk Signed-off-by: Dmitry Torokhov --- drivers/input/misc/xen-kbdfront.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 62bae99..ad2e51c 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -373,7 +373,7 @@ static struct xenbus_driver xenkbd_driver = { static int __init xenkbd_init(void) { - if (!xen_pv_domain()) + if (!xen_domain()) return -ENODEV; /* Nothing to do if running in dom0. */ -- cgit v1.1 From 2456689b3b11ddecc091cd5f00b9adea6a9854cf Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 4 Jul 2011 19:22:00 -0700 Subject: Input: wm97xx - remove redundant define Signed-off-by: Wolfram Sang Acked-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel-wm97xx.c | 2 +- drivers/input/touchscreen/mainstone-wm97xx.c | 6 +++--- drivers/input/touchscreen/wm9713.c | 4 ++-- drivers/input/touchscreen/zylonite-wm97xx.c | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c index c804189..8034cbb 100644 --- a/drivers/input/touchscreen/atmel-wm97xx.c +++ b/drivers/input/touchscreen/atmel-wm97xx.c @@ -164,7 +164,7 @@ static irqreturn_t atmel_wm97xx_channel_b_interrupt(int irq, void *dev_id) data = ac97c_readl(atmel_wm97xx, CBRHR); value = data & 0x0fff; - source = data & WM97XX_ADCSRC_MASK; + source = data & WM97XX_ADCSEL_MASK; pen_down = (data & WM97XX_PEN_DOWN) >> 8; if (source == WM97XX_ADCSEL_X) diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 3242e70..e966c29 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c @@ -157,9 +157,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) x, y, p); /* are samples valid */ - if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || - (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || - (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES) + if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X || + (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y || + (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES) goto up; /* coordinate is good */ diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index 73ec995..13cd9d1 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c @@ -304,9 +304,9 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample) wm->mach_ops->post_sample(adcsel); /* check we have correct sample */ - if ((*sample & WM97XX_ADCSRC_MASK) != ffs(adcsel >> 1) << 12) { + if ((*sample & WM97XX_ADCSEL_MASK) != ffs(adcsel >> 1) << 12) { dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel, - *sample & WM97XX_ADCSRC_MASK); + *sample & WM97XX_ADCSEL_MASK); return RC_PENUP; } diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c index 5b0f15e..f6328c0 100644 --- a/drivers/input/touchscreen/zylonite-wm97xx.c +++ b/drivers/input/touchscreen/zylonite-wm97xx.c @@ -122,9 +122,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) x, y, p); /* are samples valid */ - if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || - (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || - (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES) + if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X || + (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y || + (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES) goto up; /* coordinate is good */ -- cgit v1.1 From c8f205258bc8942e79cd37ebc1c8ec4652a1a501 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 4 Jul 2011 19:22:00 -0700 Subject: Input: wm97xx - refactor channel selection in poll_sample() The current implementation of poll_sample() has the problem that one of its arguments, the channel to be selected, differs from wm9713 to other variants. This parameter gets passed to the (currently unused) mach-specific functions pre_sample() and post_sample() which thus have to deal with codec-specific differences. Refactor the routine so that the argument to poll_sample() is generic for all codecs and do necessary conversions only in the codec-specific driver. The outcome even uses less code and removes the non-standard use of the PEN_DOWN bit to mark the AUX-channels. Signed-off-by: Wolfram Sang Acked-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wm9705.c | 14 ++++++-------- drivers/input/touchscreen/wm9712.c | 14 ++++++-------- drivers/input/touchscreen/wm9713.c | 18 +++++++++--------- 3 files changed, 21 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c index 98e6117..363d61d 100644 --- a/drivers/input/touchscreen/wm9705.c +++ b/drivers/input/touchscreen/wm9705.c @@ -224,13 +224,10 @@ static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample) } /* set up digitiser */ - if (adcsel & 0x8000) - adcsel = ((adcsel & 0x7fff) + 3) << 12; - if (wm->mach_ops && wm->mach_ops->pre_sample) wm->mach_ops->pre_sample(adcsel); - wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, - adcsel | WM97XX_POLL | WM97XX_DELAY(delay)); + wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK) + | WM97XX_POLL | WM97XX_DELAY(delay)); /* wait 3 AC97 time slots + delay for conversion */ poll_delay(delay); @@ -256,9 +253,10 @@ static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample) wm->mach_ops->post_sample(adcsel); /* check we have correct sample */ - if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) { - dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel, - *sample & WM97XX_ADCSEL_MASK); + if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) { + dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x", + adcsel & WM97XX_ADCSEL_MASK, + *sample & WM97XX_ADCSEL_MASK); return RC_PENUP; } diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c index 2bc2fb8..d26093f 100644 --- a/drivers/input/touchscreen/wm9712.c +++ b/drivers/input/touchscreen/wm9712.c @@ -264,13 +264,10 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample) } /* set up digitiser */ - if (adcsel & 0x8000) - adcsel = ((adcsel & 0x7fff) + 3) << 12; - if (wm->mach_ops && wm->mach_ops->pre_sample) wm->mach_ops->pre_sample(adcsel); - wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, - adcsel | WM97XX_POLL | WM97XX_DELAY(delay)); + wm97xx_reg_write(wm, AC97_WM97XX_DIGITISER1, (adcsel & WM97XX_ADCSEL_MASK) + | WM97XX_POLL | WM97XX_DELAY(delay)); /* wait 3 AC97 time slots + delay for conversion */ poll_delay(delay); @@ -296,9 +293,10 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample) wm->mach_ops->post_sample(adcsel); /* check we have correct sample */ - if ((*sample & WM97XX_ADCSEL_MASK) != adcsel) { - dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel, - *sample & WM97XX_ADCSEL_MASK); + if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) { + dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x", + adcsel & WM97XX_ADCSEL_MASK, + *sample & WM97XX_ADCSEL_MASK); return RC_PENUP; } diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index 13cd9d1..a755801 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c @@ -270,15 +270,14 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample) } /* set up digitiser */ - if (adcsel & 0x8000) - adcsel = 1 << ((adcsel & 0x7fff) + 3); - dig1 = wm97xx_reg_read(wm, AC97_WM9713_DIG1); dig1 &= ~WM9713_ADCSEL_MASK; + /* WM97XX_ADCSEL_* channels need to be converted to WM9713 format */ + dig1 |= 1 << ((adcsel & WM97XX_ADCSEL_MASK) >> 12); if (wm->mach_ops && wm->mach_ops->pre_sample) wm->mach_ops->pre_sample(adcsel); - wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | adcsel | WM9713_POLL); + wm97xx_reg_write(wm, AC97_WM9713_DIG1, dig1 | WM9713_POLL); /* wait 3 AC97 time slots + delay for conversion */ poll_delay(delay); @@ -304,8 +303,9 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample) wm->mach_ops->post_sample(adcsel); /* check we have correct sample */ - if ((*sample & WM97XX_ADCSEL_MASK) != ffs(adcsel >> 1) << 12) { - dev_dbg(wm->dev, "adc wrong sample, read %x got %x", adcsel, + if ((*sample ^ adcsel) & WM97XX_ADCSEL_MASK) { + dev_dbg(wm->dev, "adc wrong sample, wanted %x got %x", + adcsel & WM97XX_ADCSEL_MASK, *sample & WM97XX_ADCSEL_MASK); return RC_PENUP; } @@ -400,14 +400,14 @@ static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data) if (rc != RC_VALID) return rc; } else { - rc = wm9713_poll_sample(wm, WM9713_ADCSEL_X, &data->x); + rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_X, &data->x); if (rc != RC_VALID) return rc; - rc = wm9713_poll_sample(wm, WM9713_ADCSEL_Y, &data->y); + rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y); if (rc != RC_VALID) return rc; if (pil) { - rc = wm9713_poll_sample(wm, WM9713_ADCSEL_PRES, + rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p); if (rc != RC_VALID) return rc; -- cgit v1.1 From 77da38387e1c6f473744afccd83795805f506498 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 4 Jul 2011 19:22:01 -0700 Subject: Input: wm97xx - mark channels which need pen_down Currently, battery drivers also use poll_sample() provided by the wm97xx-core but this code always checks if the pen is down. Mark the channels which really need this (i.e. for the touchscreen) with the PEN_DOWN bit, and skip the checks otherwise. Now, the battery channels can always be read. Signed-off-by: Wolfram Sang Acked-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wm9705.c | 11 ++++++----- drivers/input/touchscreen/wm9712.c | 13 ++++++++----- drivers/input/touchscreen/wm9713.c | 11 ++++++----- 3 files changed, 20 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c index 363d61d..adc13a5 100644 --- a/drivers/input/touchscreen/wm9705.c +++ b/drivers/input/touchscreen/wm9705.c @@ -215,8 +215,9 @@ static inline int is_pden(struct wm97xx *wm) static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample) { int timeout = 5 * delay; + bool wants_pen = adcsel & WM97XX_PEN_DOWN; - if (!wm->pen_probably_down) { + if (wants_pen && !wm->pen_probably_down) { u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); if (!(data & WM97XX_PEN_DOWN)) return RC_PENUP; @@ -260,7 +261,7 @@ static int wm9705_poll_sample(struct wm97xx *wm, int adcsel, int *sample) return RC_PENUP; } - if (!(*sample & WM97XX_PEN_DOWN)) { + if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) { wm->pen_probably_down = 0; return RC_PENUP; } @@ -275,14 +276,14 @@ static int wm9705_poll_touch(struct wm97xx *wm, struct wm97xx_data *data) { int rc; - rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X, &data->x); + rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x); if (rc != RC_VALID) return rc; - rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y); + rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y); if (rc != RC_VALID) return rc; if (pil) { - rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES, &data->p); + rc = wm9705_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN, &data->p); if (rc != RC_VALID) return rc; } else diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c index d26093f..6e743e3 100644 --- a/drivers/input/touchscreen/wm9712.c +++ b/drivers/input/touchscreen/wm9712.c @@ -255,8 +255,9 @@ static inline int is_pden(struct wm97xx *wm) static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample) { int timeout = 5 * delay; + bool wants_pen = adcsel & WM97XX_PEN_DOWN; - if (!wm->pen_probably_down) { + if (wants_pen && !wm->pen_probably_down) { u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); if (!(data & WM97XX_PEN_DOWN)) return RC_PENUP; @@ -300,7 +301,7 @@ static int wm9712_poll_sample(struct wm97xx *wm, int adcsel, int *sample) return RC_PENUP; } - if (!(*sample & WM97XX_PEN_DOWN)) { + if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) { wm->pen_probably_down = 0; return RC_PENUP; } @@ -385,16 +386,18 @@ static int wm9712_poll_touch(struct wm97xx *wm, struct wm97xx_data *data) if (rc != RC_VALID) return rc; } else { - rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X, &data->x); + rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, + &data->x); if (rc != RC_VALID) return rc; - rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y); + rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, + &data->y); if (rc != RC_VALID) return rc; if (pil && !five_wire) { - rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES, + rc = wm9712_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN, &data->p); if (rc != RC_VALID) return rc; diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index a755801..7405353 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c @@ -261,8 +261,9 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample) { u16 dig1; int timeout = 5 * delay; + bool wants_pen = adcsel & WM97XX_PEN_DOWN; - if (!wm->pen_probably_down) { + if (wants_pen && !wm->pen_probably_down) { u16 data = wm97xx_reg_read(wm, AC97_WM97XX_DIGITISER_RD); if (!(data & WM97XX_PEN_DOWN)) return RC_PENUP; @@ -310,7 +311,7 @@ static int wm9713_poll_sample(struct wm97xx *wm, int adcsel, int *sample) return RC_PENUP; } - if (!(*sample & WM97XX_PEN_DOWN)) { + if (wants_pen && !(*sample & WM97XX_PEN_DOWN)) { wm->pen_probably_down = 0; return RC_PENUP; } @@ -400,14 +401,14 @@ static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data) if (rc != RC_VALID) return rc; } else { - rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_X, &data->x); + rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_X | WM97XX_PEN_DOWN, &data->x); if (rc != RC_VALID) return rc; - rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_Y, &data->y); + rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_Y | WM97XX_PEN_DOWN, &data->y); if (rc != RC_VALID) return rc; if (pil) { - rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_PRES, + rc = wm9713_poll_sample(wm, WM97XX_ADCSEL_PRES | WM97XX_PEN_DOWN, &data->p); if (rc != RC_VALID) return rc; -- cgit v1.1 From e8e70d83912b40c5c9ea7b85a6110b9925fbed62 Mon Sep 17 00:00:00 2001 From: Chris Hudson Date: Wed, 6 Jul 2011 18:36:51 -0700 Subject: Input: add support for Kionix KXTJ9 accelerometer Signed-off-by: Chris Hudson Signed-off-by: Dmitry Torokhov --- drivers/input/misc/Kconfig | 17 ++ drivers/input/misc/Makefile | 1 + drivers/input/misc/kxtj9.c | 671 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 689 insertions(+) create mode 100644 drivers/input/misc/kxtj9.c (limited to 'drivers') diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 6fdce4b..0134428 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -230,6 +230,23 @@ config INPUT_KEYSPAN_REMOTE To compile this driver as a module, choose M here: the module will be called keyspan_remote. +config INPUT_KXTJ9 + tristate "Kionix KXTJ9 tri-axis digital accelerometer" + depends on I2C + help + Say Y here to enable support for the Kionix KXTJ9 digital tri-axis + accelerometer. + + To compile this driver as a module, choose M here: the module will + be called kxtj9. + +config INPUT_KXTJ9_POLLED_MODE + bool "Enable polling mode support" + depends on INPUT_KXTJ9 + select INPUT_POLLDEV + help + Say Y here if you need accelerometer to work in polling mode. + config INPUT_POWERMATE tristate "Griffin PowerMate and Contour Jog support" depends on USB_ARCH_HAS_HCD diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index b7e227a..be39d81 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o +obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o obj-$(CONFIG_INPUT_MMA8450) += mma8450.o diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c new file mode 100644 index 0000000..a416f7f --- /dev/null +++ b/drivers/input/misc/kxtj9.c @@ -0,0 +1,671 @@ +/* + * Copyright (C) 2011 Kionix, Inc. + * Written by Chris Hudson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include +#include + +#define NAME "kxtj9" +#define G_MAX 8000 +/* OUTPUT REGISTERS */ +#define XOUT_L 0x06 +#define WHO_AM_I 0x0F +/* CONTROL REGISTERS */ +#define INT_REL 0x1A +#define CTRL_REG1 0x1B +#define INT_CTRL1 0x1E +#define DATA_CTRL 0x21 +/* CONTROL REGISTER 1 BITS */ +#define PC1_OFF 0x7F +#define PC1_ON (1 << 7) +/* Data ready funtion enable bit: set during probe if using irq mode */ +#define DRDYE (1 << 5) +/* INTERRUPT CONTROL REGISTER 1 BITS */ +/* Set these during probe if using irq mode */ +#define KXTJ9_IEL (1 << 3) +#define KXTJ9_IEA (1 << 4) +#define KXTJ9_IEN (1 << 5) +/* INPUT_ABS CONSTANTS */ +#define FUZZ 3 +#define FLAT 3 +/* RESUME STATE INDICES */ +#define RES_DATA_CTRL 0 +#define RES_CTRL_REG1 1 +#define RES_INT_CTRL1 2 +#define RESUME_ENTRIES 3 + +/* + * The following table lists the maximum appropriate poll interval for each + * available output data rate. + */ +static const struct { + unsigned int cutoff; + u8 mask; +} kxtj9_odr_table[] = { + { 3, ODR800F }, + { 5, ODR400F }, + { 10, ODR200F }, + { 20, ODR100F }, + { 40, ODR50F }, + { 80, ODR25F }, + { 0, ODR12_5F}, +}; + +struct kxtj9_data { + struct i2c_client *client; + struct kxtj9_platform_data pdata; + struct input_dev *input_dev; +#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE + struct input_polled_dev *poll_dev; +#endif + unsigned int last_poll_interval; + u8 shift; + u8 ctrl_reg1; + u8 data_ctrl; + u8 int_ctrl; +}; + +static int kxtj9_i2c_read(struct kxtj9_data *tj9, u8 addr, u8 *data, int len) +{ + struct i2c_msg msgs[] = { + { + .addr = tj9->client->addr, + .flags = tj9->client->flags, + .len = 1, + .buf = &addr, + }, + { + .addr = tj9->client->addr, + .flags = tj9->client->flags | I2C_M_RD, + .len = len, + .buf = data, + }, + }; + + return i2c_transfer(tj9->client->adapter, msgs, 2); +} + +static void kxtj9_report_acceleration_data(struct kxtj9_data *tj9) +{ + s16 acc_data[3]; /* Data bytes from hardware xL, xH, yL, yH, zL, zH */ + s16 x, y, z; + int err; + + err = kxtj9_i2c_read(tj9, XOUT_L, (u8 *)acc_data, 6); + if (err < 0) + dev_err(&tj9->client->dev, "accelerometer data read failed\n"); + + x = le16_to_cpu(acc_data[tj9->pdata.axis_map_x]) >> tj9->shift; + y = le16_to_cpu(acc_data[tj9->pdata.axis_map_y]) >> tj9->shift; + z = le16_to_cpu(acc_data[tj9->pdata.axis_map_z]) >> tj9->shift; + + input_report_abs(tj9->input_dev, ABS_X, tj9->pdata.negate_x ? -x : x); + input_report_abs(tj9->input_dev, ABS_Y, tj9->pdata.negate_y ? -y : y); + input_report_abs(tj9->input_dev, ABS_Z, tj9->pdata.negate_z ? -z : z); + input_sync(tj9->input_dev); +} + +static irqreturn_t kxtj9_isr(int irq, void *dev) +{ + struct kxtj9_data *tj9 = dev; + int err; + + /* data ready is the only possible interrupt type */ + kxtj9_report_acceleration_data(tj9); + + err = i2c_smbus_read_byte_data(tj9->client, INT_REL); + if (err < 0) + dev_err(&tj9->client->dev, + "error clearing interrupt status: %d\n", err); + + return IRQ_HANDLED; +} + +static int kxtj9_update_g_range(struct kxtj9_data *tj9, u8 new_g_range) +{ + switch (new_g_range) { + case KXTJ9_G_2G: + tj9->shift = 4; + break; + case KXTJ9_G_4G: + tj9->shift = 3; + break; + case KXTJ9_G_8G: + tj9->shift = 2; + break; + default: + return -EINVAL; + } + + tj9->ctrl_reg1 &= 0xe7; + tj9->ctrl_reg1 |= new_g_range; + + return 0; +} + +static int kxtj9_update_odr(struct kxtj9_data *tj9, unsigned int poll_interval) +{ + int err; + int i; + + /* Use the lowest ODR that can support the requested poll interval */ + for (i = 0; i < ARRAY_SIZE(kxtj9_odr_table); i++) { + tj9->data_ctrl = kxtj9_odr_table[i].mask; + if (poll_interval < kxtj9_odr_table[i].cutoff) + break; + } + + err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, 0); + if (err < 0) + return err; + + err = i2c_smbus_write_byte_data(tj9->client, DATA_CTRL, tj9->data_ctrl); + if (err < 0) + return err; + + err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1); + if (err < 0) + return err; + + return 0; +} + +static int kxtj9_device_power_on(struct kxtj9_data *tj9) +{ + if (tj9->pdata.power_on) + return tj9->pdata.power_on(); + + return 0; +} + +static void kxtj9_device_power_off(struct kxtj9_data *tj9) +{ + int err; + + tj9->ctrl_reg1 &= PC1_OFF; + err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1); + if (err < 0) + dev_err(&tj9->client->dev, "soft power off failed\n"); + + if (tj9->pdata.power_off) + tj9->pdata.power_off(); +} + +static int kxtj9_enable(struct kxtj9_data *tj9) +{ + int err; + + err = kxtj9_device_power_on(tj9); + if (err < 0) + return err; + + /* ensure that PC1 is cleared before updating control registers */ + err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, 0); + if (err < 0) + return err; + + /* only write INT_CTRL_REG1 if in irq mode */ + if (tj9->client->irq) { + err = i2c_smbus_write_byte_data(tj9->client, + INT_CTRL1, tj9->int_ctrl); + if (err < 0) + return err; + } + + err = kxtj9_update_g_range(tj9, tj9->pdata.g_range); + if (err < 0) + return err; + + /* turn on outputs */ + tj9->ctrl_reg1 |= PC1_ON; + err = i2c_smbus_write_byte_data(tj9->client, CTRL_REG1, tj9->ctrl_reg1); + if (err < 0) + return err; + + err = kxtj9_update_odr(tj9, tj9->last_poll_interval); + if (err < 0) + return err; + + /* clear initial interrupt if in irq mode */ + if (tj9->client->irq) { + err = i2c_smbus_read_byte_data(tj9->client, INT_REL); + if (err < 0) { + dev_err(&tj9->client->dev, + "error clearing interrupt: %d\n", err); + goto fail; + } + } + + return 0; + +fail: + kxtj9_device_power_off(tj9); + return err; +} + +static void kxtj9_disable(struct kxtj9_data *tj9) +{ + kxtj9_device_power_off(tj9); +} + +static int kxtj9_input_open(struct input_dev *input) +{ + struct kxtj9_data *tj9 = input_get_drvdata(input); + + return kxtj9_enable(tj9); +} + +static void kxtj9_input_close(struct input_dev *dev) +{ + struct kxtj9_data *tj9 = input_get_drvdata(dev); + + kxtj9_disable(tj9); +} + +static void __devinit kxtj9_init_input_device(struct kxtj9_data *tj9, + struct input_dev *input_dev) +{ + __set_bit(EV_ABS, input_dev->evbit); + input_set_abs_params(input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT); + input_set_abs_params(input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT); + input_set_abs_params(input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT); + + input_dev->name = "kxtj9_accel"; + input_dev->id.bustype = BUS_I2C; + input_dev->dev.parent = &tj9->client->dev; +} + +static int __devinit kxtj9_setup_input_device(struct kxtj9_data *tj9) +{ + struct input_dev *input_dev; + int err; + + input_dev = input_allocate_device(); + if (!tj9->input_dev) { + dev_err(&tj9->client->dev, "input device allocate failed\n"); + return -ENOMEM; + } + + tj9->input_dev = input_dev; + + input_dev->open = kxtj9_input_open; + input_dev->close = kxtj9_input_close; + input_set_drvdata(input_dev, tj9); + + kxtj9_init_input_device(tj9, input_dev); + + err = input_register_device(tj9->input_dev); + if (err) { + dev_err(&tj9->client->dev, + "unable to register input polled device %s: %d\n", + tj9->input_dev->name, err); + input_free_device(tj9->input_dev); + return err; + } + + return 0; +} + +/* + * When IRQ mode is selected, we need to provide an interface to allow the user + * to change the output data rate of the part. For consistency, we are using + * the set_poll method, which accepts a poll interval in milliseconds, and then + * calls update_odr() while passing this value as an argument. In IRQ mode, the + * data outputs will not be read AT the requested poll interval, rather, the + * lowest ODR that can support the requested interval. The client application + * will be responsible for retrieving data from the input node at the desired + * interval. + */ + +/* Returns currently selected poll interval (in ms) */ +static ssize_t kxtj9_get_poll(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct kxtj9_data *tj9 = i2c_get_clientdata(client); + + return sprintf(buf, "%d\n", tj9->last_poll_interval); +} + +/* Allow users to select a new poll interval (in ms) */ +static ssize_t kxtj9_set_poll(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct kxtj9_data *tj9 = i2c_get_clientdata(client); + struct input_dev *input_dev = tj9->input_dev; + unsigned int interval; + int error; + + error = kstrtouint(buf, 10, &interval); + if (error < 0) + return error; + + /* Lock the device to prevent races with open/close (and itself) */ + mutex_unlock(&input_dev->mutex); + + disable_irq(client->irq); + + /* + * Set current interval to the greater of the minimum interval or + * the requested interval + */ + tj9->last_poll_interval = max(interval, tj9->pdata.min_interval); + + kxtj9_update_odr(tj9, tj9->last_poll_interval); + + enable_irq(client->irq); + mutex_unlock(&input_dev->mutex); + + return count; +} + +static DEVICE_ATTR(poll, S_IRUGO|S_IWUSR, kxtj9_get_poll, kxtj9_set_poll); + +static struct attribute *kxtj9_attributes[] = { + &dev_attr_poll.attr, + NULL +}; + +static struct attribute_group kxtj9_attribute_group = { + .attrs = kxtj9_attributes +}; + + +#ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE +static void kxtj9_poll(struct input_polled_dev *dev) +{ + struct kxtj9_data *tj9 = dev->private; + unsigned int poll_interval = dev->poll_interval; + + kxtj9_report_acceleration_data(tj9); + + if (poll_interval != tj9->last_poll_interval) { + kxtj9_update_odr(tj9, poll_interval); + tj9->last_poll_interval = poll_interval; + } +} + +static void kxtj9_polled_input_open(struct input_polled_dev *dev) +{ + struct kxtj9_data *tj9 = dev->private; + + kxtj9_enable(tj9); +} + +static void kxtj9_polled_input_close(struct input_polled_dev *dev) +{ + struct kxtj9_data *tj9 = dev->private; + + kxtj9_disable(tj9); +} + +static int __devinit kxtj9_setup_polled_device(struct kxtj9_data *tj9) +{ + int err; + struct input_polled_dev *poll_dev; + poll_dev = input_allocate_polled_device(); + + if (!poll_dev) { + dev_err(&tj9->client->dev, + "Failed to allocate polled device\n"); + return -ENOMEM; + } + + tj9->poll_dev = poll_dev; + tj9->input_dev = poll_dev->input; + + poll_dev->private = tj9; + poll_dev->poll = kxtj9_poll; + poll_dev->open = kxtj9_polled_input_open; + poll_dev->close = kxtj9_polled_input_close; + + kxtj9_init_input_device(tj9, poll_dev->input); + + err = input_register_polled_device(poll_dev); + if (err) { + dev_err(&tj9->client->dev, + "Unable to register polled device, err=%d\n", err); + input_free_polled_device(poll_dev); + return err; + } + + return 0; +} + +static void __devexit kxtj9_teardown_polled_device(struct kxtj9_data *tj9) +{ + input_unregister_polled_device(tj9->poll_dev); + input_free_polled_device(tj9->poll_dev); +} + +#else + +static inline int kxtj9_setup_polled_device(struct kxtj9_data *tj9) +{ + return -ENOSYS; +} + +static inline void kxtj9_teardown_polled_device(struct kxtj9_data *tj9) +{ +} + +#endif + +static int __devinit kxtj9_verify(struct kxtj9_data *tj9) +{ + int retval; + + retval = kxtj9_device_power_on(tj9); + if (retval < 0) + return retval; + + retval = i2c_smbus_read_byte_data(tj9->client, WHO_AM_I); + if (retval < 0) { + dev_err(&tj9->client->dev, "read err int source\n"); + goto out; + } + + retval = retval != 0x06 ? -EIO : 0; + +out: + kxtj9_device_power_off(tj9); + return retval; +} + +static int __devinit kxtj9_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + const struct kxtj9_platform_data *pdata = client->dev.platform_data; + struct kxtj9_data *tj9; + int err; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "client is not i2c capable\n"); + return -ENXIO; + } + + if (!pdata) { + dev_err(&client->dev, "platform data is NULL; exiting\n"); + return -EINVAL; + } + + tj9 = kzalloc(sizeof(*tj9), GFP_KERNEL); + if (!tj9) { + dev_err(&client->dev, + "failed to allocate memory for module data\n"); + return -ENOMEM; + } + + tj9->client = client; + tj9->pdata = *pdata; + + if (pdata->init) { + err = pdata->init(); + if (err < 0) + goto err_free_mem; + } + + err = kxtj9_verify(tj9); + if (err < 0) { + dev_err(&client->dev, "device not recognized\n"); + goto err_pdata_exit; + } + + i2c_set_clientdata(client, tj9); + + tj9->ctrl_reg1 = tj9->pdata.res_12bit | tj9->pdata.g_range; + tj9->data_ctrl = tj9->pdata.data_odr_init; + + if (client->irq) { + /* If in irq mode, populate INT_CTRL_REG1 and enable DRDY. */ + tj9->int_ctrl |= KXTJ9_IEN | KXTJ9_IEA | KXTJ9_IEL; + tj9->ctrl_reg1 |= DRDYE; + + err = kxtj9_setup_input_device(tj9); + if (err) + goto err_pdata_exit; + + err = request_threaded_irq(client->irq, NULL, kxtj9_isr, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "kxtj9-irq", tj9); + if (err) { + dev_err(&client->dev, "request irq failed: %d\n", err); + goto err_destroy_input; + } + + err = sysfs_create_group(&client->dev.kobj, &kxtj9_attribute_group); + if (err) { + dev_err(&client->dev, "sysfs create failed: %d\n", err); + goto err_free_irq; + } + + } else { + err = kxtj9_setup_polled_device(tj9); + if (err) + goto err_pdata_exit; + } + + return 0; + +err_free_irq: + free_irq(client->irq, tj9); +err_destroy_input: + input_unregister_device(tj9->input_dev); +err_pdata_exit: + if (tj9->pdata.exit) + tj9->pdata.exit(); +err_free_mem: + kfree(tj9); + return err; +} + +static int __devexit kxtj9_remove(struct i2c_client *client) +{ + struct kxtj9_data *tj9 = i2c_get_clientdata(client); + + if (client->irq) { + sysfs_remove_group(&client->dev.kobj, &kxtj9_attribute_group); + free_irq(client->irq, tj9); + input_unregister_device(tj9->input_dev); + } else { + kxtj9_teardown_polled_device(tj9); + } + + if (tj9->pdata.exit) + tj9->pdata.exit(); + + kfree(tj9); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int kxtj9_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct kxtj9_data *tj9 = i2c_get_clientdata(client); + struct input_dev *input_dev = tj9->input_dev; + + mutex_lock(&input_dev->mutex); + + if (input_dev->users) + kxtj9_disable(tj9); + + mutex_unlock(&input_dev->mutex); + return 0; +} + +static int kxtj9_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct kxtj9_data *tj9 = i2c_get_clientdata(client); + struct input_dev *input_dev = tj9->input_dev; + int retval = 0; + + mutex_lock(&input_dev->mutex); + + if (input_dev->users) + kxtj9_enable(tj9); + + mutex_unlock(&input_dev->mutex); + return retval; +} +#endif + +static SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume); + +static const struct i2c_device_id kxtj9_id[] = { + { NAME, 0 }, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, kxtj9_id); + +static struct i2c_driver kxtj9_driver = { + .driver = { + .name = NAME, + .owner = THIS_MODULE, + .pm = &kxtj9_pm_ops, + }, + .probe = kxtj9_probe, + .remove = __devexit_p(kxtj9_remove), + .id_table = kxtj9_id, +}; + +static int __init kxtj9_init(void) +{ + return i2c_add_driver(&kxtj9_driver); +} +module_init(kxtj9_init); + +static void __exit kxtj9_exit(void) +{ + i2c_del_driver(&kxtj9_driver); +} +module_exit(kxtj9_exit); + +MODULE_DESCRIPTION("KXTJ9 accelerometer driver"); +MODULE_AUTHOR("Chris Hudson "); +MODULE_LICENSE("GPL"); -- cgit v1.1 From 358ea22ee3e14894a2598580297767ccc010119b Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Wed, 6 Jul 2011 18:05:41 -0700 Subject: Input: wacom - remove BTN_TOOL_FINGER for pad BTN_TOOL_FINGER was designed to indicate a single finger touch. Remove the lines that borrowed this type for expresskeys and tablet buttons. Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 0c302c9..7ce1294 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -278,7 +278,6 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) input_report_key(input, BTN_4, (data[7] & 0x80)); rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); input_report_rel(input, REL_WHEEL, rw); - input_report_key(input, BTN_TOOL_FINGER, 0xf0); if (!prox) wacom->id[1] = 0; input_report_abs(input, ABS_MISC, wacom->id[1]); @@ -296,7 +295,6 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) input_report_key(input, BTN_4, (data[7] & 0x10)); input_report_key(input, BTN_5, (data[7] & 0x40)); input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f)); - input_report_key(input, BTN_TOOL_FINGER, 0xf0); if (!prox) wacom->id[1] = 0; input_report_abs(input, ABS_MISC, wacom->id[1]); @@ -495,10 +493,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) /* pad packets. Works as a second tool and is always in prox */ if (data[0] == WACOM_REPORT_INTUOSPAD) { - /* initiate the pad as a device */ - if (wacom->tool[1] != BTN_TOOL_FINGER) - wacom->tool[1] = BTN_TOOL_FINGER; - if (features->type >= INTUOS4S && features->type <= INTUOS4L) { input_report_key(input, BTN_0, (data[2] & 0x01)); input_report_key(input, BTN_1, (data[3] & 0x01)); @@ -1090,7 +1084,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, case WACOM_G4: input_set_capability(input_dev, EV_MSC, MSC_SERIAL); - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); __set_bit(BTN_0, input_dev->keybit); __set_bit(BTN_4, input_dev->keybit); /* fall through */ @@ -1128,7 +1121,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, case CINTIQ: for (i = 0; i < 8; i++) __set_bit(BTN_0 + i, input_dev->keybit); - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); if (wacom_wac->features.type != WACOM_21UX2) { input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); @@ -1155,8 +1147,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(BTN_2, input_dev->keybit); __set_bit(BTN_3, input_dev->keybit); - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); - input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); /* fall through */ @@ -1174,7 +1164,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, case INTUOS4S: for (i = 0; i < 7; i++) __set_bit(BTN_0 + i, input_dev->keybit); - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); wacom_setup_intuos(wacom_wac); -- cgit v1.1 From 998c454e1c850f8e5cc0ae2299c4789b395d6d98 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Wed, 6 Jul 2011 18:05:41 -0700 Subject: Input: wacom - add serial number for Graphire4 and old Bamboo With the removal of BTN_TOOL_FINGER for tablet buttons and expresskeys, serial number is needed to distingush if the events were from a regular tool (stylus, eraser, or mouse) or the attribures (buttons, strips, or wheels) on the tablet since there are overlapped events between the tools and the tablet attributes. Signed-off-by: Ping Cheng Reviewed-by: Chris Bagwell Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 7ce1294..b93501a 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -265,6 +265,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) wacom->id[0] = 0; input_report_abs(input, ABS_MISC, wacom->id[0]); /* report tool id */ input_report_key(input, wacom->tool[0], prox); + input_event(input, EV_MSC, MSC_SERIAL, 1); input_sync(input); /* sync last event */ } -- cgit v1.1 From 0bd10ef8f8a29d824561a4678f5e63350751407a Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Wed, 6 Jul 2011 18:05:42 -0700 Subject: Input: wacom - update Graphire4 and old Bamboo tablet buttons Bamboo touch sets BTN_BACK, BTN_FORWARD, BTN_LEFT, and BTN_RIGHT as the default button events for tablet buttons. Change Graphire4 and old Bamboo to the same settings. Signed-off-by: Ping Cheng Reviewed-by: Chris Bagwell Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index b93501a..19554a4 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -275,8 +275,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) prox = data[7] & 0xf8; if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; - input_report_key(input, BTN_0, (data[7] & 0x40)); - input_report_key(input, BTN_4, (data[7] & 0x80)); + input_report_key(input, BTN_BACK, (data[7] & 0x40)); + input_report_key(input, BTN_FORWARD, (data[7] & 0x80)); rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); input_report_rel(input, REL_WHEEL, rw); if (!prox) @@ -291,10 +291,10 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) prox = (data[7] & 0xf8) || data[8]; if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; - input_report_key(input, BTN_0, (data[7] & 0x08)); - input_report_key(input, BTN_1, (data[7] & 0x20)); - input_report_key(input, BTN_4, (data[7] & 0x10)); - input_report_key(input, BTN_5, (data[7] & 0x40)); + input_report_key(input, BTN_BACK, (data[7] & 0x08)); + input_report_key(input, BTN_LEFT, (data[7] & 0x20)); + input_report_key(input, BTN_FORWARD, (data[7] & 0x10)); + input_report_key(input, BTN_RIGHT, (data[7] & 0x40)); input_report_abs(input, ABS_WHEEL, (data[8] & 0x7f)); if (!prox) wacom->id[1] = 0; @@ -1076,17 +1076,14 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, switch (wacom_wac->features.type) { case WACOM_MO: - __set_bit(BTN_1, input_dev->keybit); - __set_bit(BTN_5, input_dev->keybit); - input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); /* fall through */ case WACOM_G4: input_set_capability(input_dev, EV_MSC, MSC_SERIAL); - __set_bit(BTN_0, input_dev->keybit); - __set_bit(BTN_4, input_dev->keybit); + __set_bit(BTN_BACK, input_dev->keybit); + __set_bit(BTN_FORWARD, input_dev->keybit); /* fall through */ case GRAPHIRE: -- cgit v1.1 From 84460014505685ab234fa8e1a45dffd32f3a46a7 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Wed, 6 Jul 2011 18:05:43 -0700 Subject: Input: wacom - cleanup a return value for the old Bamboo The old code may call input_sync() without sending any other events. While it will be suppressed by the input core not calling it at all is still cheaper. Signed-off-by: Ping Cheng Reviewed-by: Chris Bagwell Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 19554a4..03ebcc8 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -300,8 +300,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) wacom->id[1] = 0; input_report_abs(input, ABS_MISC, wacom->id[1]); input_event(input, EV_MSC, MSC_SERIAL, 0xf0); + retval = 1; } - retval = 1; break; } exit: -- cgit v1.1 From 8be3c650f54c259694e82282e54b12c14304487e Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Wed, 6 Jul 2011 22:27:47 -0700 Subject: Input: synaptics - set resolution for MT_POSITION_X/Y axes Set resolution for MT_POSITION_X and MT_POSITION_Y to match ABS_X and ABS_Y, respectively. Signed-off-by: Daniel Kurtz Acked-by: Chase Douglas Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index e06e045..477d1ea 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -701,6 +701,9 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) priv->x_max ?: XMAX_NOMINAL, 0, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); + + input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res); + input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res); } if (SYN_CAP_PALMDETECT(priv->capabilities)) -- cgit v1.1 From a9f0b79edfda3750d254ba5b192795e2554c361d Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Wed, 6 Jul 2011 22:39:14 -0700 Subject: Input: synaptics - fuzz position for touchpad with reduced filtering Synaptics touchpads indicate via a capability bit when they perform reduced filtering on position data. In such a case, use a non-zero fuzz value. Fuzz = 8 was chosen empirically by observing the raw position data reported by a clickpad indicating it had reduced filtering. Signed-off-by: Daniel Kurtz Acked-by: Chase Douglas Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 15 ++++++++------- drivers/input/mouse/synaptics.h | 10 +++++++--- 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 477d1ea..363aedf 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -684,23 +684,25 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) { int i; + int fuzz = SYN_CAP_REDUCED_FILTERING(priv->ext_cap_0c) ? + SYN_REDUCED_FILTER_FUZZ : 0; __set_bit(INPUT_PROP_POINTER, dev->propbit); __set_bit(EV_ABS, dev->evbit); - input_set_abs_params(dev, ABS_X, - XMIN_NOMINAL, priv->x_max ?: XMAX_NOMINAL, 0, 0); - input_set_abs_params(dev, ABS_Y, - YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0); + input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, + priv->x_max ?: XMAX_NOMINAL, fuzz, 0); + input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, + priv->y_max ?: YMAX_NOMINAL, fuzz, 0); input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); input_mt_init_slots(dev, 2); input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL, - priv->x_max ?: XMAX_NOMINAL, 0, 0); + priv->x_max ?: XMAX_NOMINAL, fuzz, 0); input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL, - priv->y_max ?: YMAX_NOMINAL, 0, 0); + priv->y_max ?: YMAX_NOMINAL, fuzz, 0); input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res); input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res); @@ -974,4 +976,3 @@ bool synaptics_supported(void) } #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ - diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 7453938..b8025b0 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -66,9 +66,9 @@ * 1 0x60 multifinger mode identifies firmware finger counting * (not reporting!) algorithm. * Not particularly meaningful - * 1 0x80 covered pad W clipped to 14, 15 == pad mostly covered - * 2 0x01 clickpad bit 1 2-button ClickPad - * 2 0x02 deluxe LED controls touchpad support LED commands + * 1 0x80 covered pad W clipped to 14, 15 == pad mostly covered + * 2 0x01 clickpad bit 1 2-button ClickPad + * 2 0x02 deluxe LED controls touchpad support LED commands * ala multimedia control bar * 2 0x04 reduced filtering firmware does less filtering on * position data, driver should watch @@ -78,6 +78,7 @@ #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) +#define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) /* synaptics modes query bits */ #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) @@ -104,6 +105,9 @@ #define SYN_NEWABS_RELAXED 2 #define SYN_OLDABS 3 +/* amount to fuzz position data when touchpad reports reduced filtering */ +#define SYN_REDUCED_FILTER_FUZZ 8 + /* * A structure to describe the state of the touchpad hardware (buttons and pad) */ -- cgit v1.1 From bea9f0ff263e1c2031d76afc21c22ad773f0b163 Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Wed, 6 Jul 2011 22:42:52 -0700 Subject: Input: synaptics - rename set_slot to be more descriptive Signed-off-by: Daniel Kurtz Acked-by: Chase Douglas Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 363aedf..c5c91bc 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -485,7 +485,8 @@ static int synaptics_parse_hw_state(const unsigned char buf[], return 0; } -static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y) +static void synaptics_report_semi_mt_slot(struct input_dev *dev, int slot, + bool active, int x, int y) { input_mt_slot(dev, slot); input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); @@ -502,14 +503,16 @@ static void synaptics_report_semi_mt_data(struct input_dev *dev, int num_fingers) { if (num_fingers >= 2) { - set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y)); - set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y)); + synaptics_report_semi_mt_slot(dev, 0, true, min(a->x, b->x), + min(a->y, b->y)); + synaptics_report_semi_mt_slot(dev, 1, true, max(a->x, b->x), + max(a->y, b->y)); } else if (num_fingers == 1) { - set_slot(dev, 0, true, a->x, a->y); - set_slot(dev, 1, false, 0, 0); + synaptics_report_semi_mt_slot(dev, 0, true, a->x, a->y); + synaptics_report_semi_mt_slot(dev, 1, false, 0, 0); } else { - set_slot(dev, 0, false, 0, 0); - set_slot(dev, 1, false, 0, 0); + synaptics_report_semi_mt_slot(dev, 0, false, 0, 0); + synaptics_report_semi_mt_slot(dev, 1, false, 0, 0); } } -- cgit v1.1 From 28d5fd860f97f017573c4cd8f199bab867c50a11 Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Wed, 6 Jul 2011 22:57:39 -0700 Subject: Input: synaptics - process button bits in AGM packets AGM packets contain valid button bits, too. This patch refactors packet processing to parse button bits in AGM packets. However, they aren't actually used or reported. The point is to more completely process AGM packets, and prepare for future patches that may actually use AGM packet button bits. Signed-off-by: Daniel Kurtz Acked-by: Chase Douglas Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index c5c91bc..86bd89a 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -406,26 +406,10 @@ static int synaptics_parse_hw_state(const unsigned char buf[], memset(hw, 0, sizeof(struct synaptics_hw_state)); if (SYN_MODEL_NEWABS(priv->model_id)) { - hw->x = (((buf[3] & 0x10) << 8) | - ((buf[1] & 0x0f) << 8) | - buf[4]); - hw->y = (((buf[3] & 0x20) << 7) | - ((buf[1] & 0xf0) << 4) | - buf[5]); - - hw->z = buf[2]; hw->w = (((buf[0] & 0x30) >> 2) | ((buf[0] & 0x04) >> 1) | ((buf[3] & 0x04) >> 2)); - if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) { - /* Gesture packet: (x, y, z) at half resolution */ - priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1; - priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1; - priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1; - return 1; - } - hw->left = (buf[0] & 0x01) ? 1 : 0; hw->right = (buf[0] & 0x02) ? 1 : 0; @@ -448,6 +432,22 @@ static int synaptics_parse_hw_state(const unsigned char buf[], hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; } + if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) { + /* Gesture packet: (x, y, z) at half resolution */ + priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1; + priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1; + priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1; + return 1; + } + + hw->x = (((buf[3] & 0x10) << 8) | + ((buf[1] & 0x0f) << 8) | + buf[4]); + hw->y = (((buf[3] & 0x20) << 7) | + ((buf[1] & 0xf0) << 4) | + buf[5]); + hw->z = buf[2]; + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && ((buf[0] ^ buf[3]) & 0x02)) { switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { -- cgit v1.1 From a66413fbc37994710d638aec3314f735a7ac0df5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 9 Jul 2011 12:32:56 -0700 Subject: Input: synaptics - set minimum coordinates as reported by firmware Newer Synaptics firmware allows to query minimum coordinates reported by the device, let's use this data. Acked-by: Chase Douglas Acked-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 56 +++++++++++++++++++++++++++-------------- drivers/input/mouse/synaptics.h | 8 ++++-- 2 files changed, 43 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 86bd89a..5538fc6 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -207,27 +207,37 @@ static int synaptics_identify(struct psmouse *psmouse) static int synaptics_resolution(struct psmouse *psmouse) { struct synaptics_data *priv = psmouse->private; - unsigned char res[3]; - unsigned char max[3]; + unsigned char resp[3]; if (SYN_ID_MAJOR(priv->identity) < 4) return 0; - if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res) == 0) { - if (res[0] != 0 && (res[1] & 0x80) && res[2] != 0) { - priv->x_res = res[0]; /* x resolution in units/mm */ - priv->y_res = res[2]; /* y resolution in units/mm */ + if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) { + if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) { + priv->x_res = resp[0]; /* x resolution in units/mm */ + priv->y_res = resp[2]; /* y resolution in units/mm */ } } if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { - if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_DIMENSIONS, max)) { - printk(KERN_ERR "Synaptics claims to have dimensions query," - " but I'm not able to read it.\n"); + if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { + printk(KERN_ERR "Synaptics claims to have max coordinates" + " query, but I'm not able to read it.\n"); + } else { + priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); + priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); + } + } + + if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 && + SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) { + if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) { + printk(KERN_ERR "Synaptics claims to have min coordinates" + " query, but I'm not able to read it.\n"); } else { - priv->x_max = (max[0] << 5) | ((max[1] & 0x0f) << 1); - priv->y_max = (max[2] << 5) | ((max[1] & 0xf0) >> 3); + priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); + priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); } } @@ -693,19 +703,27 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) __set_bit(INPUT_PROP_POINTER, dev->propbit); __set_bit(EV_ABS, dev->evbit); - input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, - priv->x_max ?: XMAX_NOMINAL, fuzz, 0); - input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, - priv->y_max ?: YMAX_NOMINAL, fuzz, 0); + input_set_abs_params(dev, ABS_X, + priv->x_min ?: XMIN_NOMINAL, + priv->x_max ?: XMAX_NOMINAL, + fuzz, 0); + input_set_abs_params(dev, ABS_Y, + priv->y_min ?: YMIN_NOMINAL, + priv->y_max ?: YMAX_NOMINAL, + fuzz, 0); input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); input_mt_init_slots(dev, 2); - input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL, - priv->x_max ?: XMAX_NOMINAL, fuzz, 0); - input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL, - priv->y_max ?: YMAX_NOMINAL, fuzz, 0); + input_set_abs_params(dev, ABS_MT_POSITION_X, + priv->x_min ?: XMIN_NOMINAL, + priv->x_max ?: XMAX_NOMINAL, + fuzz, 0); + input_set_abs_params(dev, ABS_MT_POSITION_Y, + priv->y_min ?: YMIN_NOMINAL, + priv->y_max ?: YMAX_NOMINAL, + fuzz, 0); input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res); input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res); diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index b8025b0..a4394e1 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -19,7 +19,8 @@ #define SYN_QUE_RESOLUTION 0x08 #define SYN_QUE_EXT_CAPAB 0x09 #define SYN_QUE_EXT_CAPAB_0C 0x0c -#define SYN_QUE_EXT_DIMENSIONS 0x0d +#define SYN_QUE_EXT_MAX_COORDS 0x0d +#define SYN_QUE_EXT_MIN_COORDS 0x0f /* synatics modes */ #define SYN_BIT_ABSOLUTE_MODE (1 << 7) @@ -73,10 +74,12 @@ * 2 0x04 reduced filtering firmware does less filtering on * position data, driver should watch * for noise. + * 2 0x20 report min query 0x0f gives min coord reported */ #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) +#define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & 0x000200) #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) @@ -134,7 +137,8 @@ struct synaptics_data { unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ unsigned long int identity; /* Identification */ unsigned int x_res, y_res; /* X/Y resolution in units/mm */ - unsigned int x_max, y_max; /* Max dimensions (from FW) */ + unsigned int x_max, y_max; /* Max coordinates (from FW) */ + unsigned int x_min, y_min; /* Min coordinates (from FW) */ unsigned char pkt_type; /* packet type - old, new, etc */ unsigned char mode; /* current mode byte */ -- cgit v1.1 From eadba0c9c41bfa840b0f1e9ee369a869c2a322b3 Mon Sep 17 00:00:00 2001 From: Edwin van Vliet Date: Sun, 10 Jul 2011 16:07:28 -0700 Subject: Input: aiptek - remove double define Constant AIPTEK_TOOL_BUTTON_PEN_MODE was defined twice. Signed-off-by: Edwin van Vliet Reviewed-by: Jesper Juhl Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/aiptek.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 0a619c5..6d89fd1 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -225,7 +225,6 @@ /* toolMode codes */ #define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN -#define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN #define AIPTEK_TOOL_BUTTON_PENCIL_MODE BTN_TOOL_PENCIL #define AIPTEK_TOOL_BUTTON_BRUSH_MODE BTN_TOOL_BRUSH #define AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE BTN_TOOL_AIRBRUSH -- cgit v1.1 From fd05d08920b54d189aa247c5c5701a08e539ed0b Mon Sep 17 00:00:00 2001 From: David Jander Date: Sat, 9 Jul 2011 12:41:46 -0700 Subject: Input: gpio_keys - add support for device-tree platform data This patch enables fetching configuration data, which is normally provided via platform_data, from the device-tree instead. If the device is configured from device-tree data, the platform_data struct is not used, and button data needs to be allocated dynamically. Big part of this patch deals with confining pdata usage to the probe function, to make this possible. Signed-off-by: David Jander Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 148 +++++++++++++++++++++++++++++++++---- 1 file changed, 132 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 97bada4..ad11e86 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -2,6 +2,7 @@ * Driver for keys on GPIO lines capable of generating interrupts. * * Copyright 2005 Phil Blundell + * Copyright 2010, 2011 David Jander * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -25,6 +26,8 @@ #include #include #include +#include +#include struct gpio_button_data { struct gpio_keys_button *button; @@ -445,15 +448,120 @@ static void gpio_keys_close(struct input_dev *input) ddata->disable(input->dev.parent); } +/* + * Handlers for alternative sources of platform_data + */ +#ifdef CONFIG_OF +/* + * Translate OpenFirmware node properties into platform_data + */ +static int gpio_keys_get_devtree_pdata(struct device *dev, + struct gpio_keys_platform_data *pdata) +{ + struct device_node *node, *pp; + int i; + struct gpio_keys_button *buttons; + const u32 *reg; + int len; + + node = dev->of_node; + if (node == NULL) + return -ENODEV; + + memset(pdata, 0, sizeof *pdata); + + pdata->rep = !!of_get_property(node, "autorepeat", &len); + + /* First count the subnodes */ + pdata->nbuttons = 0; + pp = NULL; + while ((pp = of_get_next_child(node, pp))) + pdata->nbuttons++; + + if (pdata->nbuttons == 0) + return -ENODEV; + + buttons = kzalloc(pdata->nbuttons * (sizeof *buttons), GFP_KERNEL); + if (!buttons) + return -ENODEV; + + pp = NULL; + i = 0; + while ((pp = of_get_next_child(node, pp))) { + enum of_gpio_flags flags; + + if (!of_find_property(pp, "gpios", NULL)) { + pdata->nbuttons--; + dev_warn(dev, "Found button without gpios\n"); + continue; + } + buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags); + buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW; + + reg = of_get_property(pp, "linux,code", &len); + if (!reg) { + dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio); + goto out_fail; + } + buttons[i].code = be32_to_cpup(reg); + + buttons[i].desc = of_get_property(pp, "label", &len); + + reg = of_get_property(pp, "linux,input-type", &len); + buttons[i].type = reg ? be32_to_cpup(reg) : EV_KEY; + + buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); + + reg = of_get_property(pp, "debounce-interval", &len); + buttons[i].debounce_interval = reg ? be32_to_cpup(reg) : 5; + + i++; + } + + pdata->buttons = buttons; + + return 0; + +out_fail: + kfree(buttons); + return -ENODEV; +} + +static struct of_device_id gpio_keys_of_match[] = { + { .compatible = "gpio-keys", }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpio_keys_of_match); + +#else + +static int gpio_keys_get_devtree_pdata(struct device *dev, + struct gpio_keys_platform_data *altp) +{ + return -ENODEV; +} + +#define gpio_keys_of_match NULL + +#endif + static int __devinit gpio_keys_probe(struct platform_device *pdev) { struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct gpio_keys_drvdata *ddata; struct device *dev = &pdev->dev; + struct gpio_keys_platform_data alt_pdata; struct input_dev *input; int i, error; int wakeup = 0; + if (!pdata) { + error = gpio_keys_get_devtree_pdata(dev, &alt_pdata); + if (error) + return error; + pdata = &alt_pdata; + } + ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + pdata->nbuttons * sizeof(struct gpio_button_data), GFP_KERNEL); @@ -544,13 +652,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) fail1: input_free_device(input); kfree(ddata); + /* If we have no platform_data, we allocated buttons dynamically. */ + if (!pdev->dev.platform_data) + kfree(pdata->buttons); return error; } static int __devexit gpio_keys_remove(struct platform_device *pdev) { - struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); struct input_dev *input = ddata->input; int i; @@ -559,32 +669,39 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); - for (i = 0; i < pdata->nbuttons; i++) { - int irq = gpio_to_irq(pdata->buttons[i].gpio); + for (i = 0; i < ddata->n_buttons; i++) { + int irq = gpio_to_irq(ddata->data[i].button->gpio); free_irq(irq, &ddata->data[i]); if (ddata->data[i].timer_debounce) del_timer_sync(&ddata->data[i].timer); cancel_work_sync(&ddata->data[i].work); - gpio_free(pdata->buttons[i].gpio); + gpio_free(ddata->data[i].button->gpio); } input_unregister_device(input); + + /* + * If we had no platform_data, we allocated buttons dynamically, and + * must free them here. ddata->data[0].button is the pointer to the + * beginning of the allocated array. + */ + if (!pdev->dev.platform_data) + kfree(ddata->data[0].button); + kfree(ddata); return 0; } - #ifdef CONFIG_PM static int gpio_keys_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; + struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); int i; - if (device_may_wakeup(&pdev->dev)) { - for (i = 0; i < pdata->nbuttons; i++) { - struct gpio_keys_button *button = &pdata->buttons[i]; + if (device_may_wakeup(dev)) { + for (i = 0; i < ddata->n_buttons; i++) { + struct gpio_keys_button *button = ddata->data[i].button; if (button->wakeup) { int irq = gpio_to_irq(button->gpio); enable_irq_wake(irq); @@ -597,15 +714,13 @@ static int gpio_keys_suspend(struct device *dev) static int gpio_keys_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); - struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; + struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); int i; - for (i = 0; i < pdata->nbuttons; i++) { + for (i = 0; i < ddata->n_buttons; i++) { - struct gpio_keys_button *button = &pdata->buttons[i]; - if (button->wakeup && device_may_wakeup(&pdev->dev)) { + struct gpio_keys_button *button = ddata->data[i].button; + if (button->wakeup && device_may_wakeup(dev)) { int irq = gpio_to_irq(button->gpio); disable_irq_wake(irq); } @@ -632,6 +747,7 @@ static struct platform_driver gpio_keys_device_driver = { #ifdef CONFIG_PM .pm = &gpio_keys_pm_ops, #endif + .of_match_table = gpio_keys_of_match, } }; -- cgit v1.1 From bdda82162837a20e591ac01b306dc8f052270510 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 9 Jul 2011 12:41:46 -0700 Subject: Input: gpio_keys - switch to using SIMPLE_DEV_PM_OPS This reduces amount #ifdeds in the code. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index ad11e86..ce281d1 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -693,7 +693,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int gpio_keys_suspend(struct device *dev) { struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); @@ -731,22 +731,17 @@ static int gpio_keys_resume(struct device *dev) return 0; } - -static const struct dev_pm_ops gpio_keys_pm_ops = { - .suspend = gpio_keys_suspend, - .resume = gpio_keys_resume, -}; #endif +static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); + static struct platform_driver gpio_keys_device_driver = { .probe = gpio_keys_probe, .remove = __devexit_p(gpio_keys_remove), .driver = { .name = "gpio-keys", .owner = THIS_MODULE, -#ifdef CONFIG_PM .pm = &gpio_keys_pm_ops, -#endif .of_match_table = gpio_keys_of_match, } }; -- cgit v1.1 From c388b2c67e64d20cc0ad0d48d0e3e819d489bfed Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 12 Jul 2011 23:59:41 -0700 Subject: Input: atkbd - make dmi callback functions return 1 We only care about if there is a successful match from the table (or no match at all), so let's make dmi_check_system return immediately instead of iterating thorough the whole table. Make the dmi callback function return 1 then dmi_check_system will return immediately if we have a successful match. Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 11478eb..19cfc0c 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -1578,14 +1578,14 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id) atkbd_platform_fixup = atkbd_apply_forced_release_keylist; atkbd_platform_fixup_data = id->driver_data; - return 0; + return 1; } static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id) { atkbd_platform_scancode_fixup = id->driver_data; - return 0; + return 1; } static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { -- cgit v1.1 From fea2021c76a414b71204cc2aea623bb037fa913b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 13 Jul 2011 00:02:21 -0700 Subject: Input: lifebook - make dmi callback functions return 1 We only care about if there is a successful match from the table (or no match at all), so let's make dmi_check_system return immediately instead of iterating thorough the whole table. Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/lifebook.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index c31ad11..83bcaba 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -33,7 +33,7 @@ static const char *desired_serio_phys; static int lifebook_limit_serio3(const struct dmi_system_id *d) { desired_serio_phys = "isa0060/serio3"; - return 0; + return 1; } static bool lifebook_use_6byte_proto; @@ -41,7 +41,7 @@ static bool lifebook_use_6byte_proto; static int lifebook_set_6byte_proto(const struct dmi_system_id *d) { lifebook_use_6byte_proto = true; - return 0; + return 1; } static const struct dmi_system_id __initconst lifebook_dmi_table[] = { -- cgit v1.1 From 21184c4efbba7b7959c7868cf2b99f43f29fc199 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 13 Jul 2011 00:03:36 -0700 Subject: Input: cy8ctmg110_ts - fix checking return value of i2c_master_send i2c_master_send returns negative errno, or else the number of bytes written. Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cy8ctmg110_ts.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index a93c5c2..b3fdd13 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -84,9 +84,9 @@ static int cy8ctmg110_write_regs(struct cy8ctmg110 *tsc, unsigned char reg, memcpy(i2c_data + 1, value, len); ret = i2c_master_send(client, i2c_data, len + 1); - if (ret != 1) { + if (ret != len + 1) { dev_err(&client->dev, "i2c write data cmd failed\n"); - return ret ? ret : -EIO; + return ret < 0 ? ret : -EIO; } return 0; -- cgit v1.1 From d448303a77d8925fd06e7b2837bd1826e340bb02 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 13 Jul 2011 00:04:36 -0700 Subject: Input: cy8ctmg110_ts - constify i2c_device_id table Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cy8ctmg110_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index b3fdd13..ecdaae5 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -328,7 +328,7 @@ static int __devexit cy8ctmg110_remove(struct i2c_client *client) return 0; } -static struct i2c_device_id cy8ctmg110_idtable[] = { +static const struct i2c_device_id cy8ctmg110_idtable[] = { { CY8CTMG110_DRIVER_NAME, 1 }, { } }; -- cgit v1.1 From 2c204109ec1018f72114c7f19132a1109a3f0653 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 18 Jul 2011 17:09:37 -0700 Subject: Input: cy8ctmg110_ts - set reset_pin and irq_pin from platform data The implementation in cy8ctmg110_probe() does not properly set reset_pin and irq_pin from platform data. Let's fix it. Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cy8ctmg110_ts.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index ecdaae5..d8815c5 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -193,6 +193,8 @@ static int __devinit cy8ctmg110_probe(struct i2c_client *client, ts->client = client; ts->input = input_dev; + ts->reset_pin = pdata->reset_pin; + ts->irq_pin = pdata->irq_pin; snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); -- cgit v1.1 From edf21d9c38b945b91d100bae59d951bce131d58b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 18 Jul 2011 17:09:22 -0700 Subject: Input: pmic8xxx-keypad - fix a leak of the IRQ during init failure Make sure we are passing the same cookie in all calls to request_any_context_irq() and free_irq(). Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/pmic8xxx-keypad.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 40b02ae..f2e8b9a 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c @@ -699,9 +699,9 @@ static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) return 0; err_pmic_reg_read: - free_irq(kp->key_stuck_irq, NULL); + free_irq(kp->key_stuck_irq, kp); err_req_stuck_irq: - free_irq(kp->key_sense_irq, NULL); + free_irq(kp->key_sense_irq, kp); err_gpio_config: err_get_irq: input_free_device(kp->input); @@ -716,8 +716,8 @@ static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev) struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); device_init_wakeup(&pdev->dev, 0); - free_irq(kp->key_stuck_irq, NULL); - free_irq(kp->key_sense_irq, NULL); + free_irq(kp->key_stuck_irq, kp); + free_irq(kp->key_sense_irq, kp); input_unregister_device(kp->input); kfree(kp); -- cgit v1.1 From dc3e8247eb90655c0ff01ce03bdf3aa5868f1cde Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 18 Jul 2011 17:09:46 -0700 Subject: Input: hp_sdc - staticize hp_sdc_kicker() It's not referenced outside this file so there's no need for it to be in the global name space. Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/serio/hp_sdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 4220620..979c443 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c @@ -795,7 +795,7 @@ int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) /************************* Keepalive timer task *********************/ -void hp_sdc_kicker (unsigned long data) +static void hp_sdc_kicker(unsigned long data) { tasklet_schedule(&hp_sdc.task); /* Re-insert the periodic task. */ -- cgit v1.1 From e449edbb91decd0260105fadd4f5fcc3ce170e01 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 18 Jul 2011 17:09:05 -0700 Subject: Input: intel-mid-touch - remove pointless checking for variable 'found' The implementation does break from the for loop after we assign 'i' to variable 'found'. Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/intel-mid-touch.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c index 66c96bf..3276952 100644 --- a/drivers/input/touchscreen/intel-mid-touch.c +++ b/drivers/input/touchscreen/intel-mid-touch.c @@ -448,15 +448,11 @@ static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev) */ static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev) { - int err, i, found; + int found = 0; + int err, i; u8 r8; - found = -1; - for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) { - if (found >= 0) - break; - err = intel_scu_ipc_ioread8(PMICADDR0 + i, &r8); if (err) return err; @@ -466,16 +462,15 @@ static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev) break; } } - if (found < 0) - return 0; if (tsdev->vendor == PMIC_VENDOR_FS) { - if (found && found > (MRSTOUCH_MAX_CHANNELS - 18)) + if (found > MRSTOUCH_MAX_CHANNELS - 18) return -ENOSPC; } else { - if (found && found > (MRSTOUCH_MAX_CHANNELS - 4)) + if (found > MRSTOUCH_MAX_CHANNELS - 4) return -ENOSPC; } + return found; } -- cgit v1.1 From 4fd9fcf7c1ee6c339504525b43ad5e77334ff1b5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Jul 2011 23:12:21 -0700 Subject: Input: kxtj9 - fix bug in probe() We are testing the wrong variable here. I believe tj9->input_dev is always NULL at this point, so probe() will fail. Signed-off-by: Dan Carpenter Signed-off-by: Dmitry Torokhov --- drivers/input/misc/kxtj9.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index a416f7f..6c96dc3 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -301,7 +301,7 @@ static int __devinit kxtj9_setup_input_device(struct kxtj9_data *tj9) int err; input_dev = input_allocate_device(); - if (!tj9->input_dev) { + if (!input_dev) { dev_err(&tj9->client->dev, "input device allocate failed\n"); return -ENOMEM; } -- cgit v1.1 From 6eab7ce65a4e6fae1d2cb5d866515ed288f2fdcc Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 19 Jul 2011 23:16:29 -0700 Subject: Input: kxtj9 - fix locking typo in kxtj9_set_poll() According to the comments we want to call mutex_lock() here instead of mutex_unlock(). That makes more sense. Signed-off-by: Dan Carpenter Signed-off-by: Dmitry Torokhov --- drivers/input/misc/kxtj9.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index 6c96dc3..c456f63 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -362,7 +362,7 @@ static ssize_t kxtj9_set_poll(struct device *dev, struct device_attribute *attr, return error; /* Lock the device to prevent races with open/close (and itself) */ - mutex_unlock(&input_dev->mutex); + mutex_lock(&input_dev->mutex); disable_irq(client->irq); -- cgit v1.1 From 5599d2e60b1191520778def7c0658fbc6de6d8c1 Mon Sep 17 00:00:00 2001 From: Rakesh Iyer Date: Mon, 25 Jul 2011 00:49:55 -0700 Subject: Input: tegra-kbc - enable key autorepeat To support key repeats, keyboard needs to be setup as an autorepeating device. Signed-off-by: Rakesh Iyer Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tegra-kbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 2b3b73e..da3828f 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -657,7 +657,7 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) input_set_drvdata(input_dev, kbc); - input_dev->evbit[0] = BIT_MASK(EV_KEY); + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_dev->keycode = kbc->keycode; -- cgit v1.1 From 3c6b50141ef9f0a8844bf1357b80c0cdf518bf05 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 25 Jul 2011 01:36:46 -0700 Subject: Input: synaptics - fix reporting of min coordinates We were testing wrong bit in the extended capability query. Reported-by: Daniel Kurtz Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index a4394e1..ca040aa 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -79,7 +79,7 @@ #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) -#define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & 0x000200) +#define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & 0x002000) #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) -- cgit v1.1