diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-21 15:54:08 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-21 15:54:08 -0400 |
| commit | b8ce8d7222b52200e61ea29523993e20751baaaa (patch) | |
| tree | 323b47725de6726121aa78f98a88738105ee8202 /drivers/input | |
| parent | 1d11437f4fd02f9b5d3749675a1232216787dcc6 (diff) | |
| parent | 48853389f206b689260ddfd3006816779ca7a52a (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull more input subsystem updates from Dmitry Torokhov:
- an update to Atmel MXT driver that makes it functional on Google
Pixel 2 boxes (both touchpad and touchscreen)
- a new VMware VMMouse driver that should allow us drop X vmmouse
driver that requires root privileges (since it accesses ioports)
- XBox One controllers now support force feedback (rumble)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
Input: lm8333 - fix broken email address
Input: cyapa - fix setting suspend scan rate
Input: elan_i2c - fix calculating number of x and y traces.
Input: elan_i2c - report hovering contacts
Input: elants_i2c - zero-extend hardware ID in firmware name
Input: alps - document separate pointstick button bits for V2 devices
Input: atmel_mxt_ts - add support for Google Pixel 2
Input: xpad - add rumble support for Xbox One controller
Input: ff-core - use new debug macros
Input: add vmmouse driver
Input: elan_i2c - adjust for newer firmware pressure reporting
Diffstat (limited to 'drivers/input')
| -rw-r--r-- | drivers/input/ff-core.c | 10 | ||||
| -rw-r--r-- | drivers/input/joystick/xpad.c | 21 | ||||
| -rw-r--r-- | drivers/input/keyboard/lm8333.c | 4 | ||||
| -rw-r--r-- | drivers/input/mouse/Kconfig | 12 | ||||
| -rw-r--r-- | drivers/input/mouse/Makefile | 1 | ||||
| -rw-r--r-- | drivers/input/mouse/cyapa.c | 4 | ||||
| -rw-r--r-- | drivers/input/mouse/elan_i2c.h | 3 | ||||
| -rw-r--r-- | drivers/input/mouse/elan_i2c_core.c | 38 | ||||
| -rw-r--r-- | drivers/input/mouse/elan_i2c_i2c.c | 27 | ||||
| -rw-r--r-- | drivers/input/mouse/elan_i2c_smbus.c | 12 | ||||
| -rw-r--r-- | drivers/input/mouse/psmouse-base.c | 17 | ||||
| -rw-r--r-- | drivers/input/mouse/psmouse.h | 1 | ||||
| -rw-r--r-- | drivers/input/mouse/vmmouse.c | 508 | ||||
| -rw-r--r-- | drivers/input/mouse/vmmouse.h | 30 | ||||
| -rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 141 | ||||
| -rw-r--r-- | drivers/input/touchscreen/elants_i2c.c | 2 |
16 files changed, 791 insertions, 40 deletions
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index f50f6dd92274..b81c88c43452 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c | |||
| @@ -23,8 +23,6 @@ | |||
| 23 | 23 | ||
| 24 | /* #define DEBUG */ | 24 | /* #define DEBUG */ |
| 25 | 25 | ||
| 26 | #define pr_fmt(fmt) KBUILD_BASENAME ": " fmt | ||
| 27 | |||
| 28 | #include <linux/input.h> | 26 | #include <linux/input.h> |
| 29 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 30 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
| @@ -116,7 +114,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, | |||
| 116 | 114 | ||
| 117 | if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX || | 115 | if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX || |
| 118 | !test_bit(effect->type, dev->ffbit)) { | 116 | !test_bit(effect->type, dev->ffbit)) { |
| 119 | pr_debug("invalid or not supported effect type in upload\n"); | 117 | dev_dbg(&dev->dev, "invalid or not supported effect type in upload\n"); |
| 120 | return -EINVAL; | 118 | return -EINVAL; |
| 121 | } | 119 | } |
| 122 | 120 | ||
| @@ -124,7 +122,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, | |||
| 124 | (effect->u.periodic.waveform < FF_WAVEFORM_MIN || | 122 | (effect->u.periodic.waveform < FF_WAVEFORM_MIN || |
| 125 | effect->u.periodic.waveform > FF_WAVEFORM_MAX || | 123 | effect->u.periodic.waveform > FF_WAVEFORM_MAX || |
| 126 | !test_bit(effect->u.periodic.waveform, dev->ffbit))) { | 124 | !test_bit(effect->u.periodic.waveform, dev->ffbit))) { |
| 127 | pr_debug("invalid or not supported wave form in upload\n"); | 125 | dev_dbg(&dev->dev, "invalid or not supported wave form in upload\n"); |
| 128 | return -EINVAL; | 126 | return -EINVAL; |
| 129 | } | 127 | } |
| 130 | 128 | ||
| @@ -246,7 +244,7 @@ static int flush_effects(struct input_dev *dev, struct file *file) | |||
| 246 | struct ff_device *ff = dev->ff; | 244 | struct ff_device *ff = dev->ff; |
| 247 | int i; | 245 | int i; |
| 248 | 246 | ||
| 249 | pr_debug("flushing now\n"); | 247 | dev_dbg(&dev->dev, "flushing now\n"); |
| 250 | 248 | ||
| 251 | mutex_lock(&ff->mutex); | 249 | mutex_lock(&ff->mutex); |
| 252 | 250 | ||
| @@ -316,7 +314,7 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects) | |||
| 316 | int i; | 314 | int i; |
| 317 | 315 | ||
| 318 | if (!max_effects) { | 316 | if (!max_effects) { |
| 319 | pr_err("cannot allocate device without any effects\n"); | 317 | dev_err(&dev->dev, "cannot allocate device without any effects\n"); |
| 320 | return -EINVAL; | 318 | return -EINVAL; |
| 321 | } | 319 | } |
| 322 | 320 | ||
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 3aa2f3f3da5b..61c761156371 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
| @@ -31,12 +31,14 @@ | |||
| 31 | * - the iForce driver drivers/char/joystick/iforce.c | 31 | * - the iForce driver drivers/char/joystick/iforce.c |
| 32 | * - the skeleton-driver drivers/usb/usb-skeleton.c | 32 | * - the skeleton-driver drivers/usb/usb-skeleton.c |
| 33 | * - Xbox 360 information http://www.free60.org/wiki/Gamepad | 33 | * - Xbox 360 information http://www.free60.org/wiki/Gamepad |
| 34 | * - Xbox One information https://github.com/quantus/xbox-one-controller-protocol | ||
| 34 | * | 35 | * |
| 35 | * Thanks to: | 36 | * Thanks to: |
| 36 | * - ITO Takayuki for providing essential xpad information on his website | 37 | * - ITO Takayuki for providing essential xpad information on his website |
| 37 | * - Vojtech Pavlik - iforce driver / input subsystem | 38 | * - Vojtech Pavlik - iforce driver / input subsystem |
| 38 | * - Greg Kroah-Hartman - usb-skeleton driver | 39 | * - Greg Kroah-Hartman - usb-skeleton driver |
| 39 | * - XBOX Linux project - extra USB id's | 40 | * - XBOX Linux project - extra USB id's |
| 41 | * - Pekka Pöyry (quantus) - Xbox One controller reverse engineering | ||
| 40 | * | 42 | * |
| 41 | * TODO: | 43 | * TODO: |
| 42 | * - fine tune axes (especially trigger axes) | 44 | * - fine tune axes (especially trigger axes) |
| @@ -828,6 +830,23 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect | |||
| 828 | 830 | ||
| 829 | return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); | 831 | return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); |
| 830 | 832 | ||
| 833 | case XTYPE_XBOXONE: | ||
| 834 | xpad->odata[0] = 0x09; /* activate rumble */ | ||
| 835 | xpad->odata[1] = 0x08; | ||
| 836 | xpad->odata[2] = 0x00; | ||
| 837 | xpad->odata[3] = 0x08; /* continuous effect */ | ||
| 838 | xpad->odata[4] = 0x00; /* simple rumble mode */ | ||
| 839 | xpad->odata[5] = 0x03; /* L and R actuator only */ | ||
| 840 | xpad->odata[6] = 0x00; /* TODO: LT actuator */ | ||
| 841 | xpad->odata[7] = 0x00; /* TODO: RT actuator */ | ||
| 842 | xpad->odata[8] = strong / 256; /* left actuator */ | ||
| 843 | xpad->odata[9] = weak / 256; /* right actuator */ | ||
| 844 | xpad->odata[10] = 0x80; /* length of pulse */ | ||
| 845 | xpad->odata[11] = 0x00; /* stop period of pulse */ | ||
| 846 | xpad->irq_out->transfer_buffer_length = 12; | ||
| 847 | |||
| 848 | return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); | ||
| 849 | |||
| 831 | default: | 850 | default: |
| 832 | dev_dbg(&xpad->dev->dev, | 851 | dev_dbg(&xpad->dev->dev, |
| 833 | "%s - rumble command sent to unsupported xpad type: %d\n", | 852 | "%s - rumble command sent to unsupported xpad type: %d\n", |
| @@ -841,7 +860,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect | |||
| 841 | 860 | ||
| 842 | static int xpad_init_ff(struct usb_xpad *xpad) | 861 | static int xpad_init_ff(struct usb_xpad *xpad) |
| 843 | { | 862 | { |
| 844 | if (xpad->xtype == XTYPE_UNKNOWN || xpad->xtype == XTYPE_XBOXONE) | 863 | if (xpad->xtype == XTYPE_UNKNOWN) |
| 845 | return 0; | 864 | return 0; |
| 846 | 865 | ||
| 847 | input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); | 866 | input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); |
diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c index 9081cbef11ea..0ad422b8a260 100644 --- a/drivers/input/keyboard/lm8333.c +++ b/drivers/input/keyboard/lm8333.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * LM8333 keypad driver | 2 | * LM8333 keypad driver |
| 3 | * Copyright (C) 2012 Wolfram Sang, Pengutronix <w.sang@pengutronix.de> | 3 | * Copyright (C) 2012 Wolfram Sang, Pengutronix <kernel@pengutronix.de> |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
| @@ -231,6 +231,6 @@ static struct i2c_driver lm8333_driver = { | |||
| 231 | }; | 231 | }; |
| 232 | module_i2c_driver(lm8333_driver); | 232 | module_i2c_driver(lm8333_driver); |
| 233 | 233 | ||
| 234 | MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); | 234 | MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>"); |
| 235 | MODULE_DESCRIPTION("LM8333 keyboard driver"); | 235 | MODULE_DESCRIPTION("LM8333 keyboard driver"); |
| 236 | MODULE_LICENSE("GPL v2"); | 236 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 4658b5d41dd7..7462d2fc8cfe 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
| @@ -149,6 +149,18 @@ config MOUSE_PS2_FOCALTECH | |||
| 149 | 149 | ||
| 150 | If unsure, say Y. | 150 | If unsure, say Y. |
| 151 | 151 | ||
| 152 | config MOUSE_PS2_VMMOUSE | ||
| 153 | bool "Virtual mouse (vmmouse)" | ||
| 154 | depends on MOUSE_PS2 && X86 && HYPERVISOR_GUEST | ||
| 155 | help | ||
| 156 | Say Y here if you are running under control of VMware hypervisor | ||
| 157 | (ESXi, Workstation or Fusion). Also make sure that when you enable | ||
| 158 | this option, you remove the xf86-input-vmmouse user-space driver | ||
| 159 | or upgrade it to at least xf86-input-vmmouse 13.0.1, which doesn't | ||
| 160 | load in the presence of an in-kernel vmmouse driver. | ||
| 161 | |||
| 162 | If unsure, say N. | ||
| 163 | |||
| 152 | config MOUSE_SERIAL | 164 | config MOUSE_SERIAL |
| 153 | tristate "Serial mouse" | 165 | tristate "Serial mouse" |
| 154 | select SERIO | 166 | select SERIO |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 8a9c98e76d9c..793300bfbddd 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
| @@ -36,6 +36,7 @@ psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o | |||
| 36 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o | 36 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o |
| 37 | psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o | 37 | psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o |
| 38 | psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o | 38 | psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o |
| 39 | psmouse-$(CONFIG_MOUSE_PS2_VMMOUSE) += vmmouse.o | ||
| 39 | 40 | ||
| 40 | elan_i2c-objs := elan_i2c_core.o | 41 | elan_i2c-objs := elan_i2c_core.o |
| 41 | elan_i2c-$(CONFIG_MOUSE_ELAN_I2C_I2C) += elan_i2c_i2c.o | 42 | elan_i2c-$(CONFIG_MOUSE_ELAN_I2C_I2C) += elan_i2c_i2c.o |
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 58f4f6fa4857..efe148474e7f 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c | |||
| @@ -723,7 +723,7 @@ static ssize_t cyapa_update_suspend_scanrate(struct device *dev, | |||
| 723 | } else if (sysfs_streq(buf, OFF_MODE_NAME)) { | 723 | } else if (sysfs_streq(buf, OFF_MODE_NAME)) { |
| 724 | cyapa->suspend_power_mode = PWR_MODE_OFF; | 724 | cyapa->suspend_power_mode = PWR_MODE_OFF; |
| 725 | } else if (!kstrtou16(buf, 10, &sleep_time)) { | 725 | } else if (!kstrtou16(buf, 10, &sleep_time)) { |
| 726 | cyapa->suspend_sleep_time = max_t(u16, sleep_time, 1000); | 726 | cyapa->suspend_sleep_time = min_t(u16, sleep_time, 1000); |
| 727 | cyapa->suspend_power_mode = | 727 | cyapa->suspend_power_mode = |
| 728 | cyapa_sleep_time_to_pwr_cmd(cyapa->suspend_sleep_time); | 728 | cyapa_sleep_time_to_pwr_cmd(cyapa->suspend_sleep_time); |
| 729 | } else { | 729 | } else { |
| @@ -840,7 +840,7 @@ static ssize_t cyapa_update_rt_suspend_scanrate(struct device *dev, | |||
| 840 | if (error) | 840 | if (error) |
| 841 | return error; | 841 | return error; |
| 842 | 842 | ||
| 843 | cyapa->runtime_suspend_sleep_time = max_t(u16, time, 1000); | 843 | cyapa->runtime_suspend_sleep_time = min_t(u16, time, 1000); |
| 844 | cyapa->runtime_suspend_power_mode = | 844 | cyapa->runtime_suspend_power_mode = |
| 845 | cyapa_sleep_time_to_pwr_cmd(cyapa->runtime_suspend_sleep_time); | 845 | cyapa_sleep_time_to_pwr_cmd(cyapa->runtime_suspend_sleep_time); |
| 846 | 846 | ||
diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index 9b2dc015f20c..6d5f8a4c1748 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #define ETP_ENABLE_CALIBRATE 0x0002 | 25 | #define ETP_ENABLE_CALIBRATE 0x0002 |
| 26 | #define ETP_DISABLE_CALIBRATE 0x0000 | 26 | #define ETP_DISABLE_CALIBRATE 0x0000 |
| 27 | #define ETP_DISABLE_POWER 0x0001 | 27 | #define ETP_DISABLE_POWER 0x0001 |
| 28 | #define ETP_PRESSURE_OFFSET 25 | ||
| 28 | 29 | ||
| 29 | /* IAP Firmware handling */ | 30 | /* IAP Firmware handling */ |
| 30 | #define ETP_FW_NAME "elan_i2c.bin" | 31 | #define ETP_FW_NAME "elan_i2c.bin" |
| @@ -79,6 +80,8 @@ struct elan_transport_ops { | |||
| 79 | struct completion *reset_done); | 80 | struct completion *reset_done); |
| 80 | 81 | ||
| 81 | int (*get_report)(struct i2c_client *client, u8 *report); | 82 | int (*get_report)(struct i2c_client *client, u8 *report); |
| 83 | int (*get_pressure_adjustment)(struct i2c_client *client, | ||
| 84 | int *adjustment); | ||
| 82 | }; | 85 | }; |
| 83 | 86 | ||
| 84 | extern const struct elan_transport_ops elan_smbus_ops, elan_i2c_ops; | 87 | extern const struct elan_transport_ops elan_smbus_ops, elan_i2c_ops; |
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 375d98f47483..fd5068b2542d 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | * Copyright (c) 2013 ELAN Microelectronics Corp. | 4 | * Copyright (c) 2013 ELAN Microelectronics Corp. |
| 5 | * | 5 | * |
| 6 | * Author: ćž—ć”żç¶ (Duson Lin) <dusonlin@emc.com.tw> | 6 | * Author: ćž—ć”żç¶ (Duson Lin) <dusonlin@emc.com.tw> |
| 7 | * Version: 1.5.6 | 7 | * Version: 1.5.7 |
| 8 | * | 8 | * |
| 9 | * Based on cyapa driver: | 9 | * Based on cyapa driver: |
| 10 | * copyright (c) 2011-2012 Cypress Semiconductor, Inc. | 10 | * copyright (c) 2011-2012 Cypress Semiconductor, Inc. |
| @@ -40,8 +40,7 @@ | |||
| 40 | #include "elan_i2c.h" | 40 | #include "elan_i2c.h" |
| 41 | 41 | ||
| 42 | #define DRIVER_NAME "elan_i2c" | 42 | #define DRIVER_NAME "elan_i2c" |
| 43 | #define ELAN_DRIVER_VERSION "1.5.6" | 43 | #define ELAN_DRIVER_VERSION "1.5.7" |
| 44 | #define ETP_PRESSURE_OFFSET 25 | ||
| 45 | #define ETP_MAX_PRESSURE 255 | 44 | #define ETP_MAX_PRESSURE 255 |
| 46 | #define ETP_FWIDTH_REDUCE 90 | 45 | #define ETP_FWIDTH_REDUCE 90 |
| 47 | #define ETP_FINGER_WIDTH 15 | 46 | #define ETP_FINGER_WIDTH 15 |
| @@ -53,6 +52,7 @@ | |||
| 53 | #define ETP_REPORT_ID_OFFSET 2 | 52 | #define ETP_REPORT_ID_OFFSET 2 |
| 54 | #define ETP_TOUCH_INFO_OFFSET 3 | 53 | #define ETP_TOUCH_INFO_OFFSET 3 |
| 55 | #define ETP_FINGER_DATA_OFFSET 4 | 54 | #define ETP_FINGER_DATA_OFFSET 4 |
| 55 | #define ETP_HOVER_INFO_OFFSET 30 | ||
| 56 | #define ETP_MAX_REPORT_LEN 34 | 56 | #define ETP_MAX_REPORT_LEN 34 |
| 57 | 57 | ||
| 58 | /* The main device structure */ | 58 | /* The main device structure */ |
| @@ -81,7 +81,7 @@ struct elan_tp_data { | |||
| 81 | u8 sm_version; | 81 | u8 sm_version; |
| 82 | u8 iap_version; | 82 | u8 iap_version; |
| 83 | u16 fw_checksum; | 83 | u16 fw_checksum; |
| 84 | 84 | int pressure_adjustment; | |
| 85 | u8 mode; | 85 | u8 mode; |
| 86 | 86 | ||
| 87 | bool irq_wake; | 87 | bool irq_wake; |
| @@ -229,6 +229,11 @@ static int elan_query_device_info(struct elan_tp_data *data) | |||
| 229 | if (error) | 229 | if (error) |
| 230 | return error; | 230 | return error; |
| 231 | 231 | ||
| 232 | error = data->ops->get_pressure_adjustment(data->client, | ||
| 233 | &data->pressure_adjustment); | ||
| 234 | if (error) | ||
| 235 | return error; | ||
| 236 | |||
| 232 | return 0; | 237 | return 0; |
| 233 | } | 238 | } |
| 234 | 239 | ||
| @@ -721,13 +726,13 @@ static const struct attribute_group *elan_sysfs_groups[] = { | |||
| 721 | */ | 726 | */ |
| 722 | static void elan_report_contact(struct elan_tp_data *data, | 727 | static void elan_report_contact(struct elan_tp_data *data, |
| 723 | int contact_num, bool contact_valid, | 728 | int contact_num, bool contact_valid, |
| 724 | u8 *finger_data) | 729 | bool hover_event, u8 *finger_data) |
| 725 | { | 730 | { |
| 726 | struct input_dev *input = data->input; | 731 | struct input_dev *input = data->input; |
| 727 | unsigned int pos_x, pos_y; | 732 | unsigned int pos_x, pos_y; |
| 728 | unsigned int pressure, mk_x, mk_y; | 733 | unsigned int pressure, mk_x, mk_y; |
| 729 | unsigned int area_x, area_y, major, minor, new_pressure; | 734 | unsigned int area_x, area_y, major, minor; |
| 730 | 735 | unsigned int scaled_pressure; | |
| 731 | 736 | ||
| 732 | if (contact_valid) { | 737 | if (contact_valid) { |
| 733 | pos_x = ((finger_data[0] & 0xf0) << 4) | | 738 | pos_x = ((finger_data[0] & 0xf0) << 4) | |
| @@ -756,15 +761,18 @@ static void elan_report_contact(struct elan_tp_data *data, | |||
| 756 | major = max(area_x, area_y); | 761 | major = max(area_x, area_y); |
| 757 | minor = min(area_x, area_y); | 762 | minor = min(area_x, area_y); |
| 758 | 763 | ||
| 759 | new_pressure = pressure + ETP_PRESSURE_OFFSET; | 764 | scaled_pressure = pressure + data->pressure_adjustment; |
| 760 | if (new_pressure > ETP_MAX_PRESSURE) | 765 | |
| 761 | new_pressure = ETP_MAX_PRESSURE; | 766 | if (scaled_pressure > ETP_MAX_PRESSURE) |
| 767 | scaled_pressure = ETP_MAX_PRESSURE; | ||
| 762 | 768 | ||
| 763 | input_mt_slot(input, contact_num); | 769 | input_mt_slot(input, contact_num); |
| 764 | input_mt_report_slot_state(input, MT_TOOL_FINGER, true); | 770 | input_mt_report_slot_state(input, MT_TOOL_FINGER, true); |
| 765 | input_report_abs(input, ABS_MT_POSITION_X, pos_x); | 771 | input_report_abs(input, ABS_MT_POSITION_X, pos_x); |
| 766 | input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y); | 772 | input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y); |
| 767 | input_report_abs(input, ABS_MT_PRESSURE, new_pressure); | 773 | input_report_abs(input, ABS_MT_DISTANCE, hover_event); |
| 774 | input_report_abs(input, ABS_MT_PRESSURE, | ||
| 775 | hover_event ? 0 : scaled_pressure); | ||
| 768 | input_report_abs(input, ABS_TOOL_WIDTH, mk_x); | 776 | input_report_abs(input, ABS_TOOL_WIDTH, mk_x); |
| 769 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, major); | 777 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, major); |
| 770 | input_report_abs(input, ABS_MT_TOUCH_MINOR, minor); | 778 | input_report_abs(input, ABS_MT_TOUCH_MINOR, minor); |
| @@ -780,11 +788,14 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet) | |||
| 780 | u8 *finger_data = &packet[ETP_FINGER_DATA_OFFSET]; | 788 | u8 *finger_data = &packet[ETP_FINGER_DATA_OFFSET]; |
| 781 | int i; | 789 | int i; |
| 782 | u8 tp_info = packet[ETP_TOUCH_INFO_OFFSET]; | 790 | u8 tp_info = packet[ETP_TOUCH_INFO_OFFSET]; |
| 783 | bool contact_valid; | 791 | u8 hover_info = packet[ETP_HOVER_INFO_OFFSET]; |
| 792 | bool contact_valid, hover_event; | ||
| 784 | 793 | ||
| 794 | hover_event = hover_info & 0x40; | ||
| 785 | for (i = 0; i < ETP_MAX_FINGERS; i++) { | 795 | for (i = 0; i < ETP_MAX_FINGERS; i++) { |
| 786 | contact_valid = tp_info & (1U << (3 + i)); | 796 | contact_valid = tp_info & (1U << (3 + i)); |
| 787 | elan_report_contact(data, i, contact_valid, finger_data); | 797 | elan_report_contact(data, i, contact_valid, hover_event, |
| 798 | finger_data); | ||
| 788 | 799 | ||
| 789 | if (contact_valid) | 800 | if (contact_valid) |
| 790 | finger_data += ETP_FINGER_DATA_LEN; | 801 | finger_data += ETP_FINGER_DATA_LEN; |
| @@ -878,6 +889,7 @@ static int elan_setup_input_device(struct elan_tp_data *data) | |||
| 878 | ETP_FINGER_WIDTH * max_width, 0, 0); | 889 | ETP_FINGER_WIDTH * max_width, 0, 0); |
| 879 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, | 890 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, |
| 880 | ETP_FINGER_WIDTH * min_width, 0, 0); | 891 | ETP_FINGER_WIDTH * min_width, 0, 0); |
| 892 | input_set_abs_params(input, ABS_MT_DISTANCE, 0, 1, 0, 0); | ||
| 881 | 893 | ||
| 882 | data->input = input; | 894 | data->input = input; |
| 883 | 895 | ||
diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index 6cf0def6d35e..a0acbbf83bfd 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #define ETP_I2C_MAX_X_AXIS_CMD 0x0106 | 41 | #define ETP_I2C_MAX_X_AXIS_CMD 0x0106 |
| 42 | #define ETP_I2C_MAX_Y_AXIS_CMD 0x0107 | 42 | #define ETP_I2C_MAX_Y_AXIS_CMD 0x0107 |
| 43 | #define ETP_I2C_RESOLUTION_CMD 0x0108 | 43 | #define ETP_I2C_RESOLUTION_CMD 0x0108 |
| 44 | #define ETP_I2C_PRESSURE_CMD 0x010A | ||
| 44 | #define ETP_I2C_IAP_VERSION_CMD 0x0110 | 45 | #define ETP_I2C_IAP_VERSION_CMD 0x0110 |
| 45 | #define ETP_I2C_SET_CMD 0x0300 | 46 | #define ETP_I2C_SET_CMD 0x0300 |
| 46 | #define ETP_I2C_POWER_CMD 0x0307 | 47 | #define ETP_I2C_POWER_CMD 0x0307 |
| @@ -364,8 +365,29 @@ static int elan_i2c_get_num_traces(struct i2c_client *client, | |||
| 364 | return error; | 365 | return error; |
| 365 | } | 366 | } |
| 366 | 367 | ||
| 367 | *x_traces = val[0] - 1; | 368 | *x_traces = val[0]; |
| 368 | *y_traces = val[1] - 1; | 369 | *y_traces = val[1]; |
| 370 | |||
| 371 | return 0; | ||
| 372 | } | ||
| 373 | |||
| 374 | static int elan_i2c_get_pressure_adjustment(struct i2c_client *client, | ||
| 375 | int *adjustment) | ||
| 376 | { | ||
| 377 | int error; | ||
| 378 | u8 val[3]; | ||
| 379 | |||
| 380 | error = elan_i2c_read_cmd(client, ETP_I2C_PRESSURE_CMD, val); | ||
| 381 | if (error) { | ||
| 382 | dev_err(&client->dev, "failed to get pressure format: %d\n", | ||
| 383 | error); | ||
| 384 | return error; | ||
| 385 | } | ||
| 386 | |||
| 387 | if ((val[0] >> 4) & 0x1) | ||
| 388 | *adjustment = 0; | ||
| 389 | else | ||
| 390 | *adjustment = ETP_PRESSURE_OFFSET; | ||
| 369 | 391 | ||
| 370 | return 0; | 392 | return 0; |
| 371 | } | 393 | } |
| @@ -602,6 +624,7 @@ const struct elan_transport_ops elan_i2c_ops = { | |||
| 602 | .get_sm_version = elan_i2c_get_sm_version, | 624 | .get_sm_version = elan_i2c_get_sm_version, |
| 603 | .get_product_id = elan_i2c_get_product_id, | 625 | .get_product_id = elan_i2c_get_product_id, |
| 604 | .get_checksum = elan_i2c_get_checksum, | 626 | .get_checksum = elan_i2c_get_checksum, |
| 627 | .get_pressure_adjustment = elan_i2c_get_pressure_adjustment, | ||
| 605 | 628 | ||
| 606 | .get_max = elan_i2c_get_max, | 629 | .get_max = elan_i2c_get_max, |
| 607 | .get_resolution = elan_i2c_get_resolution, | 630 | .get_resolution = elan_i2c_get_resolution, |
diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c index 06a2bcd1cda2..30ab80dbcdd6 100644 --- a/drivers/input/mouse/elan_i2c_smbus.c +++ b/drivers/input/mouse/elan_i2c_smbus.c | |||
| @@ -268,12 +268,19 @@ static int elan_smbus_get_num_traces(struct i2c_client *client, | |||
| 268 | return error; | 268 | return error; |
| 269 | } | 269 | } |
| 270 | 270 | ||
| 271 | *x_traces = val[1] - 1; | 271 | *x_traces = val[1]; |
| 272 | *y_traces = val[2] - 1; | 272 | *y_traces = val[2]; |
| 273 | 273 | ||
| 274 | return 0; | 274 | return 0; |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | static int elan_smbus_get_pressure_adjustment(struct i2c_client *client, | ||
| 278 | int *adjustment) | ||
| 279 | { | ||
| 280 | *adjustment = ETP_PRESSURE_OFFSET; | ||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | |||
| 277 | static int elan_smbus_iap_get_mode(struct i2c_client *client, | 284 | static int elan_smbus_iap_get_mode(struct i2c_client *client, |
| 278 | enum tp_mode *mode) | 285 | enum tp_mode *mode) |
| 279 | { | 286 | { |
| @@ -497,6 +504,7 @@ const struct elan_transport_ops elan_smbus_ops = { | |||
| 497 | .get_sm_version = elan_smbus_get_sm_version, | 504 | .get_sm_version = elan_smbus_get_sm_version, |
| 498 | .get_product_id = elan_smbus_get_product_id, | 505 | .get_product_id = elan_smbus_get_product_id, |
| 499 | .get_checksum = elan_smbus_get_checksum, | 506 | .get_checksum = elan_smbus_get_checksum, |
| 507 | .get_pressure_adjustment = elan_smbus_get_pressure_adjustment, | ||
| 500 | 508 | ||
| 501 | .get_max = elan_smbus_get_max, | 509 | .get_max = elan_smbus_get_max, |
| 502 | .get_resolution = elan_smbus_get_resolution, | 510 | .get_resolution = elan_smbus_get_resolution, |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 27057df7ba74..5bb1658f60c7 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include "sentelic.h" | 36 | #include "sentelic.h" |
| 37 | #include "cypress_ps2.h" | 37 | #include "cypress_ps2.h" |
| 38 | #include "focaltech.h" | 38 | #include "focaltech.h" |
| 39 | #include "vmmouse.h" | ||
| 39 | 40 | ||
| 40 | #define DRIVER_DESC "PS/2 mouse driver" | 41 | #define DRIVER_DESC "PS/2 mouse driver" |
| 41 | 42 | ||
| @@ -790,6 +791,13 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
| 790 | } | 791 | } |
| 791 | } | 792 | } |
| 792 | 793 | ||
| 794 | if (psmouse_do_detect(vmmouse_detect, psmouse, set_properties) == 0) { | ||
| 795 | if (max_proto > PSMOUSE_IMEX) { | ||
| 796 | if (!set_properties || vmmouse_init(psmouse) == 0) | ||
| 797 | return PSMOUSE_VMMOUSE; | ||
| 798 | } | ||
| 799 | } | ||
| 800 | |||
| 793 | /* | 801 | /* |
| 794 | * Try Kensington ThinkingMouse (we try first, because synaptics probe | 802 | * Try Kensington ThinkingMouse (we try first, because synaptics probe |
| 795 | * upsets the thinkingmouse). | 803 | * upsets the thinkingmouse). |
| @@ -1113,6 +1121,15 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
| 1113 | .init = focaltech_init, | 1121 | .init = focaltech_init, |
| 1114 | }, | 1122 | }, |
| 1115 | #endif | 1123 | #endif |
| 1124 | #ifdef CONFIG_MOUSE_PS2_VMMOUSE | ||
| 1125 | { | ||
| 1126 | .type = PSMOUSE_VMMOUSE, | ||
| 1127 | .name = VMMOUSE_PSNAME, | ||
| 1128 | .alias = "vmmouse", | ||
| 1129 | .detect = vmmouse_detect, | ||
| 1130 | .init = vmmouse_init, | ||
| 1131 | }, | ||
| 1132 | #endif | ||
| 1116 | { | 1133 | { |
| 1117 | .type = PSMOUSE_AUTO, | 1134 | .type = PSMOUSE_AUTO, |
| 1118 | .name = "auto", | 1135 | .name = "auto", |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index d02e1bdc9ae4..ad5a5a1ea872 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
| @@ -103,6 +103,7 @@ enum psmouse_type { | |||
| 103 | PSMOUSE_SYNAPTICS_RELATIVE, | 103 | PSMOUSE_SYNAPTICS_RELATIVE, |
| 104 | PSMOUSE_CYPRESS, | 104 | PSMOUSE_CYPRESS, |
| 105 | PSMOUSE_FOCALTECH, | 105 | PSMOUSE_FOCALTECH, |
| 106 | PSMOUSE_VMMOUSE, | ||
| 106 | PSMOUSE_AUTO /* This one should always be last */ | 107 | PSMOUSE_AUTO /* This one should always be last */ |
| 107 | }; | 108 | }; |
| 108 | 109 | ||
diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c new file mode 100644 index 000000000000..e272f06258ce --- /dev/null +++ b/drivers/input/mouse/vmmouse.c | |||
| @@ -0,0 +1,508 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Virtual PS/2 Mouse on VMware and QEMU hypervisors. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014, VMware, Inc. All Rights Reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License version 2 as published by | ||
| 8 | * the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Twin device code is hugely inspired by the ALPS driver. | ||
| 11 | * Authors: | ||
| 12 | * Dmitry Torokhov <dmitry.torokhov@gmail.com> | ||
| 13 | * Thomas Hellstrom <thellstrom@vmware.com> | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/input.h> | ||
| 17 | #include <linux/serio.h> | ||
| 18 | #include <linux/libps2.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <asm/hypervisor.h> | ||
| 22 | |||
| 23 | #include "psmouse.h" | ||
| 24 | #include "vmmouse.h" | ||
| 25 | |||
| 26 | #define VMMOUSE_PROTO_MAGIC 0x564D5868U | ||
| 27 | #define VMMOUSE_PROTO_PORT 0x5658 | ||
| 28 | |||
| 29 | /* | ||
| 30 | * Main commands supported by the vmmouse hypervisor port. | ||
| 31 | */ | ||
| 32 | #define VMMOUSE_PROTO_CMD_GETVERSION 10 | ||
| 33 | #define VMMOUSE_PROTO_CMD_ABSPOINTER_DATA 39 | ||
| 34 | #define VMMOUSE_PROTO_CMD_ABSPOINTER_STATUS 40 | ||
| 35 | #define VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND 41 | ||
| 36 | #define VMMOUSE_PROTO_CMD_ABSPOINTER_RESTRICT 86 | ||
| 37 | |||
| 38 | /* | ||
| 39 | * Subcommands for VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND | ||
| 40 | */ | ||
| 41 | #define VMMOUSE_CMD_ENABLE 0x45414552U | ||
| 42 | #define VMMOUSE_CMD_DISABLE 0x000000f5U | ||
| 43 | #define VMMOUSE_CMD_REQUEST_RELATIVE 0x4c455252U | ||
| 44 | #define VMMOUSE_CMD_REQUEST_ABSOLUTE 0x53424152U | ||
| 45 | |||
| 46 | #define VMMOUSE_ERROR 0xffff0000U | ||
| 47 | |||
| 48 | #define VMMOUSE_VERSION_ID 0x3442554aU | ||
| 49 | |||
| 50 | #define VMMOUSE_RELATIVE_PACKET 0x00010000U | ||
| 51 | |||
| 52 | #define VMMOUSE_LEFT_BUTTON 0x20 | ||
| 53 | #define VMMOUSE_RIGHT_BUTTON 0x10 | ||
| 54 | #define VMMOUSE_MIDDLE_BUTTON 0x08 | ||
| 55 | |||
| 56 | /* | ||
| 57 | * VMMouse Restrict command | ||
| 58 | */ | ||
| 59 | #define VMMOUSE_RESTRICT_ANY 0x00 | ||
| 60 | #define VMMOUSE_RESTRICT_CPL0 0x01 | ||
| 61 | #define VMMOUSE_RESTRICT_IOPL 0x02 | ||
| 62 | |||
| 63 | #define VMMOUSE_MAX_X 0xFFFF | ||
| 64 | #define VMMOUSE_MAX_Y 0xFFFF | ||
| 65 | |||
| 66 | #define VMMOUSE_VENDOR "VMware" | ||
| 67 | #define VMMOUSE_NAME "VMMouse" | ||
| 68 | |||
| 69 | /** | ||
| 70 | * struct vmmouse_data - private data structure for the vmmouse driver | ||
| 71 | * | ||
| 72 | * @abs_dev: "Absolute" device used to report absolute mouse movement. | ||
| 73 | * @phys: Physical path for the absolute device. | ||
| 74 | * @dev_name: Name attribute name for the absolute device. | ||
| 75 | */ | ||
| 76 | struct vmmouse_data { | ||
| 77 | struct input_dev *abs_dev; | ||
| 78 | char phys[32]; | ||
| 79 | char dev_name[128]; | ||
| 80 | }; | ||
| 81 | |||
| 82 | /** | ||
| 83 | * Hypervisor-specific bi-directional communication channel | ||
| 84 | * implementing the vmmouse protocol. Should never execute on | ||
| 85 | * bare metal hardware. | ||
| 86 | */ | ||
| 87 | #define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4) \ | ||
| 88 | ({ \ | ||
| 89 | unsigned long __dummy1, __dummy2; \ | ||
| 90 | __asm__ __volatile__ ("inl %%dx" : \ | ||
| 91 | "=a"(out1), \ | ||
| 92 | "=b"(out2), \ | ||
| 93 | "=c"(out3), \ | ||
| 94 | "=d"(out4), \ | ||
| 95 | "=S"(__dummy1), \ | ||
| 96 | "=D"(__dummy2) : \ | ||
| 97 | "a"(VMMOUSE_PROTO_MAGIC), \ | ||
| 98 | "b"(in1), \ | ||
| 99 | "c"(VMMOUSE_PROTO_CMD_##cmd), \ | ||
| 100 | "d"(VMMOUSE_PROTO_PORT) : \ | ||
| 101 | "memory"); \ | ||
| 102 | }) | ||
| 103 | |||
| 104 | /** | ||
| 105 | * vmmouse_report_button - report button state on the correct input device | ||
| 106 | * | ||
| 107 | * @psmouse: Pointer to the psmouse struct | ||
| 108 | * @abs_dev: The absolute input device | ||
| 109 | * @rel_dev: The relative input device | ||
| 110 | * @pref_dev: The preferred device for reporting | ||
| 111 | * @code: Button code | ||
| 112 | * @value: Button value | ||
| 113 | * | ||
| 114 | * Report @value and @code on @pref_dev, unless the button is already | ||
| 115 | * pressed on the other device, in which case the state is reported on that | ||
| 116 | * device. | ||
| 117 | */ | ||
| 118 | static void vmmouse_report_button(struct psmouse *psmouse, | ||
| 119 | struct input_dev *abs_dev, | ||
| 120 | struct input_dev *rel_dev, | ||
| 121 | struct input_dev *pref_dev, | ||
| 122 | unsigned int code, int value) | ||
| 123 | { | ||
| 124 | if (test_bit(code, abs_dev->key)) | ||
| 125 | pref_dev = abs_dev; | ||
| 126 | else if (test_bit(code, rel_dev->key)) | ||
| 127 | pref_dev = rel_dev; | ||
| 128 | |||
| 129 | input_report_key(pref_dev, code, value); | ||
| 130 | } | ||
| 131 | |||
| 132 | /** | ||
| 133 | * vmmouse_report_events - process events on the vmmouse communications channel | ||
| 134 | * | ||
| 135 | * @psmouse: Pointer to the psmouse struct | ||
| 136 | * | ||
| 137 | * This function pulls events from the vmmouse communications channel and | ||
| 138 | * reports them on the correct (absolute or relative) input device. When the | ||
| 139 | * communications channel is drained, or if we've processed more than 255 | ||
| 140 | * psmouse commands, the function returns PSMOUSE_FULL_PACKET. If there is a | ||
| 141 | * host- or synchronization error, the function returns PSMOUSE_BAD_DATA in | ||
| 142 | * the hope that the caller will reset the communications channel. | ||
| 143 | */ | ||
| 144 | static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse) | ||
| 145 | { | ||
| 146 | struct input_dev *rel_dev = psmouse->dev; | ||
| 147 | struct vmmouse_data *priv = psmouse->private; | ||
| 148 | struct input_dev *abs_dev = priv->abs_dev; | ||
| 149 | struct input_dev *pref_dev; | ||
| 150 | u32 status, x, y, z; | ||
| 151 | u32 dummy1, dummy2, dummy3; | ||
| 152 | unsigned int queue_length; | ||
| 153 | unsigned int count = 255; | ||
| 154 | |||
| 155 | while (count--) { | ||
| 156 | /* See if we have motion data. */ | ||
| 157 | VMMOUSE_CMD(ABSPOINTER_STATUS, 0, | ||
| 158 | status, dummy1, dummy2, dummy3); | ||
| 159 | if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) { | ||
| 160 | psmouse_err(psmouse, "failed to fetch status data\n"); | ||
| 161 | /* | ||
| 162 | * After a few attempts this will result in | ||
| 163 | * reconnect. | ||
| 164 | */ | ||
| 165 | return PSMOUSE_BAD_DATA; | ||
| 166 | } | ||
| 167 | |||
| 168 | queue_length = status & 0xffff; | ||
| 169 | if (queue_length == 0) | ||
| 170 | break; | ||
| 171 | |||
| 172 | if (queue_length % 4) { | ||
| 173 | psmouse_err(psmouse, "invalid queue length\n"); | ||
| 174 | return PSMOUSE_BAD_DATA; | ||
| 175 | } | ||
| 176 | |||
| 177 | /* Now get it */ | ||
| 178 | VMMOUSE_CMD(ABSPOINTER_DATA, 4, status, x, y, z); | ||
| 179 | |||
| 180 | /* | ||
| 181 | * And report what we've got. Prefer to report button | ||
| 182 | * events on the same device where we report motion events. | ||
| 183 | * This doesn't work well with the mouse wheel, though. See | ||
| 184 | * below. Ideally we would want to report that on the | ||
| 185 | * preferred device as well. | ||
| 186 | */ | ||
| 187 | if (status & VMMOUSE_RELATIVE_PACKET) { | ||
| 188 | pref_dev = rel_dev; | ||
| 189 | input_report_rel(rel_dev, REL_X, (s32)x); | ||
| 190 | input_report_rel(rel_dev, REL_Y, -(s32)y); | ||
| 191 | } else { | ||
| 192 | pref_dev = abs_dev; | ||
| 193 | input_report_abs(abs_dev, ABS_X, x); | ||
| 194 | input_report_abs(abs_dev, ABS_Y, y); | ||
| 195 | } | ||
| 196 | |||
| 197 | /* Xorg seems to ignore wheel events on absolute devices */ | ||
| 198 | input_report_rel(rel_dev, REL_WHEEL, -(s8)((u8) z)); | ||
| 199 | |||
| 200 | vmmouse_report_button(psmouse, abs_dev, rel_dev, | ||
| 201 | pref_dev, BTN_LEFT, | ||
| 202 | status & VMMOUSE_LEFT_BUTTON); | ||
| 203 | vmmouse_report_button(psmouse, abs_dev, rel_dev, | ||
| 204 | pref_dev, BTN_RIGHT, | ||
| 205 | status & VMMOUSE_RIGHT_BUTTON); | ||
| 206 | vmmouse_report_button(psmouse, abs_dev, rel_dev, | ||
| 207 | pref_dev, BTN_MIDDLE, | ||
| 208 | status & VMMOUSE_MIDDLE_BUTTON); | ||
| 209 | input_sync(abs_dev); | ||
| 210 | input_sync(rel_dev); | ||
| 211 | } | ||
| 212 | |||
| 213 | return PSMOUSE_FULL_PACKET; | ||
| 214 | } | ||
| 215 | |||
| 216 | /** | ||
| 217 | * vmmouse_process_byte - process data on the ps/2 channel | ||
| 218 | * | ||
| 219 | * @psmouse: Pointer to the psmouse struct | ||
| 220 | * | ||
| 221 | * When the ps/2 channel indicates that there is vmmouse data available, | ||
| 222 | * call vmmouse channel processing. Otherwise, continue to accept bytes. If | ||
| 223 | * there is a synchronization or communication data error, return | ||
| 224 | * PSMOUSE_BAD_DATA in the hope that the caller will reset the mouse. | ||
| 225 | */ | ||
| 226 | static psmouse_ret_t vmmouse_process_byte(struct psmouse *psmouse) | ||
| 227 | { | ||
| 228 | unsigned char *packet = psmouse->packet; | ||
| 229 | |||
| 230 | switch (psmouse->pktcnt) { | ||
| 231 | case 1: | ||
| 232 | return (packet[0] & 0x8) == 0x8 ? | ||
| 233 | PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA; | ||
| 234 | |||
| 235 | case 2: | ||
| 236 | return PSMOUSE_GOOD_DATA; | ||
| 237 | |||
| 238 | default: | ||
| 239 | return vmmouse_report_events(psmouse); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | /** | ||
| 244 | * vmmouse_disable - Disable vmmouse | ||
| 245 | * | ||
| 246 | * @psmouse: Pointer to the psmouse struct | ||
| 247 | * | ||
| 248 | * Tries to disable vmmouse mode. | ||
| 249 | */ | ||
| 250 | static void vmmouse_disable(struct psmouse *psmouse) | ||
| 251 | { | ||
| 252 | u32 status; | ||
| 253 | u32 dummy1, dummy2, dummy3, dummy4; | ||
| 254 | |||
| 255 | VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE, | ||
| 256 | dummy1, dummy2, dummy3, dummy4); | ||
| 257 | |||
| 258 | VMMOUSE_CMD(ABSPOINTER_STATUS, 0, | ||
| 259 | status, dummy1, dummy2, dummy3); | ||
| 260 | |||
| 261 | if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR) | ||
| 262 | psmouse_warn(psmouse, "failed to disable vmmouse device\n"); | ||
| 263 | } | ||
| 264 | |||
| 265 | /** | ||
| 266 | * vmmouse_enable - Enable vmmouse and request absolute mode. | ||
| 267 | * | ||
| 268 | * @psmouse: Pointer to the psmouse struct | ||
| 269 | * | ||
| 270 | * Tries to enable vmmouse mode. Performs basic checks and requests | ||
| 271 | * absolute vmmouse mode. | ||
| 272 | * Returns 0 on success, -ENODEV on failure. | ||
| 273 | */ | ||
| 274 | static int vmmouse_enable(struct psmouse *psmouse) | ||
| 275 | { | ||
| 276 | u32 status, version; | ||
| 277 | u32 dummy1, dummy2, dummy3, dummy4; | ||
| 278 | |||
| 279 | /* | ||
| 280 | * Try enabling the device. If successful, we should be able to | ||
| 281 | * read valid version ID back from it. | ||
| 282 | */ | ||
| 283 | VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE, | ||
| 284 | dummy1, dummy2, dummy3, dummy4); | ||
| 285 | |||
| 286 | /* | ||
| 287 | * See if version ID can be retrieved. | ||
| 288 | */ | ||
| 289 | VMMOUSE_CMD(ABSPOINTER_STATUS, 0, status, dummy1, dummy2, dummy3); | ||
| 290 | if ((status & 0x0000ffff) == 0) { | ||
| 291 | psmouse_dbg(psmouse, "empty flags - assuming no device\n"); | ||
| 292 | return -ENXIO; | ||
| 293 | } | ||
| 294 | |||
| 295 | VMMOUSE_CMD(ABSPOINTER_DATA, 1 /* single item */, | ||
| 296 | version, dummy1, dummy2, dummy3); | ||
| 297 | if (version != VMMOUSE_VERSION_ID) { | ||
| 298 | psmouse_dbg(psmouse, "Unexpected version value: %u vs %u\n", | ||
| 299 | (unsigned) version, VMMOUSE_VERSION_ID); | ||
| 300 | vmmouse_disable(psmouse); | ||
| 301 | return -ENXIO; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* | ||
| 305 | * Restrict ioport access, if possible. | ||
| 306 | */ | ||
| 307 | VMMOUSE_CMD(ABSPOINTER_RESTRICT, VMMOUSE_RESTRICT_CPL0, | ||
| 308 | dummy1, dummy2, dummy3, dummy4); | ||
| 309 | |||
| 310 | VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_REQUEST_ABSOLUTE, | ||
| 311 | dummy1, dummy2, dummy3, dummy4); | ||
| 312 | |||
| 313 | return 0; | ||
| 314 | } | ||
| 315 | |||
| 316 | /* | ||
| 317 | * Array of supported hypervisors. | ||
| 318 | */ | ||
| 319 | static const struct hypervisor_x86 *vmmouse_supported_hypervisors[] = { | ||
| 320 | &x86_hyper_vmware, | ||
| 321 | #ifdef CONFIG_KVM_GUEST | ||
| 322 | &x86_hyper_kvm, | ||
| 323 | #endif | ||
| 324 | }; | ||
| 325 | |||
| 326 | /** | ||
| 327 | * vmmouse_check_hypervisor - Check if we're running on a supported hypervisor | ||
| 328 | */ | ||
| 329 | static bool vmmouse_check_hypervisor(void) | ||
| 330 | { | ||
| 331 | int i; | ||
| 332 | |||
| 333 | for (i = 0; i < ARRAY_SIZE(vmmouse_supported_hypervisors); i++) | ||
| 334 | if (vmmouse_supported_hypervisors[i] == x86_hyper) | ||
| 335 | return true; | ||
| 336 | |||
| 337 | return false; | ||
| 338 | } | ||
| 339 | |||
| 340 | /** | ||
| 341 | * vmmouse_detect - Probe whether vmmouse is available | ||
| 342 | * | ||
| 343 | * @psmouse: Pointer to the psmouse struct | ||
| 344 | * @set_properties: Whether to set psmouse name and vendor | ||
| 345 | * | ||
| 346 | * Returns 0 if vmmouse channel is available. Negative error code if not. | ||
| 347 | */ | ||
| 348 | int vmmouse_detect(struct psmouse *psmouse, bool set_properties) | ||
| 349 | { | ||
| 350 | u32 response, version, dummy1, dummy2; | ||
| 351 | |||
| 352 | if (!vmmouse_check_hypervisor()) { | ||
| 353 | psmouse_dbg(psmouse, | ||
| 354 | "VMMouse not running on supported hypervisor.\n"); | ||
| 355 | return -ENXIO; | ||
| 356 | } | ||
| 357 | |||
| 358 | if (!request_region(VMMOUSE_PROTO_PORT, 4, "vmmouse")) { | ||
| 359 | psmouse_dbg(psmouse, "VMMouse port in use.\n"); | ||
| 360 | return -EBUSY; | ||
| 361 | } | ||
| 362 | |||
| 363 | /* Check if the device is present */ | ||
| 364 | response = ~VMMOUSE_PROTO_MAGIC; | ||
| 365 | VMMOUSE_CMD(GETVERSION, 0, version, response, dummy1, dummy2); | ||
| 366 | if (response != VMMOUSE_PROTO_MAGIC || version == 0xffffffffU) { | ||
| 367 | release_region(VMMOUSE_PROTO_PORT, 4); | ||
| 368 | return -ENXIO; | ||
| 369 | } | ||
| 370 | |||
| 371 | if (set_properties) { | ||
| 372 | psmouse->vendor = VMMOUSE_VENDOR; | ||
| 373 | psmouse->name = VMMOUSE_NAME; | ||
| 374 | psmouse->model = version; | ||
| 375 | } | ||
| 376 | |||
| 377 | release_region(VMMOUSE_PROTO_PORT, 4); | ||
| 378 | |||
| 379 | return 0; | ||
| 380 | } | ||
| 381 | |||
| 382 | /** | ||
| 383 | * vmmouse_disconnect - Take down vmmouse driver | ||
| 384 | * | ||
| 385 | * @psmouse: Pointer to the psmouse struct | ||
| 386 | * | ||
| 387 | * Takes down vmmouse driver and frees resources set up in vmmouse_init(). | ||
| 388 | */ | ||
| 389 | static void vmmouse_disconnect(struct psmouse *psmouse) | ||
| 390 | { | ||
| 391 | struct vmmouse_data *priv = psmouse->private; | ||
| 392 | |||
| 393 | vmmouse_disable(psmouse); | ||
| 394 | psmouse_reset(psmouse); | ||
| 395 | input_unregister_device(priv->abs_dev); | ||
| 396 | kfree(priv); | ||
| 397 | release_region(VMMOUSE_PROTO_PORT, 4); | ||
| 398 | } | ||
| 399 | |||
| 400 | /** | ||
| 401 | * vmmouse_reconnect - Reset the ps/2 - and vmmouse connections | ||
| 402 | * | ||
| 403 | * @psmouse: Pointer to the psmouse struct | ||
| 404 | * | ||
| 405 | * Attempts to reset the mouse connections. Returns 0 on success and | ||
| 406 | * -1 on failure. | ||
| 407 | */ | ||
| 408 | static int vmmouse_reconnect(struct psmouse *psmouse) | ||
| 409 | { | ||
| 410 | int error; | ||
| 411 | |||
| 412 | psmouse_reset(psmouse); | ||
| 413 | vmmouse_disable(psmouse); | ||
| 414 | error = vmmouse_enable(psmouse); | ||
| 415 | if (error) { | ||
| 416 | psmouse_err(psmouse, | ||
| 417 | "Unable to re-enable mouse when reconnecting, err: %d\n", | ||
| 418 | error); | ||
| 419 | return error; | ||
| 420 | } | ||
| 421 | |||
| 422 | return 0; | ||
| 423 | } | ||
| 424 | |||
| 425 | /** | ||
| 426 | * vmmouse_init - Initialize the vmmouse driver | ||
| 427 | * | ||
| 428 | * @psmouse: Pointer to the psmouse struct | ||
| 429 | * | ||
| 430 | * Requests the device and tries to enable vmmouse mode. | ||
| 431 | * If successful, sets up the input device for relative movement events. | ||
| 432 | * It also allocates another input device and sets it up for absolute motion | ||
| 433 | * events. Returns 0 on success and -1 on failure. | ||
| 434 | */ | ||
| 435 | int vmmouse_init(struct psmouse *psmouse) | ||
| 436 | { | ||
| 437 | struct vmmouse_data *priv; | ||
| 438 | struct input_dev *rel_dev = psmouse->dev, *abs_dev; | ||
| 439 | int error; | ||
| 440 | |||
| 441 | if (!request_region(VMMOUSE_PROTO_PORT, 4, "vmmouse")) { | ||
| 442 | psmouse_dbg(psmouse, "VMMouse port in use.\n"); | ||
| 443 | return -EBUSY; | ||
| 444 | } | ||
| 445 | |||
| 446 | psmouse_reset(psmouse); | ||
| 447 | error = vmmouse_enable(psmouse); | ||
| 448 | if (error) | ||
| 449 | goto release_region; | ||
| 450 | |||
| 451 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 452 | abs_dev = input_allocate_device(); | ||
| 453 | if (!priv || !abs_dev) { | ||
| 454 | error = -ENOMEM; | ||
| 455 | goto init_fail; | ||
| 456 | } | ||
| 457 | |||
| 458 | priv->abs_dev = abs_dev; | ||
| 459 | psmouse->private = priv; | ||
| 460 | |||
| 461 | input_set_capability(rel_dev, EV_REL, REL_WHEEL); | ||
| 462 | |||
| 463 | /* Set up and register absolute device */ | ||
| 464 | snprintf(priv->phys, sizeof(priv->phys), "%s/input1", | ||
| 465 | psmouse->ps2dev.serio->phys); | ||
| 466 | |||
| 467 | /* Mimic name setup for relative device in psmouse-base.c */ | ||
| 468 | snprintf(priv->dev_name, sizeof(priv->dev_name), "%s %s %s", | ||
| 469 | VMMOUSE_PSNAME, VMMOUSE_VENDOR, VMMOUSE_NAME); | ||
| 470 | abs_dev->phys = priv->phys; | ||
| 471 | abs_dev->name = priv->dev_name; | ||
| 472 | abs_dev->id.bustype = BUS_I8042; | ||
| 473 | abs_dev->id.vendor = 0x0002; | ||
| 474 | abs_dev->id.product = PSMOUSE_VMMOUSE; | ||
| 475 | abs_dev->id.version = psmouse->model; | ||
| 476 | abs_dev->dev.parent = &psmouse->ps2dev.serio->dev; | ||
| 477 | |||
| 478 | error = input_register_device(priv->abs_dev); | ||
| 479 | if (error) | ||
| 480 | goto init_fail; | ||
| 481 | |||
| 482 | /* Set absolute device capabilities */ | ||
| 483 | input_set_capability(abs_dev, EV_KEY, BTN_LEFT); | ||
| 484 | input_set_capability(abs_dev, EV_KEY, BTN_RIGHT); | ||
| 485 | input_set_capability(abs_dev, EV_KEY, BTN_MIDDLE); | ||
| 486 | input_set_capability(abs_dev, EV_ABS, ABS_X); | ||
| 487 | input_set_capability(abs_dev, EV_ABS, ABS_Y); | ||
| 488 | input_set_abs_params(abs_dev, ABS_X, 0, VMMOUSE_MAX_X, 0, 0); | ||
| 489 | input_set_abs_params(abs_dev, ABS_Y, 0, VMMOUSE_MAX_Y, 0, 0); | ||
| 490 | |||
| 491 | psmouse->protocol_handler = vmmouse_process_byte; | ||
| 492 | psmouse->disconnect = vmmouse_disconnect; | ||
| 493 | psmouse->reconnect = vmmouse_reconnect; | ||
| 494 | |||
| 495 | return 0; | ||
| 496 | |||
| 497 | init_fail: | ||
| 498 | vmmouse_disable(psmouse); | ||
| 499 | psmouse_reset(psmouse); | ||
| 500 | input_free_device(abs_dev); | ||
| 501 | kfree(priv); | ||
| 502 | psmouse->private = NULL; | ||
| 503 | |||
| 504 | release_region: | ||
| 505 | release_region(VMMOUSE_PROTO_PORT, 4); | ||
| 506 | |||
| 507 | return error; | ||
| 508 | } | ||
diff --git a/drivers/input/mouse/vmmouse.h b/drivers/input/mouse/vmmouse.h new file mode 100644 index 000000000000..6f126017a24c --- /dev/null +++ b/drivers/input/mouse/vmmouse.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Virtual PS/2 Mouse on VMware and QEMU hypervisors. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014, VMware, Inc. All Rights Reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License version 2 as published by | ||
| 8 | * the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef _VMMOUSE_H | ||
| 12 | #define _VMMOUSE_H | ||
| 13 | |||
| 14 | #ifdef CONFIG_MOUSE_PS2_VMMOUSE | ||
| 15 | #define VMMOUSE_PSNAME "VirtualPS/2" | ||
| 16 | |||
| 17 | int vmmouse_detect(struct psmouse *psmouse, bool set_properties); | ||
| 18 | int vmmouse_init(struct psmouse *psmouse); | ||
| 19 | #else | ||
| 20 | static inline int vmmouse_detect(struct psmouse *psmouse, bool set_properties) | ||
| 21 | { | ||
| 22 | return -ENOSYS; | ||
| 23 | } | ||
| 24 | static inline int vmmouse_init(struct psmouse *psmouse) | ||
| 25 | { | ||
| 26 | return -ENOSYS; | ||
| 27 | } | ||
| 28 | #endif | ||
| 29 | |||
| 30 | #endif | ||
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 2875ddf37289..40b98dda8f38 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | * | 14 | * |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #include <linux/acpi.h> | ||
| 18 | #include <linux/dmi.h> | ||
| 17 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 18 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 19 | #include <linux/completion.h> | 21 | #include <linux/completion.h> |
| @@ -2371,7 +2373,7 @@ static void mxt_input_close(struct input_dev *dev) | |||
| 2371 | } | 2373 | } |
| 2372 | 2374 | ||
| 2373 | #ifdef CONFIG_OF | 2375 | #ifdef CONFIG_OF |
| 2374 | static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) | 2376 | static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) |
| 2375 | { | 2377 | { |
| 2376 | struct mxt_platform_data *pdata; | 2378 | struct mxt_platform_data *pdata; |
| 2377 | u32 *keymap; | 2379 | u32 *keymap; |
| @@ -2379,7 +2381,7 @@ static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) | |||
| 2379 | int proplen, i, ret; | 2381 | int proplen, i, ret; |
| 2380 | 2382 | ||
| 2381 | if (!client->dev.of_node) | 2383 | if (!client->dev.of_node) |
| 2382 | return ERR_PTR(-ENODEV); | 2384 | return ERR_PTR(-ENOENT); |
| 2383 | 2385 | ||
| 2384 | pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); | 2386 | pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); |
| 2385 | if (!pdata) | 2387 | if (!pdata) |
| @@ -2410,25 +2412,132 @@ static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) | |||
| 2410 | return pdata; | 2412 | return pdata; |
| 2411 | } | 2413 | } |
| 2412 | #else | 2414 | #else |
| 2413 | static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) | 2415 | static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) |
| 2414 | { | 2416 | { |
| 2415 | dev_dbg(&client->dev, "No platform data specified\n"); | 2417 | return ERR_PTR(-ENOENT); |
| 2416 | return ERR_PTR(-EINVAL); | 2418 | } |
| 2419 | #endif | ||
| 2420 | |||
| 2421 | #ifdef CONFIG_ACPI | ||
| 2422 | |||
| 2423 | struct mxt_acpi_platform_data { | ||
| 2424 | const char *hid; | ||
| 2425 | struct mxt_platform_data pdata; | ||
| 2426 | }; | ||
| 2427 | |||
| 2428 | static unsigned int samus_touchpad_buttons[] = { | ||
| 2429 | KEY_RESERVED, | ||
| 2430 | KEY_RESERVED, | ||
| 2431 | KEY_RESERVED, | ||
| 2432 | BTN_LEFT | ||
| 2433 | }; | ||
| 2434 | |||
| 2435 | static struct mxt_acpi_platform_data samus_platform_data[] = { | ||
| 2436 | { | ||
| 2437 | /* Touchpad */ | ||
| 2438 | .hid = "ATML0000", | ||
| 2439 | .pdata = { | ||
| 2440 | .t19_num_keys = ARRAY_SIZE(samus_touchpad_buttons), | ||
| 2441 | .t19_keymap = samus_touchpad_buttons, | ||
| 2442 | }, | ||
| 2443 | }, | ||
| 2444 | { | ||
| 2445 | /* Touchscreen */ | ||
| 2446 | .hid = "ATML0001", | ||
| 2447 | }, | ||
| 2448 | { } | ||
| 2449 | }; | ||
| 2450 | |||
| 2451 | static const struct dmi_system_id mxt_dmi_table[] = { | ||
| 2452 | { | ||
| 2453 | /* 2015 Google Pixel */ | ||
| 2454 | .ident = "Chromebook Pixel 2", | ||
| 2455 | .matches = { | ||
| 2456 | DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), | ||
| 2457 | DMI_MATCH(DMI_PRODUCT_NAME, "Samus"), | ||
| 2458 | }, | ||
| 2459 | .driver_data = samus_platform_data, | ||
| 2460 | }, | ||
| 2461 | { } | ||
| 2462 | }; | ||
| 2463 | |||
| 2464 | static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client) | ||
| 2465 | { | ||
| 2466 | struct acpi_device *adev; | ||
| 2467 | const struct dmi_system_id *system_id; | ||
| 2468 | const struct mxt_acpi_platform_data *acpi_pdata; | ||
| 2469 | |||
| 2470 | /* | ||
| 2471 | * Ignore ACPI devices representing bootloader mode. | ||
| 2472 | * | ||
| 2473 | * This is a bit of a hack: Google Chromebook BIOS creates ACPI | ||
| 2474 | * devices for both application and bootloader modes, but we are | ||
| 2475 | * interested in application mode only (if device is in bootloader | ||
| 2476 | * mode we'll end up switching into application anyway). So far | ||
| 2477 | * application mode addresses were all above 0x40, so we'll use it | ||
| 2478 | * as a threshold. | ||
| 2479 | */ | ||
| 2480 | if (client->addr < 0x40) | ||
| 2481 | return ERR_PTR(-ENXIO); | ||
| 2482 | |||
| 2483 | adev = ACPI_COMPANION(&client->dev); | ||
| 2484 | if (!adev) | ||
| 2485 | return ERR_PTR(-ENOENT); | ||
| 2486 | |||
| 2487 | system_id = dmi_first_match(mxt_dmi_table); | ||
| 2488 | if (!system_id) | ||
| 2489 | return ERR_PTR(-ENOENT); | ||
| 2490 | |||
| 2491 | acpi_pdata = system_id->driver_data; | ||
| 2492 | if (!acpi_pdata) | ||
| 2493 | return ERR_PTR(-ENOENT); | ||
| 2494 | |||
| 2495 | while (acpi_pdata->hid) { | ||
| 2496 | if (!strcmp(acpi_device_hid(adev), acpi_pdata->hid)) | ||
| 2497 | return &acpi_pdata->pdata; | ||
| 2498 | |||
| 2499 | acpi_pdata++; | ||
| 2500 | } | ||
| 2501 | |||
| 2502 | return ERR_PTR(-ENOENT); | ||
| 2503 | } | ||
| 2504 | #else | ||
| 2505 | static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client) | ||
| 2506 | { | ||
| 2507 | return ERR_PTR(-ENOENT); | ||
| 2417 | } | 2508 | } |
| 2418 | #endif | 2509 | #endif |
| 2419 | 2510 | ||
| 2511 | static const struct mxt_platform_data * | ||
| 2512 | mxt_get_platform_data(struct i2c_client *client) | ||
| 2513 | { | ||
| 2514 | const struct mxt_platform_data *pdata; | ||
| 2515 | |||
| 2516 | pdata = dev_get_platdata(&client->dev); | ||
| 2517 | if (pdata) | ||
| 2518 | return pdata; | ||
| 2519 | |||
| 2520 | pdata = mxt_parse_dt(client); | ||
| 2521 | if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT) | ||
| 2522 | return pdata; | ||
| 2523 | |||
| 2524 | pdata = mxt_parse_acpi(client); | ||
| 2525 | if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT) | ||
| 2526 | return pdata; | ||
| 2527 | |||
| 2528 | dev_err(&client->dev, "No platform data specified\n"); | ||
| 2529 | return ERR_PTR(-EINVAL); | ||
| 2530 | } | ||
| 2531 | |||
| 2420 | static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) | 2532 | static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) |
| 2421 | { | 2533 | { |
| 2422 | struct mxt_data *data; | 2534 | struct mxt_data *data; |
| 2423 | const struct mxt_platform_data *pdata; | 2535 | const struct mxt_platform_data *pdata; |
| 2424 | int error; | 2536 | int error; |
| 2425 | 2537 | ||
| 2426 | pdata = dev_get_platdata(&client->dev); | 2538 | pdata = mxt_get_platform_data(client); |
| 2427 | if (!pdata) { | 2539 | if (IS_ERR(pdata)) |
| 2428 | pdata = mxt_parse_dt(client); | 2540 | return PTR_ERR(pdata); |
| 2429 | if (IS_ERR(pdata)) | ||
| 2430 | return PTR_ERR(pdata); | ||
| 2431 | } | ||
| 2432 | 2541 | ||
| 2433 | data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); | 2542 | data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); |
| 2434 | if (!data) { | 2543 | if (!data) { |
| @@ -2536,6 +2645,15 @@ static const struct of_device_id mxt_of_match[] = { | |||
| 2536 | }; | 2645 | }; |
| 2537 | MODULE_DEVICE_TABLE(of, mxt_of_match); | 2646 | MODULE_DEVICE_TABLE(of, mxt_of_match); |
| 2538 | 2647 | ||
| 2648 | #ifdef CONFIG_ACPI | ||
| 2649 | static const struct acpi_device_id mxt_acpi_id[] = { | ||
| 2650 | { "ATML0000", 0 }, /* Touchpad */ | ||
| 2651 | { "ATML0001", 0 }, /* Touchscreen */ | ||
| 2652 | { } | ||
| 2653 | }; | ||
| 2654 | MODULE_DEVICE_TABLE(acpi, mxt_acpi_id); | ||
| 2655 | #endif | ||
| 2656 | |||
| 2539 | static const struct i2c_device_id mxt_id[] = { | 2657 | static const struct i2c_device_id mxt_id[] = { |
| 2540 | { "qt602240_ts", 0 }, | 2658 | { "qt602240_ts", 0 }, |
| 2541 | { "atmel_mxt_ts", 0 }, | 2659 | { "atmel_mxt_ts", 0 }, |
| @@ -2550,6 +2668,7 @@ static struct i2c_driver mxt_driver = { | |||
| 2550 | .name = "atmel_mxt_ts", | 2668 | .name = "atmel_mxt_ts", |
| 2551 | .owner = THIS_MODULE, | 2669 | .owner = THIS_MODULE, |
| 2552 | .of_match_table = of_match_ptr(mxt_of_match), | 2670 | .of_match_table = of_match_ptr(mxt_of_match), |
| 2671 | .acpi_match_table = ACPI_PTR(mxt_acpi_id), | ||
| 2553 | .pm = &mxt_pm_ops, | 2672 | .pm = &mxt_pm_ops, |
| 2554 | }, | 2673 | }, |
| 2555 | .probe = mxt_probe, | 2674 | .probe = mxt_probe, |
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 43b3c9c2d788..0efd766a545b 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c | |||
| @@ -699,7 +699,7 @@ static int elants_i2c_fw_update(struct elants_data *ts) | |||
| 699 | char *fw_name; | 699 | char *fw_name; |
| 700 | int error; | 700 | int error; |
| 701 | 701 | ||
| 702 | fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%4x.bin", ts->hw_version); | 702 | fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%04x.bin", ts->hw_version); |
| 703 | if (!fw_name) | 703 | if (!fw_name) |
| 704 | return -ENOMEM; | 704 | return -ENOMEM; |
| 705 | 705 | ||
