summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-06-24 11:16:06 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-06-24 11:16:06 -0700
commite1611017870fa1582b5ff9ec0edc09542318daa6 (patch)
treefaff3dcc5bd72395f407a01922ac5366f9a76cea /drivers/input/touchscreen
parentf0e6f20cb52b14c2c441f04e21cef0c95d498cac (diff)
parent7a0e692a0381254b2f77c54dec100cd3325a6fdf (diff)
Merge tag 'input-for-v7.2-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: - A new driver for Wacom W9000-series penabled touchscreens - Updates to STM FTS driver adding support for reset line and preparing the driver for STMFTS5 support - Updates to RMI4 and IMS PCU drivers hardening the code - Support for half-duplex mode restored in ADS7846 driver - Updates to driver's device_id tables to use named initializers - Removal of no longer used PCAP keys and touchscreen drivers (support for the ezx series of phones was removed in 2022) - Removal of xilinx_ps2 driver which is no longer used either - Updates to userio to allow setting up additional serio port characteristics (such as id, extra and proto) - Assorted hardening and cleanup fixes for other drivers * tag 'input-for-v7.2-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (72 commits) Input: mms114 - fix touch indexing for MMS134S and MMS136 Input: elan_i2c - prevent division by zero and arithmetic underflow Input: stop force-feedback timer when unregistering input devices Input: iforce - bound the device-reported force-feedback effect index Input: goodix - clamp the device-reported contact count Input: mms114 - reject an oversized device packet size Input: touchwin - reset the packet index on every complete packet Input: rmi4 - update formatting in F12 Input: rmi4 - propagate proper error code in F12 sensor tuning Input: rmi4 - simplify size calculations in F12 Input: rmi4 - use sizeof(*ptr) and idiomatic checks in f12 allocators Input: rmi4 - use devm_kmalloc for F12 data packet buffer Input: rmi4 - use flexible array member for IRQ masks in F12 Input: rmi4 - use unaligned access helpers in F12 Input: rmi4 - change reg_size type to u32 Input: rmi4 - refactor F12 probe function Input: rmi4 - use kzalloc_flex() for struct rmi_function Input: rmi4 - refactor function allocation and registration Input: rmi4 - use local presence map in rmi_read_register_desc() Input: rmi4 - fix limit in rmi_register_desc_has_subpacket() ...
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r--drivers/input/touchscreen/Kconfig22
-rw-r--r--drivers/input/touchscreen/Makefile2
-rw-r--r--drivers/input/touchscreen/ad7879-i2c.c4
-rw-r--r--drivers/input/touchscreen/ads7846.c173
-rw-r--r--drivers/input/touchscreen/ar1021_i2c.c2
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c23
-rw-r--r--drivers/input/touchscreen/auo-pixcir-ts.c2
-rw-r--r--drivers/input/touchscreen/bu21013_ts.c2
-rw-r--r--drivers/input/touchscreen/bu21029_ts.c2
-rw-r--r--drivers/input/touchscreen/cy8ctma140.c2
-rw-r--r--drivers/input/touchscreen/cy8ctmg110_ts.c2
-rw-r--r--drivers/input/touchscreen/cyttsp5.c2
-rw-r--r--drivers/input/touchscreen/cyttsp_i2c.c2
-rw-r--r--drivers/input/touchscreen/eeti_ts.c2
-rw-r--r--drivers/input/touchscreen/egalax_ts.c2
-rw-r--r--drivers/input/touchscreen/elants_i2c.c6
-rw-r--r--drivers/input/touchscreen/exc3000.c8
-rw-r--r--drivers/input/touchscreen/goodix.c5
-rw-r--r--drivers/input/touchscreen/hideep.c2
-rw-r--r--drivers/input/touchscreen/himax_hx83112b.c4
-rw-r--r--drivers/input/touchscreen/hynitron-cst816x.c2
-rw-r--r--drivers/input/touchscreen/ili210x.c8
-rw-r--r--drivers/input/touchscreen/ilitek_ts_i2c.c2
-rw-r--r--drivers/input/touchscreen/iqs5xx.c6
-rw-r--r--drivers/input/touchscreen/max11801_ts.c2
-rw-r--r--drivers/input/touchscreen/melfas_mip4.c2
-rw-r--r--drivers/input/touchscreen/migor_ts.c2
-rw-r--r--drivers/input/touchscreen/mms114.c26
-rw-r--r--drivers/input/touchscreen/novatek-nvt-ts.c4
-rw-r--r--drivers/input/touchscreen/pcap_ts.c252
-rw-r--r--drivers/input/touchscreen/pixcir_i2c_ts.c4
-rw-r--r--drivers/input/touchscreen/raydium_i2c_ts.c4
-rw-r--r--drivers/input/touchscreen/rohm_bu21023.c2
-rw-r--r--drivers/input/touchscreen/s6sy761.c2
-rw-r--r--drivers/input/touchscreen/silead.c12
-rw-r--r--drivers/input/touchscreen/sis_i2c.c4
-rw-r--r--drivers/input/touchscreen/st1232.c4
-rw-r--r--drivers/input/touchscreen/stmfts.c162
-rw-r--r--drivers/input/touchscreen/touchwin.c15
-rw-r--r--drivers/input/touchscreen/tsc2004.c2
-rw-r--r--drivers/input/touchscreen/tsc2007_core.c8
-rw-r--r--drivers/input/touchscreen/wacom_i2c.c2
-rw-r--r--drivers/input/touchscreen/wacom_w9000.c444
-rw-r--r--drivers/input/touchscreen/wdt87xx_i2c.c2
-rw-r--r--drivers/input/touchscreen/zet6223.c2
-rw-r--r--drivers/input/touchscreen/zforce_ts.c2
46 files changed, 833 insertions, 413 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index aeaf9a9cbb41..9b9ae8ac3f7f 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -610,6 +610,18 @@ config TOUCHSCREEN_WACOM_I2C
To compile this driver as a module, choose M here: the module
will be called wacom_i2c.
+config TOUCHSCREEN_WACOM_W9000
+ tristate "Wacom W9000-series penabled touchscreen (I2C)"
+ depends on I2C
+ help
+ Say Y here if you have a Wacom W9000-series penabled I2C touchscreen.
+ This driver supports models W9002 and W9007A.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the module
+ will be called wacom_w9000.
+
config TOUCHSCREEN_LPC32XX
tristate "LPC32XX touchscreen controller"
depends on ARCH_LPC32XX
@@ -1178,16 +1190,6 @@ config TOUCHSCREEN_TSC2007_IIO
or ambient light monitoring), temperature and raw input
values.
-config TOUCHSCREEN_PCAP
- tristate "Motorola PCAP touchscreen"
- depends on EZX_PCAP
- help
- Say Y here if you have a Motorola EZX telephone and
- want to enable support for the built-in touchscreen.
-
- To compile this driver as a module, choose M here: the
- module will be called pcap_ts.
-
config TOUCHSCREEN_RM_TS
tristate "Raydium I2C Touchscreen"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index f2b002abebe8..bfd9de83389d 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -74,7 +74,6 @@ obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_IPAQ_MICRO) += ipaq-micro-ts.o
obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o
-obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o
obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_RM_TS) += raydium_i2c_ts.o
@@ -101,6 +100,7 @@ tsc2007-$(CONFIG_TOUCHSCREEN_TSC2007_IIO) += tsc2007_iio.o
obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o
obj-$(CONFIG_TOUCHSCREEN_WACOM_I2C) += wacom_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_WACOM_W9000) += wacom_w9000.o
obj-$(CONFIG_TOUCHSCREEN_WDT87XX_I2C) += wdt87xx_i2c.o
obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c
index e5b99312c3d9..c1ccdf86b74c 100644
--- a/drivers/input/touchscreen/ad7879-i2c.c
+++ b/drivers/input/touchscreen/ad7879-i2c.c
@@ -42,8 +42,8 @@ static int ad7879_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id ad7879_id[] = {
- { "ad7879" },
- { "ad7889" },
+ { .name = "ad7879" },
+ { .name = "ad7889" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ad7879_id);
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 4b39f7212d35..8d6416ac283e 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -134,6 +134,9 @@ struct ads7846 {
bool disabled; /* P: lock */
bool suspended; /* P: lock */
+ int (*setup_spi_msg)(struct ads7846 *ts,
+ const struct ads7846_platform_data *pdata);
+ void (*read_state)(struct ads7846 *ts);
int (*filter)(void *data, int data_idx, int *val);
void *filter_data;
int (*get_pendown_state)(void);
@@ -325,7 +328,6 @@ struct ser_req {
u8 ref_on;
u8 command;
u8 ref_off;
- u16 scratch;
struct spi_message msg;
struct spi_transfer xfer[8];
/*
@@ -333,6 +335,7 @@ struct ser_req {
* transfer buffers to live in their own cache lines.
*/
__be16 sample ____cacheline_aligned;
+ u16 scratch;
};
struct ads7845_ser_req {
@@ -403,8 +406,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
spi_message_add_tail(&req->xfer[5], &req->msg);
/* clear the command register */
- req->scratch = 0;
- req->xfer[6].tx_buf = &req->scratch;
+ req->xfer[6].rx_buf = &req->scratch;
req->xfer[6].len = 1;
spi_message_add_tail(&req->xfer[6], &req->msg);
@@ -789,6 +791,22 @@ static int ads7846_filter(struct ads7846 *ts)
return 0;
}
+static int ads7846_filter_one(struct ads7846 *ts, unsigned int cmd_idx)
+{
+ struct ads7846_packet *packet = ts->packet;
+ struct ads7846_buf_layout *l = &packet->l[cmd_idx];
+ int action, val;
+
+ val = ads7846_get_value(&packet->rx[l->offset + l->count - 1]);
+ action = ts->filter(ts->filter_data, cmd_idx, &val);
+ if (action == ADS7846_FILTER_REPEAT)
+ return -EAGAIN;
+ else if (action != ADS7846_FILTER_OK)
+ return -EIO;
+ ads7846_set_cmd_val(ts, cmd_idx, val);
+ return 0;
+}
+
static void ads7846_wait_for_hsync(struct ads7846 *ts)
{
if (ts->wait_for_sync) {
@@ -811,6 +829,45 @@ static void ads7846_wait_for_hsync(struct ads7846 *ts)
cpu_relax();
}
+static void ads7846_halfd_read_state(struct ads7846 *ts)
+{
+ struct ads7846_packet *packet = ts->packet;
+ int msg_idx = 0;
+
+ packet->ignore = false;
+
+ while (msg_idx < ts->msg_count) {
+ int error;
+
+ ads7846_wait_for_hsync(ts);
+
+ error = spi_sync(ts->spi, &ts->msg[msg_idx]);
+ if (error) {
+ dev_err_ratelimited(&ts->spi->dev, "spi_sync --> %d\n",
+ error);
+ packet->ignore = true;
+ return;
+ }
+
+ /*
+ * Last message is power down request, no need to convert
+ * or filter the value.
+ */
+ if (msg_idx == ts->msg_count - 1)
+ break;
+
+ error = ads7846_filter_one(ts, msg_idx);
+ if (error == -EAGAIN) {
+ continue;
+ } else if (error) {
+ packet->ignore = true;
+ msg_idx = ts->msg_count - 1;
+ } else {
+ msg_idx++;
+ }
+ }
+}
+
static void ads7846_read_state(struct ads7846 *ts)
{
struct ads7846_packet *packet = ts->packet;
@@ -939,7 +996,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
while (!ts->stopped && get_pendown_state(ts)) {
/* pen is down, continue with the measurement */
- ads7846_read_state(ts);
+ ts->read_state(ts);
if (!ts->stopped)
ads7846_report_state(ts);
@@ -1026,6 +1083,102 @@ static int ads7846_setup_pendown(struct spi_device *spi,
* Set up the transfers to read touchscreen state; this assumes we
* use formula #2 for pressure, not #3.
*/
+static int ads7846_halfd_spi_msg(struct ads7846 *ts,
+ const struct ads7846_platform_data *pdata)
+{
+ struct spi_message *m = ts->msg;
+ struct spi_transfer *x = ts->xfer;
+ struct ads7846_packet *packet = ts->packet;
+ int vref = pdata->keep_vref_on;
+ unsigned int offset = 0;
+ unsigned int cmd_idx, b;
+ size_t size = 0;
+
+ if (pdata->settle_delay_usecs)
+ packet->count = 2;
+ else
+ packet->count = 1;
+
+ if (ts->model == 7846)
+ packet->cmds = 5; /* x, y, z1, z2, pwdown */
+ else
+ packet->cmds = 3; /* x, y, pwdown */
+
+ for (cmd_idx = 0; cmd_idx < packet->cmds; cmd_idx++) {
+ struct ads7846_buf_layout *l = &packet->l[cmd_idx];
+ unsigned int max_count;
+
+ if (cmd_idx == packet->cmds - 1) {
+ cmd_idx = ADS7846_PWDOWN;
+ max_count = 1;
+ } else {
+ max_count = packet->count;
+ }
+
+ l->offset = offset;
+ offset += max_count;
+ l->count = max_count;
+ l->skip = 0;
+ size += sizeof(*packet->rx) * max_count;
+ }
+
+ /* We use two transfers per command. */
+ if (ARRAY_SIZE(ts->xfer) < offset * 2)
+ return -ENOMEM;
+
+ packet->rx = devm_kzalloc(&ts->spi->dev, size, GFP_KERNEL);
+ if (!packet->rx)
+ return -ENOMEM;
+
+ if (ts->model == 7873) {
+ /*
+ * The AD7873 is almost identical to the ADS7846
+ * keep VREF off during differential/ratiometric
+ * conversion modes.
+ */
+ ts->model = 7846;
+ vref = 0;
+ }
+
+ ts->msg_count = 0;
+
+ for (cmd_idx = 0; cmd_idx < packet->cmds; cmd_idx++) {
+ struct ads7846_buf_layout *l = &packet->l[cmd_idx];
+ u8 cmd;
+
+ ts->msg_count++;
+ spi_message_init(m);
+ m->context = ts;
+
+ if (cmd_idx == packet->cmds - 1)
+ cmd_idx = ADS7846_PWDOWN;
+
+ cmd = ads7846_get_cmd(cmd_idx, vref);
+
+ for (b = 0; b < l->count; b++) {
+ packet->rx[l->offset + b].cmd = cmd;
+ x->tx_buf = &packet->rx[l->offset + b].cmd;
+ x->len = 1;
+ spi_message_add_tail(x, m);
+ x++;
+ x->rx_buf = &packet->rx[l->offset + b].data;
+ x->len = 2;
+ if (b < l->count - 1 && l->count > 1) {
+ x->delay.value = pdata->settle_delay_usecs;
+ x->delay.unit = SPI_DELAY_UNIT_USECS;
+ }
+ spi_message_add_tail(x, m);
+ x++;
+ }
+ m++;
+ }
+ return 0;
+}
+
+/*
+ * Set up the transfers to read touchscreen state; this assumes we
+ * use formula #2 for pressure, not #3.
+ */
static int ads7846_setup_spi_msg(struct ads7846 *ts,
const struct ads7846_platform_data *pdata)
{
@@ -1236,6 +1389,14 @@ static int ads7846_probe(struct spi_device *spi)
if (!ts)
return -ENOMEM;
+ if (spi->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) {
+ ts->setup_spi_msg = ads7846_halfd_spi_msg;
+ ts->read_state = ads7846_halfd_read_state;
+ } else {
+ ts->setup_spi_msg = ads7846_setup_spi_msg;
+ ts->read_state = ads7846_read_state;
+ }
+
packet = devm_kzalloc(dev, sizeof(struct ads7846_packet), GFP_KERNEL);
if (!packet)
return -ENOMEM;
@@ -1330,7 +1491,9 @@ static int ads7846_probe(struct spi_device *spi)
ts->core_prop.swap_x_y = true;
}
- ads7846_setup_spi_msg(ts, pdata);
+ err = ts->setup_spi_msg(ts, pdata);
+ if (err)
+ return err;
ts->reg = devm_regulator_get(dev, "vcc");
if (IS_ERR(ts->reg)) {
diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c
index 8a588202447d..aa43fc1549df 100644
--- a/drivers/input/touchscreen/ar1021_i2c.c
+++ b/drivers/input/touchscreen/ar1021_i2c.c
@@ -164,7 +164,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(ar1021_i2c_pm,
ar1021_i2c_suspend, ar1021_i2c_resume);
static const struct i2c_device_id ar1021_i2c_id[] = {
- { "ar1021" },
+ { .name = "ar1021" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id);
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index f21bf2844112..2c0e5a67135b 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1397,7 +1397,8 @@ static int mxt_prepare_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg)
{
struct device *dev = &data->client->dev;
struct mxt_object *object;
- unsigned int type, instance, size, byte_offset;
+ unsigned int type, instance, size;
+ int byte_offset;
int offset;
int ret;
int i;
@@ -2840,14 +2841,12 @@ static ssize_t mxt_object_show(struct device *dev,
int count = 0;
int i, j;
int error;
- u8 *obuf;
/* Pre-allocate buffer large enough to hold max sized object. */
- obuf = kmalloc(256, GFP_KERNEL);
+ u8 *obuf __free(kfree) = kmalloc(256, GFP_KERNEL);
if (!obuf)
return -ENOMEM;
- error = 0;
for (i = 0; i < data->info->object_num; i++) {
object = data->object_table + i;
@@ -2862,15 +2861,13 @@ static ssize_t mxt_object_show(struct device *dev,
error = __mxt_read_reg(data->client, addr, size, obuf);
if (error)
- goto done;
+ return error;
count = mxt_show_instance(buf, count, object, j, obuf);
}
}
-done:
- kfree(obuf);
- return error ?: count;
+ return count;
}
static int mxt_check_firmware_format(struct device *dev,
@@ -3420,11 +3417,11 @@ MODULE_DEVICE_TABLE(acpi, mxt_acpi_id);
#endif
static const struct i2c_device_id mxt_id[] = {
- { "qt602240_ts" },
- { "atmel_mxt_ts" },
- { "atmel_mxt_tp" },
- { "maxtouch" },
- { "mXT224" },
+ { .name = "qt602240_ts" },
+ { .name = "atmel_mxt_ts" },
+ { .name = "atmel_mxt_tp" },
+ { .name = "maxtouch" },
+ { .name = "mXT224" },
{ }
};
MODULE_DEVICE_TABLE(i2c, mxt_id);
diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c
index 401b2264f585..6c6ebebacba9 100644
--- a/drivers/input/touchscreen/auo-pixcir-ts.c
+++ b/drivers/input/touchscreen/auo-pixcir-ts.c
@@ -618,7 +618,7 @@ static int auo_pixcir_probe(struct i2c_client *client)
}
static const struct i2c_device_id auo_pixcir_idtable[] = {
- { "auo_pixcir_ts" },
+ { .name = "auo_pixcir_ts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable);
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
index 6baebb7ec089..d1bdccc56fc8 100644
--- a/drivers/input/touchscreen/bu21013_ts.c
+++ b/drivers/input/touchscreen/bu21013_ts.c
@@ -597,7 +597,7 @@ static int bu21013_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(bu21013_dev_pm_ops, bu21013_suspend, bu21013_resume);
static const struct i2c_device_id bu21013_id[] = {
- { DRIVER_TP },
+ { .name = DRIVER_TP },
{ }
};
MODULE_DEVICE_TABLE(i2c, bu21013_id);
diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c
index 68d9cd55ceeb..339fee1622fb 100644
--- a/drivers/input/touchscreen/bu21029_ts.c
+++ b/drivers/input/touchscreen/bu21029_ts.c
@@ -442,7 +442,7 @@ static int bu21029_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(bu21029_pm_ops, bu21029_suspend, bu21029_resume);
static const struct i2c_device_id bu21029_ids[] = {
- { DRIVER_NAME },
+ { .name = DRIVER_NAME },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, bu21029_ids);
diff --git a/drivers/input/touchscreen/cy8ctma140.c b/drivers/input/touchscreen/cy8ctma140.c
index 2d4b6e343203..0ac48eff3376 100644
--- a/drivers/input/touchscreen/cy8ctma140.c
+++ b/drivers/input/touchscreen/cy8ctma140.c
@@ -322,7 +322,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cy8ctma140_pm,
cy8ctma140_suspend, cy8ctma140_resume);
static const struct i2c_device_id cy8ctma140_idtable[] = {
- { CY8CTMA140_NAME },
+ { .name = CY8CTMA140_NAME },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, cy8ctma140_idtable);
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
index 54d6c4869eb0..33ad4f0512a0 100644
--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
+++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
@@ -267,7 +267,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cy8ctmg110_pm,
cy8ctmg110_suspend, cy8ctmg110_resume);
static const struct i2c_device_id cy8ctmg110_idtable[] = {
- { CY8CTMG110_DRIVER_NAME, 1 },
+ { .name = CY8CTMG110_DRIVER_NAME, .driver_data = 1 },
{ }
};
diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c
index 47f4271395a6..73c397e44da4 100644
--- a/drivers/input/touchscreen/cyttsp5.c
+++ b/drivers/input/touchscreen/cyttsp5.c
@@ -938,7 +938,7 @@ static const struct of_device_id cyttsp5_of_match[] = {
MODULE_DEVICE_TABLE(of, cyttsp5_of_match);
static const struct i2c_device_id cyttsp5_i2c_id[] = {
- { CYTTSP5_NAME },
+ { .name = CYTTSP5_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id);
diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c
index cb15600549cd..17524f7e944d 100644
--- a/drivers/input/touchscreen/cyttsp_i2c.c
+++ b/drivers/input/touchscreen/cyttsp_i2c.c
@@ -103,7 +103,7 @@ static int cyttsp_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id cyttsp_i2c_id[] = {
- { CY_I2C_NAME },
+ { .name = CY_I2C_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id);
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c
index 492e19a28a74..b12602bc368e 100644
--- a/drivers/input/touchscreen/eeti_ts.c
+++ b/drivers/input/touchscreen/eeti_ts.c
@@ -266,7 +266,7 @@ static int eeti_ts_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume);
static const struct i2c_device_id eeti_ts_id[] = {
- { "eeti_ts" },
+ { .name = "eeti_ts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, eeti_ts_id);
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index eb3cc2befcdf..76cf8085553f 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -219,7 +219,7 @@ static int egalax_ts_probe(struct i2c_client *client)
}
static const struct i2c_device_id egalax_ts_id[] = {
- { "egalax_ts" },
+ { .name = "egalax_ts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, egalax_ts_id);
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index 835d91dff0a4..17175adcaebb 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -1615,9 +1615,9 @@ static DEFINE_SIMPLE_DEV_PM_OPS(elants_i2c_pm_ops,
elants_i2c_suspend, elants_i2c_resume);
static const struct i2c_device_id elants_i2c_id[] = {
- { DEVICE_NAME, EKTH3500 },
- { "ekth3500", EKTH3500 },
- { "ektf3624", EKTF3624 },
+ { .name = DEVICE_NAME, .driver_data = EKTH3500 },
+ { .name = "ekth3500", .driver_data = EKTH3500 },
+ { .name = "ektf3624", .driver_data = EKTF3624 },
{ }
};
MODULE_DEVICE_TABLE(i2c, elants_i2c_id);
diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c
index 78c0911ba6e2..037bb35238a3 100644
--- a/drivers/input/touchscreen/exc3000.c
+++ b/drivers/input/touchscreen/exc3000.c
@@ -432,10 +432,10 @@ static int exc3000_probe(struct i2c_client *client)
}
static const struct i2c_device_id exc3000_id[] = {
- { "exc3000", EETI_EXC3000 },
- { "exc80h60", EETI_EXC80H60 },
- { "exc80h84", EETI_EXC80H84 },
- { "exc81w32", EETI_EXC81W32 },
+ { .name = "exc3000", .driver_data = EETI_EXC3000 },
+ { .name = "exc80h60", .driver_data = EETI_EXC80H60 },
+ { .name = "exc80h84", .driver_data = EETI_EXC80H84 },
+ { .name = "exc81w32", .driver_data = EETI_EXC81W32 },
{ }
};
MODULE_DEVICE_TABLE(i2c, exc3000_id);
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index f8798d11ec03..03efc0c792c2 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -1057,7 +1057,8 @@ static void goodix_read_config(struct goodix_ts_data *ts)
}
ts->int_trigger_type = ts->config[TRIGGER_LOC] & 0x03;
- ts->max_touch_num = ts->config[MAX_CONTACTS_LOC] & 0x0f;
+ ts->max_touch_num = min(ts->config[MAX_CONTACTS_LOC] & 0x0f,
+ GOODIX_MAX_CONTACTS);
x_max = get_unaligned_le16(&ts->config[RESOLUTION_LOC]);
y_max = get_unaligned_le16(&ts->config[RESOLUTION_LOC + 2]);
@@ -1523,7 +1524,7 @@ static int goodix_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(goodix_pm_ops, goodix_suspend, goodix_resume);
static const struct i2c_device_id goodix_ts_id[] = {
- { "GDIX1001:00" },
+ { .name = "GDIX1001:00" },
{ }
};
MODULE_DEVICE_TABLE(i2c, goodix_ts_id);
diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c
index 62041bcca83d..58e00c314ace 100644
--- a/drivers/input/touchscreen/hideep.c
+++ b/drivers/input/touchscreen/hideep.c
@@ -1081,7 +1081,7 @@ static int hideep_probe(struct i2c_client *client)
}
static const struct i2c_device_id hideep_i2c_id[] = {
- { HIDEEP_I2C_NAME },
+ { .name = HIDEEP_I2C_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, hideep_i2c_id);
diff --git a/drivers/input/touchscreen/himax_hx83112b.c b/drivers/input/touchscreen/himax_hx83112b.c
index 896a145ddb2b..0aa67dfacbad 100644
--- a/drivers/input/touchscreen/himax_hx83112b.c
+++ b/drivers/input/touchscreen/himax_hx83112b.c
@@ -406,8 +406,8 @@ static const struct himax_chip hx83112b_chip = {
};
static const struct i2c_device_id himax_ts_id[] = {
- { "hx83100a", (kernel_ulong_t)&hx83100a_chip },
- { "hx83112b", (kernel_ulong_t)&hx83112b_chip },
+ { .name = "hx83100a", .driver_data = (kernel_ulong_t)&hx83100a_chip },
+ { .name = "hx83112b", .driver_data = (kernel_ulong_t)&hx83112b_chip },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, himax_ts_id);
diff --git a/drivers/input/touchscreen/hynitron-cst816x.c b/drivers/input/touchscreen/hynitron-cst816x.c
index b64d7928e18f..47d9cd7412d1 100644
--- a/drivers/input/touchscreen/hynitron-cst816x.c
+++ b/drivers/input/touchscreen/hynitron-cst816x.c
@@ -226,7 +226,7 @@ static int cst816x_probe(struct i2c_client *client)
}
static const struct i2c_device_id cst816x_id[] = {
- { .name = "cst816s", 0 },
+ { .name = "cst816s" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cst816x_id);
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index 3bf524a6ee20..66ada7ffbc80 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -1049,10 +1049,10 @@ static int ili210x_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id ili210x_i2c_id[] = {
- { "ili210x", (long)&ili210x_chip },
- { "ili2117", (long)&ili211x_chip },
- { "ili2120", (long)&ili212x_chip },
- { "ili251x", (long)&ili251x_chip },
+ { .name = "ili210x", .driver_data = (long)&ili210x_chip },
+ { .name = "ili2117", .driver_data = (long)&ili211x_chip },
+ { .name = "ili2120", .driver_data = (long)&ili212x_chip },
+ { .name = "ili251x", .driver_data = (long)&ili251x_chip },
{ }
};
MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
diff --git a/drivers/input/touchscreen/ilitek_ts_i2c.c b/drivers/input/touchscreen/ilitek_ts_i2c.c
index 0706443792ba..3de0fbf8da38 100644
--- a/drivers/input/touchscreen/ilitek_ts_i2c.c
+++ b/drivers/input/touchscreen/ilitek_ts_i2c.c
@@ -639,7 +639,7 @@ static int ilitek_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(ilitek_pm_ops, ilitek_suspend, ilitek_resume);
static const struct i2c_device_id ilitek_ts_i2c_id[] = {
- { ILITEK_TS_NAME },
+ { .name = ILITEK_TS_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, ilitek_ts_i2c_id);
diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c
index 587665e4e6fd..b9bbe8b3eab8 100644
--- a/drivers/input/touchscreen/iqs5xx.c
+++ b/drivers/input/touchscreen/iqs5xx.c
@@ -1049,9 +1049,9 @@ static int iqs5xx_probe(struct i2c_client *client)
}
static const struct i2c_device_id iqs5xx_id[] = {
- { "iqs550", 0 },
- { "iqs572", 1 },
- { "iqs525", 2 },
+ { .name = "iqs550" },
+ { .name = "iqs572" },
+ { .name = "iqs525" },
{ }
};
MODULE_DEVICE_TABLE(i2c, iqs5xx_id);
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
index f39633fc8dc2..3996e4a61ff7 100644
--- a/drivers/input/touchscreen/max11801_ts.c
+++ b/drivers/input/touchscreen/max11801_ts.c
@@ -213,7 +213,7 @@ static int max11801_ts_probe(struct i2c_client *client)
}
static const struct i2c_device_id max11801_ts_id[] = {
- { "max11801" },
+ { .name = "max11801" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max11801_ts_id);
diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c
index 10fccf4e5bb1..fd6c0ac301a2 100644
--- a/drivers/input/touchscreen/melfas_mip4.c
+++ b/drivers/input/touchscreen/melfas_mip4.c
@@ -1536,7 +1536,7 @@ MODULE_DEVICE_TABLE(acpi, mip4_acpi_match);
#endif
static const struct i2c_device_id mip4_i2c_ids[] = {
- { MIP4_DEVICE_NAME },
+ { .name = MIP4_DEVICE_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, mip4_i2c_ids);
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c
index 993d945dcd23..9d221e340404 100644
--- a/drivers/input/touchscreen/migor_ts.c
+++ b/drivers/input/touchscreen/migor_ts.c
@@ -211,7 +211,7 @@ static int migor_ts_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(migor_ts_pm, migor_ts_suspend, migor_ts_resume);
static const struct i2c_device_id migor_ts_id[] = {
- { "migor_ts" },
+ { .name = "migor_ts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, migor_ts_id);
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index af462086a65c..53ad35d61d47 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -217,7 +217,9 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
struct mms114_data *data = dev_id;
struct i2c_client *client = data->client;
struct mms114_touch touch[MMS114_MAX_TOUCH];
+ struct mms114_touch *t;
int packet_size;
+ int event_size;
int touch_size;
int index;
int error;
@@ -226,11 +228,19 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
if (packet_size <= 0)
goto out;
+ if (packet_size > sizeof(touch)) {
+ dev_err(&client->dev, "Invalid packet size %d (max %zu)\n",
+ packet_size, sizeof(touch));
+ goto out;
+ }
+
/* MMS136 has slightly different event size */
if (data->type == TYPE_MMS134S || data->type == TYPE_MMS136)
- touch_size = packet_size / MMS136_EVENT_SIZE;
+ event_size = MMS136_EVENT_SIZE;
else
- touch_size = packet_size / MMS114_EVENT_SIZE;
+ event_size = MMS114_EVENT_SIZE;
+
+ touch_size = packet_size / event_size;
error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size,
(u8 *)touch);
@@ -238,18 +248,20 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
goto out;
for (index = 0; index < touch_size; index++) {
- switch (touch[index].type) {
+ t = (struct mms114_touch *)((u8 *)touch + index * event_size);
+
+ switch (t->type) {
case MMS114_TYPE_TOUCHSCREEN:
- mms114_process_mt(data, touch + index);
+ mms114_process_mt(data, t);
break;
case MMS114_TYPE_TOUCHKEY:
- mms114_process_touchkey(data, touch + index);
+ mms114_process_touchkey(data, t);
break;
default:
dev_err(&client->dev, "Wrong touch type (%d)\n",
- touch[index].type);
+ t->type);
break;
}
}
@@ -667,7 +679,7 @@ static int mms114_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(mms114_pm_ops, mms114_suspend, mms114_resume);
static const struct i2c_device_id mms114_id[] = {
- { "mms114" },
+ { .name = "mms114" },
{ }
};
MODULE_DEVICE_TABLE(i2c, mms114_id);
diff --git a/drivers/input/touchscreen/novatek-nvt-ts.c b/drivers/input/touchscreen/novatek-nvt-ts.c
index 708bfb933ddd..0f771f681952 100644
--- a/drivers/input/touchscreen/novatek-nvt-ts.c
+++ b/drivers/input/touchscreen/novatek-nvt-ts.c
@@ -326,8 +326,8 @@ static const struct of_device_id nvt_ts_of_match[] = {
MODULE_DEVICE_TABLE(of, nvt_ts_of_match);
static const struct i2c_device_id nvt_ts_i2c_id[] = {
- { "nt11205-ts", (unsigned long) &nvt_nt11205_ts_data },
- { "nt36672a-ts", (unsigned long) &nvt_nt36672a_ts_data },
+ { .name = "nt11205-ts", .driver_data = (unsigned long)&nvt_nt11205_ts_data },
+ { .name = "nt36672a-ts", .driver_data = (unsigned long)&nvt_nt36672a_ts_data },
{ }
};
MODULE_DEVICE_TABLE(i2c, nvt_ts_i2c_id);
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c
deleted file mode 100644
index 7b89eb74b9de..000000000000
--- a/drivers/input/touchscreen/pcap_ts.c
+++ /dev/null
@@ -1,252 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Driver for Motorola PCAP2 touchscreen as found in the EZX phone platform.
- *
- * Copyright (C) 2006 Harald Welte <laforge@openezx.org>
- * Copyright (C) 2009 Daniel Ribeiro <drwyrm@gmail.com>
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/pm.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/mfd/ezx-pcap.h>
-
-struct pcap_ts {
- struct pcap_chip *pcap;
- struct input_dev *input;
- struct delayed_work work;
- u16 x, y;
- u16 pressure;
- u8 read_state;
-};
-
-#define SAMPLE_DELAY 20 /* msecs */
-
-#define X_AXIS_MIN 0
-#define X_AXIS_MAX 1023
-#define Y_AXIS_MAX X_AXIS_MAX
-#define Y_AXIS_MIN X_AXIS_MIN
-#define PRESSURE_MAX X_AXIS_MAX
-#define PRESSURE_MIN X_AXIS_MIN
-
-static void pcap_ts_read_xy(void *data, u16 res[2])
-{
- struct pcap_ts *pcap_ts = data;
-
- switch (pcap_ts->read_state) {
- case PCAP_ADC_TS_M_PRESSURE:
- /* pressure reading is unreliable */
- if (res[0] > PRESSURE_MIN && res[0] < PRESSURE_MAX)
- pcap_ts->pressure = res[0];
- pcap_ts->read_state = PCAP_ADC_TS_M_XY;
- schedule_delayed_work(&pcap_ts->work, 0);
- break;
- case PCAP_ADC_TS_M_XY:
- pcap_ts->y = res[0];
- pcap_ts->x = res[1];
- if (pcap_ts->x <= X_AXIS_MIN || pcap_ts->x >= X_AXIS_MAX ||
- pcap_ts->y <= Y_AXIS_MIN || pcap_ts->y >= Y_AXIS_MAX) {
- /* pen has been released */
- input_report_abs(pcap_ts->input, ABS_PRESSURE, 0);
- input_report_key(pcap_ts->input, BTN_TOUCH, 0);
-
- pcap_ts->read_state = PCAP_ADC_TS_M_STANDBY;
- schedule_delayed_work(&pcap_ts->work, 0);
- } else {
- /* pen is touching the screen */
- input_report_abs(pcap_ts->input, ABS_X, pcap_ts->x);
- input_report_abs(pcap_ts->input, ABS_Y, pcap_ts->y);
- input_report_key(pcap_ts->input, BTN_TOUCH, 1);
- input_report_abs(pcap_ts->input, ABS_PRESSURE,
- pcap_ts->pressure);
-
- /* switch back to pressure read mode */
- pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
- schedule_delayed_work(&pcap_ts->work,
- msecs_to_jiffies(SAMPLE_DELAY));
- }
- input_sync(pcap_ts->input);
- break;
- default:
- dev_warn(&pcap_ts->input->dev,
- "pcap_ts: Warning, unhandled read_state %d\n",
- pcap_ts->read_state);
- break;
- }
-}
-
-static void pcap_ts_work(struct work_struct *work)
-{
- struct delayed_work *dw = to_delayed_work(work);
- struct pcap_ts *pcap_ts = container_of(dw, struct pcap_ts, work);
- u8 ch[2];
-
- pcap_set_ts_bits(pcap_ts->pcap,
- pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
-
- if (pcap_ts->read_state == PCAP_ADC_TS_M_STANDBY)
- return;
-
- /* start adc conversion */
- ch[0] = PCAP_ADC_CH_TS_X1;
- ch[1] = PCAP_ADC_CH_TS_Y1;
- pcap_adc_async(pcap_ts->pcap, PCAP_ADC_BANK_1, 0, ch,
- pcap_ts_read_xy, pcap_ts);
-}
-
-static irqreturn_t pcap_ts_event_touch(int pirq, void *data)
-{
- struct pcap_ts *pcap_ts = data;
-
- if (pcap_ts->read_state == PCAP_ADC_TS_M_STANDBY) {
- pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE;
- schedule_delayed_work(&pcap_ts->work, 0);
- }
- return IRQ_HANDLED;
-}
-
-static int pcap_ts_open(struct input_dev *dev)
-{
- struct pcap_ts *pcap_ts = input_get_drvdata(dev);
-
- pcap_ts->read_state = PCAP_ADC_TS_M_STANDBY;
- schedule_delayed_work(&pcap_ts->work, 0);
-
- return 0;
-}
-
-static void pcap_ts_close(struct input_dev *dev)
-{
- struct pcap_ts *pcap_ts = input_get_drvdata(dev);
-
- cancel_delayed_work_sync(&pcap_ts->work);
-
- pcap_ts->read_state = PCAP_ADC_TS_M_NONTS;
- pcap_set_ts_bits(pcap_ts->pcap,
- pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
-}
-
-static int pcap_ts_probe(struct platform_device *pdev)
-{
- struct input_dev *input_dev;
- struct pcap_ts *pcap_ts;
- int err = -ENOMEM;
-
- pcap_ts = kzalloc_obj(*pcap_ts);
- if (!pcap_ts)
- return err;
-
- pcap_ts->pcap = dev_get_drvdata(pdev->dev.parent);
- platform_set_drvdata(pdev, pcap_ts);
-
- input_dev = input_allocate_device();
- if (!input_dev)
- goto fail;
-
- INIT_DELAYED_WORK(&pcap_ts->work, pcap_ts_work);
-
- pcap_ts->read_state = PCAP_ADC_TS_M_NONTS;
- pcap_set_ts_bits(pcap_ts->pcap,
- pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
-
- pcap_ts->input = input_dev;
- input_set_drvdata(input_dev, pcap_ts);
-
- input_dev->name = "pcap-touchscreen";
- input_dev->phys = "pcap_ts/input0";
- input_dev->id.bustype = BUS_HOST;
- input_dev->id.vendor = 0x0001;
- input_dev->id.product = 0x0002;
- input_dev->id.version = 0x0100;
- input_dev->dev.parent = &pdev->dev;
- input_dev->open = pcap_ts_open;
- input_dev->close = pcap_ts_close;
-
- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
- input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
- input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN,
- PRESSURE_MAX, 0, 0);
-
- err = input_register_device(pcap_ts->input);
- if (err)
- goto fail_allocate;
-
- err = request_irq(pcap_to_irq(pcap_ts->pcap, PCAP_IRQ_TS),
- pcap_ts_event_touch, 0, "Touch Screen", pcap_ts);
- if (err)
- goto fail_register;
-
- return 0;
-
-fail_register:
- input_unregister_device(input_dev);
- goto fail;
-fail_allocate:
- input_free_device(input_dev);
-fail:
- kfree(pcap_ts);
-
- return err;
-}
-
-static void pcap_ts_remove(struct platform_device *pdev)
-{
- struct pcap_ts *pcap_ts = platform_get_drvdata(pdev);
-
- free_irq(pcap_to_irq(pcap_ts->pcap, PCAP_IRQ_TS), pcap_ts);
- cancel_delayed_work_sync(&pcap_ts->work);
-
- input_unregister_device(pcap_ts->input);
-
- kfree(pcap_ts);
-}
-
-#ifdef CONFIG_PM
-static int pcap_ts_suspend(struct device *dev)
-{
- struct pcap_ts *pcap_ts = dev_get_drvdata(dev);
-
- pcap_set_ts_bits(pcap_ts->pcap, PCAP_ADC_TS_REF_LOWPWR);
- return 0;
-}
-
-static int pcap_ts_resume(struct device *dev)
-{
- struct pcap_ts *pcap_ts = dev_get_drvdata(dev);
-
- pcap_set_ts_bits(pcap_ts->pcap,
- pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT);
- return 0;
-}
-
-static const struct dev_pm_ops pcap_ts_pm_ops = {
- .suspend = pcap_ts_suspend,
- .resume = pcap_ts_resume,
-};
-#define PCAP_TS_PM_OPS (&pcap_ts_pm_ops)
-#else
-#define PCAP_TS_PM_OPS NULL
-#endif
-
-static struct platform_driver pcap_ts_driver = {
- .probe = pcap_ts_probe,
- .remove = pcap_ts_remove,
- .driver = {
- .name = "pcap-ts",
- .pm = PCAP_TS_PM_OPS,
- },
-};
-module_platform_driver(pcap_ts_driver);
-
-MODULE_DESCRIPTION("Motorola PCAP2 touchscreen driver");
-MODULE_AUTHOR("Daniel Ribeiro / Harald Welte");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pcap_ts");
diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c
index c6b3615c8775..1ca5920846df 100644
--- a/drivers/input/touchscreen/pixcir_i2c_ts.c
+++ b/drivers/input/touchscreen/pixcir_i2c_ts.c
@@ -580,8 +580,8 @@ static const struct pixcir_i2c_chip_data pixcir_tangoc_data = {
};
static const struct i2c_device_id pixcir_i2c_ts_id[] = {
- { "pixcir_ts", (unsigned long) &pixcir_ts_data },
- { "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data },
+ { .name = "pixcir_ts", .driver_data = (unsigned long)&pixcir_ts_data },
+ { .name = "pixcir_tangoc", .driver_data = (unsigned long)&pixcir_tangoc_data },
{ }
};
MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id);
diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c
index f2d33ad86fd2..0256055abcef 100644
--- a/drivers/input/touchscreen/raydium_i2c_ts.c
+++ b/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -1219,8 +1219,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(raydium_i2c_pm_ops,
raydium_i2c_suspend, raydium_i2c_resume);
static const struct i2c_device_id raydium_i2c_id[] = {
- { "raydium_i2c" },
- { "rm32380" },
+ { .name = "raydium_i2c" },
+ { .name = "rm32380" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, raydium_i2c_id);
diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c
index 295d8d75ba32..a5c06b7423c0 100644
--- a/drivers/input/touchscreen/rohm_bu21023.c
+++ b/drivers/input/touchscreen/rohm_bu21023.c
@@ -1144,7 +1144,7 @@ static int rohm_bu21023_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id rohm_bu21023_i2c_id[] = {
- { BU21023_NAME },
+ { .name = BU21023_NAME },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, rohm_bu21023_i2c_id);
diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c
index e1518a75a51b..0f24a9b73063 100644
--- a/drivers/input/touchscreen/s6sy761.c
+++ b/drivers/input/touchscreen/s6sy761.c
@@ -520,7 +520,7 @@ MODULE_DEVICE_TABLE(of, s6sy761_of_match);
#endif
static const struct i2c_device_id s6sy761_id[] = {
- { "s6sy761" },
+ { .name = "s6sy761" },
{ }
};
MODULE_DEVICE_TABLE(i2c, s6sy761_id);
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
index 5ccc96764742..44d7141103f4 100644
--- a/drivers/input/touchscreen/silead.c
+++ b/drivers/input/touchscreen/silead.c
@@ -776,12 +776,12 @@ static int silead_ts_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(silead_ts_pm, silead_ts_suspend, silead_ts_resume);
static const struct i2c_device_id silead_ts_id[] = {
- { "gsl1680" },
- { "gsl1688" },
- { "gsl3670" },
- { "gsl3675" },
- { "gsl3692" },
- { "mssl1680" },
+ { .name = "gsl1680" },
+ { .name = "gsl1688" },
+ { .name = "gsl3670" },
+ { .name = "gsl3675" },
+ { .name = "gsl3692" },
+ { .name = "mssl1680" },
{ }
};
MODULE_DEVICE_TABLE(i2c, silead_ts_id);
diff --git a/drivers/input/touchscreen/sis_i2c.c b/drivers/input/touchscreen/sis_i2c.c
index a625f2ad809d..4fa93cd31ee4 100644
--- a/drivers/input/touchscreen/sis_i2c.c
+++ b/drivers/input/touchscreen/sis_i2c.c
@@ -374,8 +374,8 @@ MODULE_DEVICE_TABLE(of, sis_ts_dt_ids);
#endif
static const struct i2c_device_id sis_ts_id[] = {
- { SIS_I2C_NAME },
- { "9200-ts" },
+ { .name = SIS_I2C_NAME },
+ { .name = "9200-ts" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, sis_ts_id);
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index 9b266927b7fe..c2dcfce5003d 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -453,8 +453,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops,
st1232_ts_suspend, st1232_ts_resume);
static const struct i2c_device_id st1232_ts_id[] = {
- { ST1232_TS_NAME, (unsigned long)&st1232_chip_info },
- { ST1633_TS_NAME, (unsigned long)&st1633_chip_info },
+ { .name = ST1232_TS_NAME, .driver_data = (unsigned long)&st1232_chip_info },
+ { .name = ST1633_TS_NAME, .driver_data = (unsigned long)&st1633_chip_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, st1232_ts_id);
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 8af87d0b6eb6..972687797f82 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -5,6 +5,7 @@
// Copyright (c) 2017 Andi Shyti <andi@etezian.org>
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
@@ -69,20 +70,21 @@
#define STMFTS_MAX_FINGERS 10
#define STMFTS_DEV_NAME "stmfts"
-enum stmfts_regulators {
- STMFTS_REGULATOR_VDD,
- STMFTS_REGULATOR_AVDD,
+static const struct regulator_bulk_data stmfts_supplies[] = {
+ { .supply = "vdd" },
+ { .supply = "avdd" },
};
struct stmfts_data {
struct i2c_client *client;
struct input_dev *input;
+ struct gpio_desc *reset_gpio;
struct led_classdev led_cdev;
struct mutex mutex;
struct touchscreen_properties prop;
- struct regulator_bulk_data regulators[2];
+ struct regulator_bulk_data *supplies;
/*
* Presence of ledvdd will be used also to check
@@ -107,7 +109,7 @@ struct stmfts_data {
};
static int stmfts_brightness_set(struct led_classdev *led_cdev,
- enum led_brightness value)
+ enum led_brightness value)
{
struct stmfts_data *sdata = container_of(led_cdev,
struct stmfts_data, led_cdev);
@@ -250,7 +252,6 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
u8 *event = &sdata->data[i * STMFTS_EVENT_SIZE];
switch (event[0]) {
-
case STMFTS_EV_CONTROLLER_READY:
case STMFTS_EV_SLEEP_OUT_CONTROLLER_READY:
case STMFTS_EV_STATUS:
@@ -263,7 +264,6 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
}
switch (event[0] & STMFTS_MASK_EVENT_ID) {
-
case STMFTS_EV_MULTI_TOUCH_ENTER:
case STMFTS_EV_MULTI_TOUCH_MOTION:
stmfts_report_contact_event(sdata, event);
@@ -285,9 +285,9 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
case STMFTS_EV_ERROR:
dev_warn(&sdata->client->dev,
- "error code: 0x%x%x%x%x%x%x",
- event[6], event[5], event[4],
- event[3], event[2], event[1]);
+ "error code: 0x%x%x%x%x%x%x",
+ event[6], event[5], event[4],
+ event[3], event[2], event[1]);
break;
default:
@@ -404,7 +404,7 @@ static void stmfts_input_close(struct input_dev *dev)
}
static ssize_t stmfts_sysfs_chip_id(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -412,7 +412,8 @@ static ssize_t stmfts_sysfs_chip_id(struct device *dev,
}
static ssize_t stmfts_sysfs_chip_version(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -420,7 +421,7 @@ static ssize_t stmfts_sysfs_chip_version(struct device *dev,
}
static ssize_t stmfts_sysfs_fw_ver(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -428,7 +429,7 @@ static ssize_t stmfts_sysfs_fw_ver(struct device *dev,
}
static ssize_t stmfts_sysfs_config_id(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -436,7 +437,8 @@ static ssize_t stmfts_sysfs_config_id(struct device *dev,
}
static ssize_t stmfts_sysfs_config_version(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -444,7 +446,8 @@ static ssize_t stmfts_sysfs_config_version(struct device *dev,
}
static ssize_t stmfts_sysfs_read_status(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
u8 status[4];
@@ -459,7 +462,8 @@ static ssize_t stmfts_sysfs_read_status(struct device *dev,
}
static ssize_t stmfts_sysfs_hover_enable_read(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
@@ -467,8 +471,8 @@ static ssize_t stmfts_sysfs_hover_enable_read(struct device *dev,
}
static ssize_t stmfts_sysfs_hover_enable_write(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
+ struct device_attribute *attr,
+ const char *buf, size_t len)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
unsigned long value;
@@ -485,8 +489,8 @@ static ssize_t stmfts_sysfs_hover_enable_write(struct device *dev,
if (hover != sdata->hover_enabled) {
if (sdata->running) {
err = i2c_smbus_write_byte(sdata->client,
- value ? STMFTS_SS_HOVER_SENSE_ON :
- STMFTS_SS_HOVER_SENSE_OFF);
+ value ? STMFTS_SS_HOVER_SENSE_ON :
+ STMFTS_SS_HOVER_SENSE_OFF);
if (err)
return err;
}
@@ -518,22 +522,11 @@ static struct attribute *stmfts_sysfs_attrs[] = {
};
ATTRIBUTE_GROUPS(stmfts_sysfs);
-static int stmfts_power_on(struct stmfts_data *sdata)
+static int stmfts_read_system_info(struct stmfts_data *sdata)
{
int err;
u8 reg[8];
- err = regulator_bulk_enable(ARRAY_SIZE(sdata->regulators),
- sdata->regulators);
- if (err)
- return err;
-
- /*
- * The datasheet does not specify the power on time, but considering
- * that the reset time is < 10ms, I sleep 20ms to be sure
- */
- msleep(20);
-
err = i2c_smbus_read_i2c_block_data(sdata->client, STMFTS_READ_INFO,
sizeof(reg), reg);
if (err < 0)
@@ -547,9 +540,21 @@ static int stmfts_power_on(struct stmfts_data *sdata)
sdata->config_id = reg[4];
sdata->config_ver = reg[5];
- enable_irq(sdata->client->irq);
+ return 0;
+}
+static void stmfts_reset(struct stmfts_data *sdata)
+{
+ gpiod_set_value_cansleep(sdata->reset_gpio, 1);
+ msleep(20);
+
+ gpiod_set_value_cansleep(sdata->reset_gpio, 0);
msleep(50);
+}
+
+static int stmfts_configure(struct stmfts_data *sdata)
+{
+ int err;
err = stmfts_command(sdata, STMFTS_SYSTEM_RESET);
if (err)
@@ -575,13 +580,52 @@ static int stmfts_power_on(struct stmfts_data *sdata)
if (err)
return err;
+ return 0;
+}
+
+static int stmfts_power_on(struct stmfts_data *sdata)
+{
+ int err;
+
+ err = regulator_bulk_enable(ARRAY_SIZE(stmfts_supplies),
+ sdata->supplies);
+ if (err)
+ return err;
+
+ /*
+ * The datasheet does not specify the power on time, but considering
+ * that the reset time is < 10ms, I sleep 20ms to be sure
+ */
+ msleep(20);
+
+ if (sdata->reset_gpio)
+ stmfts_reset(sdata);
+
+ err = stmfts_read_system_info(sdata);
+ if (err)
+ goto err_disable_regulators;
+
+ enable_irq(sdata->client->irq);
+
+ msleep(50);
+
+ err = stmfts_configure(sdata);
+ if (err)
+ goto err_disable_irq;
+
/*
* At this point no one is using the touchscreen
* and I don't really care about the return value
*/
- (void) i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN);
+ (void)i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN);
return 0;
+
+err_disable_irq:
+ disable_irq(sdata->client->irq);
+err_disable_regulators:
+ regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies), sdata->supplies);
+ return err;
}
static void stmfts_power_off(void *data)
@@ -589,8 +633,11 @@ static void stmfts_power_off(void *data)
struct stmfts_data *sdata = data;
disable_irq(sdata->client->irq);
- regulator_bulk_disable(ARRAY_SIZE(sdata->regulators),
- sdata->regulators);
+
+ if (sdata->reset_gpio)
+ gpiod_set_value_cansleep(sdata->reset_gpio, 1);
+
+ regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies), sdata->supplies);
}
static int stmfts_enable_led(struct stmfts_data *sdata)
@@ -619,6 +666,7 @@ static int stmfts_enable_led(struct stmfts_data *sdata)
static int stmfts_probe(struct i2c_client *client)
{
+ struct device *dev = &client->dev;
int err;
struct stmfts_data *sdata;
@@ -627,7 +675,7 @@ static int stmfts_probe(struct i2c_client *client)
I2C_FUNC_SMBUS_I2C_BLOCK))
return -ENODEV;
- sdata = devm_kzalloc(&client->dev, sizeof(*sdata), GFP_KERNEL);
+ sdata = devm_kzalloc(dev, sizeof(*sdata), GFP_KERNEL);
if (!sdata)
return -ENOMEM;
@@ -637,15 +685,19 @@ static int stmfts_probe(struct i2c_client *client)
mutex_init(&sdata->mutex);
init_completion(&sdata->cmd_done);
- sdata->regulators[STMFTS_REGULATOR_VDD].supply = "vdd";
- sdata->regulators[STMFTS_REGULATOR_AVDD].supply = "avdd";
- err = devm_regulator_bulk_get(&client->dev,
- ARRAY_SIZE(sdata->regulators),
- sdata->regulators);
+ err = devm_regulator_bulk_get_const(dev,
+ ARRAY_SIZE(stmfts_supplies),
+ stmfts_supplies,
+ &sdata->supplies);
if (err)
return err;
- sdata->input = devm_input_allocate_device(&client->dev);
+ sdata->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(sdata->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(sdata->reset_gpio),
+ "Failed to get GPIO 'reset'\n");
+
+ sdata->input = devm_input_allocate_device(dev);
if (!sdata->input)
return -ENOMEM;
@@ -664,8 +716,7 @@ static int stmfts_probe(struct i2c_client *client)
input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
input_set_abs_params(sdata->input, ABS_DISTANCE, 0, 255, 0, 0);
- sdata->use_key = device_property_read_bool(&client->dev,
- "touch-key-connected");
+ sdata->use_key = device_property_read_bool(dev, "touch-key-connected");
if (sdata->use_key) {
input_set_capability(sdata->input, EV_KEY, KEY_MENU);
input_set_capability(sdata->input, EV_KEY, KEY_BACK);
@@ -685,20 +736,20 @@ static int stmfts_probe(struct i2c_client *client)
* interrupts. To be on the safe side it's better to not enable
* the interrupts during their request.
*/
- err = devm_request_threaded_irq(&client->dev, client->irq,
+ err = devm_request_threaded_irq(dev, client->irq,
NULL, stmfts_irq_handler,
IRQF_ONESHOT | IRQF_NO_AUTOEN,
"stmfts_irq", sdata);
if (err)
return err;
- dev_dbg(&client->dev, "initializing ST-Microelectronics FTS...\n");
+ dev_dbg(dev, "initializing ST-Microelectronics FTS...\n");
err = stmfts_power_on(sdata);
if (err)
return err;
- err = devm_add_action_or_reset(&client->dev, stmfts_power_off, sdata);
+ err = devm_add_action_or_reset(dev, stmfts_power_off, sdata);
if (err)
return err;
@@ -715,13 +766,13 @@ static int stmfts_probe(struct i2c_client *client)
* without LEDs. The ledvdd regulator pointer will be
* used as a flag.
*/
- dev_warn(&client->dev, "unable to use touchkey leds\n");
+ dev_warn(dev, "unable to use touchkey leds\n");
sdata->ledvdd = NULL;
}
}
- pm_runtime_enable(&client->dev);
- device_enable_async_suspend(&client->dev);
+ pm_runtime_enable(dev);
+ device_enable_async_suspend(dev);
return 0;
}
@@ -746,9 +797,10 @@ static int stmfts_runtime_suspend(struct device *dev)
static int stmfts_runtime_resume(struct device *dev)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
+ struct i2c_client *client = sdata->client;
int ret;
- ret = i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_OUT);
+ ret = i2c_smbus_write_byte(client, STMFTS_SLEEP_OUT);
if (ret)
dev_err(dev, "failed to resume device: %d\n", ret);
@@ -785,7 +837,7 @@ MODULE_DEVICE_TABLE(of, stmfts_of_match);
#endif
static const struct i2c_device_id stmfts_id[] = {
- { "stmfts" },
+ { .name = "stmfts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, stmfts_id);
@@ -807,4 +859,4 @@ module_i2c_driver(stmfts_driver);
MODULE_AUTHOR("Andi Shyti <andi.shyti@samsung.com>");
MODULE_DESCRIPTION("STMicroelectronics FTS Touch Screen");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c
index 099fd88e65d8..3ed33378dfcd 100644
--- a/drivers/input/touchscreen/touchwin.c
+++ b/drivers/input/touchscreen/touchwin.c
@@ -63,12 +63,15 @@ static irqreturn_t tw_interrupt(struct serio *serio,
if (data) { /* touch */
tw->touched = 1;
tw->data[tw->idx++] = data;
- /* verify length and that the two Y's are the same */
- if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) {
- input_report_abs(dev, ABS_X, tw->data[0]);
- input_report_abs(dev, ABS_Y, tw->data[1]);
- input_report_key(dev, BTN_TOUCH, 1);
- input_sync(dev);
+ /* a full packet ends the accumulation, valid or not */
+ if (tw->idx == TW_LENGTH) {
+ /* report only if the two Y's are the same */
+ if (tw->data[1] == tw->data[2]) {
+ input_report_abs(dev, ABS_X, tw->data[0]);
+ input_report_abs(dev, ABS_Y, tw->data[1]);
+ input_report_key(dev, BTN_TOUCH, 1);
+ input_sync(dev);
+ }
tw->idx = 0;
}
} else if (tw->touched) { /* untouch */
diff --git a/drivers/input/touchscreen/tsc2004.c b/drivers/input/touchscreen/tsc2004.c
index 787f2caf4f73..130aeb735b65 100644
--- a/drivers/input/touchscreen/tsc2004.c
+++ b/drivers/input/touchscreen/tsc2004.c
@@ -43,7 +43,7 @@ static int tsc2004_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id tsc2004_idtable[] = {
- { "tsc2004" },
+ { .name = "tsc2004" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tsc2004_idtable);
diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c
index 524f14eb3da2..4a775c5df0ea 100644
--- a/drivers/input/touchscreen/tsc2007_core.c
+++ b/drivers/input/touchscreen/tsc2007_core.c
@@ -61,10 +61,8 @@ static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc)
/* turn y+ off, x- on; we'll use formula #1 */
tc->z1 = tsc2007_xfer(tsc, READ_Z1);
- tc->z2 = tsc2007_xfer(tsc, READ_Z2);
-
- /* Prepare for next touch reading - power down ADC, enable PENIRQ */
- tsc2007_xfer(tsc, PWRDOWN);
+ /* Read Z2 and power down ADC after A/D conversion, enable PENIRQ */
+ tc->z2 = tsc2007_xfer(tsc, (TSC2007_POWER_OFF_IRQ_EN | TSC2007_MEASURE_Z2));
}
u32 tsc2007_calculate_resistance(struct tsc2007 *tsc, struct ts_event *tc)
@@ -407,7 +405,7 @@ static int tsc2007_probe(struct i2c_client *client)
}
static const struct i2c_device_id tsc2007_idtable[] = {
- { "tsc2007" },
+ { .name = "tsc2007" },
{ }
};
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c
index fd97a83f5664..dd7c2a8a831b 100644
--- a/drivers/input/touchscreen/wacom_i2c.c
+++ b/drivers/input/touchscreen/wacom_i2c.c
@@ -253,7 +253,7 @@ static int wacom_i2c_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume);
static const struct i2c_device_id wacom_i2c_id[] = {
- { "WAC_I2C_EMR" },
+ { .name = "WAC_I2C_EMR" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wacom_i2c_id);
diff --git a/drivers/input/touchscreen/wacom_w9000.c b/drivers/input/touchscreen/wacom_w9000.c
new file mode 100644
index 000000000000..4a2629a54167
--- /dev/null
+++ b/drivers/input/touchscreen/wacom_w9000.c
@@ -0,0 +1,444 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Wacom W9000-series penabled I2C touchscreen driver
+ *
+ * Copyright (c) 2026 Hendrik Noack <hendrik-noack@gmx.de>
+ *
+ * Partially based on vendor driver:
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/lockdep.h>
+#include <linux/regulator/consumer.h>
+#include <linux/unaligned.h>
+
+/* Some chips have flaky firmware that requires many retries before responding. */
+#define CMD_QUERY_RETRIES 8
+
+/* Message length */
+#define CMD_QUERY_NUM_MAX 9
+#define MSG_COORD_NUM_MAX 12
+
+/* Commands */
+#define CMD_QUERY 0x2a
+
+struct wacom_w9000_variant {
+ const u8 cmd_query_num;
+ const u8 msg_coord_num;
+ const char *name;
+};
+
+struct wacom_w9000_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ const struct wacom_w9000_variant *variant;
+ u16 fw_version;
+
+ struct touchscreen_properties prop;
+ u16 max_pressure;
+
+ struct regulator *regulator;
+
+ struct gpio_desc *flash_mode_gpio;
+ struct gpio_desc *reset_gpio;
+
+ unsigned int irq;
+
+ bool pen_proximity;
+};
+
+static int wacom_w9000_read(struct i2c_client *client, u8 command, u8 len, u8 *data)
+{
+ int error, res;
+ struct i2c_msg msg[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .buf = &command,
+ .len = sizeof(command),
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .buf = data,
+ .len = len,
+ }
+ };
+
+ res = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+ if (res != ARRAY_SIZE(msg)) {
+ error = res < 0 ? res : -EIO;
+ dev_err(&client->dev, "%s: i2c transfer failed: %d (%d)\n",
+ __func__, error, res);
+ return error;
+ }
+
+ return 0;
+}
+
+static int wacom_w9000_query(struct wacom_w9000_data *wacom_data)
+{
+ struct i2c_client *client = wacom_data->client;
+ struct device *dev = &wacom_data->client->dev;
+ u8 data[CMD_QUERY_NUM_MAX];
+ int retry;
+ int error;
+
+ for (retry = 0; retry < CMD_QUERY_RETRIES; retry++) {
+ error = wacom_w9000_read(client, CMD_QUERY,
+ wacom_data->variant->cmd_query_num,
+ data);
+ if (!error && data[0] == 0x0f)
+ break;
+ }
+
+ if (error)
+ return error;
+
+ if (data[0] != 0x0f)
+ return -EIO;
+
+ dev_dbg(dev, "query: %*ph, %d\n",
+ wacom_data->variant->cmd_query_num, data, retry);
+
+ wacom_data->prop.max_x = get_unaligned_be16(&data[1]);
+ wacom_data->prop.max_y = get_unaligned_be16(&data[3]);
+ wacom_data->max_pressure = get_unaligned_be16(&data[5]);
+ wacom_data->fw_version = get_unaligned_be16(&data[7]);
+
+ dev_dbg(dev, "max_x:%d, max_y:%d, max_pressure:%d, fw:%#x\n",
+ wacom_data->prop.max_x, wacom_data->prop.max_y,
+ wacom_data->max_pressure, wacom_data->fw_version);
+
+ return 0;
+}
+
+static int wacom_w9000_power_on(struct wacom_w9000_data *wacom_data)
+{
+ int error;
+
+ lockdep_assert_held(&wacom_data->input_dev->mutex);
+
+ error = regulator_enable(wacom_data->regulator);
+ if (error) {
+ dev_err(&wacom_data->client->dev, "Failed to enable regulators: %d\n", error);
+ return error;
+ }
+
+ msleep(200);
+
+ gpiod_set_value_cansleep(wacom_data->reset_gpio, 0);
+ enable_irq(wacom_data->irq);
+
+ return 0;
+}
+
+static int wacom_w9000_power_off(struct wacom_w9000_data *wacom_data)
+{
+ lockdep_assert_held(&wacom_data->input_dev->mutex);
+
+ disable_irq(wacom_data->irq);
+ gpiod_set_value_cansleep(wacom_data->reset_gpio, 1);
+ regulator_disable(wacom_data->regulator);
+
+ return 0;
+}
+
+static void wacom_w9000_coord(struct wacom_w9000_data *wacom_data)
+{
+ struct i2c_client *client = wacom_data->client;
+ struct device *dev = &wacom_data->client->dev;
+ u8 data[MSG_COORD_NUM_MAX];
+ bool touch, rubber, side_button;
+ u16 x, y, pressure;
+ u8 distance = 0;
+ int error;
+
+ error = i2c_master_recv(client, data, wacom_data->variant->msg_coord_num);
+ if (error != wacom_data->variant->msg_coord_num) {
+ if (error >= 0)
+ error = -EIO;
+ dev_err_ratelimited(dev, "%s: i2c receive failed (%d)\n", __func__, error);
+ return;
+ }
+
+ dev_dbg(dev, "data: %*ph\n", wacom_data->variant->msg_coord_num, data);
+
+ if (data[0] & BIT(7)) {
+ wacom_data->pen_proximity = true;
+
+ touch = !!(data[0] & BIT(4));
+ side_button = !!(data[0] & BIT(5));
+ rubber = !!(data[0] & BIT(6));
+
+ x = get_unaligned_be16(&data[1]);
+ y = get_unaligned_be16(&data[3]);
+ pressure = get_unaligned_be16(&data[5]);
+
+ if (wacom_data->variant->msg_coord_num > 7)
+ distance = data[7];
+
+ if (x > wacom_data->prop.max_x || y > wacom_data->prop.max_y) {
+ dev_warn_ratelimited(dev, "Coordinates out of range x=%d, y=%d\n", x, y);
+ return;
+ }
+
+ if (pressure > wacom_data->max_pressure) {
+ dev_warn_ratelimited(dev, "Pressure out of range %d\n", pressure);
+ return;
+ }
+
+ touchscreen_report_pos(wacom_data->input_dev, &wacom_data->prop, x, y, false);
+ input_report_abs(wacom_data->input_dev, ABS_PRESSURE, pressure);
+
+ if (wacom_data->variant->msg_coord_num > 7)
+ input_report_abs(wacom_data->input_dev, ABS_DISTANCE, distance);
+
+ input_report_key(wacom_data->input_dev, BTN_STYLUS, side_button);
+ input_report_key(wacom_data->input_dev, BTN_TOUCH, touch);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_PEN, !rubber);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_RUBBER, rubber);
+ input_sync(wacom_data->input_dev);
+ } else if (wacom_data->pen_proximity) {
+ input_report_abs(wacom_data->input_dev, ABS_PRESSURE, 0);
+
+ if (wacom_data->variant->msg_coord_num > 7)
+ input_report_abs(wacom_data->input_dev, ABS_DISTANCE, 255);
+
+ input_report_key(wacom_data->input_dev, BTN_STYLUS, 0);
+ input_report_key(wacom_data->input_dev, BTN_TOUCH, 0);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_PEN, 0);
+ input_report_key(wacom_data->input_dev, BTN_TOOL_RUBBER, 0);
+ input_sync(wacom_data->input_dev);
+
+ wacom_data->pen_proximity = false;
+ }
+}
+
+static irqreturn_t wacom_w9000_interrupt(int irq, void *dev_id)
+{
+ struct wacom_w9000_data *wacom_data = dev_id;
+
+ wacom_w9000_coord(wacom_data);
+
+ return IRQ_HANDLED;
+}
+
+static int wacom_w9000_open(struct input_dev *dev)
+{
+ struct wacom_w9000_data *wacom_data = input_get_drvdata(dev);
+
+ return wacom_w9000_power_on(wacom_data);
+}
+
+static void wacom_w9000_close(struct input_dev *dev)
+{
+ struct wacom_w9000_data *wacom_data = input_get_drvdata(dev);
+
+ wacom_w9000_power_off(wacom_data);
+}
+
+static int wacom_w9000_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct wacom_w9000_data *wacom_data;
+ struct input_dev *input_dev;
+ int error;
+ u32 val;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(dev, "i2c_check_functionality error\n");
+ return -EIO;
+ }
+
+ wacom_data = devm_kzalloc(dev, sizeof(*wacom_data), GFP_KERNEL);
+ if (!wacom_data)
+ return -ENOMEM;
+
+ wacom_data->variant = i2c_get_match_data(client);
+ if (!wacom_data->variant) {
+ dev_err(dev, "No i2c match_data available\n");
+ return -EINVAL;
+ }
+
+ if (wacom_data->variant->cmd_query_num > CMD_QUERY_NUM_MAX ||
+ wacom_data->variant->msg_coord_num > MSG_COORD_NUM_MAX) {
+ dev_err(dev, "Length of message for %s exceeds the maximum\n",
+ wacom_data->variant->name);
+ return -EINVAL;
+ }
+
+ if (wacom_data->variant->msg_coord_num < 7) {
+ dev_err(dev, "Length of coordinates message for %s too short\n",
+ wacom_data->variant->name);
+ return -EINVAL;
+ }
+
+ wacom_data->client = client;
+ wacom_data->irq = client->irq;
+ i2c_set_clientdata(client, wacom_data);
+
+ wacom_data->regulator = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(wacom_data->regulator))
+ return dev_err_probe(dev, PTR_ERR(wacom_data->regulator),
+ "Failed to get regulators\n");
+
+ wacom_data->flash_mode_gpio = devm_gpiod_get_optional(dev, "flash-mode", GPIOD_OUT_LOW);
+ if (IS_ERR(wacom_data->flash_mode_gpio))
+ return dev_err_probe(dev, PTR_ERR(wacom_data->flash_mode_gpio),
+ "Failed to get flash-mode gpio\n");
+
+ wacom_data->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(wacom_data->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(wacom_data->reset_gpio),
+ "Failed to get reset gpio\n");
+
+ error = regulator_enable(wacom_data->regulator);
+ if (error)
+ return dev_err_probe(dev, error, "Failed to enable regulators\n");
+
+ msleep(200);
+
+ gpiod_set_value_cansleep(wacom_data->reset_gpio, 0);
+
+ error = wacom_w9000_query(wacom_data);
+
+ gpiod_set_value_cansleep(wacom_data->reset_gpio, 1);
+ regulator_disable(wacom_data->regulator);
+
+ if (error)
+ return dev_err_probe(dev, error, "Failed to query\n");
+
+ error = devm_request_threaded_irq(dev, wacom_data->irq, NULL, wacom_w9000_interrupt,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN, client->name, wacom_data);
+ if (error)
+ return dev_err_probe(dev, error, "Failed to register interrupt\n");
+
+ input_dev = devm_input_allocate_device(dev);
+ if (!input_dev)
+ return -ENOMEM;
+
+ wacom_data->input_dev = input_dev;
+ input_set_drvdata(input_dev, wacom_data);
+
+ input_dev->name = wacom_data->variant->name;
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->id.vendor = 0x56a;
+ input_dev->id.version = wacom_data->fw_version;
+ input_dev->open = wacom_w9000_open;
+ input_dev->close = wacom_w9000_close;
+
+ input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
+ input_set_capability(input_dev, EV_KEY, BTN_TOOL_PEN);
+ input_set_capability(input_dev, EV_KEY, BTN_TOOL_RUBBER);
+ input_set_capability(input_dev, EV_KEY, BTN_STYLUS);
+
+ input_set_abs_params(input_dev, ABS_X, 0, wacom_data->prop.max_x, 4, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, wacom_data->prop.max_y, 4, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_data->max_pressure, 0, 0);
+
+ if (wacom_data->variant->msg_coord_num > 7)
+ input_set_abs_params(input_dev, ABS_DISTANCE, 0, 255, 0, 0);
+
+ touchscreen_parse_properties(input_dev, false, &wacom_data->prop);
+
+ dev_info(dev, "%s size X%uY%u\n", wacom_data->variant->name,
+ wacom_data->prop.max_x, wacom_data->prop.max_y);
+
+ error = device_property_read_u32(dev, "touchscreen-x-mm", &val);
+ if (!error && val)
+ input_abs_set_res(input_dev, wacom_data->prop.swap_x_y ? ABS_Y : ABS_X,
+ wacom_data->prop.max_x / val);
+ error = device_property_read_u32(dev, "touchscreen-y-mm", &val);
+ if (!error && val)
+ input_abs_set_res(input_dev, wacom_data->prop.swap_x_y ? ABS_X : ABS_Y,
+ wacom_data->prop.max_y / val);
+
+ error = input_register_device(wacom_data->input_dev);
+ if (error)
+ return dev_err_probe(dev, error, "Failed to register input device\n");
+
+ return 0;
+}
+
+static int wacom_w9000_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
+
+ guard(mutex)(&wacom_data->input_dev->mutex);
+
+ if (input_device_enabled(wacom_data->input_dev))
+ return wacom_w9000_power_off(wacom_data);
+
+ return 0;
+}
+
+static int wacom_w9000_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct wacom_w9000_data *wacom_data = i2c_get_clientdata(client);
+
+ guard(mutex)(&wacom_data->input_dev->mutex);
+
+ if (input_device_enabled(wacom_data->input_dev))
+ return wacom_w9000_power_on(wacom_data);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(wacom_w9000_pm, wacom_w9000_suspend, wacom_w9000_resume);
+
+static const struct wacom_w9000_variant w9002 = {
+ .cmd_query_num = 9,
+ .msg_coord_num = 7,
+ .name = "Wacom W9002 Digitizer",
+};
+
+static const struct wacom_w9000_variant w9007a_lt03 = {
+ .cmd_query_num = 9,
+ .msg_coord_num = 8,
+ .name = "Wacom W9007A LT03 Digitizer",
+};
+
+static const struct wacom_w9000_variant w9007a_v1 = {
+ .cmd_query_num = 9,
+ .msg_coord_num = 12,
+ .name = "Wacom W9007A V1 Digitizer",
+};
+
+static const struct of_device_id wacom_w9000_of_match[] = {
+ { .compatible = "wacom,w9002", .data = &w9002 },
+ { .compatible = "wacom,w9007a-lt03", .data = &w9007a_lt03, },
+ { .compatible = "wacom,w9007a-v1", .data = &w9007a_v1, },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wacom_w9000_of_match);
+
+static const struct i2c_device_id wacom_w9000_id[] = {
+ { .name = "w9002", .driver_data = (kernel_ulong_t)&w9002 },
+ { .name = "w9007a-lt03", .driver_data = (kernel_ulong_t)&w9007a_lt03 },
+ { .name = "w9007a-v1", .driver_data = (kernel_ulong_t)&w9007a_v1 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wacom_w9000_id);
+
+static struct i2c_driver wacom_w9000_driver = {
+ .driver = {
+ .name = "wacom_w9000",
+ .of_match_table = wacom_w9000_of_match,
+ .pm = pm_sleep_ptr(&wacom_w9000_pm),
+ },
+ .probe = wacom_w9000_probe,
+ .id_table = wacom_w9000_id,
+};
+module_i2c_driver(wacom_w9000_driver);
+
+MODULE_AUTHOR("Hendrik Noack <hendrik-noack@gmx.de>");
+MODULE_DESCRIPTION("Wacom W9000-series penabled touchscreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c
index bdaabb14dc8c..1af309252092 100644
--- a/drivers/input/touchscreen/wdt87xx_i2c.c
+++ b/drivers/input/touchscreen/wdt87xx_i2c.c
@@ -1140,7 +1140,7 @@ static int wdt87xx_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(wdt87xx_pm_ops, wdt87xx_suspend, wdt87xx_resume);
static const struct i2c_device_id wdt87xx_dev_id[] = {
- { WDT87XX_NAME },
+ { .name = WDT87XX_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, wdt87xx_dev_id);
diff --git a/drivers/input/touchscreen/zet6223.c b/drivers/input/touchscreen/zet6223.c
index 943634ba9cd9..a341142f3708 100644
--- a/drivers/input/touchscreen/zet6223.c
+++ b/drivers/input/touchscreen/zet6223.c
@@ -236,7 +236,7 @@ static const struct of_device_id zet6223_of_match[] = {
MODULE_DEVICE_TABLE(of, zet6223_of_match);
static const struct i2c_device_id zet6223_id[] = {
- { "zet6223" },
+ { .name = "zet6223" },
{ }
};
MODULE_DEVICE_TABLE(i2c, zet6223_id);
diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c
index a360749fa076..4bfc9560bd6c 100644
--- a/drivers/input/touchscreen/zforce_ts.c
+++ b/drivers/input/touchscreen/zforce_ts.c
@@ -831,7 +831,7 @@ static int zforce_probe(struct i2c_client *client)
}
static const struct i2c_device_id zforce_idtable[] = {
- { "zforce-ts" },
+ { .name = "zforce-ts" },
{ }
};
MODULE_DEVICE_TABLE(i2c, zforce_idtable);