summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-pxa/spitz.c2
-rw-r--r--drivers/input/input.c134
-rw-r--r--drivers/input/joystick/xpad.c3
-rw-r--r--drivers/input/keyboard/adp5588-keys.c8
-rw-r--r--drivers/input/keyboard/adp5589-keys.c22
-rw-r--r--drivers/input/misc/cs40l50-vibra.c6
-rw-r--r--drivers/input/mouse/Kconfig12
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/pixart_ps2.c300
-rw-r--r--drivers/input/mouse/pixart_ps2.h36
-rw-r--r--drivers/input/mouse/psmouse-base.c17
-rw-r--r--drivers/input/mouse/psmouse.h3
-rw-r--r--drivers/input/serio/i8042-acpipnpio.h37
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c19
-rw-r--r--drivers/input/touchscreen/hynitron_cstxxx.c2
-rw-r--r--drivers/input/touchscreen/zinitix.c34
-rw-r--r--include/linux/input.h10
17 files changed, 187 insertions, 459 deletions
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 690596f36979..33533e35720f 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -403,7 +403,7 @@ static const struct software_node_ref_args spitz_mkp_col_gpios[] = {
};
static const struct property_entry spitz_mkp_properties[] = {
- PROPERTY_ENTRY_ARRAY_U32("linux,keymap", spitz_keymap),
+ PROPERTY_ENTRY_U32_ARRAY("linux,keymap", spitz_keymap),
PROPERTY_ENTRY_REF_ARRAY("row-gpios", spitz_mkp_row_gpios),
PROPERTY_ENTRY_REF_ARRAY("col-gpios", spitz_mkp_col_gpios),
PROPERTY_ENTRY_U32("col-scan-delay-us", 10),
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 3b1e88ead97e..fd9d40286b75 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -119,12 +119,12 @@ static void input_pass_values(struct input_dev *dev,
handle = rcu_dereference(dev->grab);
if (handle) {
- count = handle->handler->events(handle, vals, count);
+ count = handle->handle_events(handle, vals, count);
} else {
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
if (handle->open) {
- count = handle->handler->events(handle, vals,
- count);
+ count = handle->handle_events(handle, vals,
+ count);
if (!count)
break;
}
@@ -2542,57 +2542,6 @@ static int input_handler_check_methods(const struct input_handler *handler)
return 0;
}
-/*
- * An implementation of input_handler's events() method that simply
- * invokes handler->event() method for each event one by one.
- */
-static unsigned int input_handler_events_default(struct input_handle *handle,
- struct input_value *vals,
- unsigned int count)
-{
- struct input_handler *handler = handle->handler;
- struct input_value *v;
-
- for (v = vals; v != vals + count; v++)
- handler->event(handle, v->type, v->code, v->value);
-
- return count;
-}
-
-/*
- * An implementation of input_handler's events() method that invokes
- * handler->filter() method for each event one by one and removes events
- * that were filtered out from the "vals" array.
- */
-static unsigned int input_handler_events_filter(struct input_handle *handle,
- struct input_value *vals,
- unsigned int count)
-{
- struct input_handler *handler = handle->handler;
- struct input_value *end = vals;
- struct input_value *v;
-
- for (v = vals; v != vals + count; v++) {
- if (handler->filter(handle, v->type, v->code, v->value))
- continue;
- if (end != v)
- *end = *v;
- end++;
- }
-
- return end - vals;
-}
-
-/*
- * An implementation of input_handler's events() method that does nothing.
- */
-static unsigned int input_handler_events_null(struct input_handle *handle,
- struct input_value *vals,
- unsigned int count)
-{
- return count;
-}
-
/**
* input_register_handler - register a new input handler
* @handler: handler to be registered
@@ -2612,13 +2561,6 @@ int input_register_handler(struct input_handler *handler)
INIT_LIST_HEAD(&handler->h_list);
- if (handler->filter)
- handler->events = input_handler_events_filter;
- else if (handler->event)
- handler->events = input_handler_events_default;
- else if (!handler->events)
- handler->events = input_handler_events_null;
-
error = mutex_lock_interruptible(&input_mutex);
if (error)
return error;
@@ -2692,6 +2634,75 @@ int input_handler_for_each_handle(struct input_handler *handler, void *data,
}
EXPORT_SYMBOL(input_handler_for_each_handle);
+/*
+ * An implementation of input_handle's handle_events() method that simply
+ * invokes handler->event() method for each event one by one.
+ */
+static unsigned int input_handle_events_default(struct input_handle *handle,
+ struct input_value *vals,
+ unsigned int count)
+{
+ struct input_handler *handler = handle->handler;
+ struct input_value *v;
+
+ for (v = vals; v != vals + count; v++)
+ handler->event(handle, v->type, v->code, v->value);
+
+ return count;
+}
+
+/*
+ * An implementation of input_handle's handle_events() method that invokes
+ * handler->filter() method for each event one by one and removes events
+ * that were filtered out from the "vals" array.
+ */
+static unsigned int input_handle_events_filter(struct input_handle *handle,
+ struct input_value *vals,
+ unsigned int count)
+{
+ struct input_handler *handler = handle->handler;
+ struct input_value *end = vals;
+ struct input_value *v;
+
+ for (v = vals; v != vals + count; v++) {
+ if (handler->filter(handle, v->type, v->code, v->value))
+ continue;
+ if (end != v)
+ *end = *v;
+ end++;
+ }
+
+ return end - vals;
+}
+
+/*
+ * An implementation of input_handle's handle_events() method that does nothing.
+ */
+static unsigned int input_handle_events_null(struct input_handle *handle,
+ struct input_value *vals,
+ unsigned int count)
+{
+ return count;
+}
+
+/*
+ * Sets up appropriate handle->event_handler based on the input_handler
+ * associated with the handle.
+ */
+static void input_handle_setup_event_handler(struct input_handle *handle)
+{
+ struct input_handler *handler = handle->handler;
+
+ if (handler->filter)
+ handle->handle_events = input_handle_events_filter;
+ else if (handler->event)
+ handle->handle_events = input_handle_events_default;
+ else if (handler->events)
+ handle->handle_events = handler->events;
+ else
+ handle->handle_events = input_handle_events_null;
+}
+
/**
* input_register_handle - register a new input handle
* @handle: handle to register
@@ -2709,6 +2720,7 @@ int input_register_handle(struct input_handle *handle)
struct input_dev *dev = handle->dev;
int error;
+ input_handle_setup_event_handler(handle);
/*
* We take dev->mutex here to prevent race with
* input_release_device().
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 3e61df927277..ff9bc87f2f70 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -218,6 +218,7 @@ static const struct xpad_device {
{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
{ 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX },
{ 0x0d2f, 0x0002, "Andamiro Pump It Up pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x0db0, 0x1901, "Micro Star International Xbox360 Controller for Windows", 0, XTYPE_XBOX360 },
{ 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX },
{ 0x0e4c, 0x1103, "Radica Gamester Reflex", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX },
{ 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX },
@@ -373,6 +374,7 @@ static const struct xpad_device {
{ 0x294b, 0x3404, "Snakebyte GAMEPAD RGB X", 0, XTYPE_XBOXONE },
{ 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE },
{ 0x2dc8, 0x3106, "8BitDo Pro 2 Wired Controller", 0, XTYPE_XBOX360 },
+ { 0x2dc8, 0x310a, "8BitDo Ultimate 2C Wireless Controller", 0, XTYPE_XBOX360 },
{ 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE },
{ 0x31e3, 0x1100, "Wooting One", 0, XTYPE_XBOX360 },
{ 0x31e3, 0x1200, "Wooting Two", 0, XTYPE_XBOX360 },
@@ -492,6 +494,7 @@ static const struct usb_device_id xpad_table[] = {
XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz Gamepad */
XPAD_XBOXONE_VENDOR(0x0b05), /* ASUS controllers */
XPAD_XBOX360_VENDOR(0x0c12), /* Zeroplus X-Box 360 controllers */
+ XPAD_XBOX360_VENDOR(0x0db0), /* Micro Star International X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f Xbox 360 controllers */
XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f Xbox One controllers */
XPAD_XBOX360_VENDOR(0x0f0d), /* Hori controllers */
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index b5f4becf5cb6..dc734974ce06 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -620,7 +620,7 @@ static int adp5588_setup(struct adp5588_kpad *kpad)
for (i = 0; i < KEYP_MAX_EVENT; i++) {
ret = adp5588_read(client, KEY_EVENTA);
- if (ret)
+ if (ret < 0)
return ret;
}
@@ -822,7 +822,8 @@ static int adp5588_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
- disable_irq(client->irq);
+ if (client->irq)
+ disable_irq(client->irq);
return 0;
}
@@ -831,7 +832,8 @@ static int adp5588_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
- enable_irq(client->irq);
+ if (client->irq)
+ enable_irq(client->irq);
return 0;
}
diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
index 735d96b056d4..81d0876ee358 100644
--- a/drivers/input/keyboard/adp5589-keys.c
+++ b/drivers/input/keyboard/adp5589-keys.c
@@ -391,10 +391,17 @@ static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off)
struct adp5589_kpad *kpad = gpiochip_get_data(chip);
unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
+ int val;
- return !!(adp5589_read(kpad->client,
- kpad->var->reg(ADP5589_GPI_STATUS_A) + bank) &
- bit);
+ mutex_lock(&kpad->gpio_lock);
+ if (kpad->dir[bank] & bit)
+ val = kpad->dat_out[bank];
+ else
+ val = adp5589_read(kpad->client,
+ kpad->var->reg(ADP5589_GPI_STATUS_A) + bank);
+ mutex_unlock(&kpad->gpio_lock);
+
+ return !!(val & bit);
}
static void adp5589_gpio_set_value(struct gpio_chip *chip,
@@ -933,10 +940,9 @@ static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid)
static void adp5589_clear_config(void *data)
{
- struct i2c_client *client = data;
- struct adp5589_kpad *kpad = i2c_get_clientdata(client);
+ struct adp5589_kpad *kpad = data;
- adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
+ adp5589_write(kpad->client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
}
static int adp5589_probe(struct i2c_client *client)
@@ -980,7 +986,7 @@ static int adp5589_probe(struct i2c_client *client)
}
error = devm_add_action_or_reset(&client->dev, adp5589_clear_config,
- client);
+ kpad);
if (error)
return error;
@@ -1007,8 +1013,6 @@ static int adp5589_probe(struct i2c_client *client)
if (error)
return error;
- i2c_set_clientdata(client, kpad);
-
dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
return 0;
}
diff --git a/drivers/input/misc/cs40l50-vibra.c b/drivers/input/misc/cs40l50-vibra.c
index 03bdb7c26ec0..dce3b0ec8cf3 100644
--- a/drivers/input/misc/cs40l50-vibra.c
+++ b/drivers/input/misc/cs40l50-vibra.c
@@ -334,11 +334,12 @@ static int cs40l50_add(struct input_dev *dev, struct ff_effect *effect,
work_data.custom_len = effect->u.periodic.custom_len;
work_data.vib = vib;
work_data.effect = effect;
- INIT_WORK(&work_data.work, cs40l50_add_worker);
+ INIT_WORK_ONSTACK(&work_data.work, cs40l50_add_worker);
/* Push to the workqueue to serialize with playbacks */
queue_work(vib->vib_wq, &work_data.work);
flush_work(&work_data.work);
+ destroy_work_on_stack(&work_data.work);
kfree(work_data.custom_data);
@@ -467,11 +468,12 @@ static int cs40l50_erase(struct input_dev *dev, int effect_id)
work_data.vib = vib;
work_data.effect = &dev->ff->effects[effect_id];
- INIT_WORK(&work_data.work, cs40l50_erase_worker);
+ INIT_WORK_ONSTACK(&work_data.work, cs40l50_erase_worker);
/* Push to workqueue to serialize with playbacks */
queue_work(vib->vib_wq, &work_data.work);
flush_work(&work_data.work);
+ destroy_work_on_stack(&work_data.work);
return work_data.error;
}
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 8a27a20d04b0..833b643f0616 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -69,18 +69,6 @@ config MOUSE_PS2_LOGIPS2PP
If unsure, say Y.
-config MOUSE_PS2_PIXART
- bool "PixArt PS/2 touchpad protocol extension" if EXPERT
- default y
- depends on MOUSE_PS2
- help
- This driver supports the PixArt PS/2 touchpad found in some
- laptops.
- Say Y here if you have a PixArt PS/2 TouchPad connected to
- your system.
-
- If unsure, say Y.
-
config MOUSE_PS2_SYNAPTICS
bool "Synaptics PS/2 mouse protocol extension" if EXPERT
default y
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 563029551529..a1336d5bee6f 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -32,7 +32,6 @@ psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o
psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o
psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o
psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o
-psmouse-$(CONFIG_MOUSE_PS2_PIXART) += pixart_ps2.o
psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o
psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o
diff --git a/drivers/input/mouse/pixart_ps2.c b/drivers/input/mouse/pixart_ps2.c
deleted file mode 100644
index 1993fc760d7b..000000000000
--- a/drivers/input/mouse/pixart_ps2.c
+++ /dev/null
@@ -1,300 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Pixart Touchpad Controller 1336U PS2 driver
- *
- * Author: Jon Xie <jon_xie@pixart.com>
- * Jay Lee <jay_lee@pixart.com>
- * Further cleanup and restructuring by:
- * Binbin Zhou <zhoubinbin@loongson.cn>
- *
- * Copyright (C) 2021-2024 Pixart Imaging.
- * Copyright (C) 2024 Loongson Technology Corporation Limited.
- *
- */
-
-#include <linux/bitfield.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/input.h>
-#include <linux/input/mt.h>
-#include <linux/libps2.h>
-#include <linux/serio.h>
-#include <linux/slab.h>
-
-#include "pixart_ps2.h"
-
-static int pixart_read_tp_mode(struct ps2dev *ps2dev, u8 *mode)
-{
- int error;
- u8 param[1] = { 0 };
-
- error = ps2_command(ps2dev, param, PIXART_CMD_REPORT_FORMAT);
- if (error)
- return error;
-
- *mode = param[0] == 1 ? PIXART_MODE_ABS : PIXART_MODE_REL;
-
- return 0;
-}
-
-static int pixart_read_tp_type(struct ps2dev *ps2dev, u8 *type)
-{
- int error;
- u8 param[3] = { 0 };
-
- param[0] = 0x0a;
- error = ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
- if (error)
- return error;
-
- param[0] = 0x0;
- error = ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
- if (error)
- return error;
-
- error = ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
- if (error)
- return error;
-
- error = ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
- if (error)
- return error;
-
- param[0] = 0x03;
- error = ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES);
- if (error)
- return error;
-
- error = ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO);
- if (error)
- return error;
-
- *type = param[0] == 0x0e ? PIXART_TYPE_TOUCHPAD : PIXART_TYPE_CLICKPAD;
-
- return 0;
-}
-
-static void pixart_reset(struct psmouse *psmouse)
-{
- ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
-
- /* according to PixArt, 100ms is required for the upcoming reset */
- msleep(100);
- psmouse_reset(psmouse);
-}
-
-static void pixart_process_packet(struct psmouse *psmouse)
-{
- struct pixart_data *priv = psmouse->private;
- struct input_dev *dev = psmouse->dev;
- const u8 *pkt = psmouse->packet;
- unsigned int contact_cnt = FIELD_GET(CONTACT_CNT_MASK, pkt[0]);
- unsigned int i, id, abs_x, abs_y;
- bool tip;
-
- for (i = 0; i < contact_cnt; i++) {
- const u8 *p = &pkt[i * 3];
-
- id = FIELD_GET(SLOT_ID_MASK, p[3]);
- abs_y = FIELD_GET(ABS_Y_MASK, p[3]) << 8 | p[1];
- abs_x = FIELD_GET(ABS_X_MASK, p[3]) << 8 | p[2];
-
- if (i == PIXART_MAX_FINGERS - 1)
- tip = pkt[14] & BIT(1);
- else
- tip = pkt[3 * contact_cnt + 1] & BIT(2 * i + 1);
-
- input_mt_slot(dev, id);
- if (input_mt_report_slot_state(dev, MT_TOOL_FINGER, tip)) {
- input_report_abs(dev, ABS_MT_POSITION_Y, abs_y);
- input_report_abs(dev, ABS_MT_POSITION_X, abs_x);
- }
- }
-
- input_mt_sync_frame(dev);
-
- if (priv->type == PIXART_TYPE_CLICKPAD) {
- input_report_key(dev, BTN_LEFT, pkt[0] & 0x03);
- } else {
- input_report_key(dev, BTN_LEFT, pkt[0] & BIT(0));
- input_report_key(dev, BTN_RIGHT, pkt[0] & BIT(1));
- }
-
- input_sync(dev);
-}
-
-static psmouse_ret_t pixart_protocol_handler(struct psmouse *psmouse)
-{
- u8 *pkt = psmouse->packet;
- u8 contact_cnt;
-
- if ((pkt[0] & 0x8c) != 0x80)
- return PSMOUSE_BAD_DATA;
-
- contact_cnt = FIELD_GET(CONTACT_CNT_MASK, pkt[0]);
- if (contact_cnt > PIXART_MAX_FINGERS)
- return PSMOUSE_BAD_DATA;
-
- if (contact_cnt == PIXART_MAX_FINGERS &&
- psmouse->pktcnt < psmouse->pktsize) {
- return PSMOUSE_GOOD_DATA;
- }
-
- if (contact_cnt == 0 && psmouse->pktcnt < 5)
- return PSMOUSE_GOOD_DATA;
-
- if (psmouse->pktcnt < 3 * contact_cnt + 2)
- return PSMOUSE_GOOD_DATA;
-
- pixart_process_packet(psmouse);
-
- return PSMOUSE_FULL_PACKET;
-}
-
-static void pixart_disconnect(struct psmouse *psmouse)
-{
- pixart_reset(psmouse);
- kfree(psmouse->private);
- psmouse->private = NULL;
-}
-
-static int pixart_reconnect(struct psmouse *psmouse)
-{
- struct ps2dev *ps2dev = &psmouse->ps2dev;
- u8 mode;
- int error;
-
- pixart_reset(psmouse);
-
- error = pixart_read_tp_mode(ps2dev, &mode);
- if (error)
- return error;
-
- if (mode != PIXART_MODE_ABS)
- return -EIO;
-
- error = ps2_command(ps2dev, NULL, PIXART_CMD_SWITCH_PROTO);
- if (error)
- return error;
-
- return 0;
-}
-
-static int pixart_set_input_params(struct input_dev *dev,
- struct pixart_data *priv)
-{
- /* No relative support */
- __clear_bit(EV_REL, dev->evbit);
- __clear_bit(REL_X, dev->relbit);
- __clear_bit(REL_Y, dev->relbit);
- __clear_bit(BTN_MIDDLE, dev->keybit);
-
- /* Buttons */
- __set_bit(EV_KEY, dev->evbit);
- __set_bit(BTN_LEFT, dev->keybit);
- if (priv->type == PIXART_TYPE_CLICKPAD)
- __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
- else
- __set_bit(BTN_RIGHT, dev->keybit);
-
- /* Absolute position */
- input_set_abs_params(dev, ABS_X, 0, PIXART_PAD_WIDTH, 0, 0);
- input_set_abs_params(dev, ABS_Y, 0, PIXART_PAD_HEIGHT, 0, 0);
-
- input_set_abs_params(dev, ABS_MT_POSITION_X,
- 0, PIXART_PAD_WIDTH, 0, 0);
- input_set_abs_params(dev, ABS_MT_POSITION_Y,
- 0, PIXART_PAD_HEIGHT, 0, 0);
-
- return input_mt_init_slots(dev, PIXART_MAX_FINGERS, INPUT_MT_POINTER);
-}
-
-static int pixart_query_hardware(struct ps2dev *ps2dev, u8 *mode, u8 *type)
-{
- int error;
-
- error = pixart_read_tp_type(ps2dev, type);
- if (error)
- return error;
-
- error = pixart_read_tp_mode(ps2dev, mode);
- if (error)
- return error;
-
- return 0;
-}
-
-int pixart_detect(struct psmouse *psmouse, bool set_properties)
-{
- u8 type;
- int error;
-
- pixart_reset(psmouse);
-
- error = pixart_read_tp_type(&psmouse->ps2dev, &type);
- if (error)
- return error;
-
- if (set_properties) {
- psmouse->vendor = "PixArt";
- psmouse->name = (type == PIXART_TYPE_TOUCHPAD) ?
- "touchpad" : "clickpad";
- }
-
- return 0;
-}
-
-int pixart_init(struct psmouse *psmouse)
-{
- int error;
- struct pixart_data *priv;
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- psmouse->private = priv;
- pixart_reset(psmouse);
-
- error = pixart_query_hardware(&psmouse->ps2dev,
- &priv->mode, &priv->type);
- if (error) {
- psmouse_err(psmouse, "init: Unable to query PixArt touchpad hardware.\n");
- goto err_exit;
- }
-
- /* Relative mode follows standard PS/2 mouse protocol */
- if (priv->mode != PIXART_MODE_ABS) {
- error = -EIO;
- goto err_exit;
- }
-
- /* Set absolute mode */
- error = ps2_command(&psmouse->ps2dev, NULL, PIXART_CMD_SWITCH_PROTO);
- if (error) {
- psmouse_err(psmouse, "init: Unable to initialize PixArt absolute mode.\n");
- goto err_exit;
- }
-
- error = pixart_set_input_params(psmouse->dev, priv);
- if (error) {
- psmouse_err(psmouse, "init: Unable to set input params.\n");
- goto err_exit;
- }
-
- psmouse->pktsize = 15;
- psmouse->protocol_handler = pixart_protocol_handler;
- psmouse->disconnect = pixart_disconnect;
- psmouse->reconnect = pixart_reconnect;
- psmouse->cleanup = pixart_reset;
- /* resync is not supported yet */
- psmouse->resync_time = 0;
-
- return 0;
-
-err_exit:
- pixart_reset(psmouse);
- kfree(priv);
- psmouse->private = NULL;
- return error;
-}
diff --git a/drivers/input/mouse/pixart_ps2.h b/drivers/input/mouse/pixart_ps2.h
deleted file mode 100644
index 47a1d040f2d1..000000000000
--- a/drivers/input/mouse/pixart_ps2.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _PIXART_PS2_H
-#define _PIXART_PS2_H
-
-#include "psmouse.h"
-
-#define PIXART_PAD_WIDTH 1023
-#define PIXART_PAD_HEIGHT 579
-#define PIXART_MAX_FINGERS 4
-
-#define PIXART_CMD_REPORT_FORMAT 0x01d8
-#define PIXART_CMD_SWITCH_PROTO 0x00de
-
-#define PIXART_MODE_REL 0
-#define PIXART_MODE_ABS 1
-
-#define PIXART_TYPE_CLICKPAD 0
-#define PIXART_TYPE_TOUCHPAD 1
-
-#define CONTACT_CNT_MASK GENMASK(6, 4)
-
-#define SLOT_ID_MASK GENMASK(2, 0)
-#define ABS_Y_MASK GENMASK(5, 4)
-#define ABS_X_MASK GENMASK(7, 6)
-
-struct pixart_data {
- u8 mode;
- u8 type;
- int x_max;
- int y_max;
-};
-
-int pixart_detect(struct psmouse *psmouse, bool set_properties);
-int pixart_init(struct psmouse *psmouse);
-
-#endif /* _PIXART_PS2_H */
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 5a4defe9cf32..a2c9f7144864 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -36,7 +36,6 @@
#include "focaltech.h"
#include "vmmouse.h"
#include "byd.h"
-#include "pixart_ps2.h"
#define DRIVER_DESC "PS/2 mouse driver"
@@ -907,15 +906,6 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.init = byd_init,
},
#endif
-#ifdef CONFIG_MOUSE_PS2_PIXART
- {
- .type = PSMOUSE_PIXART,
- .name = "PixArtPS/2",
- .alias = "pixart",
- .detect = pixart_detect,
- .init = pixart_init,
- },
-#endif
{
.type = PSMOUSE_AUTO,
.name = "auto",
@@ -1182,13 +1172,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
return ret;
}
- /* Try PixArt touchpad */
- if (max_proto > PSMOUSE_IMEX &&
- psmouse_try_protocol(psmouse, PSMOUSE_PIXART, &max_proto,
- set_properties, true)) {
- return PSMOUSE_PIXART;
- }
-
if (max_proto > PSMOUSE_IMEX) {
if (psmouse_try_protocol(psmouse, PSMOUSE_GENPS,
&max_proto, set_properties, true))
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 23f7fa7243cb..4d8acfe0d82a 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -69,7 +69,6 @@ enum psmouse_type {
PSMOUSE_BYD,
PSMOUSE_SYNAPTICS_SMBUS,
PSMOUSE_ELANTECH_SMBUS,
- PSMOUSE_PIXART,
PSMOUSE_AUTO /* This one should always be last */
};
@@ -95,7 +94,7 @@ struct psmouse {
const char *vendor;
const char *name;
const struct psmouse_protocol *protocol;
- unsigned char packet[16];
+ unsigned char packet[8];
unsigned char badbyte;
unsigned char pktcnt;
unsigned char pktsize;
diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h
index d236469032b1..127cfdc8668a 100644
--- a/drivers/input/serio/i8042-acpipnpio.h
+++ b/drivers/input/serio/i8042-acpipnpio.h
@@ -1121,6 +1121,43 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
},
/*
+ * Some TongFang barebones have touchpad and/or keyboard issues after
+ * suspend fixable with nomux + reset + noloop + nopnp. Luckily, none of
+ * them have an external PS/2 port so this can safely be set for all of
+ * them.
+ * TongFang barebones come with board_vendor and/or system_vendor set to
+ * a different value for each individual reseller. The only somewhat
+ * universal way to identify them is by board_name.
+ */
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GMxXGxX"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+ },
+ /*
* A lot of modern Clevo barebones have touchpad and/or keyboard issues
* after suspend fixable with nomux + reset + noloop + nopnp. Luckily,
* none of them have an external PS/2 port so this can safely be set for
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 8c77e9f347c5..b6a66bd370d0 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -1121,6 +1121,14 @@ static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
}
}
+static void edt_ft5x06_exit_regmap(void *arg)
+{
+ struct edt_ft5x06_ts_data *data = arg;
+
+ if (!IS_ERR_OR_NULL(data->regmap))
+ regmap_exit(data->regmap);
+}
+
static void edt_ft5x06_disable_regulators(void *arg)
{
struct edt_ft5x06_ts_data *data = arg;
@@ -1154,6 +1162,16 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
return PTR_ERR(tsdata->regmap);
}
+ /*
+ * We are not using devm_regmap_init_i2c() and instead install a
+ * custom action because we may replace regmap with M06-specific one
+ * and we need to make sure that it will not be released too early.
+ */
+ error = devm_add_action_or_reset(&client->dev, edt_ft5x06_exit_regmap,
+ tsdata);
+ if (error)
+ return error;
+
chip_data = device_get_match_data(&client->dev);
if (!chip_data)
chip_data = (const struct edt_i2c_chip_data *)id->driver_data;
@@ -1347,7 +1365,6 @@ static void edt_ft5x06_ts_remove(struct i2c_client *client)
struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
edt_ft5x06_ts_teardown_debugfs(tsdata);
- regmap_exit(tsdata->regmap);
}
static int edt_ft5x06_ts_suspend(struct device *dev)
diff --git a/drivers/input/touchscreen/hynitron_cstxxx.c b/drivers/input/touchscreen/hynitron_cstxxx.c
index 05946fee4fd4..f72834859282 100644
--- a/drivers/input/touchscreen/hynitron_cstxxx.c
+++ b/drivers/input/touchscreen/hynitron_cstxxx.c
@@ -470,7 +470,7 @@ static const struct hynitron_ts_chip_data cst3xx_data = {
};
static const struct i2c_device_id hyn_tpd_id[] = {
- { .name = "hynitron_ts", 0 },
+ { .name = "hynitron_ts" },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(i2c, hyn_tpd_id);
diff --git a/drivers/input/touchscreen/zinitix.c b/drivers/input/touchscreen/zinitix.c
index 52b3950460e2..716d6fa60f86 100644
--- a/drivers/input/touchscreen/zinitix.c
+++ b/drivers/input/touchscreen/zinitix.c
@@ -645,19 +645,29 @@ static int zinitix_ts_probe(struct i2c_client *client)
return error;
}
- bt541->num_keycodes = device_property_count_u32(&client->dev, "linux,keycodes");
- if (bt541->num_keycodes > ARRAY_SIZE(bt541->keycodes)) {
- dev_err(&client->dev, "too many keys defined (%d)\n", bt541->num_keycodes);
- return -EINVAL;
- }
+ if (device_property_present(&client->dev, "linux,keycodes")) {
+ bt541->num_keycodes = device_property_count_u32(&client->dev,
+ "linux,keycodes");
+ if (bt541->num_keycodes < 0) {
+ dev_err(&client->dev, "Failed to count keys (%d)\n",
+ bt541->num_keycodes);
+ return bt541->num_keycodes;
+ } else if (bt541->num_keycodes > ARRAY_SIZE(bt541->keycodes)) {
+ dev_err(&client->dev, "Too many keys defined (%d)\n",
+ bt541->num_keycodes);
+ return -EINVAL;
+ }
- error = device_property_read_u32_array(&client->dev, "linux,keycodes",
- bt541->keycodes,
- bt541->num_keycodes);
- if (error) {
- dev_err(&client->dev,
- "Unable to parse \"linux,keycodes\" property: %d\n", error);
- return error;
+ error = device_property_read_u32_array(&client->dev,
+ "linux,keycodes",
+ bt541->keycodes,
+ bt541->num_keycodes);
+ if (error) {
+ dev_err(&client->dev,
+ "Unable to parse \"linux,keycodes\" property: %d\n",
+ error);
+ return error;
+ }
}
error = zinitix_init_input_dev(bt541);
diff --git a/include/linux/input.h b/include/linux/input.h
index 6437c35f0796..7d7cb0593a63 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -344,12 +344,16 @@ struct input_handler {
* @name: name given to the handle by handler that created it
* @dev: input device the handle is attached to
* @handler: handler that works with the device through this handle
+ * @handle_events: event sequence handler. It is set up by the input core
+ * according to event handling method specified in the @handler. See
+ * input_handle_setup_event_handler().
+ * This method is being called by the input core with interrupts disabled
+ * and dev->event_lock spinlock held and so it may not sleep.
* @d_node: used to put the handle on device's list of attached handles
* @h_node: used to put the handle on handler's list of handles from which
* it gets events
*/
struct input_handle {
-
void *private;
int open;
@@ -358,6 +362,10 @@ struct input_handle {
struct input_dev *dev;
struct input_handler *handler;
+ unsigned int (*handle_events)(struct input_handle *handle,
+ struct input_value *vals,
+ unsigned int count);
+
struct list_head d_node;
struct list_head h_node;
};