diff options
author | Sean Paul <seanpaul@chromium.org> | 2017-09-21 23:18:46 +0200 |
---|---|---|
committer | Sean Paul <seanpaul@chromium.org> | 2017-09-21 23:18:46 +0200 |
commit | 1ebfc603d046f1dda6507d11803f9b4046cee712 (patch) | |
tree | 3be6790f2ce819929b1ccff7993c636e0944705a /drivers/input | |
parent | qxl: fix primary surface handling (diff) | |
parent | Merge tag 'kbuild-fixes-v4.14' of git://git.kernel.org/pub/scm/linux/kernel/g... (diff) | |
download | linux-1ebfc603d046f1dda6507d11803f9b4046cee712.tar.xz linux-1ebfc603d046f1dda6507d11803f9b4046cee712.zip |
Merge remote-tracking branch 'origin/master' into drm-misc-fixes
Pick up 4.14-rc1
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Diffstat (limited to 'drivers/input')
96 files changed, 1343 insertions, 291 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c index 7e6842bd525c..d268fdc23c64 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1398,7 +1398,7 @@ static struct attribute *input_dev_attrs[] = { NULL }; -static struct attribute_group input_dev_attr_group = { +static const struct attribute_group input_dev_attr_group = { .attrs = input_dev_attrs, }; @@ -1425,7 +1425,7 @@ static struct attribute *input_dev_id_attrs[] = { NULL }; -static struct attribute_group input_dev_id_attr_group = { +static const struct attribute_group input_dev_id_attr_group = { .name = "id", .attrs = input_dev_id_attrs, }; @@ -1495,7 +1495,7 @@ static struct attribute *input_dev_caps_attrs[] = { NULL }; -static struct attribute_group input_dev_caps_attr_group = { +static const struct attribute_group input_dev_caps_attr_group = { .name = "capabilities", .attrs = input_dev_caps_attrs, }; diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index d09cefa37931..15a71acb6997 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c @@ -313,7 +313,7 @@ static void adi_close(struct input_dev *dev) static void adi_init_digital(struct gameport *gameport) { - int seq[] = { 4, -2, -3, 10, -6, -11, -7, -9, 11, 0 }; + static const int seq[] = { 4, -2, -3, 10, -6, -11, -7, -9, 11, 0 }; int i; for (i = 0; seq[i]; i++) { diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index 46d5041d2d9d..154e827b559b 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -164,7 +164,7 @@ static void iforce_serio_disconnect(struct serio *serio) kfree(iforce); } -static struct serio_device_id iforce_serio_ids[] = { +static const struct serio_device_id iforce_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_IFORCE, diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index db64adfbe1af..e8724f1a4a25 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -209,7 +209,7 @@ static void iforce_usb_disconnect(struct usb_interface *intf) kfree(iforce); } -static struct usb_device_id iforce_usb_ids [] = { +static const struct usb_device_id iforce_usb_ids[] = { { USB_DEVICE(0x044f, 0xa01c) }, /* Thrustmaster Motor Sport GT */ { USB_DEVICE(0x046d, 0xc281) }, /* Logitech WingMan Force */ { USB_DEVICE(0x046d, 0xc291) }, /* Logitech WingMan Formula Force */ diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c index c5358ba1f571..a9d0e3edca94 100644 --- a/drivers/input/joystick/magellan.c +++ b/drivers/input/joystick/magellan.c @@ -198,7 +198,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id magellan_serio_ids[] = { +static const struct serio_device_id magellan_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_MAGELLAN, diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index f4445a4e8d6a..e9712a1b7cad 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -272,7 +272,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id spaceball_serio_ids[] = { +static const struct serio_device_id spaceball_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_SPACEBALL, diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index f2667820e8c5..05da0ed514e2 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c @@ -213,7 +213,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id spaceorb_serio_ids[] = { +static const struct serio_device_id spaceorb_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_SPACEORB, diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c index 099c6d7b5e08..cb10e7b097ae 100644 --- a/drivers/input/joystick/stinger.c +++ b/drivers/input/joystick/stinger.c @@ -184,7 +184,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id stinger_serio_ids[] = { +static const struct serio_device_id stinger_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_STINGER, diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c index 7f7e5ab3f9e3..e60cb004cb8c 100644 --- a/drivers/input/joystick/twidjoy.c +++ b/drivers/input/joystick/twidjoy.c @@ -233,7 +233,7 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id twidjoy_serio_ids[] = { +static const struct serio_device_id twidjoy_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_TWIDJOY, diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c index e13a9144a25d..ef5391ba4470 100644 --- a/drivers/input/joystick/warrior.c +++ b/drivers/input/joystick/warrior.c @@ -193,7 +193,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id warrior_serio_ids[] = { +static const struct serio_device_id warrior_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_WARRIOR, diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 298a6ba51411..d86e59515b9c 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -408,7 +408,7 @@ static const signed short xpad_abs_triggers[] = { #define XPAD_XBOXONE_VENDOR(vend) \ { XPAD_XBOXONE_VENDOR_PROTOCOL(vend, 208) } -static struct usb_device_id xpad_table[] = { +static const struct usb_device_id xpad_table[] = { { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ @@ -476,10 +476,21 @@ static const u8 xboxone_hori_init[] = { }; /* - * A rumble packet is required for some PowerA pads to start + * A specific rumble packet is required for some PowerA pads to start * sending input reports. One of those pads is (0x24c6:0x543a). */ -static const u8 xboxone_zerorumble_init[] = { +static const u8 xboxone_rumblebegin_init[] = { + 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, + 0x1D, 0x1D, 0xFF, 0x00, 0x00 +}; + +/* + * A rumble packet with zero FF intensity will immediately + * terminate the rumbling required to init PowerA pads. + * This should happen fast enough that the motors don't + * spin up to enough speed to actually vibrate the gamepad. + */ +static const u8 xboxone_rumbleend_init[] = { 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -494,9 +505,12 @@ static const struct xboxone_init_packet xboxone_init_packets[] = { XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init), XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init), XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init), - XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_zerorumble_init), - XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_zerorumble_init), - XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_zerorumble_init), + XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init), + XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init), + XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init), + XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumbleend_init), + XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumbleend_init), + XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumbleend_init), }; struct xpad_output_packet { @@ -1750,10 +1764,12 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id struct usb_endpoint_descriptor *ep = &intf->cur_altsetting->endpoint[i].desc; - if (usb_endpoint_dir_in(ep)) - ep_irq_in = ep; - else - ep_irq_out = ep; + if (usb_endpoint_xfer_int(ep)) { + if (usb_endpoint_dir_in(ep)) + ep_irq_in = ep; + else + ep_irq_out = ep; + } } if (!ep_irq_in || !ep_irq_out) { diff --git a/drivers/input/joystick/zhenhua.c b/drivers/input/joystick/zhenhua.c index 4a8258bf13fd..5c6d5de743f1 100644 --- a/drivers/input/joystick/zhenhua.c +++ b/drivers/input/joystick/zhenhua.c @@ -192,7 +192,7 @@ static int zhenhua_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id zhenhua_serio_ids[] = { +static const struct serio_device_id zhenhua_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_ZHENHUA, diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index ec876b5b1382..7e75835e220f 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -1270,7 +1270,7 @@ static int atkbd_reconnect(struct serio *serio) return retval; } -static struct serio_device_id atkbd_serio_ids[] = { +static const struct serio_device_id atkbd_serio_ids[] = { { .type = SERIO_8042, .proto = SERIO_ANY, diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index a047b9af8369..e9f0ebf3267a 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -353,7 +353,7 @@ static struct attribute *gpio_keys_attrs[] = { NULL, }; -static struct attribute_group gpio_keys_attr_group = { +static const struct attribute_group gpio_keys_attr_group = { .attrs = gpio_keys_attrs, }; @@ -827,7 +827,7 @@ static int gpio_keys_probe(struct platform_device *pdev) fwnode_handle_put(child); - error = sysfs_create_group(&dev->kobj, &gpio_keys_attr_group); + error = devm_device_add_group(dev, &gpio_keys_attr_group); if (error) { dev_err(dev, "Unable to export keys/switches, error: %d\n", error); @@ -838,23 +838,12 @@ static int gpio_keys_probe(struct platform_device *pdev) if (error) { dev_err(dev, "Unable to register input device, error: %d\n", error); - goto err_remove_group; + return error; } device_init_wakeup(dev, wakeup); return 0; - -err_remove_group: - sysfs_remove_group(&dev->kobj, &gpio_keys_attr_group); - return error; -} - -static int gpio_keys_remove(struct platform_device *pdev) -{ - sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); - - return 0; } static int __maybe_unused gpio_keys_suspend(struct device *dev) @@ -912,7 +901,6 @@ 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 = gpio_keys_remove, .driver = { .name = "gpio-keys", .pm = &gpio_keys_pm_ops, diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 5b152f25a8e1..bb29a7c9a1c0 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -559,7 +559,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv) return error; } -static struct serio_device_id hil_dev_ids[] = { +static const struct serio_device_id hil_dev_ids[] = { { .type = SERIO_HIL_MLC, .proto = SERIO_HIL, diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index 198dc07a1be5..a4e404aaf64b 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c @@ -299,7 +299,7 @@ static void hil_keyb_exit(void) } #if defined(CONFIG_PARISC) -static int hil_probe_chip(struct parisc_device *dev) +static int __init hil_probe_chip(struct parisc_device *dev) { /* Only allow one HIL keyboard */ if (hil_dev.dev) @@ -320,14 +320,14 @@ static int hil_probe_chip(struct parisc_device *dev) return hil_keyb_init(); } -static int hil_remove_chip(struct parisc_device *dev) +static int __exit hil_remove_chip(struct parisc_device *dev) { hil_keyb_exit(); return 0; } -static struct parisc_device_id hil_tbl[] = { +static const struct parisc_device_id hil_tbl[] __initconst = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 }, { 0, } }; @@ -337,11 +337,11 @@ static struct parisc_device_id hil_tbl[] = { MODULE_DEVICE_TABLE(parisc, hil_tbl); #endif -static struct parisc_driver hil_driver = { +static struct parisc_driver hil_driver __refdata = { .name = "hil", .id_table = hil_tbl, .probe = hil_probe_chip, - .remove = hil_remove_chip, + .remove = __exit_p(hil_remove_chip), }; static int __init hil_init(void) diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 9fcd9f1d5dc8..471d53815c6d 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -707,7 +707,7 @@ static void lkkbd_disconnect(struct serio *serio) kfree(lk); } -static struct serio_device_id lkkbd_serio_ids[] = { +static const struct serio_device_id lkkbd_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_LKKBD, diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index 20f044377990..fb9b8e23ab93 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c @@ -142,7 +142,7 @@ static void nkbd_disconnect(struct serio *serio) kfree(nkbd); } -static struct serio_device_id nkbd_serio_ids[] = { +static const struct serio_device_id nkbd_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_NEWTON, diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 3841fa30db33..d0bdaeadf86d 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -644,9 +644,12 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) static int pxa27x_keypad_open(struct input_dev *dev) { struct pxa27x_keypad *keypad = input_get_drvdata(dev); - + int ret; /* Enable unit clock */ - clk_prepare_enable(keypad->clk); + ret = clk_prepare_enable(keypad->clk); + if (ret) + return ret; + pxa27x_keypad_config(keypad); return 0; @@ -683,6 +686,7 @@ static int pxa27x_keypad_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); struct input_dev *input_dev = keypad->input_dev; + int ret = 0; /* * If the keypad is used as wake up source, the clock is not turned @@ -695,14 +699,15 @@ static int pxa27x_keypad_resume(struct device *dev) if (input_dev->users) { /* Enable unit clock */ - clk_prepare_enable(keypad->clk); - pxa27x_keypad_config(keypad); + ret = clk_prepare_enable(keypad->clk); + if (!ret) + pxa27x_keypad_config(keypad); } mutex_unlock(&input_dev->mutex); } - return 0; + return ret; } #endif diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c index a6e0d565e306..8b6de9a692dc 100644 --- a/drivers/input/keyboard/stowaway.c +++ b/drivers/input/keyboard/stowaway.c @@ -146,7 +146,7 @@ static void skbd_disconnect(struct serio *serio) kfree(skbd); } -static struct serio_device_id skbd_serio_ids[] = { +static const struct serio_device_id skbd_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_STOWAWAY, diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index dc6bb9d5b4f0..c95707ea2656 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -339,7 +339,7 @@ static void sunkbd_disconnect(struct serio *serio) kfree(sunkbd); } -static struct serio_device_id sunkbd_serio_ids[] = { +static const struct serio_device_id sunkbd_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_SUNKBD, diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 0c07e1023a46..edc1385ca00b 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -370,8 +370,11 @@ static int tegra_kbc_start(struct tegra_kbc *kbc) { unsigned int debounce_cnt; u32 val = 0; + int ret; - clk_prepare_enable(kbc->clk); + ret = clk_prepare_enable(kbc->clk); + if (ret) + return ret; /* Reset the KBC controller to clear all previous status.*/ reset_control_assert(kbc->rst); diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 39e72b3219d8..f9f98ef1d98e 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -30,7 +30,7 @@ #include <linux/interrupt.h> #include <linux/input.h> #include <linux/platform_device.h> -#include <linux/i2c/twl.h> +#include <linux/mfd/twl.h> #include <linux/slab.h> #include <linux/of.h> diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index 7c2325bd7408..8f64b9ded8d0 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c @@ -145,7 +145,7 @@ static void xtkbd_disconnect(struct serio *serio) kfree(xtkbd); } -static struct serio_device_id xtkbd_serio_ids[] = { +static const struct serio_device_id xtkbd_serio_ids[] = { { .type = SERIO_XT, .proto = SERIO_ANY, diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 3872488c3fd7..9f082a388388 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -581,6 +581,29 @@ config INPUT_PWM_BEEPER To compile this driver as a module, choose M here: the module will be called pwm-beeper. +config INPUT_PWM_VIBRA + tristate "PWM vibrator support" + depends on PWM + select INPUT_FF_MEMLESS + help + Say Y here to get support for PWM based vibrator devices. + + If unsure, say N. + + To compile this driver as a module, choose M here: the module will be + called pwm-vibra. + +config INPUT_RK805_PWRKEY + tristate "Rockchip RK805 PMIC power key support" + depends on MFD_RK808 + help + Select this option to enable power key driver for RK805. + + If unsure, say N. + + To compile this driver as a module, choose M here: the module will be + called rk805_pwrkey. + config INPUT_GPIO_ROTARY_ENCODER tristate "Rotary encoders connected to GPIO pins" depends on GPIOLIB || COMPILE_TEST diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index b923a9828c88..03fd4262ada9 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -59,11 +59,13 @@ obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o obj-$(CONFIG_INPUT_POWERMATE) += powermate.o obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o +obj-$(CONFIG_INPUT_PWM_VIBRA) += pwm-vibra.o obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o obj-$(CONFIG_INPUT_AXP20X_PEK) += axp20x-pek.o obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o +obj-$(CONFIG_INPUT_RK805_PWRKEY) += rk805-pwrkey.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 1c5914cae853..ebf4448b31b9 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -110,7 +110,7 @@ static const struct kernel_param_ops param_ops_mode_mask = { module_param(mode_mask, mode_mask, 0644); MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); -static struct usb_device_id ati_remote2_id_table[] = { +static const struct usb_device_id ati_remote2_id_table[] = { { USB_DEVICE(0x0471, 0x0602) }, /* ATI Remote Wonder II */ { } }; diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c index 38c79ebff033..6cee5adc3b5c 100644 --- a/drivers/input/misc/axp20x-pek.c +++ b/drivers/input/misc/axp20x-pek.c @@ -29,9 +29,17 @@ #define AXP20X_PEK_STARTUP_MASK (0xc0) #define AXP20X_PEK_SHUTDOWN_MASK (0x03) +struct axp20x_info { + const struct axp20x_time *startup_time; + unsigned int startup_mask; + const struct axp20x_time *shutdown_time; + unsigned int shutdown_mask; +}; + struct axp20x_pek { struct axp20x_dev *axp20x; struct input_dev *input; + struct axp20x_info *info; int irq_dbr; int irq_dbf; }; @@ -48,6 +56,13 @@ static const struct axp20x_time startup_time[] = { { .time = 2000, .idx = 3 }, }; +static const struct axp20x_time axp221_startup_time[] = { + { .time = 128, .idx = 0 }, + { .time = 1000, .idx = 1 }, + { .time = 2000, .idx = 2 }, + { .time = 3000, .idx = 3 }, +}; + static const struct axp20x_time shutdown_time[] = { { .time = 4000, .idx = 0 }, { .time = 6000, .idx = 1 }, @@ -55,31 +70,25 @@ static const struct axp20x_time shutdown_time[] = { { .time = 10000, .idx = 3 }, }; -struct axp20x_pek_ext_attr { - const struct axp20x_time *p_time; - unsigned int mask; -}; - -static struct axp20x_pek_ext_attr axp20x_pek_startup_ext_attr = { - .p_time = startup_time, - .mask = AXP20X_PEK_STARTUP_MASK, +static const struct axp20x_info axp20x_info = { + .startup_time = startup_time, + .startup_mask = AXP20X_PEK_STARTUP_MASK, + .shutdown_time = shutdown_time, + .shutdown_mask = AXP20X_PEK_SHUTDOWN_MASK, }; -static struct axp20x_pek_ext_attr axp20x_pek_shutdown_ext_attr = { - .p_time = shutdown_time, - .mask = AXP20X_PEK_SHUTDOWN_MASK, +static const struct axp20x_info axp221_info = { + .startup_time = axp221_startup_time, + .startup_mask = AXP20X_PEK_STARTUP_MASK, + .shutdown_time = shutdown_time, + .shutdown_mask = AXP20X_PEK_SHUTDOWN_MASK, }; -static struct axp20x_pek_ext_attr *get_axp_ext_attr(struct device_attribute *attr) -{ - return container_of(attr, struct dev_ext_attribute, attr)->var; -} - -static ssize_t axp20x_show_ext_attr(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t axp20x_show_attr(struct device *dev, + const struct axp20x_time *time, + unsigned int mask, char *buf) { struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev); - struct axp20x_pek_ext_attr *axp20x_ea = get_axp_ext_attr(attr); unsigned int val; int ret, i; @@ -87,22 +96,42 @@ static ssize_t axp20x_show_ext_attr(struct device *dev, if (ret != 0) return ret; - val &= axp20x_ea->mask; - val >>= ffs(axp20x_ea->mask) - 1; + val &= mask; + val >>= ffs(mask) - 1; for (i = 0; i < 4; i++) - if (val == axp20x_ea->p_time[i].idx) - val = axp20x_ea->p_time[i].time; + if (val == time[i].idx) + val = time[i].time; return sprintf(buf, "%u\n", val); } -static ssize_t axp20x_store_ext_attr(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t axp20x_show_attr_startup(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev); + + return axp20x_show_attr(dev, axp20x_pek->info->startup_time, + axp20x_pek->info->startup_mask, buf); +} + +static ssize_t axp20x_show_attr_shutdown(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev); + + return axp20x_show_attr(dev, axp20x_pek->info->shutdown_time, + axp20x_pek->info->shutdown_mask, buf); +} + +static ssize_t axp20x_store_attr(struct device *dev, + const struct axp20x_time *time, + unsigned int mask, const char *buf, + size_t count) { struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev); - struct axp20x_pek_ext_attr *axp20x_ea = get_axp_ext_attr(attr); char val_str[20]; size_t len; int ret, i; @@ -123,39 +152,52 @@ static ssize_t axp20x_store_ext_attr(struct device *dev, for (i = 3; i >= 0; i--) { unsigned int err; - err = abs(axp20x_ea->p_time[i].time - val); + err = abs(time[i].time - val); if (err < best_err) { best_err = err; - idx = axp20x_ea->p_time[i].idx; + idx = time[i].idx; } if (!err) break; } - idx <<= ffs(axp20x_ea->mask) - 1; - ret = regmap_update_bits(axp20x_pek->axp20x->regmap, - AXP20X_PEK_KEY, - axp20x_ea->mask, idx); + idx <<= ffs(mask) - 1; + ret = regmap_update_bits(axp20x_pek->axp20x->regmap, AXP20X_PEK_KEY, + mask, idx); if (ret != 0) return -EINVAL; return count; } -static struct dev_ext_attribute axp20x_dev_attr_startup = { - .attr = __ATTR(startup, 0644, axp20x_show_ext_attr, axp20x_store_ext_attr), - .var = &axp20x_pek_startup_ext_attr, -}; +static ssize_t axp20x_store_attr_startup(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev); -static struct dev_ext_attribute axp20x_dev_attr_shutdown = { - .attr = __ATTR(shutdown, 0644, axp20x_show_ext_attr, axp20x_store_ext_attr), - .var = &axp20x_pek_shutdown_ext_attr, -}; + return axp20x_store_attr(dev, axp20x_pek->info->startup_time, + axp20x_pek->info->startup_mask, buf, count); +} + +static ssize_t axp20x_store_attr_shutdown(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev); + + return axp20x_store_attr(dev, axp20x_pek->info->shutdown_time, + axp20x_pek->info->shutdown_mask, buf, count); +} + +DEVICE_ATTR(startup, 0644, axp20x_show_attr_startup, axp20x_store_attr_startup); +DEVICE_ATTR(shutdown, 0644, axp20x_show_attr_shutdown, + axp20x_store_attr_shutdown); static struct attribute *axp20x_attributes[] = { - &axp20x_dev_attr_startup.attr.attr, - &axp20x_dev_attr_shutdown.attr.attr, + &dev_attr_startup.attr, + &dev_attr_shutdown.attr, NULL, }; @@ -182,13 +224,6 @@ static irqreturn_t axp20x_pek_irq(int irq, void *pwr) return IRQ_HANDLED; } -static void axp20x_remove_sysfs_group(void *_data) -{ - struct device *dev = _data; - - sysfs_remove_group(&dev->kobj, &axp20x_attribute_group); -} - static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek, struct platform_device *pdev) { @@ -298,8 +333,14 @@ static bool axp20x_pek_should_register_input(struct axp20x_pek *axp20x_pek, static int axp20x_pek_probe(struct platform_device *pdev) { struct axp20x_pek *axp20x_pek; + const struct platform_device_id *match = platform_get_device_id(pdev); int error; + if (!match) { + dev_err(&pdev->dev, "Failed to get platform_device_id\n"); + return -EINVAL; + } + axp20x_pek = devm_kzalloc(&pdev->dev, sizeof(struct axp20x_pek), GFP_KERNEL); if (!axp20x_pek) @@ -313,18 +354,11 @@ static int axp20x_pek_probe(struct platform_device *pdev) return error; } - error = sysfs_create_group(&pdev->dev.kobj, &axp20x_attribute_group); - if (error) { - dev_err(&pdev->dev, "Failed to create sysfs attributes: %d\n", - error); - return error; - } + axp20x_pek->info = (struct axp20x_info *)match->driver_data; - error = devm_add_action(&pdev->dev, - axp20x_remove_sysfs_group, &pdev->dev); + error = devm_device_add_group(&pdev->dev, &axp20x_attribute_group); if (error) { - axp20x_remove_sysfs_group(&pdev->dev); - dev_err(&pdev->dev, "Failed to add sysfs cleanup action: %d\n", + dev_err(&pdev->dev, "Failed to create sysfs attributes: %d\n", error); return error; } @@ -358,8 +392,21 @@ static const struct dev_pm_ops axp20x_pek_pm_ops = { #endif }; +static const struct platform_device_id axp_pek_id_match[] = { + { + .name = "axp20x-pek", + .driver_data = (kernel_ulong_t)&axp20x_info, + }, + { + .name = "axp221-pek", + .driver_data = (kernel_ulong_t)&axp221_info, + }, + { /* sentinel */ } +}; + static struct platform_driver axp20x_pek_driver = { .probe = axp20x_pek_probe, + .id_table = axp_pek_id_match, .driver = { .name = "axp20x-pek", .pm = &axp20x_pek_pm_ops, diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index bab256ef32b9..c803db64a376 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c @@ -15,7 +15,7 @@ #include <linux/platform_device.h> #include <linux/interrupt.h> -#include <linux/i2c/dm355evm_msp.h> +#include <linux/mfd/dm355evm_msp.h> #include <linux/module.h> diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index f4e8fbec6a94..6bf82ea8c918 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -1261,7 +1261,7 @@ static umode_t ims_pcu_is_attr_visible(struct kobject *kobj, return mode; } -static struct attribute_group ims_pcu_attr_group = { +static const struct attribute_group ims_pcu_attr_group = { .is_visible = ims_pcu_is_attr_visible, .attrs = ims_pcu_attrs, }; @@ -1480,7 +1480,7 @@ static struct attribute *ims_pcu_ofn_attrs[] = { NULL }; -static struct attribute_group ims_pcu_ofn_attr_group = { +static const struct attribute_group ims_pcu_ofn_attr_group = { .name = "ofn", .attrs = ims_pcu_ofn_attrs, }; diff --git a/drivers/input/misc/keyspan_remote.c b/drivers/input/misc/keyspan_remote.c index a3fe4a990cc9..77c47d6325fe 100644 --- a/drivers/input/misc/keyspan_remote.c +++ b/drivers/input/misc/keyspan_remote.c @@ -85,7 +85,7 @@ static const unsigned short keyspan_key_table[] = { }; /* table of devices that work with this driver */ -static struct usb_device_id keyspan_table[] = { +static const struct usb_device_id keyspan_table[] = { { USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) }, { } /* Terminating entry */ }; diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 72b1fc3ab910..56ddba21de84 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -18,25 +18,30 @@ #include <linux/input.h> #include <linux/platform_device.h> #include <linux/timex.h> -#include <asm/io.h> +#include <linux/io.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("PC Speaker beeper driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:pcspkr"); -static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) +static int pcspkr_event(struct input_dev *dev, unsigned int type, + unsigned int code, int value) { unsigned int count = 0; unsigned long flags; if (type != EV_SND) - return -1; + return -EINVAL; switch (code) { - case SND_BELL: if (value) value = 1000; - case SND_TONE: break; - default: return -1; + case SND_BELL: + if (value) + value = 1000; + case SND_TONE: + break; + default: + return -EINVAL; } if (value > 20 && value < 32767) diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index 84909a12ff36..5c8c79623c87 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c @@ -432,7 +432,7 @@ static void powermate_disconnect(struct usb_interface *intf) } } -static struct usb_device_id powermate_devices [] = { +static const struct usb_device_id powermate_devices[] = { { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_NEW) }, { USB_DEVICE(POWERMATE_VENDOR, POWERMATE_PRODUCT_OLD) }, { USB_DEVICE(CONTOUR_VENDOR, CONTOUR_JOG) }, diff --git a/drivers/input/misc/pwm-vibra.c b/drivers/input/misc/pwm-vibra.c new file mode 100644 index 000000000000..55da191ae550 --- /dev/null +++ b/drivers/input/misc/pwm-vibra.c @@ -0,0 +1,267 @@ +/* + * PWM vibrator driver + * + * Copyright (C) 2017 Collabora Ltd. + * + * Based on previous work from: + * Copyright (C) 2012 Dmitry Torokhov <dmitry.torokhov@gmail.com> + * + * Based on PWM beeper driver: + * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> + * + * 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. + */ + +#include <linux/input.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/property.h> +#include <linux/pwm.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> + +struct pwm_vibrator { + struct input_dev *input; + struct pwm_device *pwm; + struct pwm_device *pwm_dir; + struct regulator *vcc; + + struct work_struct play_work; + u16 level; + u32 direction_duty_cycle; +}; + +static int pwm_vibrator_start(struct pwm_vibrator *vibrator) +{ + struct device *pdev = vibrator->input->dev.parent; + struct pwm_state state; + int err; + + err = regulator_enable(vibrator->vcc); + if (err) { + dev_err(pdev, "failed to enable regulator: %d", err); + return err; + } + + pwm_get_state(vibrator->pwm, &state); + pwm_set_relative_duty_cycle(&state, vibrator->level, 0xffff); + state.enabled = true; + + err = pwm_apply_state(vibrator->pwm, &state); + if (err) { + dev_err(pdev, "failed to apply pwm state: %d", err); + return err; + } + + if (vibrator->pwm_dir) { + pwm_get_state(vibrator->pwm_dir, &state); + state.duty_cycle = vibrator->direction_duty_cycle; + state.enabled = true; + + err = pwm_apply_state(vibrator->pwm_dir, &state); + if (err) { + dev_err(pdev, "failed to apply dir-pwm state: %d", err); + pwm_disable(vibrator->pwm); + return err; + } + } + + return 0; +} + +static void pwm_vibrator_stop(struct pwm_vibrator *vibrator) +{ + regulator_disable(vibrator->vcc); + + if (vibrator->pwm_dir) + pwm_disable(vibrator->pwm_dir); + pwm_disable(vibrator->pwm); +} + +static void pwm_vibrator_play_work(struct work_struct *work) +{ + struct pwm_vibrator *vibrator = container_of(work, + struct pwm_vibrator, play_work); + + if (vibrator->level) + pwm_vibrator_start(vibrator); + else + pwm_vibrator_stop(vibrator); +} + +static int pwm_vibrator_play_effect(struct input_dev *dev, void *data, + struct ff_effect *effect) +{ + struct pwm_vibrator *vibrator = input_get_drvdata(dev); + + vibrator->level = effect->u.rumble.strong_magnitude; + if (!vibrator->level) + vibrator->level = effect->u.rumble.weak_magnitude; + + schedule_work(&vibrator->play_work); + + return 0; +} + +static void pwm_vibrator_close(struct input_dev *input) +{ + struct pwm_vibrator *vibrator = input_get_drvdata(input); + + cancel_work_sync(&vibrator->play_work); + pwm_vibrator_stop(vibrator); +} + +static int pwm_vibrator_probe(struct platform_device *pdev) +{ + struct pwm_vibrator *vibrator; + struct pwm_state state; + int err; + + vibrator = devm_kzalloc(&pdev->dev, sizeof(*vibrator), GFP_KERNEL); + if (!vibrator) + return -ENOMEM; + + vibrator->input = devm_input_allocate_device(&pdev->dev); + if (!vibrator->input) + return -ENOMEM; + + vibrator->vcc = devm_regulator_get(&pdev->dev, "vcc"); + err = PTR_ERR_OR_ZERO(vibrator->vcc); + if (err) { + if (err != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to request regulator: %d", + err); + return err; + } + + vibrator->pwm = devm_pwm_get(&pdev->dev, "enable"); + err = PTR_ERR_OR_ZERO(vibrator->pwm); + if (err) { + if (err != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to request main pwm: %d", + err); + return err; + } + + INIT_WORK(&vibrator->play_work, pwm_vibrator_play_work); + + /* Sync up PWM state and ensure it is off. */ + pwm_init_state(vibrator->pwm, &state); + state.enabled = false; + err = pwm_apply_state(vibrator->pwm, &state); + if (err) { + dev_err(&pdev->dev, "failed to apply initial PWM state: %d", + err); + return err; + } + + vibrator->pwm_dir = devm_pwm_get(&pdev->dev, "direction"); + err = PTR_ERR_OR_ZERO(vibrator->pwm_dir); + switch (err) { + case 0: + /* Sync up PWM state and ensure it is off. */ + pwm_init_state(vibrator->pwm_dir, &state); + state.enabled = false; + err = pwm_apply_state(vibrator->pwm_dir, &state); + if (err) { + dev_err(&pdev->dev, "failed to apply initial PWM state: %d", + err); + return err; + } + + vibrator->direction_duty_cycle = + pwm_get_period(vibrator->pwm_dir) / 2; + device_property_read_u32(&pdev->dev, "direction-duty-cycle-ns", + &vibrator->direction_duty_cycle); + break; + + case -ENODATA: + /* Direction PWM is optional */ + vibrator->pwm_dir = NULL; + break; + + default: + dev_err(&pdev->dev, "Failed to request direction pwm: %d", err); + /* Fall through */ + + case -EPROBE_DEFER: + return err; + } + + vibrator->input->name = "pwm-vibrator"; + vibrator->input->id.bustype = BUS_HOST; + vibrator->input->dev.parent = &pdev->dev; + vibrator->input->close = pwm_vibrator_close; + + input_set_drvdata(vibrator->input, vibrator); + input_set_capability(vibrator->input, EV_FF, FF_RUMBLE); + + err = input_ff_create_memless(vibrator->input, NULL, + pwm_vibrator_play_effect); + if (err) { + dev_err(&pdev->dev, "Couldn't create FF dev: %d", err); + return err; + } + + err = input_register_device(vibrator->input); + if (err) { + dev_err(&pdev->dev, "Couldn't register input dev: %d", err); + return err; + } + + platform_set_drvdata(pdev, vibrator); + + return 0; +} + +static int __maybe_unused pwm_vibrator_suspend(struct device *dev) +{ + struct pwm_vibrator *vibrator = dev_get_drvdata(dev); + + cancel_work_sync(&vibrator->play_work); + if (vibrator->level) + pwm_vibrator_stop(vibrator); + + return 0; +} + +static int __maybe_unused pwm_vibrator_resume(struct device *dev) +{ + struct pwm_vibrator *vibrator = dev_get_drvdata(dev); + + if (vibrator->level) + pwm_vibrator_start(vibrator); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(pwm_vibrator_pm_ops, + pwm_vibrator_suspend, pwm_vibrator_resume); + +#ifdef CONFIG_OF +static const struct of_device_id pwm_vibra_dt_match_table[] = { + { .compatible = "pwm-vibrator" }, + {}, +}; +MODULE_DEVICE_TABLE(of, pwm_vibra_dt_match_table); +#endif + +static struct platform_driver pwm_vibrator_driver = { + .probe = pwm_vibrator_probe, + .driver = { + .name = "pwm-vibrator", + .pm = &pwm_vibrator_pm_ops, + .of_match_table = of_match_ptr(pwm_vibra_dt_match_table), + }, +}; +module_platform_driver(pwm_vibrator_driver); + +MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>"); +MODULE_DESCRIPTION("PWM vibrator driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:pwm-vibrator"); diff --git a/drivers/input/misc/rk805-pwrkey.c b/drivers/input/misc/rk805-pwrkey.c new file mode 100644 index 000000000000..921003963a53 --- /dev/null +++ b/drivers/input/misc/rk805-pwrkey.c @@ -0,0 +1,111 @@ +/* + * Rockchip RK805 PMIC Power Key driver + * + * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: Joseph Chen <chenjh@rock-chips.com> + * + * 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. + */ + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +static irqreturn_t pwrkey_fall_irq(int irq, void *_pwr) +{ + struct input_dev *pwr = _pwr; + + input_report_key(pwr, KEY_POWER, 1); + input_sync(pwr); + + return IRQ_HANDLED; +} + +static irqreturn_t pwrkey_rise_irq(int irq, void *_pwr) +{ + struct input_dev *pwr = _pwr; + + input_report_key(pwr, KEY_POWER, 0); + input_sync(pwr); + + return IRQ_HANDLED; +} + +static int rk805_pwrkey_probe(struct platform_device *pdev) +{ + struct input_dev *pwr; + int fall_irq, rise_irq; + int err; + + pwr = devm_input_allocate_device(&pdev->dev); + if (!pwr) { + dev_err(&pdev->dev, "Can't allocate power button\n"); + return -ENOMEM; + } + + pwr->name = "rk805 pwrkey"; + pwr->phys = "rk805_pwrkey/input0"; + pwr->id.bustype = BUS_HOST; + input_set_capability(pwr, EV_KEY, KEY_POWER); + + fall_irq = platform_get_irq(pdev, 0); + if (fall_irq < 0) { + dev_err(&pdev->dev, "Can't get fall irq: %d\n", fall_irq); + return fall_irq; + } + + rise_irq = platform_get_irq(pdev, 1); + if (rise_irq < 0) { + dev_err(&pdev->dev, "Can't get rise irq: %d\n", rise_irq); + return rise_irq; + } + + err = devm_request_any_context_irq(&pwr->dev, fall_irq, + pwrkey_fall_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "rk805_pwrkey_fall", pwr); + if (err < 0) { + dev_err(&pdev->dev, "Can't register fall irq: %d\n", err); + return err; + } + + err = devm_request_any_context_irq(&pwr->dev, rise_irq, + pwrkey_rise_irq, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "rk805_pwrkey_rise", pwr); + if (err < 0) { + dev_err(&pdev->dev, "Can't register rise irq: %d\n", err); + return err; + } + + err = input_register_device(pwr); + if (err) { + dev_err(&pdev->dev, "Can't register power button: %d\n", err); + return err; + } + + platform_set_drvdata(pdev, pwr); + device_init_wakeup(&pdev->dev, true); + + return 0; +} + +static struct platform_driver rk805_pwrkey_driver = { + .probe = rk805_pwrkey_probe, + .driver = { + .name = "rk805-pwrkey", + }, +}; +module_platform_driver(rk805_pwrkey_driver); + +MODULE_AUTHOR("Joseph Chen <chenjh@rock-chips.com>"); +MODULE_DESCRIPTION("RK805 PMIC Power Key driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index f600f3a7a3c6..23520df7650f 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -331,7 +331,7 @@ static int soc_button_probe(struct platform_device *pdev) error = gpiod_count(dev, NULL); if (error < 0) { dev_dbg(dev, "no GPIO attached, ignoring...\n"); - return error; + return -ENODEV; } priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index 1c13005b228f..b307cca17022 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -27,7 +27,7 @@ #include <linux/input.h> #include <linux/interrupt.h> #include <linux/platform_device.h> -#include <linux/i2c/twl.h> +#include <linux/mfd/twl.h> #define PWR_PWRON_IRQ (1 << 0) diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index caa5a62c42fb..6c51d404874b 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -28,7 +28,7 @@ #include <linux/platform_device.h> #include <linux/of.h> #include <linux/workqueue.h> -#include <linux/i2c/twl.h> +#include <linux/mfd/twl.h> #include <linux/mfd/twl4030-audio.h> #include <linux/input.h> #include <linux/slab.h> diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index fa130e7b734c..6bf56bb5f8d9 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -84,17 +84,20 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info, struct xenkbd_key *key) { struct input_dev *dev; + int value = key->pressed; if (test_bit(key->keycode, info->ptr->keybit)) { dev = info->ptr; } else if (test_bit(key->keycode, info->kbd->keybit)) { dev = info->kbd; + if (key->pressed && test_bit(key->keycode, info->kbd->key)) + value = 2; /* Mark as autorepeat */ } else { pr_warn("unhandled keycode 0x%x\n", key->keycode); return; } - input_report_key(dev, key->keycode, key->pressed); + input_event(dev, EV_KEY, key->keycode, value); input_sync(dev); } diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 6e7ff9561d92..a1e0ff59d2f2 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c @@ -798,7 +798,7 @@ static struct attribute *yld_attributes[] = { NULL }; -static struct attribute_group yld_attr_group = { +static const struct attribute_group yld_attr_group = { .attrs = yld_attributes }; diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 262d1057c1da..850b00e3ad8e 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -1215,14 +1215,24 @@ static int alps_decode_ss4_v2(struct alps_fields *f, case SS4_PACKET_ID_TWO: if (priv->flags & ALPS_BUTTONPAD) { - f->mt[0].x = SS4_BTL_MF_X_V2(p, 0); + if (IS_SS4PLUS_DEV(priv->dev_id)) { + f->mt[0].x = SS4_PLUS_BTL_MF_X_V2(p, 0); + f->mt[1].x = SS4_PLUS_BTL_MF_X_V2(p, 1); + } else { + f->mt[0].x = SS4_BTL_MF_X_V2(p, 0); + f->mt[1].x = SS4_BTL_MF_X_V2(p, 1); + } f->mt[0].y = SS4_BTL_MF_Y_V2(p, 0); - f->mt[1].x = SS4_BTL_MF_X_V2(p, 1); f->mt[1].y = SS4_BTL_MF_Y_V2(p, 1); } else { - f->mt[0].x = SS4_STD_MF_X_V2(p, 0); + if (IS_SS4PLUS_DEV(priv->dev_id)) { + f->mt[0].x = SS4_PLUS_STD_MF_X_V2(p, 0); + f->mt[1].x = SS4_PLUS_STD_MF_X_V2(p, 1); + } else { + f->mt[0].x = SS4_STD_MF_X_V2(p, 0); + f->mt[1].x = SS4_STD_MF_X_V2(p, 1); + } f->mt[0].y = SS4_STD_MF_Y_V2(p, 0); - f->mt[1].x = SS4_STD_MF_X_V2(p, 1); f->mt[1].y = SS4_STD_MF_Y_V2(p, 1); } f->pressure = SS4_MF_Z_V2(p, 0) ? 0x30 : 0; @@ -1239,16 +1249,27 @@ static int alps_decode_ss4_v2(struct alps_fields *f, case SS4_PACKET_ID_MULTI: if (priv->flags & ALPS_BUTTONPAD) { - f->mt[2].x = SS4_BTL_MF_X_V2(p, 0); + if (IS_SS4PLUS_DEV(priv->dev_id)) { + f->mt[0].x = SS4_PLUS_BTL_MF_X_V2(p, 0); + f->mt[1].x = SS4_PLUS_BTL_MF_X_V2(p, 1); + } else { + f->mt[2].x = SS4_BTL_MF_X_V2(p, 0); + f->mt[3].x = SS4_BTL_MF_X_V2(p, 1); + } + f->mt[2].y = SS4_BTL_MF_Y_V2(p, 0); - f->mt[3].x = SS4_BTL_MF_X_V2(p, 1); f->mt[3].y = SS4_BTL_MF_Y_V2(p, 1); no_data_x = SS4_MFPACKET_NO_AX_BL; no_data_y = SS4_MFPACKET_NO_AY_BL; } else { - f->mt[2].x = SS4_STD_MF_X_V2(p, 0); + if (IS_SS4PLUS_DEV(priv->dev_id)) { + f->mt[0].x = SS4_PLUS_STD_MF_X_V2(p, 0); + f->mt[1].x = SS4_PLUS_STD_MF_X_V2(p, 1); + } else { + f->mt[0].x = SS4_STD_MF_X_V2(p, 0); + f->mt[1].x = SS4_STD_MF_X_V2(p, 1); + } f->mt[2].y = SS4_STD_MF_Y_V2(p, 0); - f->mt[3].x = SS4_STD_MF_X_V2(p, 1); f->mt[3].y = SS4_STD_MF_Y_V2(p, 1); no_data_x = SS4_MFPACKET_NO_AX; no_data_y = SS4_MFPACKET_NO_AY; @@ -2541,8 +2562,8 @@ static int alps_set_defaults_ss4_v2(struct psmouse *psmouse, memset(otp, 0, sizeof(otp)); - if (alps_get_otp_values_ss4_v2(psmouse, 0, &otp[0][0]) || - alps_get_otp_values_ss4_v2(psmouse, 1, &otp[1][0])) + if (alps_get_otp_values_ss4_v2(psmouse, 1, &otp[1][0]) || + alps_get_otp_values_ss4_v2(psmouse, 0, &otp[0][0])) return -1; alps_update_device_area_ss4_v2(otp, priv); diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index ed2d6879fa52..c80a7c76cb76 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h @@ -100,6 +100,10 @@ enum SS4_PACKET_ID { ((_b[1 + _i * 3] << 5) & 0x1F00) \ ) +#define SS4_PLUS_STD_MF_X_V2(_b, _i) (((_b[0 + (_i) * 3] << 4) & 0x0070) | \ + ((_b[1 + (_i) * 3] << 4) & 0x0F80) \ + ) + #define SS4_STD_MF_Y_V2(_b, _i) (((_b[1 + (_i) * 3] << 3) & 0x0010) | \ ((_b[2 + (_i) * 3] << 5) & 0x01E0) | \ ((_b[2 + (_i) * 3] << 4) & 0x0E00) \ @@ -109,6 +113,10 @@ enum SS4_PACKET_ID { ((_b[0 + (_i) * 3] >> 3) & 0x0010) \ ) +#define SS4_PLUS_BTL_MF_X_V2(_b, _i) (SS4_PLUS_STD_MF_X_V2(_b, _i) | \ + ((_b[0 + (_i) * 3] >> 4) & 0x0008) \ + ) + #define SS4_BTL_MF_Y_V2(_b, _i) (SS4_STD_MF_Y_V2(_b, _i) | \ ((_b[0 + (_i) * 3] >> 3) & 0x0008) \ ) diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index ef234c9b2f2f..81a695d0b4e0 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -125,7 +125,7 @@ static const struct atp_info geyser4_info = { * According to Info.plist Geyser IV is the same as Geyser III.) */ -static struct usb_device_id atp_table[] = { +static const struct usb_device_id atp_table[] = { /* PowerBooks Feb 2005, iBooks G4 */ ATP_DEVICE(0x020e, fountain_info), /* FOUNTAIN ANSI */ ATP_DEVICE(0x020f, fountain_info), /* FOUNTAIN ISO */ diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c index b27aa637f877..b64b81599f7e 100644 --- a/drivers/input/mouse/byd.c +++ b/drivers/input/mouse/byd.c @@ -344,7 +344,7 @@ static int byd_reset_touchpad(struct psmouse *psmouse) u8 param[4]; size_t i; - const struct { + static const struct { u16 command; u8 arg; } seq[] = { diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index 61c202436250..599544c1a91c 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h @@ -58,7 +58,7 @@ struct elan_transport_ops { int (*get_version)(struct i2c_client *client, bool iap, u8 *version); int (*get_sm_version)(struct i2c_client *client, - u16 *ic_type, u8 *version); + u16 *ic_type, u8 *version, u8 *clickpad); int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum); int (*get_product_id)(struct i2c_client *client, u16 *id); diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 3b616cb7c67f..0e761d079dc4 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -95,6 +95,7 @@ struct elan_tp_data { u8 min_baseline; u8 max_baseline; bool baseline_ready; + u8 clickpad; }; static int elan_get_fwinfo(u16 ic_type, u16 *validpage_count, @@ -213,7 +214,7 @@ static int elan_query_product(struct elan_tp_data *data) return error; error = data->ops->get_sm_version(data->client, &data->ic_type, - &data->sm_version); + &data->sm_version, &data->clickpad); if (error) return error; @@ -923,6 +924,7 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet) } input_report_key(input, BTN_LEFT, tp_info & 0x01); + input_report_key(input, BTN_RIGHT, tp_info & 0x02); input_report_abs(input, ABS_DISTANCE, hover_event != 0); input_mt_report_pointer_emulation(input, true); input_sync(input); @@ -991,7 +993,10 @@ static int elan_setup_input_device(struct elan_tp_data *data) __set_bit(EV_ABS, input->evbit); __set_bit(INPUT_PROP_POINTER, input->propbit); - __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); + if (data->clickpad) + __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); + else + __set_bit(BTN_RIGHT, input->keybit); __set_bit(BTN_LEFT, input->keybit); /* Set up ST parameters */ @@ -1247,7 +1252,12 @@ static const struct acpi_device_id elan_acpi_id[] = { { "ELAN0000", 0 }, { "ELAN0100", 0 }, { "ELAN0600", 0 }, + { "ELAN0602", 0 }, + { "ELAN0605", 0 }, + { "ELAN0608", 0 }, { "ELAN0605", 0 }, + { "ELAN0609", 0 }, + { "ELAN060B", 0 }, { "ELAN1000", 0 }, { } }; diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index 80172f25974d..15b1330606c1 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -288,7 +288,8 @@ static int elan_i2c_get_version(struct i2c_client *client, } static int elan_i2c_get_sm_version(struct i2c_client *client, - u16 *ic_type, u8 *version) + u16 *ic_type, u8 *version, + u8 *clickpad) { int error; u8 pattern_ver; @@ -317,6 +318,7 @@ static int elan_i2c_get_sm_version(struct i2c_client *client, return error; } *version = val[1]; + *clickpad = val[0] & 0x10; } else { error = elan_i2c_read_cmd(client, ETP_I2C_OSM_VERSION_CMD, val); if (error) { @@ -326,6 +328,15 @@ static int elan_i2c_get_sm_version(struct i2c_client *client, } *version = val[0]; *ic_type = val[1]; + + error = elan_i2c_read_cmd(client, ETP_I2C_NSM_VERSION_CMD, + val); + if (error) { + dev_err(&client->dev, "failed to get SM version: %d\n", + error); + return error; + } + *clickpad = val[0] & 0x10; } return 0; diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c index df7a57ca7331..29f99529b187 100644 --- a/drivers/input/mouse/elan_i2c_smbus.c +++ b/drivers/input/mouse/elan_i2c_smbus.c @@ -166,7 +166,8 @@ static int elan_smbus_get_version(struct i2c_client *client, } static int elan_smbus_get_sm_version(struct i2c_client *client, - u16 *ic_type, u8 *version) + u16 *ic_type, u8 *version, + u8 *clickpad) { int error; u8 val[3]; @@ -180,6 +181,7 @@ static int elan_smbus_get_sm_version(struct i2c_client *client, *version = val[0]; *ic_type = val[1]; + *clickpad = val[0] & 0x10; return 0; } diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 791993215ea3..b84cd978fce2 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -700,7 +700,9 @@ static int elantech_debounce_check_v2(struct psmouse *psmouse) * When we encounter packet that matches this exactly, it means the * hardware is in debounce status. Just ignore the whole packet. */ - const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff }; + static const u8 debounce_packet[] = { + 0x84, 0xff, 0xff, 0x02, 0xff, 0xff + }; unsigned char *packet = psmouse->packet; return !memcmp(packet, debounce_packet, sizeof(debounce_packet)); @@ -741,7 +743,9 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) static int elantech_packet_check_v3(struct psmouse *psmouse) { struct elantech_data *etd = psmouse->private; - const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; + static const u8 debounce_packet[] = { + 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff + }; unsigned char *packet = psmouse->packet; /* @@ -1377,7 +1381,7 @@ static struct attribute *elantech_attrs[] = { NULL }; -static struct attribute_group elantech_attr_group = { +static const struct attribute_group elantech_attr_group = { .attrs = elantech_attrs, }; diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index f73b47b8c578..6a5649e52eed 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -101,7 +101,7 @@ static struct attribute *psmouse_attributes[] = { NULL }; -static struct attribute_group psmouse_attribute_group = { +static const struct attribute_group psmouse_attribute_group = { .attrs = psmouse_attributes, }; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 16c30460ef04..5af0b7d200bc 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -535,16 +535,17 @@ static void synaptics_apply_quirks(struct psmouse *psmouse, } } +static bool synaptics_has_agm(struct synaptics_data *priv) +{ + return (SYN_CAP_ADV_GESTURE(priv->info.ext_cap_0c) || + SYN_CAP_IMAGE_SENSOR(priv->info.ext_cap_0c)); +} + static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) { static u8 param = 0xc8; - struct synaptics_data *priv = psmouse->private; int error; - if (!(SYN_CAP_ADV_GESTURE(priv->info.ext_cap_0c) || - SYN_CAP_IMAGE_SENSOR(priv->info.ext_cap_0c))) - return 0; - error = psmouse_sliced_command(psmouse, SYN_QUE_MODEL); if (error) return error; @@ -553,9 +554,6 @@ static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse) if (error) return error; - /* Advanced gesture mode also sends multi finger data */ - priv->info.capabilities |= BIT(1); - return 0; } @@ -578,7 +576,7 @@ static int synaptics_set_mode(struct psmouse *psmouse) if (error) return error; - if (priv->absolute_mode) { + if (priv->absolute_mode && synaptics_has_agm(priv)) { error = synaptics_set_advanced_gesture_mode(psmouse); if (error) { psmouse_err(psmouse, @@ -766,9 +764,7 @@ static int synaptics_parse_hw_state(const u8 buf[], ((buf[0] & 0x04) >> 1) | ((buf[3] & 0x04) >> 2)); - if ((SYN_CAP_ADV_GESTURE(priv->info.ext_cap_0c) || - SYN_CAP_IMAGE_SENSOR(priv->info.ext_cap_0c)) && - hw->w == 2) { + if (synaptics_has_agm(priv) && hw->w == 2) { synaptics_parse_agm(buf, priv, hw); return 1; } @@ -1033,6 +1029,15 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse, synaptics_report_mt_data(psmouse, sgm, num_fingers); } +static bool synaptics_has_multifinger(struct synaptics_data *priv) +{ + if (SYN_CAP_MULTIFINGER(priv->info.capabilities)) + return true; + + /* Advanced gesture mode also sends multi finger data */ + return synaptics_has_agm(priv); +} + /* * called for each full received packet from the touchpad */ @@ -1079,7 +1084,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) if (SYN_CAP_EXTENDED(info->capabilities)) { switch (hw.w) { case 0 ... 1: - if (SYN_CAP_MULTIFINGER(info->capabilities)) + if (synaptics_has_multifinger(priv)) num_fingers = hw.w + 2; break; case 2: @@ -1123,7 +1128,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) input_report_abs(dev, ABS_TOOL_WIDTH, finger_width); input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1); - if (SYN_CAP_MULTIFINGER(info->capabilities)) { + if (synaptics_has_multifinger(priv)) { input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); } @@ -1283,7 +1288,7 @@ static void set_input_params(struct psmouse *psmouse, __set_bit(BTN_TOUCH, dev->keybit); __set_bit(BTN_TOOL_FINGER, dev->keybit); - if (SYN_CAP_MULTIFINGER(info->capabilities)) { + if (synaptics_has_multifinger(priv)) { __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); } diff --git a/drivers/input/mouse/synaptics_usb.c b/drivers/input/mouse/synaptics_usb.c index 6bcc0189c1c9..cb7d15d826d0 100644 --- a/drivers/input/mouse/synaptics_usb.c +++ b/drivers/input/mouse/synaptics_usb.c @@ -525,7 +525,7 @@ static int synusb_reset_resume(struct usb_interface *intf) return synusb_resume(intf); } -static struct usb_device_id synusb_idtable[] = { +static const struct usb_device_id synusb_idtable[] = { { USB_DEVICE_SYNAPTICS(TP, SYNUSB_TOUCHPAD) }, { USB_DEVICE_SYNAPTICS(INT_TP, SYNUSB_TOUCHPAD) }, { USB_DEVICE_SYNAPTICS(CPAD, diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 922ea02edcc3..0871010f18d5 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -265,7 +265,8 @@ static int trackpoint_start_protocol(struct psmouse *psmouse, unsigned char *fir if (ps2_command(&psmouse->ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID))) return -1; - if (param[0] != TP_MAGIC_IDENT) + /* add new TP ID. */ + if (!(param[0] & TP_MAGIC_IDENT)) return -1; if (firmware_id) @@ -380,8 +381,8 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) return 0; if (trackpoint_read(ps2dev, TP_EXT_BTN, &button_info)) { - psmouse_warn(psmouse, "failed to get extended button data\n"); - button_info = 0; + psmouse_warn(psmouse, "failed to get extended button data, assuming 3 buttons\n"); + button_info = 0x33; } psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h index 5617ed3a7d7a..88055755f82e 100644 --- a/drivers/input/mouse/trackpoint.h +++ b/drivers/input/mouse/trackpoint.h @@ -21,8 +21,9 @@ #define TP_COMMAND 0xE2 /* Commands start with this */ #define TP_READ_ID 0xE1 /* Sent for device identification */ -#define TP_MAGIC_IDENT 0x01 /* Sent after a TP_READ_ID followed */ +#define TP_MAGIC_IDENT 0x03 /* Sent after a TP_READ_ID followed */ /* by the firmware ID */ + /* Firmware ID includes 0x1, 0x2, 0x3 */ /* diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 0e0ff84088fd..2d7f691ec71c 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -15,6 +15,7 @@ #define MOUSEDEV_MINORS 31 #define MOUSEDEV_MIX 63 +#include <linux/bitops.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/poll.h> @@ -103,7 +104,7 @@ struct mousedev_client { spinlock_t packet_lock; int pos_x, pos_y; - signed char ps2[6]; + u8 ps2[6]; unsigned char ready, buffer, bufsiz; unsigned char imexseq, impsseq; enum mousedev_emul mode; @@ -291,11 +292,10 @@ static void mousedev_notify_readers(struct mousedev *mousedev, } client->pos_x += packet->dx; - client->pos_x = client->pos_x < 0 ? - 0 : (client->pos_x >= xres ? xres : client->pos_x); + client->pos_x = clamp_val(client->pos_x, 0, xres); + client->pos_y += packet->dy; - client->pos_y = client->pos_y < 0 ? - 0 : (client->pos_y >= yres ? yres : client->pos_y); + client->pos_y = clamp_val(client->pos_y, 0, yres); p->dx += packet->dx; p->dy += packet->dy; @@ -571,44 +571,50 @@ static int mousedev_open(struct inode *inode, struct file *file) return error; } -static inline int mousedev_limit_delta(int delta, int limit) -{ - return delta > limit ? limit : (delta < -limit ? -limit : delta); -} - -static void mousedev_packet(struct mousedev_client *client, - signed char *ps2_data) +static void mousedev_packet(struct mousedev_client *client, u8 *ps2_data) { struct mousedev_motion *p = &client->packets[client->tail]; + s8 dx, dy, dz; + + dx = clamp_val(p->dx, -127, 127); + p->dx -= dx; + + dy = clamp_val(p->dy, -127, 127); + p->dy -= dy; - ps2_data[0] = 0x08 | - ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07); - ps2_data[1] = mousedev_limit_delta(p->dx, 127); - ps2_data[2] = mousedev_limit_delta(p->dy, 127); - p->dx -= ps2_data[1]; - p->dy -= ps2_data[2]; + ps2_data[0] = BIT(3); + ps2_data[0] |= ((dx & BIT(7)) >> 3) | ((dy & BIT(7)) >> 2); + ps2_data[0] |= p->buttons & 0x07; + ps2_data[1] = dx; + ps2_data[2] = dy; switch (client->mode) { case MOUSEDEV_EMUL_EXPS: - ps2_data[3] = mousedev_limit_delta(p->dz, 7); - p->dz -= ps2_data[3]; - ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1); + dz = clamp_val(p->dz, -7, 7); + p->dz -= dz; + + ps2_data[3] = (dz & 0x0f) | ((p->buttons & 0x18) << 1); client->bufsiz = 4; break; case MOUSEDEV_EMUL_IMPS: - ps2_data[0] |= - ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); - ps2_data[3] = mousedev_limit_delta(p->dz, 127); - p->dz -= ps2_data[3]; + dz = clamp_val(p->dz, -127, 127); + p->dz -= dz; + + ps2_data[0] |= ((p->buttons & 0x10) >> 3) | + ((p->buttons & 0x08) >> 1); + ps2_data[3] = dz; + client->bufsiz = 4; break; case MOUSEDEV_EMUL_PS2: default: - ps2_data[0] |= - ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1); p->dz = 0; + + ps2_data[0] |= ((p->buttons & 0x10) >> 3) | + ((p->buttons & 0x08) >> 1); + client->bufsiz = 3; break; } @@ -714,7 +720,7 @@ static ssize_t mousedev_read(struct file *file, char __user *buffer, { struct mousedev_client *client = file->private_data; struct mousedev *mousedev = client->mousedev; - signed char data[sizeof(client->ps2)]; + u8 data[sizeof(client->ps2)]; int retval = 0; if (!client->ready && !client->buffer && mousedev->exist && diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c index 7f7e9176f7ea..ae966e333a2f 100644 --- a/drivers/input/rmi4/rmi_f01.c +++ b/drivers/input/rmi4/rmi_f01.c @@ -334,7 +334,7 @@ static struct attribute *rmi_f01_attrs[] = { NULL }; -static struct attribute_group rmi_f01_attr_group = { +static const struct attribute_group rmi_f01_attr_group = { .attrs = rmi_f01_attrs, }; @@ -570,18 +570,14 @@ static int rmi_f01_probe(struct rmi_function *fn) dev_set_drvdata(&fn->dev, f01); - error = sysfs_create_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group); + error = devm_device_add_group(&fn->rmi_dev->dev, &rmi_f01_attr_group); if (error) - dev_warn(&fn->dev, "Failed to create sysfs group: %d\n", error); + dev_warn(&fn->dev, + "Failed to create attribute group: %d\n", error); return 0; } -static void rmi_f01_remove(struct rmi_function *fn) -{ - sysfs_remove_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group); -} - static int rmi_f01_config(struct rmi_function *fn) { struct f01_data *f01 = dev_get_drvdata(&fn->dev); @@ -721,7 +717,6 @@ struct rmi_function_handler rmi_f01_handler = { }, .func = 0x01, .probe = rmi_f01_probe, - .remove = rmi_f01_remove, .config = rmi_f01_config, .attention = rmi_f01_attention, .suspend = rmi_f01_suspend, diff --git a/drivers/input/rmi4/rmi_f34.c b/drivers/input/rmi4/rmi_f34.c index b8ee78e0d61f..4cfe9703a8e7 100644 --- a/drivers/input/rmi4/rmi_f34.c +++ b/drivers/input/rmi4/rmi_f34.c @@ -516,7 +516,7 @@ static struct attribute *rmi_firmware_attrs[] = { NULL }; -static struct attribute_group rmi_firmware_attr_group = { +static const struct attribute_group rmi_firmware_attr_group = { .attrs = rmi_firmware_attrs, }; diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index c3d05b4d3118..21488c048fa3 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -292,6 +292,17 @@ config SERIO_SUN4I_PS2 To compile this driver as a module, choose M here: the module will be called sun4i-ps2. +config SERIO_GPIO_PS2 + tristate "GPIO PS/2 bit banging driver" + depends on GPIOLIB + help + Say Y here if you want PS/2 bit banging support via GPIO. + + To compile this driver as a module, choose M here: the + module will be called ps2-gpio. + + If you are unsure, say N. + config USERIO tristate "User space serio port driver support" help diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index 2374ef9b33d7..767bd9b6e1ed 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile @@ -30,4 +30,5 @@ obj-$(CONFIG_SERIO_APBPS2) += apbps2.o obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o obj-$(CONFIG_HYPERV_KEYBOARD) += hyperv-keyboard.o obj-$(CONFIG_SERIO_SUN4I_PS2) += sun4i-ps2.o +obj-$(CONFIG_SERIO_GPIO_PS2) += ps2-gpio.o obj-$(CONFIG_USERIO) += userio.o diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index c6606cacb6a7..ff3875cf3da1 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -187,7 +187,7 @@ static int __maybe_unused amba_kmi_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(amba_kmi_dev_pm_ops, NULL, amba_kmi_resume); -static struct amba_id amba_kmi_idtable[] = { +static const struct amba_id amba_kmi_idtable[] = { { .id = 0x00041050, .mask = 0x000fffff, diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index ecba666afadb..aa9f29b875de 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -325,7 +325,7 @@ static void gscps2_close(struct serio *port) * @return: success/error report */ -static int gscps2_probe(struct parisc_device *dev) +static int __init gscps2_probe(struct parisc_device *dev) { struct gscps2port *ps2port; struct serio *serio; @@ -412,7 +412,7 @@ fail_nomem: * @return: success/error report */ -static int gscps2_remove(struct parisc_device *dev) +static int __exit gscps2_remove(struct parisc_device *dev) { struct gscps2port *ps2port = dev_get_drvdata(&dev->dev); @@ -430,7 +430,7 @@ static int gscps2_remove(struct parisc_device *dev) } -static struct parisc_device_id gscps2_device_tbl[] = { +static const struct parisc_device_id gscps2_device_tbl[] __initconst = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 }, /* LASI PS/2 */ #ifdef DINO_TESTED { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00096 }, /* DINO PS/2 */ @@ -439,11 +439,11 @@ static struct parisc_device_id gscps2_device_tbl[] = { }; MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl); -static struct parisc_driver parisc_ps2_driver = { +static struct parisc_driver parisc_ps2_driver __refdata = { .name = "gsc_ps2", .id_table = gscps2_device_tbl, .probe = gscps2_probe, - .remove = gscps2_remove, + .remove = __exit_p(gscps2_remove), }; static int __init gscps2_init(void) diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 1bfdae4b0d99..8eef6849d066 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c @@ -805,7 +805,7 @@ static void hp_sdc_kicker(unsigned long data) #if defined(__hppa__) -static const struct parisc_device_id hp_sdc_tbl[] = { +static const struct parisc_device_id hp_sdc_tbl[] __initconst = { { .hw_type = HPHW_FIO, .hversion_rev = HVERSION_REV_ANY_ID, @@ -820,7 +820,7 @@ MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl); static int __init hp_sdc_init_hppa(struct parisc_device *d); static struct delayed_work moduleloader_work; -static struct parisc_driver hp_sdc_driver = { +static struct parisc_driver hp_sdc_driver __refdata = { .name = "hp_sdc", .id_table = hp_sdc_tbl, .probe = hp_sdc_init_hppa, diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index f932a83b4990..6cbbdc6e9687 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -840,6 +840,13 @@ static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = { }, }, { + /* Gigabyte P57 - Elantech touchpad */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "P57"), + }, + }, + { /* Schenker XMG C504 - Elantech touchpad */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "XMG"), @@ -927,7 +934,7 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id * return 0; } -static struct pnp_device_id pnp_kbd_devids[] = { +static const struct pnp_device_id pnp_kbd_devids[] = { { .id = "PNP0300", .driver_data = 0 }, { .id = "PNP0301", .driver_data = 0 }, { .id = "PNP0302", .driver_data = 0 }, @@ -957,7 +964,7 @@ static struct pnp_driver i8042_pnp_kbd_driver = { }, }; -static struct pnp_device_id pnp_aux_devids[] = { +static const struct pnp_device_id pnp_aux_devids[] = { { .id = "AUI0200", .driver_data = 0 }, { .id = "FJC6000", .driver_data = 0 }, { .id = "FJC6001", .driver_data = 0 }, diff --git a/drivers/input/serio/ps2-gpio.c b/drivers/input/serio/ps2-gpio.c new file mode 100644 index 000000000000..b50e3817f3c4 --- /dev/null +++ b/drivers/input/serio/ps2-gpio.c @@ -0,0 +1,453 @@ +/* + * GPIO based serio bus driver for bit banging the PS/2 protocol + * + * Author: Danilo Krummrich <danilokrummrich@dk-develop.de> + * + * 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. + */ + +#include <linux/gpio/consumer.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/serio.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/workqueue.h> +#include <linux/completion.h> +#include <linux/mutex.h> +#include <linux/preempt.h> +#include <linux/property.h> +#include <linux/of.h> +#include <linux/jiffies.h> +#include <linux/delay.h> + +#define DRIVER_NAME "ps2-gpio" + +#define PS2_MODE_RX 0 +#define PS2_MODE_TX 1 + +#define PS2_START_BIT 0 +#define PS2_DATA_BIT0 1 +#define PS2_DATA_BIT1 2 +#define PS2_DATA_BIT2 3 +#define PS2_DATA_BIT3 4 +#define PS2_DATA_BIT4 5 +#define PS2_DATA_BIT5 6 +#define PS2_DATA_BIT6 7 +#define PS2_DATA_BIT7 8 +#define PS2_PARITY_BIT 9 +#define PS2_STOP_BIT 10 +#define PS2_TX_TIMEOUT 11 +#define PS2_ACK_BIT 12 + +#define PS2_DEV_RET_ACK 0xfa +#define PS2_DEV_RET_NACK 0xfe + +#define PS2_CMD_RESEND 0xfe + +struct ps2_gpio_data { + struct device *dev; + struct serio *serio; + unsigned char mode; + struct gpio_desc *gpio_clk; + struct gpio_desc *gpio_data; + bool write_enable; + int irq; + unsigned char rx_cnt; + unsigned char rx_byte; + unsigned char tx_cnt; + unsigned char tx_byte; + struct completion tx_done; + struct mutex tx_mutex; + struct delayed_work tx_work; +}; + +static int ps2_gpio_open(struct serio *serio) +{ + struct ps2_gpio_data *drvdata = serio->port_data; + + enable_irq(drvdata->irq); + return 0; +} + +static void ps2_gpio_close(struct serio *serio) +{ + struct ps2_gpio_data *drvdata = serio->port_data; + + disable_irq(drvdata->irq); +} + +static int __ps2_gpio_write(struct serio *serio, unsigned char val) +{ + struct ps2_gpio_data *drvdata = serio->port_data; + + disable_irq_nosync(drvdata->irq); + gpiod_direction_output(drvdata->gpio_clk, 0); + + drvdata->mode = PS2_MODE_TX; + drvdata->tx_byte = val; + + schedule_delayed_work(&drvdata->tx_work, usecs_to_jiffies(200)); + + return 0; +} + +static int ps2_gpio_write(struct serio *serio, unsigned char val) +{ + struct ps2_gpio_data *drvdata = serio->port_data; + int ret = 0; + + if (in_task()) { + mutex_lock(&drvdata->tx_mutex); + __ps2_gpio_write(serio, val); + if (!wait_for_completion_timeout(&drvdata->tx_done, + msecs_to_jiffies(10000))) + ret = SERIO_TIMEOUT; + mutex_unlock(&drvdata->tx_mutex); + } else { + __ps2_gpio_write(serio, val); + } + + return ret; +} + +static void ps2_gpio_tx_work_fn(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct ps2_gpio_data *drvdata = container_of(dwork, + struct ps2_gpio_data, + tx_work); + + enable_irq(drvdata->irq); + gpiod_direction_output(drvdata->gpio_data, 0); + gpiod_direction_input(drvdata->gpio_clk); +} + +static irqreturn_t ps2_gpio_irq_rx(struct ps2_gpio_data *drvdata) +{ + unsigned char byte, cnt; + int data; + int rxflags = 0; + static unsigned long old_jiffies; + + byte = drvdata->rx_byte; + cnt = drvdata->rx_cnt; + + if (old_jiffies == 0) + old_jiffies = jiffies; + + if ((jiffies - old_jiffies) > usecs_to_jiffies(100)) { + dev_err(drvdata->dev, + "RX: timeout, probably we missed an interrupt\n"); + goto err; + } + old_jiffies = jiffies; + + data = gpiod_get_value(drvdata->gpio_data); + if (unlikely(data < 0)) { + dev_err(drvdata->dev, "RX: failed to get data gpio val: %d\n", + data); + goto err; + } + + switch (cnt) { + case PS2_START_BIT: + /* start bit should be low */ + if (unlikely(data)) { + dev_err(drvdata->dev, "RX: start bit should be low\n"); + goto err; + } + break; + case PS2_DATA_BIT0: + case PS2_DATA_BIT1: + case PS2_DATA_BIT2: + case PS2_DATA_BIT3: + case PS2_DATA_BIT4: + case PS2_DATA_BIT5: + case PS2_DATA_BIT6: + case PS2_DATA_BIT7: + /* processing data bits */ + if (data) + byte |= (data << (cnt - 1)); + break; + case PS2_PARITY_BIT: + /* check odd parity */ + if (!((hweight8(byte) & 1) ^ data)) { + rxflags |= SERIO_PARITY; + dev_warn(drvdata->dev, "RX: parity error\n"); + if (!drvdata->write_enable) + goto err; + } + + /* Do not send spurious ACK's and NACK's when write fn is + * not provided. + */ + if (!drvdata->write_enable) { + if (byte == PS2_DEV_RET_NACK) + goto err; + else if (byte == PS2_DEV_RET_ACK) + break; + } + + /* Let's send the data without waiting for the stop bit to be + * sent. It may happen that we miss the stop bit. When this + * happens we have no way to recover from this, certainly + * missing the parity bit would be recognized when processing + * the stop bit. When missing both, data is lost. + */ + serio_interrupt(drvdata->serio, byte, rxflags); + dev_dbg(drvdata->dev, "RX: sending byte 0x%x\n", byte); + break; + case PS2_STOP_BIT: + /* stop bit should be high */ + if (unlikely(!data)) { + dev_err(drvdata->dev, "RX: stop bit should be high\n"); + goto err; + } + cnt = byte = 0; + old_jiffies = 0; + goto end; /* success */ + default: + dev_err(drvdata->dev, "RX: got out of sync with the device\n"); + goto err; + } + + cnt++; + goto end; /* success */ + +err: + cnt = byte = 0; + old_jiffies = 0; + __ps2_gpio_write(drvdata->serio, PS2_CMD_RESEND); +end: + drvdata->rx_cnt = cnt; + drvdata->rx_byte = byte; + return IRQ_HANDLED; +} + +static irqreturn_t ps2_gpio_irq_tx(struct ps2_gpio_data *drvdata) +{ + unsigned char byte, cnt; + int data; + static unsigned long old_jiffies; + + cnt = drvdata->tx_cnt; + byte = drvdata->tx_byte; + + if (old_jiffies == 0) + old_jiffies = jiffies; + + if ((jiffies - old_jiffies) > usecs_to_jiffies(100)) { + dev_err(drvdata->dev, + "TX: timeout, probably we missed an interrupt\n"); + goto err; + } + old_jiffies = jiffies; + + switch (cnt) { + case PS2_START_BIT: + /* should never happen */ + dev_err(drvdata->dev, + "TX: start bit should have been sent already\n"); + goto err; + case PS2_DATA_BIT0: + case PS2_DATA_BIT1: + case PS2_DATA_BIT2: + case PS2_DATA_BIT3: + case PS2_DATA_BIT4: + case PS2_DATA_BIT5: + case PS2_DATA_BIT6: + case PS2_DATA_BIT7: + data = byte & BIT(cnt - 1); + gpiod_set_value(drvdata->gpio_data, data); + break; + case PS2_PARITY_BIT: + /* do odd parity */ + data = !(hweight8(byte) & 1); + gpiod_set_value(drvdata->gpio_data, data); + break; + case PS2_STOP_BIT: + /* release data line to generate stop bit */ + gpiod_direction_input(drvdata->gpio_data); + break; + case PS2_TX_TIMEOUT: + /* Devices generate one extra clock pulse before sending the + * acknowledgment. + */ + break; + case PS2_ACK_BIT: + gpiod_direction_input(drvdata->gpio_data); + data = gpiod_get_value(drvdata->gpio_data); + if (data) { + dev_warn(drvdata->dev, "TX: received NACK, retry\n"); + goto err; + } + + drvdata->mode = PS2_MODE_RX; + complete(&drvdata->tx_done); + + cnt = 1; + old_jiffies = 0; + goto end; /* success */ + default: + /* Probably we missed the stop bit. Therefore we release data + * line and try again. + */ + gpiod_direction_input(drvdata->gpio_data); + dev_err(drvdata->dev, "TX: got out of sync with the device\n"); + goto err; + } + + cnt++; + goto end; /* success */ + +err: + cnt = 1; + old_jiffies = 0; + gpiod_direction_input(drvdata->gpio_data); + __ps2_gpio_write(drvdata->serio, drvdata->tx_byte); +end: + drvdata->tx_cnt = cnt; + return IRQ_HANDLED; +} + +static irqreturn_t ps2_gpio_irq(int irq, void *dev_id) +{ + struct ps2_gpio_data *drvdata = dev_id; + + return drvdata->mode ? ps2_gpio_irq_tx(drvdata) : + ps2_gpio_irq_rx(drvdata); +} + +static int ps2_gpio_get_props(struct device *dev, + struct ps2_gpio_data *drvdata) +{ + drvdata->gpio_data = devm_gpiod_get(dev, "data", GPIOD_IN); + if (IS_ERR(drvdata->gpio_data)) { + dev_err(dev, "failed to request data gpio: %ld", + PTR_ERR(drvdata->gpio_data)); + return PTR_ERR(drvdata->gpio_data); + } + + drvdata->gpio_clk = devm_gpiod_get(dev, "clk", GPIOD_IN); + if (IS_ERR(drvdata->gpio_clk)) { + dev_err(dev, "failed to request clock gpio: %ld", + PTR_ERR(drvdata->gpio_clk)); + return PTR_ERR(drvdata->gpio_clk); + } + + drvdata->write_enable = device_property_read_bool(dev, + "write-enable"); + + return 0; +} + +static int ps2_gpio_probe(struct platform_device *pdev) +{ + struct ps2_gpio_data *drvdata; + struct serio *serio; + struct device *dev = &pdev->dev; + int error; + + drvdata = devm_kzalloc(dev, sizeof(struct ps2_gpio_data), GFP_KERNEL); + serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + if (!drvdata || !serio) { + error = -ENOMEM; + goto err_free_serio; + } + + error = ps2_gpio_get_props(dev, drvdata); + if (error) + goto err_free_serio; + + if (gpiod_cansleep(drvdata->gpio_data) || + gpiod_cansleep(drvdata->gpio_clk)) { + dev_err(dev, "GPIO data or clk are connected via slow bus\n"); + error = -EINVAL; + } + + drvdata->irq = platform_get_irq(pdev, 0); + if (drvdata->irq < 0) { + dev_err(dev, "failed to get irq from platform resource: %d\n", + drvdata->irq); + error = drvdata->irq; + goto err_free_serio; + } + + error = devm_request_irq(dev, drvdata->irq, ps2_gpio_irq, + IRQF_NO_THREAD, DRIVER_NAME, drvdata); + if (error) { + dev_err(dev, "failed to request irq %d: %d\n", + drvdata->irq, error); + goto err_free_serio; + } + + /* Keep irq disabled until serio->open is called. */ + disable_irq(drvdata->irq); + + serio->id.type = SERIO_8042; + serio->open = ps2_gpio_open; + serio->close = ps2_gpio_close; + /* Write can be enabled in platform/dt data, but possibly it will not + * work because of the tough timings. + */ + serio->write = drvdata->write_enable ? ps2_gpio_write : NULL; + serio->port_data = drvdata; + serio->dev.parent = dev; + strlcpy(serio->name, dev_name(dev), sizeof(serio->name)); + strlcpy(serio->phys, dev_name(dev), sizeof(serio->phys)); + + drvdata->serio = serio; + drvdata->dev = dev; + drvdata->mode = PS2_MODE_RX; + + /* Tx count always starts at 1, as the start bit is sent implicitly by + * host-to-device communication initialization. + */ + drvdata->tx_cnt = 1; + + INIT_DELAYED_WORK(&drvdata->tx_work, ps2_gpio_tx_work_fn); + init_completion(&drvdata->tx_done); + mutex_init(&drvdata->tx_mutex); + + serio_register_port(serio); + platform_set_drvdata(pdev, drvdata); + + return 0; /* success */ + +err_free_serio: + kfree(serio); + return error; +} + +static int ps2_gpio_remove(struct platform_device *pdev) +{ + struct ps2_gpio_data *drvdata = platform_get_drvdata(pdev); + + serio_unregister_port(drvdata->serio); + return 0; +} + +#if defined(CONFIG_OF) +static const struct of_device_id ps2_gpio_match[] = { + { .compatible = "ps2-gpio", }, + { }, +}; +MODULE_DEVICE_TABLE(of, ps2_gpio_match); +#endif + +static struct platform_driver ps2_gpio_driver = { + .probe = ps2_gpio_probe, + .remove = ps2_gpio_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = of_match_ptr(ps2_gpio_match), + }, +}; +module_platform_driver(ps2_gpio_driver); + +MODULE_AUTHOR("Danilo Krummrich <danilokrummrich@dk-develop.de>"); +MODULE_DESCRIPTION("GPIO PS2 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 30d6230d48f7..24a90c8db5b3 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -469,7 +469,7 @@ static struct attribute *serio_device_id_attrs[] = { NULL }; -static struct attribute_group serio_id_attr_group = { +static const struct attribute_group serio_id_attr_group = { .name = "id", .attrs = serio_device_id_attrs, }; @@ -489,7 +489,7 @@ static struct attribute *serio_device_attrs[] = { NULL }; -static struct attribute_group serio_device_attr_group = { +static const struct attribute_group serio_device_attr_group = { .attrs = serio_device_attrs, }; diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 71ef5d65a0c6..516f9fe77a17 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -410,7 +410,7 @@ static void serio_raw_disconnect(struct serio *serio) serio_set_drvdata(serio, NULL); } -static struct serio_device_id serio_raw_serio_ids[] = { +static const struct serio_device_id serio_raw_serio_ids[] = { { .type = SERIO_8042, .proto = SERIO_ANY, diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index 14c40892ed82..07de1b49293c 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -45,8 +45,10 @@ #define XPS2_STATUS_RX_FULL 0x00000001 /* Receive Full */ #define XPS2_STATUS_TX_FULL 0x00000002 /* Transmit Full */ -/* Bit definitions for ISR/IER registers. Both the registers have the same bit - * definitions and are only defined once. */ +/* + * Bit definitions for ISR/IER registers. Both the registers have the same bit + * definitions and are only defined once. + */ #define XPS2_IPIXR_WDT_TOUT 0x00000001 /* Watchdog Timeout Interrupt */ #define XPS2_IPIXR_TX_NOACK 0x00000002 /* Transmit No ACK Interrupt */ #define XPS2_IPIXR_TX_ACK 0x00000004 /* Transmit ACK (Data) Interrupt */ @@ -292,8 +294,10 @@ static int xps2_of_probe(struct platform_device *ofdev) /* Disable all the interrupts, just in case */ out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0); - /* Reset the PS2 device and abort any current transaction, to make sure - * we have the PS2 in a good state */ + /* + * Reset the PS2 device and abort any current transaction, + * to make sure we have the PS2 in a good state. + */ out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET); dev_info(dev, "Xilinx PS2 at 0x%08llX mapped to 0x%p, irq=%d\n", diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index e86e377a90f5..aebb3f9090cd 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -260,7 +260,7 @@ static void usb_acecad_disconnect(struct usb_interface *intf) kfree(acecad); } -static struct usb_device_id usb_acecad_id_table [] = { +static const struct usb_device_id usb_acecad_id_table[] = { { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_FLAIR), .driver_info = 0 }, { USB_DEVICE(USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_302), .driver_info = 1 }, { } diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index d67547bded3e..0b55e1f375b3 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -1676,7 +1676,7 @@ static struct attribute *aiptek_attributes[] = { NULL }; -static struct attribute_group aiptek_attribute_group = { +static const struct attribute_group aiptek_attribute_group = { .attrs = aiptek_attributes, }; diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index 4d9d64908b59..a41c3ff7c9af 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c @@ -88,7 +88,7 @@ static void kbtab_irq(struct urb *urb) __func__, retval); } -static struct usb_device_id kbtab_ids[] = { +static const struct usb_device_id kbtab_ids[] = { { USB_DEVICE(USB_VENDOR_ID_KBGEAR, 0x1001), .driver_info = 0 }, { } }; diff --git a/drivers/input/tablet/wacom_serial4.c b/drivers/input/tablet/wacom_serial4.c index 20ab802461e7..38bfaca48eab 100644 --- a/drivers/input/tablet/wacom_serial4.c +++ b/drivers/input/tablet/wacom_serial4.c @@ -594,7 +594,7 @@ free_device: return err; } -static struct serio_device_id wacom_serio_ids[] = { +static const struct serio_device_id wacom_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_WACOM_IV, diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 735a0be1ad95..a2f45aefce08 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -499,7 +499,7 @@ static struct attribute *ads7846_attributes[] = { NULL, }; -static struct attribute_group ads7846_attr_group = { +static const struct attribute_group ads7846_attr_group = { .attrs = ads7846_attributes, .is_visible = ads7846_is_visible, }; @@ -599,7 +599,7 @@ static struct attribute *ads784x_attributes[] = { NULL, }; -static struct attribute_group ads784x_attr_group = { +static const struct attribute_group ads784x_attr_group = { .attrs = ads784x_attributes, }; diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index dd042a9b0aaa..7659bc48f1db 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -28,6 +28,7 @@ #include <linux/interrupt.h> #include <linux/of.h> #include <linux/slab.h> +#include <linux/gpio/consumer.h> #include <asm/unaligned.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> @@ -300,6 +301,7 @@ struct mxt_data { u8 multitouch; struct t7_config t7_cfg; struct mxt_dbg dbg; + struct gpio_desc *reset_gpio; /* Cached parameters from object table */ u16 T5_address; @@ -3117,11 +3119,9 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) if (IS_ERR(pdata)) return PTR_ERR(pdata); - data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); - if (!data) { - dev_err(&client->dev, "Failed to allocate memory\n"); + data = devm_kzalloc(&client->dev, sizeof(struct mxt_data), GFP_KERNEL); + if (!data) return -ENOMEM; - } snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", client->adapter->nr, client->addr); @@ -3135,19 +3135,40 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) init_completion(&data->reset_completion); init_completion(&data->crc_completion); - error = request_threaded_irq(client->irq, NULL, mxt_interrupt, - pdata->irqflags | IRQF_ONESHOT, - client->name, data); + data->reset_gpio = devm_gpiod_get_optional(&client->dev, + "reset", GPIOD_OUT_LOW); + if (IS_ERR(data->reset_gpio)) { + error = PTR_ERR(data->reset_gpio); + dev_err(&client->dev, "Failed to get reset gpio: %d\n", error); + return error; + } + + error = devm_request_threaded_irq(&client->dev, client->irq, + NULL, mxt_interrupt, + pdata->irqflags | IRQF_ONESHOT, + client->name, data); if (error) { dev_err(&client->dev, "Failed to register interrupt\n"); - goto err_free_mem; + return error; + } + + if (data->reset_gpio) { + data->in_bootloader = true; + msleep(MXT_RESET_TIME); + reinit_completion(&data->bl_completion); + gpiod_set_value(data->reset_gpio, 1); + error = mxt_wait_for_completion(data, &data->bl_completion, + MXT_RESET_TIMEOUT); + if (error) + return error; + data->in_bootloader = false; } disable_irq(client->irq); error = mxt_initialize(data); if (error) - goto err_free_irq; + return error; error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); if (error) { @@ -3161,10 +3182,6 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) err_free_object: mxt_free_input_device(data); mxt_free_object_table(data); -err_free_irq: - free_irq(client->irq, data); -err_free_mem: - kfree(data); return error; } @@ -3172,11 +3189,10 @@ static int mxt_remove(struct i2c_client *client) { struct mxt_data *data = i2c_get_clientdata(client); + disable_irq(data->irq); sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); - free_irq(data->irq, data); mxt_free_input_device(data); mxt_free_object_table(data); - kfree(data); return 0; } diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c index 86237a910876..5b1b66fffbe3 100644 --- a/drivers/input/touchscreen/dynapro.c +++ b/drivers/input/touchscreen/dynapro.c @@ -164,7 +164,7 @@ static int dynapro_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id dynapro_serio_ids[] = { +static const struct serio_device_id dynapro_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_DYNAPRO, diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index f872817e81e4..5bf63f76ddda 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -593,7 +593,7 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) tsdata->gain); edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, tsdata->offset); - if (reg_addr->reg_report_rate) + if (reg_addr->reg_report_rate != NO_REGISTER) edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate, tsdata->report_rate); @@ -874,6 +874,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) case M09: reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; + reg_addr->reg_report_rate = NO_REGISTER; reg_addr->reg_gain = M09_REGISTER_GAIN; reg_addr->reg_offset = M09_REGISTER_OFFSET; reg_addr->reg_num_x = M09_REGISTER_NUM_X; diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 872750eeca93..0f4cda7282a2 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1066,7 +1066,7 @@ static struct attribute *elants_attributes[] = { NULL }; -static struct attribute_group elants_attribute_group = { +static const struct attribute_group elants_attribute_group = { .attrs = elants_attributes, }; diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 8051a4b704ea..83433e8efff7 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -381,7 +381,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id elo_serio_ids[] = { +static const struct serio_device_id elo_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_ELO, diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c index d0e46a7e183b..a0fbb454499d 100644 --- a/drivers/input/touchscreen/fujitsu_ts.c +++ b/drivers/input/touchscreen/fujitsu_ts.c @@ -151,7 +151,7 @@ static int fujitsu_connect(struct serio *serio, struct serio_driver *drv) /* * The serio driver structure. */ -static struct serio_device_id fujitsu_serio_ids[] = { +static const struct serio_device_id fujitsu_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_FUJITSU, diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 240b16f3ee97..32d2762448aa 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -267,6 +267,12 @@ static void goodix_process_events(struct goodix_ts_data *ts) if (touch_num < 0) return; + /* + * Bit 4 of the first byte reports the status of the capacitive + * Windows/Home button. + */ + input_report_key(ts->input_dev, KEY_LEFTMETA, point_data[0] & BIT(4)); + for (i = 0; i < touch_num; i++) goodix_ts_report_touch(ts, &point_data[1 + GOODIX_CONTACT_SIZE * i]); @@ -612,6 +618,9 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts) ts->input_dev->id.product = ts->id; ts->input_dev->id.version = ts->version; + /* Capacitive Windows/Home button on some devices */ + input_set_capability(ts->input_dev, EV_KEY, KEY_LEFTMETA); + error = input_register_device(ts->input_dev); if (error) { dev_err(&ts->client->dev, diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index e2ee62615273..481586909d28 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c @@ -162,7 +162,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id gunze_serio_ids[] = { +static const struct serio_device_id gunze_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_GUNZE, diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c index ecb1e0e01328..eb052d559e54 100644 --- a/drivers/input/touchscreen/hampshire.c +++ b/drivers/input/touchscreen/hampshire.c @@ -163,7 +163,7 @@ static int hampshire_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id hampshire_serio_ids[] = { +static const struct serio_device_id hampshire_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_HAMPSHIRE, diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c index 92e2243fb77d..8fd909285877 100644 --- a/drivers/input/touchscreen/htcpen.c +++ b/drivers/input/touchscreen/htcpen.c @@ -219,7 +219,7 @@ static struct isa_driver htcpen_isa_driver = { } }; -static struct dmi_system_id htcshift_dmi_table[] __initdata = { +static const struct dmi_system_id htcshift_dmi_table[] __initconst = { { .ident = "Shift", .matches = { diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c index adb80b65a259..b9bc56233ccc 100644 --- a/drivers/input/touchscreen/inexio.c +++ b/drivers/input/touchscreen/inexio.c @@ -165,7 +165,7 @@ static int inexio_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id inexio_serio_ids[] = { +static const struct serio_device_id inexio_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_INEXIO, diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index 9b5552a26169..a3707fad4d1c 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c @@ -178,7 +178,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id mtouch_serio_ids[] = { +static const struct serio_device_id mtouch_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_MICROTOUCH, diff --git a/drivers/input/touchscreen/mxs-lradc-ts.c b/drivers/input/touchscreen/mxs-lradc-ts.c index 58c016cd6809..3707e927f770 100644 --- a/drivers/input/touchscreen/mxs-lradc-ts.c +++ b/drivers/input/touchscreen/mxs-lradc-ts.c @@ -30,7 +30,7 @@ #include <linux/of_irq.h> #include <linux/platform_device.h> -const char *mxs_lradc_ts_irq_names[] = { +static const char * const mxs_lradc_ts_irq_names[] = { "mxs-lradc-touchscreen", "mxs-lradc-channel6", "mxs-lradc-channel7", @@ -630,9 +630,11 @@ static int mxs_lradc_ts_probe(struct platform_device *pdev) spin_lock_init(&ts->lock); iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!iores) + return -EINVAL; ts->base = devm_ioremap(dev, iores->start, resource_size(iores)); - if (IS_ERR(ts->base)) - return PTR_ERR(ts->base); + if (!ts->base) + return -ENOMEM; ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires", &ts_wires); diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c index 417d87379265..6e6d7fd98cd2 100644 --- a/drivers/input/touchscreen/penmount.c +++ b/drivers/input/touchscreen/penmount.c @@ -293,7 +293,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id pm_serio_ids[] = { +static const struct serio_device_id pm_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_PENMOUNT, diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c index 1252e49ccfa1..4f1d3fd5d412 100644 --- a/drivers/input/touchscreen/raydium_i2c_ts.c +++ b/drivers/input/touchscreen/raydium_i2c_ts.c @@ -939,7 +939,7 @@ static struct attribute *raydium_i2c_attributes[] = { NULL }; -static struct attribute_group raydium_i2c_attribute_group = { +static const struct attribute_group raydium_i2c_attribute_group = { .attrs = raydium_i2c_attributes, }; diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c index d07dd29d4848..d2e14d9e5975 100644 --- a/drivers/input/touchscreen/sun4i-ts.c +++ b/drivers/input/touchscreen/sun4i-ts.c @@ -206,7 +206,7 @@ static int sun4i_get_tz_temp(void *data, int *temp) return sun4i_get_temp(data, temp); } -static struct thermal_zone_of_device_ops sun4i_ts_tz_ops = { +static const struct thermal_zone_of_device_ops sun4i_ts_tz_ops = { .get_temp = sun4i_get_tz_temp, }; diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index 128e5bd74720..f16f8358c70a 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -59,7 +59,7 @@ struct sur40_blob { __le16 blob_id; u8 action; /* 0x02 = enter/exit, 0x03 = update (?) */ - u8 unknown; /* always 0x01 or 0x02 (no idea what this is?) */ + u8 type; /* bitmask (0x01 blob, 0x02 touch, 0x04 tag) */ __le16 bb_pos_x; /* upper left corner of bounding box */ __le16 bb_pos_y; @@ -133,12 +133,19 @@ struct sur40_image_header { /* control commands */ #define SUR40_GET_VERSION 0xb0 /* 12 bytes string */ -#define SUR40_UNKNOWN1 0xb3 /* 5 bytes */ -#define SUR40_UNKNOWN2 0xc1 /* 24 bytes */ +#define SUR40_ACCEL_CAPS 0xb3 /* 5 bytes */ +#define SUR40_SENSOR_CAPS 0xc1 /* 24 bytes */ + +#define SUR40_POKE 0xc5 /* poke register byte */ +#define SUR40_PEEK 0xc4 /* 48 bytes registers */ #define SUR40_GET_STATE 0xc5 /* 4 bytes state (?) */ #define SUR40_GET_SENSORS 0xb1 /* 8 bytes sensors */ +#define SUR40_BLOB 0x01 +#define SUR40_TOUCH 0x02 +#define SUR40_TAG 0x04 + static const struct v4l2_pix_format sur40_pix_format[] = { { .pixelformat = V4L2_TCH_FMT_TU08, @@ -238,11 +245,11 @@ static int sur40_init(struct sur40_state *dev) if (result < 0) goto error; - result = sur40_command(dev, SUR40_UNKNOWN2, 0x00, buffer, 24); + result = sur40_command(dev, SUR40_SENSOR_CAPS, 0x00, buffer, 24); if (result < 0) goto error; - result = sur40_command(dev, SUR40_UNKNOWN1, 0x00, buffer, 5); + result = sur40_command(dev, SUR40_ACCEL_CAPS, 0x00, buffer, 5); if (result < 0) goto error; @@ -289,20 +296,24 @@ static void sur40_close(struct input_polled_dev *polldev) static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input) { int wide, major, minor; + int bb_size_x, bb_size_y, pos_x, pos_y, ctr_x, ctr_y, slotnum; - int bb_size_x = le16_to_cpu(blob->bb_size_x); - int bb_size_y = le16_to_cpu(blob->bb_size_y); - - int pos_x = le16_to_cpu(blob->pos_x); - int pos_y = le16_to_cpu(blob->pos_y); - - int ctr_x = le16_to_cpu(blob->ctr_x); - int ctr_y = le16_to_cpu(blob->ctr_y); + if (blob->type != SUR40_TOUCH) + return; - int slotnum = input_mt_get_slot_by_key(input, blob->blob_id); + slotnum = input_mt_get_slot_by_key(input, blob->blob_id); if (slotnum < 0 || slotnum >= MAX_CONTACTS) return; + bb_size_x = le16_to_cpu(blob->bb_size_x); + bb_size_y = le16_to_cpu(blob->bb_size_y); + + pos_x = le16_to_cpu(blob->pos_x); + pos_y = le16_to_cpu(blob->pos_y); + + ctr_x = le16_to_cpu(blob->ctr_x); + ctr_y = le16_to_cpu(blob->ctr_y); + input_mt_slot(input, slotnum); input_mt_report_slot_state(input, MT_TOOL_FINGER, 1); wide = (bb_size_x > bb_size_y); @@ -367,10 +378,13 @@ static void sur40_poll(struct input_polled_dev *polldev) /* * Sanity check. when video data is also being retrieved, the * packet ID will usually increase in the middle of a series - * instead of at the end. - */ + * instead of at the end. However, the data is still consistent, + * so the packet ID is probably just valid for the first packet + * in a series. + if (packet_id != le32_to_cpu(header->packet_id)) dev_dbg(sur40->dev, "packet ID mismatch\n"); + */ packet_blobs = result / sizeof(struct sur40_blob); dev_dbg(sur40->dev, "received %d blobs\n", packet_blobs); diff --git a/drivers/input/touchscreen/surface3_spi.c b/drivers/input/touchscreen/surface3_spi.c index e12fb9b63f31..5db0f1c4ef38 100644 --- a/drivers/input/touchscreen/surface3_spi.c +++ b/drivers/input/touchscreen/surface3_spi.c @@ -173,7 +173,7 @@ static void surface3_spi_process_pen(struct surface3_ts_data *ts_data, u8 *data) static void surface3_spi_process(struct surface3_ts_data *ts_data) { - const char header[] = { + static const char header[] = { 0xff, 0xff, 0xff, 0xff, 0xa5, 0x5a, 0xe7, 0x7e, 0x01 }; u8 *data = ts_data->rd_buf; diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c index c27cf8f3d1ca..98a16698be8e 100644 --- a/drivers/input/touchscreen/touchit213.c +++ b/drivers/input/touchscreen/touchit213.c @@ -192,7 +192,7 @@ static int touchit213_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id touchit213_serio_ids[] = { +static const struct serio_device_id touchit213_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_TOUCHIT213, diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c index 4000e5205407..45c325c33f21 100644 --- a/drivers/input/touchscreen/touchright.c +++ b/drivers/input/touchscreen/touchright.c @@ -152,7 +152,7 @@ static int tr_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id tr_serio_ids[] = { +static const struct serio_device_id tr_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_TOUCHRIGHT, diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c index ba90f447df75..2ba6b4ca28cb 100644 --- a/drivers/input/touchscreen/touchwin.c +++ b/drivers/input/touchscreen/touchwin.c @@ -159,7 +159,7 @@ static int tw_connect(struct serio *serio, struct serio_driver *drv) * The serio driver structure. */ -static struct serio_device_id tw_serio_ids[] = { +static const struct serio_device_id tw_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_TOUCHWIN, diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 29687872cb94..d4ae4ba84c1f 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -141,7 +141,7 @@ static void tsc_disconnect(struct serio *serio) serio_set_drvdata(serio, NULL); } -static struct serio_device_id tsc_serio_ids[] = { +static const struct serio_device_id tsc_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_TSC40, diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index c1e23cfc6155..1a86cbd9326f 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -414,7 +414,7 @@ static int __maybe_unused ucb1400_ts_suspend(struct device *dev) mutex_lock(&idev->mutex); if (idev->users) - ucb1400_ts_start(ucb); + ucb1400_ts_stop(ucb); mutex_unlock(&idev->mutex); return 0; @@ -428,7 +428,7 @@ static int __maybe_unused ucb1400_ts_resume(struct device *dev) mutex_lock(&idev->mutex); if (idev->users) - ucb1400_ts_stop(ucb); + ucb1400_ts_start(ucb); mutex_unlock(&idev->mutex); return 0; diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 85e95725d0df..3715d1eace92 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -681,7 +681,7 @@ fail1: return err; } -static struct serio_device_id w8001_serio_ids[] = { +static const struct serio_device_id w8001_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_W8001, |