diff options
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/misc/adxl34x.c | 2 | ||||
-rw-r--r-- | drivers/input/mouse/elan_i2c_core.c | 11 | ||||
-rw-r--r-- | drivers/input/mouse/gpio_mouse.c | 206 | ||||
-rw-r--r-- | drivers/input/rmi4/rmi_f54.c | 2 | ||||
-rw-r--r-- | drivers/input/serio/sa1111ps2.c | 69 | ||||
-rw-r--r-- | drivers/input/touchscreen/Kconfig | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/ad7879.c | 13 | ||||
-rw-r--r-- | drivers/input/touchscreen/edt-ft5x06.c | 173 | ||||
-rw-r--r-- | drivers/input/touchscreen/elants_i2c.c | 19 | ||||
-rw-r--r-- | drivers/input/touchscreen/melfas_mip4.c | 17 | ||||
-rw-r--r-- | drivers/input/touchscreen/raydium_i2c_ts.c | 18 | ||||
-rw-r--r-- | drivers/input/touchscreen/rohm_bu21023.c | 17 | ||||
-rw-r--r-- | drivers/input/touchscreen/stmfts.c | 4 | ||||
-rw-r--r-- | drivers/input/touchscreen/wdt87xx_i2c.c | 10 |
14 files changed, 289 insertions, 274 deletions
diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index 2b2d02f408bb..a3e79bf5a04b 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -796,7 +796,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, if (pdata->watermark) { ac->int_mask |= WATERMARK; - if (!FIFO_MODE(pdata->fifo_mode)) + if (FIFO_MODE(pdata->fifo_mode) == FIFO_BYPASS) ac->pdata.fifo_mode |= FIFO_STREAM; } else { ac->int_mask |= DATA_READY; diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 0e761d079dc4..c33f2cce6ba9 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -26,6 +26,7 @@ #include <linux/init.h> #include <linux/input/mt.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/kernel.h> @@ -1141,10 +1142,13 @@ static int elan_probe(struct i2c_client *client, return error; /* - * Systems using device tree should set up interrupt via DTS, - * the rest will use the default falling edge interrupts. + * Platform code (ACPI, DTS) should normally set up interrupt + * for us, but in case it did not let's fall back to using falling + * edge to be compatible with older Chromebooks. */ - irqflags = dev->of_node ? 0 : IRQF_TRIGGER_FALLING; + irqflags = irq_get_trigger_type(client->irq); + if (!irqflags) + irqflags = IRQF_TRIGGER_FALLING; error = devm_request_threaded_irq(dev, client->irq, NULL, elan_isr, irqflags | IRQF_ONESHOT, @@ -1255,7 +1259,6 @@ static const struct acpi_device_id elan_acpi_id[] = { { "ELAN0602", 0 }, { "ELAN0605", 0 }, { "ELAN0608", 0 }, - { "ELAN0605", 0 }, { "ELAN0609", 0 }, { "ELAN060B", 0 }, { "ELAN1000", 0 }, diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index ced07391304b..a26d8be6f795 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -2,6 +2,7 @@ * Driver for simulating a mouse on GPIO lines. * * Copyright (C) 2007 Atmel Corporation + * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -11,9 +12,35 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/input-polldev.h> -#include <linux/gpio.h> -#include <linux/gpio_mouse.h> - +#include <linux/gpio/consumer.h> +#include <linux/property.h> +#include <linux/of.h> + +/** + * struct gpio_mouse + * @scan_ms: the scan interval in milliseconds. + * @up: GPIO line for up value. + * @down: GPIO line for down value. + * @left: GPIO line for left value. + * @right: GPIO line for right value. + * @bleft: GPIO line for left button. + * @bmiddle: GPIO line for middle button. + * @bright: GPIO line for right button. + * + * This struct must be added to the platform_device in the board code. + * It is used by the gpio_mouse driver to setup GPIO lines and to + * calculate mouse movement. + */ +struct gpio_mouse { + u32 scan_ms; + struct gpio_desc *up; + struct gpio_desc *down; + struct gpio_desc *left; + struct gpio_desc *right; + struct gpio_desc *bleft; + struct gpio_desc *bmiddle; + struct gpio_desc *bright; +}; /* * Timer function which is run every scan_ms ms when the device is opened. @@ -21,24 +48,22 @@ */ static void gpio_mouse_scan(struct input_polled_dev *dev) { - struct gpio_mouse_platform_data *gpio = dev->private; + struct gpio_mouse *gpio = dev->private; struct input_dev *input = dev->input; int x, y; - if (gpio->bleft >= 0) + if (gpio->bleft) input_report_key(input, BTN_LEFT, - gpio_get_value(gpio->bleft) ^ gpio->polarity); - if (gpio->bmiddle >= 0) + gpiod_get_value(gpio->bleft)); + if (gpio->bmiddle) input_report_key(input, BTN_MIDDLE, - gpio_get_value(gpio->bmiddle) ^ gpio->polarity); - if (gpio->bright >= 0) + gpiod_get_value(gpio->bmiddle)); + if (gpio->bright) input_report_key(input, BTN_RIGHT, - gpio_get_value(gpio->bright) ^ gpio->polarity); + gpiod_get_value(gpio->bright)); - x = (gpio_get_value(gpio->right) ^ gpio->polarity) - - (gpio_get_value(gpio->left) ^ gpio->polarity); - y = (gpio_get_value(gpio->down) ^ gpio->polarity) - - (gpio_get_value(gpio->up) ^ gpio->polarity); + x = gpiod_get_value(gpio->right) - gpiod_get_value(gpio->left); + y = gpiod_get_value(gpio->down) - gpiod_get_value(gpio->up); input_report_rel(input, REL_X, x); input_report_rel(input, REL_Y, y); @@ -47,65 +72,61 @@ static void gpio_mouse_scan(struct input_polled_dev *dev) static int gpio_mouse_probe(struct platform_device *pdev) { - struct gpio_mouse_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct device *dev = &pdev->dev; + struct gpio_mouse *gmouse; struct input_polled_dev *input_poll; struct input_dev *input; - int pin, i; - int error; - - if (!pdata) { - dev_err(&pdev->dev, "no platform data\n"); - error = -ENXIO; - goto out; - } - - if (pdata->scan_ms < 0) { - dev_err(&pdev->dev, "invalid scan time\n"); - error = -EINVAL; - goto out; - } - - for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) { - pin = pdata->pins[i]; - - if (pin < 0) { - - if (i <= GPIO_MOUSE_PIN_RIGHT) { - /* Mouse direction is required. */ - dev_err(&pdev->dev, - "missing GPIO for directions\n"); - error = -EINVAL; - goto out_free_gpios; - } - - if (i == GPIO_MOUSE_PIN_BLEFT) - dev_dbg(&pdev->dev, "no left button defined\n"); - - } else { - error = gpio_request(pin, "gpio_mouse"); - if (error) { - dev_err(&pdev->dev, "fail %d pin (%d idx)\n", - pin, i); - goto out_free_gpios; - } - - gpio_direction_input(pin); - } + int ret; + + gmouse = devm_kzalloc(dev, sizeof(*gmouse), GFP_KERNEL); + if (!gmouse) + return -ENOMEM; + + /* Assign some default scanning time */ + ret = device_property_read_u32(dev, "scan-interval-ms", + &gmouse->scan_ms); + if (ret || gmouse->scan_ms == 0) { + dev_warn(dev, "invalid scan time, set to 50 ms\n"); + gmouse->scan_ms = 50; } - input_poll = input_allocate_polled_device(); + gmouse->up = devm_gpiod_get(dev, "up", GPIOD_IN); + if (IS_ERR(gmouse->up)) + return PTR_ERR(gmouse->up); + gmouse->down = devm_gpiod_get(dev, "down", GPIOD_IN); + if (IS_ERR(gmouse->down)) + return PTR_ERR(gmouse->down); + gmouse->left = devm_gpiod_get(dev, "left", GPIOD_IN); + if (IS_ERR(gmouse->left)) + return PTR_ERR(gmouse->left); + gmouse->right = devm_gpiod_get(dev, "right", GPIOD_IN); + if (IS_ERR(gmouse->right)) + return PTR_ERR(gmouse->right); + + gmouse->bleft = devm_gpiod_get_optional(dev, "button-left", GPIOD_IN); + if (IS_ERR(gmouse->bleft)) + return PTR_ERR(gmouse->bleft); + gmouse->bmiddle = devm_gpiod_get_optional(dev, "button-middle", + GPIOD_IN); + if (IS_ERR(gmouse->bmiddle)) + return PTR_ERR(gmouse->bmiddle); + gmouse->bright = devm_gpiod_get_optional(dev, "button-right", + GPIOD_IN); + if (IS_ERR(gmouse->bright)) + return PTR_ERR(gmouse->bright); + + input_poll = devm_input_allocate_polled_device(dev); if (!input_poll) { - dev_err(&pdev->dev, "not enough memory for input device\n"); - error = -ENOMEM; - goto out_free_gpios; + dev_err(dev, "not enough memory for input device\n"); + return -ENOMEM; } platform_set_drvdata(pdev, input_poll); /* set input-polldev handlers */ - input_poll->private = pdata; + input_poll->private = gmouse; input_poll->poll = gpio_mouse_scan; - input_poll->poll_interval = pdata->scan_ms; + input_poll->poll_interval = gmouse->scan_ms; input = input_poll->input; input->name = pdev->name; @@ -114,63 +135,39 @@ static int gpio_mouse_probe(struct platform_device *pdev) input_set_capability(input, EV_REL, REL_X); input_set_capability(input, EV_REL, REL_Y); - if (pdata->bleft >= 0) + if (gmouse->bleft) input_set_capability(input, EV_KEY, BTN_LEFT); - if (pdata->bmiddle >= 0) + if (gmouse->bmiddle) input_set_capability(input, EV_KEY, BTN_MIDDLE); - if (pdata->bright >= 0) + if (gmouse->bright) input_set_capability(input, EV_KEY, BTN_RIGHT); - error = input_register_polled_device(input_poll); - if (error) { - dev_err(&pdev->dev, "could not register input device\n"); - goto out_free_polldev; + ret = input_register_polled_device(input_poll); + if (ret) { + dev_err(dev, "could not register input device\n"); + return ret; } - dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n", - pdata->scan_ms, - pdata->bleft < 0 ? "" : "left ", - pdata->bmiddle < 0 ? "" : "middle ", - pdata->bright < 0 ? "" : "right"); + dev_dbg(dev, "%d ms scan time, buttons: %s%s%s\n", + gmouse->scan_ms, + gmouse->bleft ? "" : "left ", + gmouse->bmiddle ? "" : "middle ", + gmouse->bright ? "" : "right"); return 0; - - out_free_polldev: - input_free_polled_device(input_poll); - - out_free_gpios: - while (--i >= 0) { - pin = pdata->pins[i]; - if (pin) - gpio_free(pin); - } - out: - return error; } -static int gpio_mouse_remove(struct platform_device *pdev) -{ - struct input_polled_dev *input = platform_get_drvdata(pdev); - struct gpio_mouse_platform_data *pdata = input->private; - int pin, i; - - input_unregister_polled_device(input); - input_free_polled_device(input); - - for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) { - pin = pdata->pins[i]; - if (pin >= 0) - gpio_free(pin); - } - - return 0; -} +static const struct of_device_id gpio_mouse_of_match[] = { + { .compatible = "gpio-mouse", }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpio_mouse_of_match); static struct platform_driver gpio_mouse_device_driver = { .probe = gpio_mouse_probe, - .remove = gpio_mouse_remove, .driver = { .name = "gpio_mouse", + .of_match_table = gpio_mouse_of_match, } }; module_platform_driver(gpio_mouse_device_driver); @@ -179,4 +176,3 @@ MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>"); MODULE_DESCRIPTION("GPIO mouse driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */ - diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c index f5206e2c767e..5343f2c08f15 100644 --- a/drivers/input/rmi4/rmi_f54.c +++ b/drivers/input/rmi4/rmi_f54.c @@ -73,7 +73,7 @@ enum rmi_f54_report_type { F54_MAX_REPORT_TYPE, }; -const char *rmi_f54_report_type_names[] = { +static const char * const rmi_f54_report_type_names[] = { [F54_REPORT_NONE] = "Unknown", [F54_8BIT_IMAGE] = "Normalized 8-Bit Image", [F54_16BIT_IMAGE] = "Normalized 16-Bit Image", diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index b3e688911fd9..f9e5c793f4f0 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -47,6 +47,8 @@ struct ps2if { struct serio *io; struct sa1111_dev *dev; void __iomem *base; + int rx_irq; + int tx_irq; unsigned int open; spinlock_t lock; unsigned int head; @@ -64,22 +66,22 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id) struct ps2if *ps2if = dev_id; unsigned int scancode, flag, status; - status = sa1111_readl(ps2if->base + PS2STAT); + status = readl_relaxed(ps2if->base + PS2STAT); while (status & PS2STAT_RXF) { if (status & PS2STAT_STP) - sa1111_writel(PS2STAT_STP, ps2if->base + PS2STAT); + writel_relaxed(PS2STAT_STP, ps2if->base + PS2STAT); flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) | (status & PS2STAT_RXP ? 0 : SERIO_PARITY); - scancode = sa1111_readl(ps2if->base + PS2DATA) & 0xff; + scancode = readl_relaxed(ps2if->base + PS2DATA) & 0xff; if (hweight8(scancode) & 1) flag ^= SERIO_PARITY; serio_interrupt(ps2if->io, scancode, flag); - status = sa1111_readl(ps2if->base + PS2STAT); + status = readl_relaxed(ps2if->base + PS2STAT); } return IRQ_HANDLED; @@ -94,12 +96,12 @@ static irqreturn_t ps2_txint(int irq, void *dev_id) unsigned int status; spin_lock(&ps2if->lock); - status = sa1111_readl(ps2if->base + PS2STAT); + status = readl_relaxed(ps2if->base + PS2STAT); if (ps2if->head == ps2if->tail) { disable_irq_nosync(irq); /* done */ } else if (status & PS2STAT_TXE) { - sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + PS2DATA); + writel_relaxed(ps2if->buf[ps2if->tail], ps2if->base + PS2DATA); ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1); } spin_unlock(&ps2if->lock); @@ -122,11 +124,11 @@ static int ps2_write(struct serio *io, unsigned char val) /* * If the TX register is empty, we can go straight out. */ - if (sa1111_readl(ps2if->base + PS2STAT) & PS2STAT_TXE) { - sa1111_writel(val, ps2if->base + PS2DATA); + if (readl_relaxed(ps2if->base + PS2STAT) & PS2STAT_TXE) { + writel_relaxed(val, ps2if->base + PS2DATA); } else { if (ps2if->head == ps2if->tail) - enable_irq(ps2if->dev->irq[1]); + enable_irq(ps2if->tx_irq); head = (ps2if->head + 1) & (sizeof(ps2if->buf) - 1); if (head != ps2if->tail) { ps2if->buf[ps2if->head] = val; @@ -147,30 +149,30 @@ static int ps2_open(struct serio *io) if (ret) return ret; - ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0, + ret = request_irq(ps2if->rx_irq, ps2_rxint, 0, SA1111_DRIVER_NAME(ps2if->dev), ps2if); if (ret) { printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n", - ps2if->dev->irq[0], ret); + ps2if->rx_irq, ret); sa1111_disable_device(ps2if->dev); return ret; } - ret = request_irq(ps2if->dev->irq[1], ps2_txint, 0, + ret = request_irq(ps2if->tx_irq, ps2_txint, 0, SA1111_DRIVER_NAME(ps2if->dev), ps2if); if (ret) { printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n", - ps2if->dev->irq[1], ret); - free_irq(ps2if->dev->irq[0], ps2if); + ps2if->tx_irq, ret); + free_irq(ps2if->rx_irq, ps2if); sa1111_disable_device(ps2if->dev); return ret; } ps2if->open = 1; - enable_irq_wake(ps2if->dev->irq[0]); + enable_irq_wake(ps2if->rx_irq); - sa1111_writel(PS2CR_ENA, ps2if->base + PS2CR); + writel_relaxed(PS2CR_ENA, ps2if->base + PS2CR); return 0; } @@ -178,14 +180,14 @@ static void ps2_close(struct serio *io) { struct ps2if *ps2if = io->port_data; - sa1111_writel(0, ps2if->base + PS2CR); + writel_relaxed(0, ps2if->base + PS2CR); - disable_irq_wake(ps2if->dev->irq[0]); + disable_irq_wake(ps2if->rx_irq); ps2if->open = 0; - free_irq(ps2if->dev->irq[1], ps2if); - free_irq(ps2if->dev->irq[0], ps2if); + free_irq(ps2if->tx_irq, ps2if); + free_irq(ps2if->rx_irq, ps2if); sa1111_disable_device(ps2if->dev); } @@ -198,7 +200,7 @@ static void ps2_clear_input(struct ps2if *ps2if) int maxread = 100; while (maxread--) { - if ((sa1111_readl(ps2if->base + PS2DATA) & 0xff) == 0xff) + if ((readl_relaxed(ps2if->base + PS2DATA) & 0xff) == 0xff) break; } } @@ -208,11 +210,11 @@ static unsigned int ps2_test_one(struct ps2if *ps2if, { unsigned int val; - sa1111_writel(PS2CR_ENA | mask, ps2if->base + PS2CR); + writel_relaxed(PS2CR_ENA | mask, ps2if->base + PS2CR); - udelay(2); + udelay(10); - val = sa1111_readl(ps2if->base + PS2STAT); + val = readl_relaxed(ps2if->base + PS2STAT); return val & (PS2STAT_KBC | PS2STAT_KBD); } @@ -243,7 +245,7 @@ static int ps2_test(struct ps2if *ps2if) ret = -ENODEV; } - sa1111_writel(0, ps2if->base + PS2CR); + writel_relaxed(0, ps2if->base + PS2CR); return ret; } @@ -264,7 +266,6 @@ static int ps2_probe(struct sa1111_dev *dev) goto free; } - serio->id.type = SERIO_8042; serio->write = ps2_write; serio->open = ps2_open; @@ -279,6 +280,18 @@ static int ps2_probe(struct sa1111_dev *dev) spin_lock_init(&ps2if->lock); + ps2if->rx_irq = sa1111_get_irq(dev, 0); + if (ps2if->rx_irq <= 0) { + ret = ps2if->rx_irq ? : -ENXIO; + goto free; + } + + ps2if->tx_irq = sa1111_get_irq(dev, 1); + if (ps2if->tx_irq <= 0) { + ret = ps2if->tx_irq ? : -ENXIO; + goto free; + } + /* * Request the physical region for this PS2 port. */ @@ -297,8 +310,8 @@ static int ps2_probe(struct sa1111_dev *dev) sa1111_enable_device(ps2if->dev); /* Incoming clock is 8MHz */ - sa1111_writel(0, ps2if->base + PS2CLKDIV); - sa1111_writel(127, ps2if->base + PS2PRECNT); + writel_relaxed(0, ps2if->base + PS2CLKDIV); + writel_relaxed(127, ps2if->base + PS2PRECNT); /* * Flush any pending input. diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 64b30fe273fd..16cadc149bbc 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -949,7 +949,7 @@ config TOUCHSCREEN_USB_NEXIO config TOUCHSCREEN_USB_EASYTOUCH default y - bool "EasyTouch USB Touch controller device support" if EMBEDDED + bool "EasyTouch USB Touch controller device support" if EXPERT depends on TOUCHSCREEN_USB_COMPOSITE help Say Y here if you have an EasyTouch USB Touch controller. diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index 196028c45210..7d74a0ae2c94 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -524,13 +524,6 @@ static int ad7879_parse_dt(struct device *dev, struct ad7879 *ts) return 0; } -static void ad7879_cleanup_sysfs(void *_ts) -{ - struct ad7879 *ts = _ts; - - sysfs_remove_group(&ts->dev->kobj, &ad7879_attr_group); -} - int ad7879_probe(struct device *dev, struct regmap *regmap, int irq, u16 bustype, u8 devid) { @@ -658,11 +651,7 @@ int ad7879_probe(struct device *dev, struct regmap *regmap, __ad7879_disable(ts); - err = sysfs_create_group(&dev->kobj, &ad7879_attr_group); - if (err) - return err; - - err = devm_add_action_or_reset(dev, ad7879_cleanup_sysfs, ts); + err = devm_device_add_group(dev, &ad7879_attr_group); if (err) return err; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 5bf63f76ddda..c53a3d7239e7 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -70,8 +70,10 @@ #define EDT_RAW_DATA_DELAY 1000 /* usec */ enum edt_ver { - M06, - M09, + EDT_M06, + EDT_M09, + EDT_M12, + GENERIC_FT, }; struct edt_reg_addr { @@ -179,14 +181,16 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) int error; switch (tsdata->version) { - case M06: + case EDT_M06: cmd = 0xf9; /* tell the controller to send touch data */ offset = 5; /* where the actual touch data starts */ tplen = 4; /* data comes in so called frames */ crclen = 1; /* length of the crc data */ break; - case M09: + case EDT_M09: + case EDT_M12: + case GENERIC_FT: cmd = 0x0; offset = 3; tplen = 6; @@ -209,8 +213,8 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) goto out; } - /* M09 does not send header or CRC */ - if (tsdata->version == M06) { + /* M09/M12 does not send header or CRC */ + if (tsdata->version == EDT_M06) { if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || rdbuf[2] != datalen) { dev_err_ratelimited(dev, @@ -233,7 +237,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) continue; /* M06 sometimes sends bogus coordinates in TOUCH_DOWN */ - if (tsdata->version == M06 && type == TOUCH_EVENT_DOWN) + if (tsdata->version == EDT_M06 && type == TOUCH_EVENT_DOWN) continue; x = ((buf[0] << 8) | buf[1]) & 0x0fff; @@ -264,14 +268,16 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, u8 wrbuf[4]; switch (tsdata->version) { - case M06: + case EDT_M06: wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; wrbuf[2] = value; wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; return edt_ft5x06_ts_readwrite(tsdata->client, 4, wrbuf, 0, NULL); - case M09: + case EDT_M09: + case EDT_M12: + case GENERIC_FT: wrbuf[0] = addr; wrbuf[1] = value; @@ -290,7 +296,7 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, int error; switch (tsdata->version) { - case M06: + case EDT_M06: wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; @@ -309,7 +315,9 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, } break; - case M09: + case EDT_M09: + case EDT_M12: + case GENERIC_FT: wrbuf[0] = addr; error = edt_ft5x06_ts_readwrite(tsdata->client, 1, wrbuf, 1, rdbuf); @@ -368,11 +376,13 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev, } switch (tsdata->version) { - case M06: + case EDT_M06: addr = attr->addr_m06; break; - case M09: + case EDT_M09: + case EDT_M12: + case GENERIC_FT: addr = attr->addr_m09; break; @@ -437,11 +447,13 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev, } switch (tsdata->version) { - case M06: + case EDT_M06: addr = attr->addr_m06; break; - case M09: + case EDT_M09: + case EDT_M12: + case GENERIC_FT: addr = attr->addr_m09; break; @@ -466,14 +478,18 @@ out: return error ?: count; } +/* m06, m09: range 0-31, m12: range 0-5 */ static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, M09_REGISTER_GAIN, 0, 31); +/* m06, m09: range 0-31, m12: range 0-16 */ static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, M09_REGISTER_OFFSET, 0, 31); +/* m06: range 20 to 80, m09: range 0 to 30, m12: range 1 to 255... */ static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD, - M09_REGISTER_THRESHOLD, 0, 80); + M09_REGISTER_THRESHOLD, 0, 255); +/* m06: range 3 to 14, m12: (0x64: 100Hz) */ static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE, - NO_REGISTER, 3, 14); + NO_REGISTER, 0, 255); static struct attribute *edt_ft5x06_attrs[] = { &edt_ft5x06_attr_gain.dattr.attr, @@ -508,7 +524,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata) } /* mode register is 0x3c when in the work mode */ - if (tsdata->version == M09) + if (tsdata->version != EDT_M06) goto m09_out; error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03); @@ -545,7 +561,7 @@ err_out: return error; m09_out: - dev_err(&client->dev, "No factory mode support for M09\n"); + dev_err(&client->dev, "No factory mode support for M09/M12/GENERIC_FT\n"); return -EINVAL; } @@ -770,16 +786,17 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, * to have garbage in there */ memset(rdbuf, 0, sizeof(rdbuf)); - error = edt_ft5x06_ts_readwrite(client, 1, "\xbb", + error = edt_ft5x06_ts_readwrite(client, 1, "\xBB", EDT_NAME_LEN - 1, rdbuf); if (error) return error; - /* if we find something consistent, stay with that assumption - * at least M09 won't send 3 bytes here + /* Probe content for something consistent. + * M06 starts with a response byte, M12 gives the data directly. + * M09/Generic does not provide model number information. */ - if (!(strncasecmp(rdbuf + 1, "EP0", 3))) { - tsdata->version = M06; + if (!strncasecmp(rdbuf + 1, "EP0", 3)) { + tsdata->version = EDT_M06; /* remove last '$' end marker */ rdbuf[EDT_NAME_LEN - 1] = '\0'; @@ -792,9 +809,31 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, *p++ = '\0'; strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); + } else if (!strncasecmp(rdbuf, "EP0", 3)) { + tsdata->version = EDT_M12; + + /* remove last '$' end marker */ + rdbuf[EDT_NAME_LEN - 2] = '\0'; + if (rdbuf[EDT_NAME_LEN - 3] == '$') + rdbuf[EDT_NAME_LEN - 3] = '\0'; + + /* look for Model/Version separator */ + p = strchr(rdbuf, '*'); + if (p) + *p++ = '\0'; + strlcpy(model_name, rdbuf, EDT_NAME_LEN); + strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); } else { - /* since there are only two versions around (M06, M09) */ - tsdata->version = M09; + /* If it is not an EDT M06/M12 touchscreen, then the model + * detection is a bit hairy. The different ft5x06 + * firmares around don't reliably implement the + * identification registers. Well, we'll take a shot. + * + * The main difference between generic focaltec based + * touches and EDT M09 is that we know how to retrieve + * the max coordinates for the latter. + */ + tsdata->version = GENERIC_FT; error = edt_ft5x06_ts_readwrite(client, 1, "\xA6", 2, rdbuf); @@ -808,8 +847,34 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, if (error) return error; - snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09", - rdbuf[0] >> 4, rdbuf[0] & 0x0F); + /* This "model identification" is not exact. Unfortunately + * not all firmwares for the ft5x06 put useful values in + * the identification registers. + */ + switch (rdbuf[0]) { + case 0x35: /* EDT EP0350M09 */ + case 0x43: /* EDT EP0430M09 */ + case 0x50: /* EDT EP0500M09 */ + case 0x57: /* EDT EP0570M09 */ + case 0x70: /* EDT EP0700M09 */ + tsdata->version = EDT_M09; + snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09", + rdbuf[0] >> 4, rdbuf[0] & 0x0F); + break; + case 0xa1: /* EDT EP1010ML00 */ + tsdata->version = EDT_M09; + snprintf(model_name, EDT_NAME_LEN, "EP%i%i0ML00", + rdbuf[0] >> 4, rdbuf[0] & 0x0F); + break; + case 0x5a: /* Solomon Goldentek Display */ + snprintf(model_name, EDT_NAME_LEN, "GKTW50SCED1R0"); + break; + default: + snprintf(model_name, EDT_NAME_LEN, + "generic ft5x06 (%02x)", + rdbuf[0]); + break; + } } return 0; @@ -853,8 +918,17 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) if (reg_addr->reg_report_rate != NO_REGISTER) tsdata->report_rate = edt_ft5x06_register_read(tsdata, reg_addr->reg_report_rate); - tsdata->num_x = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_x); - tsdata->num_y = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_y); + if (tsdata->version == EDT_M06 || + tsdata->version == EDT_M09 || + tsdata->version == EDT_M12) { + tsdata->num_x = edt_ft5x06_register_read(tsdata, + reg_addr->reg_num_x); + tsdata->num_y = edt_ft5x06_register_read(tsdata, + reg_addr->reg_num_y); + } else { + tsdata->num_x = -1; + tsdata->num_y = -1; + } } static void @@ -863,7 +937,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) struct edt_reg_addr *reg_addr = &tsdata->reg_addr; switch (tsdata->version) { - case M06: + case EDT_M06: reg_addr->reg_threshold = WORK_REGISTER_THRESHOLD; reg_addr->reg_report_rate = WORK_REGISTER_REPORT_RATE; reg_addr->reg_gain = WORK_REGISTER_GAIN; @@ -872,7 +946,8 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) reg_addr->reg_num_y = WORK_REGISTER_NUM_Y; break; - case M09: + case EDT_M09: + case EDT_M12: reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; reg_addr->reg_report_rate = NO_REGISTER; reg_addr->reg_gain = M09_REGISTER_GAIN; @@ -880,6 +955,13 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) reg_addr->reg_num_x = M09_REGISTER_NUM_X; reg_addr->reg_num_y = M09_REGISTER_NUM_Y; break; + + case GENERIC_FT: + /* this is a guesswork */ + reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; + reg_addr->reg_gain = M09_REGISTER_GAIN; + reg_addr->reg_offset = M09_REGISTER_OFFSET; + break; } } @@ -969,10 +1051,20 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, input->id.bustype = BUS_I2C; input->dev.parent = &client->dev; - input_set_abs_params(input, ABS_MT_POSITION_X, - 0, tsdata->num_x * 64 - 1, 0, 0); - input_set_abs_params(input, ABS_MT_POSITION_Y, - 0, tsdata->num_y * 64 - 1, 0, 0); + if (tsdata->version == EDT_M06 || + tsdata->version == EDT_M09 || + tsdata->version == EDT_M12) { + input_set_abs_params(input, ABS_MT_POSITION_X, + 0, tsdata->num_x * 64 - 1, 0, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, + 0, tsdata->num_y * 64 - 1, 0, 0); + } else { + /* Unknown maximum values. Specify via devicetree */ + input_set_abs_params(input, ABS_MT_POSITION_X, + 0, 65535, 0, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, + 0, 65535, 0, 0); + } touchscreen_parse_properties(input, true, &tsdata->prop); @@ -998,13 +1090,13 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, return error; } - error = sysfs_create_group(&client->dev.kobj, &edt_ft5x06_attr_group); + error = devm_device_add_group(&client->dev, &edt_ft5x06_attr_group); if (error) return error; error = input_register_device(input); if (error) - goto err_remove_attrs; + return error; edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev)); device_init_wakeup(&client->dev, 1); @@ -1016,10 +1108,6 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, tsdata->reset_gpio ? desc_to_gpio(tsdata->reset_gpio) : -1); return 0; - -err_remove_attrs: - sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); - return error; } static int edt_ft5x06_ts_remove(struct i2c_client *client) @@ -1027,7 +1115,6 @@ static int edt_ft5x06_ts_remove(struct i2c_client *client) struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); edt_ft5x06_ts_teardown_debugfs(tsdata); - sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); return 0; } diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 0f4cda7282a2..e102d7764bc2 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1070,13 +1070,6 @@ static const struct attribute_group elants_attribute_group = { .attrs = elants_attributes, }; -static void elants_i2c_remove_sysfs_group(void *_data) -{ - struct elants_data *ts = _data; - - sysfs_remove_group(&ts->client->dev.kobj, &elants_attribute_group); -} - static int elants_i2c_power_on(struct elants_data *ts) { int error; @@ -1289,23 +1282,13 @@ static int elants_i2c_probe(struct i2c_client *client, if (!client->dev.of_node) device_init_wakeup(&client->dev, true); - error = sysfs_create_group(&client->dev.kobj, &elants_attribute_group); + error = devm_device_add_group(&client->dev, &elants_attribute_group); if (error) { dev_err(&client->dev, "failed to create sysfs attributes: %d\n", error); return error; } - error = devm_add_action(&client->dev, - elants_i2c_remove_sysfs_group, ts); - if (error) { - elants_i2c_remove_sysfs_group(ts); - dev_err(&client->dev, - "Failed to add sysfs cleanup action: %d\n", - error); - return error; - } - return 0; } diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c index 05108c2fea93..6892f0e28918 100644 --- a/drivers/input/touchscreen/melfas_mip4.c +++ b/drivers/input/touchscreen/melfas_mip4.c @@ -1433,13 +1433,6 @@ static const struct attribute_group mip4_attr_group = { .attrs = mip4_attrs, }; -static void mip4_sysfs_remove(void *_data) -{ - struct mip4_ts *ts = _data; - - sysfs_remove_group(&ts->client->dev.kobj, &mip4_attr_group); -} - static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct mip4_ts *ts; @@ -1535,21 +1528,13 @@ static int mip4_probe(struct i2c_client *client, const struct i2c_device_id *id) return error; } - error = sysfs_create_group(&client->dev.kobj, &mip4_attr_group); + error = devm_device_add_group(&client->dev, &mip4_attr_group); if (error) { dev_err(&client->dev, "Failed to create sysfs attribute group: %d\n", error); return error; } - error = devm_add_action(&client->dev, mip4_sysfs_remove, ts); - if (error) { - mip4_sysfs_remove(ts); - dev_err(&client->dev, - "Failed to install sysfs remoce action: %d\n", error); - return error; - } - return 0; } diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c index 4f1d3fd5d412..100538d64fff 100644 --- a/drivers/input/touchscreen/raydium_i2c_ts.c +++ b/drivers/input/touchscreen/raydium_i2c_ts.c @@ -943,13 +943,6 @@ static const struct attribute_group raydium_i2c_attribute_group = { .attrs = raydium_i2c_attributes, }; -static void raydium_i2c_remove_sysfs_group(void *_data) -{ - struct raydium_data *ts = _data; - - sysfs_remove_group(&ts->client->dev.kobj, &raydium_i2c_attribute_group); -} - static int raydium_i2c_power_on(struct raydium_data *ts) { int error; @@ -1120,7 +1113,7 @@ static int raydium_i2c_probe(struct i2c_client *client, return error; } - error = sysfs_create_group(&client->dev.kobj, + error = devm_device_add_group(&client->dev, &raydium_i2c_attribute_group); if (error) { dev_err(&client->dev, "failed to create sysfs attributes: %d\n", @@ -1128,15 +1121,6 @@ static int raydium_i2c_probe(struct i2c_client *client, return error; } - error = devm_add_action(&client->dev, - raydium_i2c_remove_sysfs_group, ts); - if (error) { - raydium_i2c_remove_sysfs_group(ts); - dev_err(&client->dev, - "Failed to add sysfs cleanup action: %d\n", error); - return error; - } - return 0; } diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c index eeaf6ff03597..bda0500c9b57 100644 --- a/drivers/input/touchscreen/rohm_bu21023.c +++ b/drivers/input/touchscreen/rohm_bu21023.c @@ -1103,13 +1103,6 @@ static void rohm_ts_close(struct input_dev *input_dev) ts->initialized = false; } -static void rohm_ts_remove_sysfs_group(void *_dev) -{ - struct device *dev = _dev; - - sysfs_remove_group(&dev->kobj, &rohm_ts_attr_group); -} - static int rohm_bu21023_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1180,20 +1173,12 @@ static int rohm_bu21023_i2c_probe(struct i2c_client *client, return error; } - error = sysfs_create_group(&dev->kobj, &rohm_ts_attr_group); + error = devm_device_add_group(dev, &rohm_ts_attr_group); if (error) { dev_err(dev, "failed to create sysfs group: %d\n", error); return error; } - error = devm_add_action(dev, rohm_ts_remove_sysfs_group, dev); - if (error) { - rohm_ts_remove_sysfs_group(dev); - dev_err(dev, "Failed to add sysfs cleanup action: %d\n", - error); - return error; - } - return error; } diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c index 8c6c6178ec12..c12d01899939 100644 --- a/drivers/input/touchscreen/stmfts.c +++ b/drivers/input/touchscreen/stmfts.c @@ -725,8 +725,7 @@ static int stmfts_probe(struct i2c_client *client, } } - err = sysfs_create_group(&sdata->client->dev.kobj, - &stmfts_attribute_group); + err = devm_device_add_group(&client->dev, &stmfts_attribute_group); if (err) return err; @@ -738,7 +737,6 @@ static int stmfts_probe(struct i2c_client *client, static int stmfts_remove(struct i2c_client *client) { pm_runtime_disable(&client->dev); - sysfs_remove_group(&client->dev.kobj, &stmfts_attribute_group); return 0; } diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c index a9132603ab34..d351efd18f89 100644 --- a/drivers/input/touchscreen/wdt87xx_i2c.c +++ b/drivers/input/touchscreen/wdt87xx_i2c.c @@ -1106,7 +1106,7 @@ static int wdt87xx_ts_probe(struct i2c_client *client, return error; } - error = sysfs_create_group(&client->dev.kobj, &wdt87xx_attr_group); + error = devm_device_add_group(&client->dev, &wdt87xx_attr_group); if (error) { dev_err(&client->dev, "create sysfs failed: %d\n", error); return error; @@ -1115,13 +1115,6 @@ static int wdt87xx_ts_probe(struct i2c_client *client, return 0; } -static int wdt87xx_ts_remove(struct i2c_client *client) -{ - sysfs_remove_group(&client->dev.kobj, &wdt87xx_attr_group); - - return 0; -} - static int __maybe_unused wdt87xx_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -1179,7 +1172,6 @@ MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id); static struct i2c_driver wdt87xx_driver = { .probe = wdt87xx_ts_probe, - .remove = wdt87xx_ts_remove, .id_table = wdt87xx_dev_id, .driver = { .name = WDT87XX_NAME, |