summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-03-17 21:51:52 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-17 21:51:52 -0700
commit10fdfee7f7fd8d4a6a8455ac4c9fbbc51d79b9f7 (patch)
treeace3300ec40d2a253c59a70ee37eb76fa53c859f /drivers
parent0f49fc95b86fc77b867d643e2d38bc9f28035ed4 (diff)
parent4d2508a55990c9b0fc1afb2c2cc5636712fd30f7 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov: "The most notable item is addition of support for Synaptics RMI4 protocol which is native protocol for all current Synaptics devices (touchscreens, touchpads). In later releases we'll switch devices using HID and PS/2 protocol emulation to RMI4. You will also get: - BYD PS/2 touchpad protocol support for psmouse - MELFAS MIP4 Touchscreen driver - rotary encoder was moved away from legacy platform data and to generic device properties API, devm_* API, and can now handle encoders using more than 2 GPIOs - Cypress touchpad driver was switched to devm_* API and device properties - other assorted driver fixes" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (40 commits) ARM: pxa/raumfeld: use PROPERTY_ENTRY_INTEGER to define props Input: synaptics-rmi4 - using logical instead of bitwise AND Input: powermate - fix oops with malicious USB descriptors Input: snvs_pwrkey - fix returned value check of syscon_regmap_lookup_by_phandle() MAINTAINERS: add devicetree bindings to Input Drivers section Input: synaptics-rmi4 - add device tree support to the SPI transport driver Input: synaptics-rmi4 - add SPI transport driver Input: synaptics-rmi4 - add support for F30 Input: synaptics-rmi4 - add support for F12 Input: synaptics-rmi4 - add device tree support for 2d sensors and F11 Input: synaptics-rmi4 - add support for 2D sensors and F11 Input: synaptics-rmi4 - add device tree support for RMI4 I2C devices Input: synaptics-rmi4 - add I2C transport driver Input: synaptics-rmi4 - add support for Synaptics RMI4 devices Input: ad7879 - add device tree support Input: ad7879 - fix default x/y axis assignment Input: ad7879 - move header to platform_data directory Input: ts4800 - add hardware dependency Input: cyapa - fix for losing events during device power transitions Input: sh_keysc - remove dependency on SUPERH ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/Kconfig2
-rw-r--r--drivers/input/Makefile2
-rw-r--r--drivers/input/keyboard/Kconfig2
-rw-r--r--drivers/input/keyboard/goldfish_events.c17
-rw-r--r--drivers/input/keyboard/snvs_pwrkey.c8
-rw-r--r--drivers/input/keyboard/spear-keyboard.c6
-rw-r--r--drivers/input/misc/powermate.c3
-rw-r--r--drivers/input/misc/rotary_encoder.c403
-rw-r--r--drivers/input/mouse/Kconfig10
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/byd.c337
-rw-r--r--drivers/input/mouse/byd.h18
-rw-r--r--drivers/input/mouse/cyapa.c22
-rw-r--r--drivers/input/mouse/cyapa.h14
-rw-r--r--drivers/input/mouse/cyapa_gen3.c108
-rw-r--r--drivers/input/mouse/cyapa_gen5.c99
-rw-r--r--drivers/input/mouse/cyapa_gen6.c4
-rw-r--r--drivers/input/mouse/psmouse-base.c14
-rw-r--r--drivers/input/mouse/psmouse.h1
-rw-r--r--drivers/input/rmi4/Kconfig63
-rw-r--r--drivers/input/rmi4/Makefile13
-rw-r--r--drivers/input/rmi4/rmi_2d_sensor.c329
-rw-r--r--drivers/input/rmi4/rmi_2d_sensor.h87
-rw-r--r--drivers/input/rmi4/rmi_bus.c419
-rw-r--r--drivers/input/rmi4/rmi_bus.h182
-rw-r--r--drivers/input/rmi4/rmi_driver.c1055
-rw-r--r--drivers/input/rmi4/rmi_driver.h105
-rw-r--r--drivers/input/rmi4/rmi_f01.c624
-rw-r--r--drivers/input/rmi4/rmi_f11.c1317
-rw-r--r--drivers/input/rmi4/rmi_f12.c457
-rw-r--r--drivers/input/rmi4/rmi_f30.c407
-rw-r--r--drivers/input/rmi4/rmi_i2c.c397
-rw-r--r--drivers/input/rmi4/rmi_spi.c589
-rw-r--r--drivers/input/touchscreen/Kconfig17
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/ad7879-i2c.c10
-rw-r--r--drivers/input/touchscreen/ad7879-spi.c10
-rw-r--r--drivers/input/touchscreen/ad7879.c160
-rw-r--r--drivers/input/touchscreen/cyttsp_core.c194
-rw-r--r--drivers/input/touchscreen/cyttsp_core.h10
-rw-r--r--drivers/input/touchscreen/cyttsp_i2c.c10
-rw-r--r--drivers/input/touchscreen/cyttsp_spi.c10
-rw-r--r--drivers/input/touchscreen/melfas_mip4.c1517
-rw-r--r--drivers/input/touchscreen/stmpe-ts.c31
44 files changed, 8613 insertions, 472 deletions
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index a35532ec00e4..6261874c07c9 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -201,6 +201,8 @@ source "drivers/input/touchscreen/Kconfig"
source "drivers/input/misc/Kconfig"
+source "drivers/input/rmi4/Kconfig"
+
endif
menu "Hardware I/O ports"
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 0c9302ca9954..595820bbabe9 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -26,3 +26,5 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
obj-$(CONFIG_INPUT_MISC) += misc/
obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
+
+obj-$(CONFIG_RMI4_CORE) += rmi4/
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index ddd8148d51d7..509608c95994 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -560,7 +560,7 @@ config KEYBOARD_SUNKBD
config KEYBOARD_SH_KEYSC
tristate "SuperH KEYSC keypad support"
- depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST
+ depends on ARCH_SHMOBILE || COMPILE_TEST
help
Say Y here if you want to use a keypad attached to the KEYSC block
on SuperH processors such as sh7722 and sh7343.
diff --git a/drivers/input/keyboard/goldfish_events.c b/drivers/input/keyboard/goldfish_events.c
index 907e4e278fce..f6e643b589b6 100644
--- a/drivers/input/keyboard/goldfish_events.c
+++ b/drivers/input/keyboard/goldfish_events.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/io.h>
+#include <linux/acpi.h>
enum {
REG_READ = 0x00,
@@ -178,10 +179,26 @@ static int events_probe(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id goldfish_events_of_match[] = {
+ { .compatible = "google,goldfish-events-keypad", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, goldfish_events_of_match);
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id goldfish_events_acpi_match[] = {
+ { "GFSH0002", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, goldfish_events_acpi_match);
+#endif
+
static struct platform_driver events_driver = {
.probe = events_probe,
.driver = {
.name = "goldfish_events",
+ .of_match_table = goldfish_events_of_match,
+ .acpi_match_table = ACPI_PTR(goldfish_events_acpi_match),
},
};
diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c
index 9adf13a5864a..24a9f599082f 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -111,9 +111,9 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
return -ENOMEM;
pdata->snvs = syscon_regmap_lookup_by_phandle(np, "regmap");
- if (!pdata->snvs) {
+ if (IS_ERR(pdata->snvs)) {
dev_err(&pdev->dev, "Can't get snvs syscon\n");
- return -ENODEV;
+ return PTR_ERR(pdata->snvs);
}
if (of_property_read_u32(np, "linux,keycode", &pdata->keycode)) {
@@ -180,7 +180,7 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev)
return 0;
}
-static int imx_snvs_pwrkey_suspend(struct device *dev)
+static int __maybe_unused imx_snvs_pwrkey_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
@@ -191,7 +191,7 @@ static int imx_snvs_pwrkey_suspend(struct device *dev)
return 0;
}
-static int imx_snvs_pwrkey_resume(struct device *dev)
+static int __maybe_unused imx_snvs_pwrkey_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct pwrkey_drv_data *pdata = platform_get_drvdata(pdev);
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index 623d451767e3..8083eaa0524a 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -288,8 +288,7 @@ static int spear_kbd_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
-static int spear_kbd_suspend(struct device *dev)
+static int __maybe_unused spear_kbd_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct spear_kbd *kbd = platform_get_drvdata(pdev);
@@ -342,7 +341,7 @@ static int spear_kbd_suspend(struct device *dev)
return 0;
}
-static int spear_kbd_resume(struct device *dev)
+static int __maybe_unused spear_kbd_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct spear_kbd *kbd = platform_get_drvdata(pdev);
@@ -368,7 +367,6 @@ static int spear_kbd_resume(struct device *dev)
return 0;
}
-#endif
static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume);
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c
index 63b539d3daba..84909a12ff36 100644
--- a/drivers/input/misc/powermate.c
+++ b/drivers/input/misc/powermate.c
@@ -307,6 +307,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
int error = -ENOMEM;
interface = intf->cur_altsetting;
+ if (interface->desc.bNumEndpoints < 1)
+ return -EINVAL;
+
endpoint = &interface->endpoint[0].desc;
if (!usb_endpoint_is_int_in(endpoint))
return -EIO;
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index 8aee71986430..96c486de49e0 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -20,70 +20,78 @@
#include <linux/input.h>
#include <linux/device.h>
#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/rotary_encoder.h>
+#include <linux/gpio/consumer.h>
#include <linux/slab.h>
#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
#include <linux/pm.h>
+#include <linux/property.h>
#define DRV_NAME "rotary-encoder"
struct rotary_encoder {
struct input_dev *input;
- const struct rotary_encoder_platform_data *pdata;
- unsigned int axis;
+ struct mutex access_mutex;
+
+ u32 steps;
+ u32 axis;
+ bool relative_axis;
+ bool rollover;
+
unsigned int pos;
- unsigned int irq_a;
- unsigned int irq_b;
+ struct gpio_descs *gpios;
+
+ unsigned int *irq;
bool armed;
- unsigned char dir; /* 0 - clockwise, 1 - CCW */
+ signed char dir; /* 1 - clockwise, -1 - CCW */
- char last_stable;
+ unsigned last_stable;
};
-static int rotary_encoder_get_state(const struct rotary_encoder_platform_data *pdata)
+static unsigned rotary_encoder_get_state(struct rotary_encoder *encoder)
{
- int a = !!gpio_get_value(pdata->gpio_a);
- int b = !!gpio_get_value(pdata->gpio_b);
+ int i;
+ unsigned ret = 0;
- a ^= pdata->inverted_a;
- b ^= pdata->inverted_b;
+ for (i = 0; i < encoder->gpios->ndescs; ++i) {
+ int val = gpiod_get_value_cansleep(encoder->gpios->desc[i]);
+ /* convert from gray encoding to normal */
+ if (ret & 1)
+ val = !val;
- return ((a << 1) | b);
+ ret = ret << 1 | val;
+ }
+
+ return ret & 3;
}
static void rotary_encoder_report_event(struct rotary_encoder *encoder)
{
- const struct rotary_encoder_platform_data *pdata = encoder->pdata;
-
- if (pdata->relative_axis) {
+ if (encoder->relative_axis) {
input_report_rel(encoder->input,
- pdata->axis, encoder->dir ? -1 : 1);
+ encoder->axis, encoder->dir);
} else {
unsigned int pos = encoder->pos;
- if (encoder->dir) {
+ if (encoder->dir < 0) {
/* turning counter-clockwise */
- if (pdata->rollover)
- pos += pdata->steps;
+ if (encoder->rollover)
+ pos += encoder->steps;
if (pos)
pos--;
} else {
/* turning clockwise */
- if (pdata->rollover || pos < pdata->steps)
+ if (encoder->rollover || pos < encoder->steps)
pos++;
}
- if (pdata->rollover)
- pos %= pdata->steps;
+ if (encoder->rollover)
+ pos %= encoder->steps;
encoder->pos = pos;
- input_report_abs(encoder->input, pdata->axis, encoder->pos);
+ input_report_abs(encoder->input, encoder->axis, encoder->pos);
}
input_sync(encoder->input);
@@ -92,9 +100,11 @@ static void rotary_encoder_report_event(struct rotary_encoder *encoder)
static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
{
struct rotary_encoder *encoder = dev_id;
- int state;
+ unsigned state;
- state = rotary_encoder_get_state(encoder->pdata);
+ mutex_lock(&encoder->access_mutex);
+
+ state = rotary_encoder_get_state(encoder);
switch (state) {
case 0x0:
@@ -105,334 +115,227 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
break;
case 0x1:
- case 0x2:
+ case 0x3:
if (encoder->armed)
- encoder->dir = state - 1;
+ encoder->dir = 2 - state;
break;
- case 0x3:
+ case 0x2:
encoder->armed = true;
break;
}
+ mutex_unlock(&encoder->access_mutex);
+
return IRQ_HANDLED;
}
static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
{
struct rotary_encoder *encoder = dev_id;
- int state;
+ unsigned int state;
- state = rotary_encoder_get_state(encoder->pdata);
+ mutex_lock(&encoder->access_mutex);
- switch (state) {
- case 0x00:
- case 0x03:
+ state = rotary_encoder_get_state(encoder);
+
+ if (state & 1) {
+ encoder->dir = ((encoder->last_stable - state + 1) % 4) - 1;
+ } else {
if (state != encoder->last_stable) {
rotary_encoder_report_event(encoder);
encoder->last_stable = state;
}
- break;
-
- case 0x01:
- case 0x02:
- encoder->dir = (encoder->last_stable + state) & 0x01;
- break;
}
+ mutex_unlock(&encoder->access_mutex);
+
return IRQ_HANDLED;
}
static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
{
struct rotary_encoder *encoder = dev_id;
- unsigned char sum;
- int state;
-
- state = rotary_encoder_get_state(encoder->pdata);
-
- /*
- * We encode the previous and the current state using a byte.
- * The previous state in the MSB nibble, the current state in the LSB
- * nibble. Then use a table to decide the direction of the turn.
- */
- sum = (encoder->last_stable << 4) + state;
- switch (sum) {
- case 0x31:
- case 0x10:
- case 0x02:
- case 0x23:
- encoder->dir = 0; /* clockwise */
- break;
+ unsigned int state;
- case 0x13:
- case 0x01:
- case 0x20:
- case 0x32:
- encoder->dir = 1; /* counter-clockwise */
- break;
+ mutex_lock(&encoder->access_mutex);
- default:
- /*
- * Ignore all other values. This covers the case when the
- * state didn't change (a spurious interrupt) and the
- * cases where the state changed by two steps, making it
- * impossible to tell the direction.
- *
- * In either case, don't report any event and save the
- * state for later.
- */
+ state = rotary_encoder_get_state(encoder);
+
+ if ((encoder->last_stable + 1) % 4 == state)
+ encoder->dir = 1;
+ else if (encoder->last_stable == (state + 1) % 4)
+ encoder->dir = -1;
+ else
goto out;
- }
rotary_encoder_report_event(encoder);
out:
encoder->last_stable = state;
+ mutex_unlock(&encoder->access_mutex);
+
return IRQ_HANDLED;
}
-#ifdef CONFIG_OF
-static const struct of_device_id rotary_encoder_of_match[] = {
- { .compatible = "rotary-encoder", },
- { },
-};
-MODULE_DEVICE_TABLE(of, rotary_encoder_of_match);
-
-static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct device *dev)
+static int rotary_encoder_probe(struct platform_device *pdev)
{
- const struct of_device_id *of_id =
- of_match_device(rotary_encoder_of_match, dev);
- struct device_node *np = dev->of_node;
- struct rotary_encoder_platform_data *pdata;
- enum of_gpio_flags flags;
- int error;
-
- if (!of_id || !np)
- return NULL;
-
- pdata = kzalloc(sizeof(struct rotary_encoder_platform_data),
- GFP_KERNEL);
- if (!pdata)
- return ERR_PTR(-ENOMEM);
-
- of_property_read_u32(np, "rotary-encoder,steps", &pdata->steps);
- of_property_read_u32(np, "linux,axis", &pdata->axis);
+ struct device *dev = &pdev->dev;
+ struct rotary_encoder *encoder;
+ struct input_dev *input;
+ irq_handler_t handler;
+ u32 steps_per_period;
+ unsigned int i;
+ int err;
- pdata->gpio_a = of_get_gpio_flags(np, 0, &flags);
- pdata->inverted_a = flags & OF_GPIO_ACTIVE_LOW;
+ encoder = devm_kzalloc(dev, sizeof(struct rotary_encoder), GFP_KERNEL);
+ if (!encoder)
+ return -ENOMEM;
- pdata->gpio_b = of_get_gpio_flags(np, 1, &flags);
- pdata->inverted_b = flags & OF_GPIO_ACTIVE_LOW;
+ mutex_init(&encoder->access_mutex);
- pdata->relative_axis =
- of_property_read_bool(np, "rotary-encoder,relative-axis");
- pdata->rollover = of_property_read_bool(np, "rotary-encoder,rollover");
+ device_property_read_u32(dev, "rotary-encoder,steps", &encoder->steps);
- error = of_property_read_u32(np, "rotary-encoder,steps-per-period",
- &pdata->steps_per_period);
- if (error) {
+ err = device_property_read_u32(dev, "rotary-encoder,steps-per-period",
+ &steps_per_period);
+ if (err) {
/*
- * The 'half-period' property has been deprecated, you must use
- * 'steps-per-period' and set an appropriate value, but we still
- * need to parse it to maintain compatibility.
+ * The 'half-period' property has been deprecated, you must
+ * use 'steps-per-period' and set an appropriate value, but
+ * we still need to parse it to maintain compatibility. If
+ * neither property is present we fall back to the one step
+ * per period behavior.
*/
- if (of_property_read_bool(np, "rotary-encoder,half-period")) {
- pdata->steps_per_period = 2;
- } else {
- /* Fallback to one step per period behavior */
- pdata->steps_per_period = 1;
- }
+ steps_per_period = device_property_read_bool(dev,
+ "rotary-encoder,half-period") ? 2 : 1;
}
- pdata->wakeup_source = of_property_read_bool(np, "wakeup-source");
+ encoder->rollover =
+ device_property_read_bool(dev, "rotary-encoder,rollover");
- return pdata;
-}
-#else
-static inline struct rotary_encoder_platform_data *
-rotary_encoder_parse_dt(struct device *dev)
-{
- return NULL;
-}
-#endif
-
-static int rotary_encoder_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- const struct rotary_encoder_platform_data *pdata = dev_get_platdata(dev);
- struct rotary_encoder *encoder;
- struct input_dev *input;
- irq_handler_t handler;
- int err;
-
- if (!pdata) {
- pdata = rotary_encoder_parse_dt(dev);
- if (IS_ERR(pdata))
- return PTR_ERR(pdata);
+ device_property_read_u32(dev, "linux,axis", &encoder->axis);
+ encoder->relative_axis =
+ device_property_read_bool(dev, "rotary-encoder,relative-axis");
- if (!pdata) {
- dev_err(dev, "missing platform data\n");
- return -EINVAL;
- }
+ encoder->gpios = devm_gpiod_get_array(dev, NULL, GPIOD_IN);
+ if (IS_ERR(encoder->gpios)) {
+ dev_err(dev, "unable to get gpios\n");
+ return PTR_ERR(encoder->gpios);
}
-
- encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL);
- input = input_allocate_device();
- if (!encoder || !input) {
- err = -ENOMEM;
- goto exit_free_mem;
+ if (encoder->gpios->ndescs < 2) {
+ dev_err(dev, "not enough gpios found\n");
+ return -EINVAL;
}
+ input = devm_input_allocate_device(dev);
+ if (!input)
+ return -ENOMEM;
+
encoder->input = input;
- encoder->pdata = pdata;
input->name = pdev->name;
input->id.bustype = BUS_HOST;
input->dev.parent = dev;
- if (pdata->relative_axis) {
- input->evbit[0] = BIT_MASK(EV_REL);
- input->relbit[0] = BIT_MASK(pdata->axis);
- } else {
- input->evbit[0] = BIT_MASK(EV_ABS);
- input_set_abs_params(encoder->input,
- pdata->axis, 0, pdata->steps, 0, 1);
- }
-
- /* request the GPIOs */
- err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev));
- if (err) {
- dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_a);
- goto exit_free_mem;
- }
-
- err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev));
- if (err) {
- dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_b);
- goto exit_free_gpio_a;
- }
-
- encoder->irq_a = gpio_to_irq(pdata->gpio_a);
- encoder->irq_b = gpio_to_irq(pdata->gpio_b);
+ if (encoder->relative_axis)
+ input_set_capability(input, EV_REL, encoder->axis);
+ else
+ input_set_abs_params(input,
+ encoder->axis, 0, encoder->steps, 0, 1);
- switch (pdata->steps_per_period) {
+ switch (steps_per_period >> (encoder->gpios->ndescs - 2)) {
case 4:
handler = &rotary_encoder_quarter_period_irq;
- encoder->last_stable = rotary_encoder_get_state(pdata);
+ encoder->last_stable = rotary_encoder_get_state(encoder);
break;
case 2:
handler = &rotary_encoder_half_period_irq;
- encoder->last_stable = rotary_encoder_get_state(pdata);
+ encoder->last_stable = rotary_encoder_get_state(encoder);
break;
case 1:
handler = &rotary_encoder_irq;
break;
default:
dev_err(dev, "'%d' is not a valid steps-per-period value\n",
- pdata->steps_per_period);
- err = -EINVAL;
- goto exit_free_gpio_b;
+ steps_per_period);
+ return -EINVAL;
}
- err = request_irq(encoder->irq_a, handler,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- DRV_NAME, encoder);
- if (err) {
- dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a);
- goto exit_free_gpio_b;
- }
-
- err = request_irq(encoder->irq_b, handler,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- DRV_NAME, encoder);
- if (err) {
- dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b);
- goto exit_free_irq_a;
+ encoder->irq =
+ devm_kzalloc(dev,
+ sizeof(*encoder->irq) * encoder->gpios->ndescs,
+ GFP_KERNEL);
+ if (!encoder->irq)
+ return -ENOMEM;
+
+ for (i = 0; i < encoder->gpios->ndescs; ++i) {
+ encoder->irq[i] = gpiod_to_irq(encoder->gpios->desc[i]);
+
+ err = devm_request_threaded_irq(dev, encoder->irq[i],
+ NULL, handler,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ DRV_NAME, encoder);
+ if (err) {
+ dev_err(dev, "unable to request IRQ %d (gpio#%d)\n",
+ encoder->irq[i], i);
+ return err;
+ }
}
err = input_register_device(input);
if (err) {
dev_err(dev, "failed to register input device\n");
- goto exit_free_irq_b;
+ return err;
}
- device_init_wakeup(&pdev->dev, pdata->wakeup_source);
+ device_init_wakeup(dev,
+ device_property_read_bool(dev, "wakeup-source"));
platform_set_drvdata(pdev, encoder);
return 0;
-
-exit_free_irq_b:
- free_irq(encoder->irq_b, encoder);
-exit_free_irq_a:
- free_irq(encoder->irq_a, encoder);
-exit_free_gpio_b:
- gpio_free(pdata->gpio_b);
-exit_free_gpio_a:
- gpio_free(pdata->gpio_a);
-exit_free_mem:
- input_free_device(input);
- kfree(encoder);
- if (!dev_get_platdata(&pdev->dev))
- kfree(pdata);
-
- return err;
}
-static int rotary_encoder_remove(struct platform_device *pdev)
-{
- struct rotary_encoder *encoder = platform_get_drvdata(pdev);
- const struct rotary_encoder_platform_data *pdata = encoder->pdata;
-
- device_init_wakeup(&pdev->dev, false);
-
- free_irq(encoder->irq_a, encoder);
- free_irq(encoder->irq_b, encoder);
- gpio_free(pdata->gpio_a);
- gpio_free(pdata->gpio_b);
-
- input_unregister_device(encoder->input);
- kfree(encoder);
-
- if (!dev_get_platdata(&pdev->dev))
- kfree(pdata);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int rotary_encoder_suspend(struct device *dev)
+static int __maybe_unused rotary_encoder_suspend(struct device *dev)
{
struct rotary_encoder *encoder = dev_get_drvdata(dev);
+ unsigned int i;
if (device_may_wakeup(dev)) {
- enable_irq_wake(encoder->irq_a);
- enable_irq_wake(encoder->irq_b);
+ for (i = 0; i < encoder->gpios->ndescs; ++i)
+ enable_irq_wake(encoder->irq[i]);
}
return 0;
}
-static int rotary_encoder_resume(struct device *dev)
+static int __maybe_unused rotary_encoder_resume(struct device *dev)
{
struct rotary_encoder *encoder = dev_get_drvdata(dev);
+ unsigned int i;
if (device_may_wakeup(dev)) {
- disable_irq_wake(encoder->irq_a);
- disable_irq_wake(encoder->irq_b);
+ for (i = 0; i < encoder->gpios->ndescs; ++i)
+ disable_irq_wake(encoder->irq[i]);
}
return 0;
}
-#endif
static SIMPLE_DEV_PM_OPS(rotary_encoder_pm_ops,
- rotary_encoder_suspend, rotary_encoder_resume);
+ rotary_encoder_suspend, rotary_encoder_resume);
+
+#ifdef CONFIG_OF
+static const struct of_device_id rotary_encoder_of_match[] = {
+ { .compatible = "rotary-encoder", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, rotary_encoder_of_match);
+#endif
static struct platform_driver rotary_encoder_driver = {
.probe = rotary_encoder_probe,
- .remove = rotary_encoder_remove,
.driver = {
.name = DRV_NAME,
.pm = &rotary_encoder_pm_ops,
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 17f97e5e11e7..096abb4ad5cd 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -48,6 +48,16 @@ config MOU