diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 16:05:14 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 16:05:14 -0700 |
commit | 2158091d9cda6f126f71973667e8a9fc1e795d03 (patch) | |
tree | 56b62dbed2eaf967be7e2d922e603140c3b71818 /drivers | |
parent | 3e1a29b3bf66c2850ea8eba78c59c234921c0b69 (diff) | |
parent | e6e7e9cd8eed0e18217c899843bffbe8c7dae564 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov:
- a new driver to ChipOne icn8505 based touchscreens
- on certain systems with Elan touch controllers they will be switched
away form PS/2 emulation and over to native SMbus mode
- assorted driver fixups and improvements
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (24 commits)
Input: elan_i2c - add ELAN0612 (Lenovo v330 14IKB) ACPI ID
Input: goodix - add new ACPI id for GPD Win 2 touch screen
Input: xpad - add GPD Win 2 Controller USB IDs
Input: ti_am335x_tsc - prevent system suspend when TSC is in use
Input: ti_am335x_tsc - ack pending IRQs at probe and before suspend
Input: cros_ec_keyb - mark cros_ec_keyb driver as wake enabled device.
Input: mk712 - update documentation web link
Input: atmel_mxt_ts - fix reset-gpio for level based irqs
Input: atmel_mxt_ts - require device properties present when probing
Input: psmouse-smbus - allow to control psmouse_deactivate
Input: elantech - detect new ICs and setup Host Notify for them
Input: elantech - add support for SMBus devices
Input: elantech - query the resolution in query_info
Input: elantech - split device info into a separate structure
Input: elan_i2c - add trackstick report
Input: usbtouchscreen - add sysfs attribute for 3M MTouch firmware rev
Input: ati_remote2 - fix typo 'can by' to 'can be'
Input: replace hard coded string with __func__ in pr_err()
Input: add support for ChipOne icn8505 based touchscreens
Input: gamecon - avoid using __set_bit() for capabilities
...
Diffstat (limited to 'drivers')
24 files changed, 1318 insertions, 389 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 9785546420a7..6365c1958264 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1943,8 +1943,7 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int break; default: - pr_err("input_set_capability: unknown type %u (code %u)\n", - type, code); + pr_err("%s: unknown type %u (code %u)\n", __func__, type, code); dump_stack(); return; } diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c index 005d852a06e9..f051993c568e 100644 --- a/drivers/input/joystick/as5011.c +++ b/drivers/input/joystick/as5011.c @@ -269,9 +269,7 @@ static int as5011_probe(struct i2c_client *client, input_dev->id.bustype = BUS_I2C; input_dev->dev.parent = &client->dev; - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(EV_ABS, input_dev->evbit); - __set_bit(BTN_JOYSTICK, input_dev->keybit); + input_set_capability(input_dev, EV_KEY, BTN_JOYSTICK); input_set_abs_params(input_dev, ABS_X, AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT); diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 2ffb2e8bdc3b..4e10ffdf8a36 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -862,7 +862,7 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type) case GC_N64: for (i = 0; i < 10; i++) - __set_bit(gc_n64_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, gc_n64_btn[i]); for (i = 0; i < 2; i++) { input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2); @@ -879,26 +879,27 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type) break; case GC_SNESMOUSE: - __set_bit(BTN_LEFT, input_dev->keybit); - __set_bit(BTN_RIGHT, input_dev->keybit); - __set_bit(REL_X, input_dev->relbit); - __set_bit(REL_Y, input_dev->relbit); + input_set_capability(input_dev, EV_KEY, BTN_LEFT); + input_set_capability(input_dev, EV_KEY, BTN_RIGHT); + input_set_capability(input_dev, EV_REL, REL_X); + input_set_capability(input_dev, EV_REL, REL_Y); break; case GC_SNES: for (i = 4; i < 8; i++) - __set_bit(gc_snes_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, gc_snes_btn[i]); /* fall through */ case GC_NES: for (i = 0; i < 4; i++) - __set_bit(gc_snes_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, gc_snes_btn[i]); break; case GC_MULTI2: - __set_bit(BTN_THUMB, input_dev->keybit); + input_set_capability(input_dev, EV_KEY, BTN_THUMB); /* fall through */ case GC_MULTI: - __set_bit(BTN_TRIGGER, input_dev->keybit); + input_set_capability(input_dev, EV_KEY, BTN_TRIGGER); + /* fall through */ break; case GC_PSX: @@ -906,15 +907,17 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type) input_set_abs_params(input_dev, gc_psx_abs[i], 4, 252, 0, 2); for (i = 0; i < 12; i++) - __set_bit(gc_psx_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, gc_psx_btn[i]); + break; break; case GC_DDR: for (i = 0; i < 4; i++) - __set_bit(gc_psx_ddr_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, + gc_psx_ddr_btn[i]); for (i = 0; i < 12; i++) - __set_bit(gc_psx_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, gc_psx_btn[i]); break; } diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 06e9650b3b30..48e36acbeb49 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -86,8 +86,10 @@ #define XPAD_PKT_LEN 64 -/* xbox d-pads should map to buttons, as is required for DDR pads - but we map them to axes when possible to simplify things */ +/* + * xbox d-pads should map to buttons, as is required for DDR pads + * but we map them to axes when possible to simplify things + */ #define MAP_DPAD_TO_BUTTONS (1 << 0) #define MAP_TRIGGERS_TO_BUTTONS (1 << 1) #define MAP_STICKS_TO_NULL (1 << 2) @@ -123,6 +125,7 @@ static const struct xpad_device { u8 mapping; u8 xtype; } xpad_device[] = { + { 0x0079, 0x18d4, "GPD Win 2 Controller", 0, XTYPE_XBOX360 }, { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX }, { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, @@ -387,15 +390,15 @@ static const signed short xpad_abs_triggers[] = { * match against vendor id as well. Wired Xbox 360 devices have protocol 1, * wireless controllers have protocol 129. */ -#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \ +#define XPAD_XBOX360_VENDOR_PROTOCOL(vend, pr) \ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \ .idVendor = (vend), \ .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ .bInterfaceSubClass = 93, \ .bInterfaceProtocol = (pr) #define XPAD_XBOX360_VENDOR(vend) \ - { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \ - { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) } + { XPAD_XBOX360_VENDOR_PROTOCOL((vend), 1) }, \ + { XPAD_XBOX360_VENDOR_PROTOCOL((vend), 129) } /* The Xbox One controller uses subclass 71 and protocol 208. */ #define XPAD_XBOXONE_VENDOR_PROTOCOL(vend, pr) \ @@ -405,10 +408,11 @@ static const signed short xpad_abs_triggers[] = { .bInterfaceSubClass = 71, \ .bInterfaceProtocol = (pr) #define XPAD_XBOXONE_VENDOR(vend) \ - { XPAD_XBOXONE_VENDOR_PROTOCOL(vend, 208) } + { XPAD_XBOXONE_VENDOR_PROTOCOL((vend), 208) } static const struct usb_device_id xpad_table[] = { { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ + XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 Controller */ XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */ @@ -1573,7 +1577,6 @@ static void xpad_close(struct input_dev *dev) static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) { struct usb_xpad *xpad = input_get_drvdata(input_dev); - set_bit(abs, input_dev->absbit); switch (abs) { case ABS_X: @@ -1593,6 +1596,9 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */ input_set_abs_params(input_dev, abs, -1, 1, 0, 0); break; + default: + input_set_abs_params(input_dev, abs, 0, 0, 0, 0); + break; } } @@ -1633,10 +1639,7 @@ static int xpad_init_input(struct usb_xpad *xpad) input_dev->close = xpad_close; } - __set_bit(EV_KEY, input_dev->evbit); - if (!(xpad->mapping & MAP_STICKS_TO_NULL)) { - __set_bit(EV_ABS, input_dev->evbit); /* set up axes */ for (i = 0; xpad_abs[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs[i]); @@ -1644,21 +1647,22 @@ static int xpad_init_input(struct usb_xpad *xpad) /* set up standard buttons */ for (i = 0; xpad_common_btn[i] >= 0; i++) - __set_bit(xpad_common_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, xpad_common_btn[i]); /* set up model-specific ones */ if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W || xpad->xtype == XTYPE_XBOXONE) { for (i = 0; xpad360_btn[i] >= 0; i++) - __set_bit(xpad360_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, xpad360_btn[i]); } else { for (i = 0; xpad_btn[i] >= 0; i++) - __set_bit(xpad_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, xpad_btn[i]); } if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { for (i = 0; xpad_btn_pad[i] >= 0; i++) - __set_bit(xpad_btn_pad[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, + xpad_btn_pad[i]); } /* @@ -1675,7 +1679,8 @@ static int xpad_init_input(struct usb_xpad *xpad) if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { for (i = 0; xpad_btn_triggers[i] >= 0; i++) - __set_bit(xpad_btn_triggers[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, + xpad_btn_triggers[i]); } else { for (i = 0; xpad_abs_triggers[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs_triggers[i]); diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 79eb29550c34..489ddd37bd4e 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -244,24 +244,35 @@ static int cros_ec_keyb_work(struct notifier_block *nb, switch (ckdev->ec->event_data.event_type) { case EC_MKBP_EVENT_KEY_MATRIX: - /* - * If EC is not the wake source, discard key state changes - * during suspend. - */ - if (queued_during_suspend) - return NOTIFY_OK; + if (device_may_wakeup(ckdev->dev)) { + pm_wakeup_event(ckdev->dev, 0); + } else { + /* + * If keyboard is not wake enabled, discard key state + * changes during suspend. Switches will be re-checked + * in cros_ec_keyb_resume() to be sure nothing is lost. + */ + if (queued_during_suspend) + return NOTIFY_OK; + } if (ckdev->ec->event_size != ckdev->cols) { dev_err(ckdev->dev, "Discarded incomplete key matrix event.\n"); return NOTIFY_OK; } + cros_ec_keyb_process(ckdev, ckdev->ec->event_data.data.key_matrix, ckdev->ec->event_size); break; case EC_MKBP_EVENT_SYSRQ: + if (device_may_wakeup(ckdev->dev)) + pm_wakeup_event(ckdev->dev, 0); + else if (queued_during_suspend) + return NOTIFY_OK; + val = get_unaligned_le32(&ckdev->ec->event_data.data.sysrq); dev_dbg(ckdev->dev, "sysrq code from EC: %#x\n", val); handle_sysrq(val); @@ -269,12 +280,9 @@ static int cros_ec_keyb_work(struct notifier_block *nb, case EC_MKBP_EVENT_BUTTON: case EC_MKBP_EVENT_SWITCH: - /* - * If EC is not the wake source, discard key state - * changes during suspend. Switches will be re-checked in - * cros_ec_keyb_resume() to be sure nothing is lost. - */ - if (queued_during_suspend) + if (device_may_wakeup(ckdev->dev)) + pm_wakeup_event(ckdev->dev, 0); + else if (queued_during_suspend) return NOTIFY_OK; if (ckdev->ec->event_data.event_type == EC_MKBP_EVENT_BUTTON) { @@ -639,6 +647,7 @@ static int cros_ec_keyb_probe(struct platform_device *pdev) return err; } + device_init_wakeup(ckdev->dev, true); return 0; } diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index ded5b84e336d..d8fd58fdf050 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -22,7 +22,7 @@ MODULE_LICENSE("GPL"); /* * ATI Remote Wonder II Channel Configuration * - * The remote control can by assigned one of sixteen "channels" in order to facilitate + * The remote control can be assigned one of sixteen "channels" in order to facilitate * the use of multiple remote controls within range of each other. * A remote's "channel" may be altered by pressing and holding the "PC" button for * approximately 3 seconds, after which the button will slowly flash the count of the diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 89ebb8f39fee..f27f23f2d99a 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -133,6 +133,18 @@ config MOUSE_PS2_ELANTECH If unsure, say N. +config MOUSE_PS2_ELANTECH_SMBUS + bool "Elantech PS/2 SMbus companion" if EXPERT + default y + depends on MOUSE_PS2 && MOUSE_PS2_ELANTECH + depends on I2C=y || I2C=MOUSE_PS2 + select MOUSE_PS2_SMBUS + help + Say Y here if you have a Elantech touchpad connected to + to an SMBus, but enumerated through PS/2. + + If unsure, say Y. + config MOUSE_PS2_SENTELIC bool "Sentelic Finger Sensing Pad PS/2 protocol extension" depends on MOUSE_PS2 diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 38f9501acdf0..cb5579716dba 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -2049,14 +2049,11 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) return 0; } -static int alps_hw_init_v6(struct psmouse *psmouse) +/* Must be in passthrough mode when calling this function */ +static int alps_trackstick_enter_extended_mode_v3_v6(struct psmouse *psmouse) { unsigned char param[2] = {0xC8, 0x14}; - /* Enter passthrough mode to let trackpoint enter 6byte raw mode */ - if (alps_passthrough_mode_v2(psmouse, true)) - return -1; - if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || @@ -2064,9 +2061,25 @@ static int alps_hw_init_v6(struct psmouse *psmouse) ps2_command(&psmouse->ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) return -1; + return 0; +} + +static int alps_hw_init_v6(struct psmouse *psmouse) +{ + int ret; + + /* Enter passthrough mode to let trackpoint enter 6byte raw mode */ + if (alps_passthrough_mode_v2(psmouse, true)) + return -1; + + ret = alps_trackstick_enter_extended_mode_v3_v6(psmouse); + if (alps_passthrough_mode_v2(psmouse, false)) return -1; + if (ret) + return ret; + if (alps_absolute_mode_v6(psmouse)) { psmouse_err(psmouse, "Failed to enable absolute mode\n"); return -1; @@ -2140,10 +2153,18 @@ error: static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) { - struct ps2dev *ps2dev = &psmouse->ps2dev; int ret = 0; + int reg_val; unsigned char param[4]; + /* + * We need to configure trackstick to report data for touchpad in + * extended format. And also we need to tell touchpad to expect data + * from trackstick in extended format. Without this configuration + * trackstick packets sent from touchpad are in basic format which is + * different from what we expect. + */ + if (alps_passthrough_mode_v3(psmouse, reg_base, true)) return -EIO; @@ -2161,39 +2182,36 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) ret = -ENODEV; } else { psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param); - - /* - * Not sure what this does, but it is absolutely - * essential. Without it, the touchpad does not - * work at all and the trackstick just emits normal - * PS/2 packets. - */ - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - alps_command_mode_send_nibble(psmouse, 0x9) || - alps_command_mode_send_nibble(psmouse, 0x4)) { - psmouse_err(psmouse, - "Error sending magic E6 sequence\n"); + if (alps_trackstick_enter_extended_mode_v3_v6(psmouse)) { + psmouse_err(psmouse, "Failed to enter into trackstick extended mode\n"); ret = -EIO; - goto error; } + } + + if (alps_passthrough_mode_v3(psmouse, reg_base, false)) + return -EIO; + + if (ret) + return ret; + if (alps_enter_command_mode(psmouse)) + return -EIO; + + reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); + if (reg_val == -1) { + ret = -EIO; + } else { /* - * This ensures the trackstick packets are in the format - * supported by this driver. If bit 1 isn't set the packet - * format is different. + * Tell touchpad that trackstick is now in extended mode. + * If bit 1 isn't set the packet format is different. */ - if (alps_enter_command_mode(psmouse) || - alps_command_mode_write_reg(psmouse, - reg_base + 0x08, 0x82) || - alps_exit_command_mode(psmouse)) + reg_val |= BIT(1); + if (__alps_command_mode_write_reg(psmouse, reg_val)) ret = -EIO; } -error: - if (alps_passthrough_mode_v3(psmouse, reg_base, false)) - ret = -EIO; + if (alps_exit_command_mode(psmouse)) + return -EIO; return ret; } diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 75e757520ef0..8ff75114e762 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -36,6 +36,7 @@ #include <linux/jiffies.h> #include <linux/completion.h> #include <linux/of.h> +#include <linux/property.h> #include <linux/regulator/consumer.h> #include <asm/unaligned.h> @@ -51,6 +52,7 @@ #define ETP_MAX_FINGERS 5 #define ETP_FINGER_DATA_LEN 5 #define ETP_REPORT_ID 0x5D +#define ETP_TP_REPORT_ID 0x5E #define ETP_REPORT_ID_OFFSET 2 #define ETP_TOUCH_INFO_OFFSET 3 #define ETP_FINGER_DATA_OFFSET 4 @@ -61,6 +63,7 @@ struct elan_tp_data { struct i2c_client *client; struct input_dev *input; + struct input_dev *tp_input; /* trackpoint input node */ struct regulator *vcc; const struct elan_transport_ops *ops; @@ -930,6 +933,33 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet) input_sync(input); } +static void elan_report_trackpoint(struct elan_tp_data *data, u8 *report) +{ + struct input_dev *input = data->tp_input; + u8 *packet = &report[ETP_REPORT_ID_OFFSET + 1]; + int x, y; + + if (!data->tp_input) { + dev_warn_once(&data->client->dev, + "received a trackpoint report while no trackpoint device has been created. Please report upstream.\n"); + return; + } + + input_report_key(input, BTN_LEFT, packet[0] & 0x01); + input_report_key(input, BTN_RIGHT, packet[0] & 0x02); + input_report_key(input, BTN_MIDDLE, packet[0] & 0x04); + + if ((packet[3] & 0x0F) == 0x06) { + x = packet[4] - (int)((packet[1] ^ 0x80) << 1); + y = (int)((packet[2] ^ 0x80) << 1) - packet[5]; + + input_report_rel(input, REL_X, x); + input_report_rel(input, REL_Y, y); + } + + input_sync(input); +} + static irqreturn_t elan_isr(int irq, void *dev_id) { struct elan_tp_data *data = dev_id; @@ -951,11 +981,17 @@ static irqreturn_t elan_isr(int irq, void *dev_id) if (error) goto out; - if (report[ETP_REPORT_ID_OFFSET] != ETP_REPORT_ID) + switch (report[ETP_REPORT_ID_OFFSET]) { + case ETP_REPORT_ID: + elan_report_absolute(data, report); + break; + case ETP_TP_REPORT_ID: + elan_report_trackpoint(data, report); + break; + default: dev_err(dev, "invalid report id data (%x)\n", report[ETP_REPORT_ID_OFFSET]); - else - elan_report_absolute(data, report); + } out: return IRQ_HANDLED; @@ -966,6 +1002,36 @@ out: * Elan initialization functions ****************************************************************** */ + +static int elan_setup_trackpoint_input_device(struct elan_tp_data *data) +{ + struct device *dev = &data->client->dev; + struct input_dev *input; + + input = devm_input_allocate_device(dev); + if (!input) + return -ENOMEM; + + input->name = "Elan TrackPoint"; + input->id.bustype = BUS_I2C; + input->id.vendor = ELAN_VENDOR_ID; + input->id.product = data->product_id; + input_set_drvdata(input, data); + + input_set_capability(input, EV_REL, REL_X); + input_set_capability(input, EV_REL, REL_Y); + input_set_capability(input, EV_KEY, BTN_LEFT); + input_set_capability(input, EV_KEY, BTN_RIGHT); + input_set_capability(input, EV_KEY, BTN_MIDDLE); + + __set_bit(INPUT_PROP_POINTER, input->propbit); + __set_bit(INPUT_PROP_POINTING_STICK, input->propbit); + + data->tp_input = input; + + return 0; +} + static int elan_setup_input_device(struct elan_tp_data *data) { struct device *dev = &data->client->dev; @@ -1140,6 +1206,12 @@ static int elan_probe(struct i2c_client *client, if (error) return error; + if (device_property_read_bool(&client->dev, "elan,trackpoint")) { + error = elan_setup_trackpoint_input_device(data); + if (error) + return error; + } + /* * Platform code (ACPI, DTS) should normally set up interrupt * for us, but in case it did not let's fall back to using falling @@ -1177,6 +1249,16 @@ static int elan_probe(struct i2c_client *client, return error; } + if (data->tp_input) { + error = input_register_device(data->tp_input); + if (error) { + dev_err(&client->dev, + "failed to register TrackPoint input device: %d\n", + error); + return error; + } + } + /* * Systems using device tree should set up wakeup via DTS, * the rest will configure device as wakeup source by default. @@ -1262,6 +1344,7 @@ static const struct acpi_device_id elan_acpi_id[] = { { "ELAN060B", 0 }, { "ELAN060C", 0 }, { "ELAN0611", 0 }, + { "ELAN0612", 0 }, { "ELAN1000", 0 }, { } }; diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index db47a5e1d114..fb4d902c4403 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -14,17 +14,20 @@ #include <linux/dmi.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/i2c.h> #include <linux/input.h> #include <linux/input/mt.h> +#include <linux/platform_device.h> #include <linux/serio.h> #include <linux/libps2.h> #include <asm/unaligned.h> #include "psmouse.h" #include "elantech.h" +#include "elan_i2c.h" #define elantech_debug(fmt, ...) \ do { \ - if (etd->debug) \ + if (etd->info.debug) \ psmouse_printk(KERN_DEBUG, psmouse, \ fmt, ##__VA_ARGS__); \ } while (0) @@ -105,7 +108,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, if (reg > 0x11 && reg < 0x20) return -1; - switch (etd->hw_version) { + switch (etd->info.hw_version) { case 1: if (ps2_sliced_command(&psmouse->ps2dev, ETP_REGISTER_READ) || ps2_sliced_command(&psmouse->ps2dev, reg) || @@ -137,7 +140,7 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, if (rc) psmouse_err(psmouse, "failed to read register 0x%02x.\n", reg); - else if (etd->hw_version != 4) + else if (etd->info.hw_version != 4) *val = param[0]; else *val = param[1]; @@ -160,7 +163,7 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, if (reg > 0x11 && reg < 0x20) return -1; - switch (etd->hw_version) { + switch (etd->info.hw_version) { case 1: if (ps2_sliced_command(&psmouse->ps2dev, ETP_REGISTER_WRITE) || ps2_sliced_command(&psmouse->ps2dev, reg) || @@ -237,7 +240,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) unsigned char *packet = psmouse->packet; int fingers; - if (etd->fw_version < 0x020000) { + if (etd->info.fw_version < 0x020000) { /* * byte 0: D U p1 p2 1 p3 R L * byte 1: f 0 th tw x9 x8 y9 y8 @@ -252,7 +255,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) fingers = (packet[0] & 0xc0) >> 6; } - if (etd->jumpy_cursor) { + if (etd->info.jumpy_cursor) { if (fingers != 1) { etd->single_finger_reports = 0; } else if (etd->single_finger_reports < 2) { @@ -282,8 +285,8 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) psmouse_report_standard_buttons(dev, packet[0]); - if (etd->fw_version < 0x020000 && - (etd->capabilities[0] & ETP_CAP_HAS_ROCKER)) { + if (etd->info.fw_version < 0x020000 && + (etd->info.capabilities[0] & ETP_CAP_HAS_ROCKER)) { /* rocker up */ input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); /* rocker down */ @@ -391,7 +394,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); psmouse_report_standard_buttons(dev, packet[0]); - if (etd->reports_pressure) { + if (etd->info.reports_pressure) { input_report_abs(dev, ABS_PRESSURE, pres); input_report_abs(dev, ABS_TOOL_WIDTH, width); } @@ -444,7 +447,7 @@ static void elantech_report_trackpoint(struct psmouse *psmouse, default: /* Dump unexpected packet sequences if debug=1 (default) */ - if (etd->debug == 1) + if (etd->info.debug == 1) elantech_packet_dump(psmouse); break; @@ -523,7 +526,7 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); /* For clickpads map both buttons to BTN_LEFT */ - if (etd->fw_version & 0x001000) + if (etd->info.fw_version & 0x001000) input_report_key(dev, BTN_LEFT, packet[0] & 0x03); else psmouse_report_standard_buttons(dev, packet[0]); @@ -541,7 +544,7 @@ static void elantech_input_sync_v4(struct psmouse *psmouse) unsigned char *packet = psmouse->packet; /* For clickpads map both buttons to BTN_LEFT */ - if (etd->fw_version & 0x001000) + if (etd->info.fw_version & 0x001000) input_report_key(dev, BTN_LEFT, packet[0] & 0x03); else psmouse_report_standard_buttons(dev, packet[0]); @@ -669,7 +672,7 @@ static int elantech_packet_check_v1(struct psmouse *psmouse) unsigned char p1, p2, p3; /* Parity bits are placed differently */ - if (etd->fw_version < 0x020000) { + if (etd->info.fw_version < 0x020000) { /* byte 0: D U p1 p2 1 p3 R L */ p1 = (packet[0] & 0x20) >> 5; p2 = (packet[0] & 0x10) >> 4; @@ -714,7 +717,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) * With all three cases, if the constant bits are not exactly what I * expected, I consider them invalid. */ - if (etd->reports_pressure) + if (etd->info.reports_pressure) return (packet[0] & 0x0c) == 0x04 && (packet[3] & 0x0f) == 0x02; @@ -751,7 +754,7 @@ static int elantech_packet_check_v3(struct psmouse *psmouse) * If the hardware flag 'crc_enabled' is set the packets have * different signatures. */ - if (etd->crc_enabled) { + if (etd->info.crc_enabled) { if ((packet[3] & 0x09) == 0x08) return PACKET_V3_HEAD; @@ -782,7 +785,7 @@ static int elantech_packet_check_v4(struct psmouse *psmouse) return PACKET_TRACKPOINT; /* This represents the version of IC body. */ - ic_version = (etd->fw_version & 0x0f0000) >> 16; + ic_version = (etd->info.fw_version & 0x0f0000) >> 16; /* * Sanity check based on the constant bits of a packet. @@ -791,9 +794,9 @@ static int elantech_packet_check_v4(struct psmouse *psmouse) * the IC body, but are the same for every packet, * regardless of the type. */ - if (etd->crc_enabled) + if (etd->info.crc_enabled) sanity_check = ((packet[3] & 0x08) == 0x00); - else if (ic_version == 7 && etd->samples[1] == 0x2A) + else if (ic_version == 7 && etd->info.samples[1] == 0x2A) sanity_check = ((packet[3] & 0x1c) == 0x10); else sanity_check = ((packet[0] & 0x0c) == 0x04 && @@ -827,12 +830,12 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) if (psmouse->pktcnt < psmouse->pktsize) return PSMOUSE_GOOD_DATA; - if (etd->debug > 1) + if (etd->info.debug > 1) elantech_packet_dump(psmouse); - switch (etd->hw_version) { + switch (etd->info.hw_version) { case 1: - if (etd->paritycheck && !elantech_packet_check_v1(psmouse)) + if (etd->info.paritycheck && !elantech_packet_check_v1(psmouse)) return PSMOUSE_BAD_DATA; elantech_report_absolute_v1(psmouse); @@ -843,7 +846,7 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) if (elantech_debounce_check_v2(psmouse)) return PSMOUSE_FULL_PACKET; - if (etd->paritycheck && !elantech_packet_check_v2(psmouse)) + if (etd->info.paritycheck && !elantech_packet_check_v2(psmouse)) return PSMOUSE_BAD_DATA; elantech_report_absolute_v2(psmouse); @@ -916,7 +919,7 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) int tries = ETP_READ_BACK_TRIES; int rc = 0; - switch (etd->hw_version) { + switch (etd->info.hw_version) { case 1 |