Commit f4f9b8fc authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:
 "A big update to the Atmel touchscreen driver, devm support for polled
  input devices, several drivers have been converted to using managed
  resources, and assorted driver fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (87 commits)
  Input: synaptics - fix resolution for manually provided min/max
  Input: atmel_mxt_ts - fix invalid return from mxt_get_bootloader_version
  Input: max8997_haptic - add error handling for regulator and pwm
  Input: elantech - don't set bit 1 of reg_10 when the no_hw_res quirk is set
  Input: elantech - deal with clickpads reporting right button events
  Input: edt-ft5x06 - fix an i2c write for M09 support
  Input: omap-keypad - remove platform data support
  ARM: OMAP2+: remove unused omap4-keypad file and code
  Input: ab8500-ponkey - switch to using managed resources
  Input: max8925_onkey - switch to using managed resources
  Input: 88pm860x-ts - switch to using managed resources
  Input: 88pm860x_onkey - switch to using managed resources
  Input: intel-mid-touch - switch to using managed resources
  Input: wacom - process outbound for newer Cintiqs
  Input: wacom - set stylus_in_proximity when pen is in range
  DTS: ARM: OMAP3-N900: Add tsc2005 support
  Input: tsc2005 - add DT support
  Input: add common DT binding for touchscreens
  Input: jornada680_kbd - switch top using managed resources
  Input: adp5520-keys - switch to using managed resources
  ...
parents 9894e6d9 a292241c
* ST Keyscan controller Device Tree bindings
The ST keyscan controller Device Tree binding is based on the
matrix-keymap.
Required properties:
- compatible: "st,sti-keyscan"
- reg: Register base address and size of st-keyscan controller.
- interrupts: Interrupt number for the st-keyscan controller.
- clocks: Must contain one entry, for the module clock.
See ../clocks/clock-bindings.txt for details.
- pinctrl: Should specify pin control groups used for this controller.
See ../pinctrl/pinctrl-bindings.txt for details.
- linux,keymap: The keymap for keys as described in the binding document
devicetree/bindings/input/matrix-keymap.txt.
- keypad,num-rows: Number of row lines connected to the keypad controller.
- keypad,num-columns: Number of column lines connected to the keypad
controller.
Optional property:
- st,debounce_us: Debouncing interval time in microseconds
Example:
keyscan: keyscan@fe4b0000 {
compatible = "st,sti-keyscan";
reg = <0xfe4b0000 0x2000>;
interrupts = <GIC_SPI 212 IRQ_TYPE_NONE>;
clocks = <&CLK_SYSIN>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_keyscan>;
keypad,num-rows = <4>;
keypad,num-columns = <4>;
st,debounce_us = <5000>;
linux,keymap = < MATRIX_KEY(0x00, 0x00, KEY_F13)
MATRIX_KEY(0x00, 0x01, KEY_F9)
MATRIX_KEY(0x00, 0x02, KEY_F5)
MATRIX_KEY(0x00, 0x03, KEY_F1)
MATRIX_KEY(0x01, 0x00, KEY_F14)
MATRIX_KEY(0x01, 0x01, KEY_F10)
MATRIX_KEY(0x01, 0x02, KEY_F6)
MATRIX_KEY(0x01, 0x03, KEY_F2)
MATRIX_KEY(0x02, 0x00, KEY_F15)
MATRIX_KEY(0x02, 0x01, KEY_F11)
MATRIX_KEY(0x02, 0x02, KEY_F7)
MATRIX_KEY(0x02, 0x03, KEY_F3)
MATRIX_KEY(0x03, 0x00, KEY_F16)
MATRIX_KEY(0x03, 0x01, KEY_F12)
MATRIX_KEY(0x03, 0x02, KEY_F8)
MATRIX_KEY(0x03, 0x03, KEY_F4) >;
};
sun4i resistive touchscreen controller
--------------------------------------
Required properties:
- compatible: "allwinner,sun4i-a10-ts"
- reg: mmio address range of the chip
- interrupts: interrupt to which the chip is connected
Optional properties:
- allwinner,ts-attached: boolean indicating that an actual touchscreen is
attached to the controller
Example:
rtp: rtp@01c25000 {
compatible = "allwinner,sun4i-a10-ts";
reg = <0x01c25000 0x100>;
interrupts = <29>;
allwinner,ts-attached;
};
General Touchscreen Properties:
Optional properties for Touchscreens:
- touchscreen-size-x : horizontal resolution of touchscreen
(in pixels)
- touchscreen-size-y : vertical resolution of touchscreen
(in pixels)
- touchscreen-max-pressure : maximum reported pressure (arbitrary range
dependent on the controller)
- touchscreen-fuzz-x : horizontal noise value of the absolute input
device (in pixels)
- touchscreen-fuzz-y : vertical noise value of the absolute input
device (in pixels)
- touchscreen-fuzz-pressure : pressure noise value of the absolute input
device (arbitrary range dependent on the
controller)
- touchscreen-inverted-x : X axis is inverted (boolean)
- touchscreen-inverted-y : Y axis is inverted (boolean)
Deprecated properties for Touchscreens:
- x-size : deprecated name for touchscreen-size-x
- y-size : deprecated name for touchscreen-size-y
- moving-threshold : deprecated name for a combination of
touchscreen-fuzz-x and touchscreen-fuzz-y
- contact-threshold : deprecated name for touchscreen-fuzz-pressure
- x-invert : deprecated name for touchscreen-inverted-x
- y-invert : deprecated name for touchscreen-inverted-y
* Texas Instruments tsc2005 touchscreen controller
Required properties:
- compatible : "ti,tsc2005"
- reg : SPI device address
- spi-max-frequency : Maximal SPI speed
- interrupts : IRQ specifier
- reset-gpios : GPIO specifier
- vio-supply : Regulator specifier
Optional properties:
- ti,x-plate-ohms : integer, resistance of the touchscreen's X plates
in ohm (defaults to 280)
- ti,esd-recovery-timeout-ms : integer, if the touchscreen does not respond after
the configured time (in milli seconds), the driver
will reset it. This is disabled by default.
- properties defined in touchscreen.txt
Example:
&mcspi1 {
tsc2005@0 {
compatible = "ti,tsc2005";
spi-max-frequency = <6000000>;
reg = <0>;
vio-supply = <&vio>;
reset-gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>; /* 104 */
interrupts-extended = <&gpio4 4 IRQ_TYPE_EDGE_RISING>; /* 100 */
touchscreen-fuzz-x = <4>;
touchscreen-fuzz-y = <7>;
touchscreen-fuzz-pressure = <2>;
touchscreen-max-x = <4096>;
touchscreen-max-y = <4096>;
touchscreen-max-pressure = <2048>;
ti,x-plate-ohms = <280>;
ti,esd-recovery-timeout-ms = <8000>;
};
}
...@@ -651,9 +651,24 @@ &mcspi1 { ...@@ -651,9 +651,24 @@ &mcspi1 {
* Also... order in the device tree actually matters here. * Also... order in the device tree actually matters here.
*/ */
tsc2005@0 { tsc2005@0 {
compatible = "tsc2005"; compatible = "ti,tsc2005";
spi-max-frequency = <6000000>; spi-max-frequency = <6000000>;
reg = <0>; reg = <0>;
vio-supply = <&vio>;
reset-gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>; /* 104 */
interrupts-extended = <&gpio4 4 IRQ_TYPE_EDGE_RISING>; /* 100 */
touchscreen-fuzz-x = <4>;
touchscreen-fuzz-y = <7>;
touchscreen-fuzz-pressure = <2>;
touchscreen-max-x = <4096>;
touchscreen-max-y = <4096>;
touchscreen-max-pressure = <2048>;
ti,x-plate-ohms = <280>;
ti,esd-recovery-timeout-ms = <8000>;
}; };
acx565akm@2 { acx565akm@2 {
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/pinctrl/machine.h> #include <linux/pinctrl/machine.h>
#include <linux/platform_data/omap4-keypad.h>
#include <linux/platform_data/mailbox-omap.h> #include <linux/platform_data/mailbox-omap.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
...@@ -29,7 +28,6 @@ ...@@ -29,7 +28,6 @@
#include "iomap.h" #include "iomap.h"
#include "omap_hwmod.h" #include "omap_hwmod.h"
#include "omap_device.h" #include "omap_device.h"
#include "omap4-keypad.h"
#include "soc.h" #include "soc.h"
#include "common.h" #include "common.h"
...@@ -255,37 +253,6 @@ static inline void omap_init_camera(void) ...@@ -255,37 +253,6 @@ static inline void omap_init_camera(void)
#endif #endif
} }
int __init omap4_keyboard_init(struct omap4_keypad_platform_data
*sdp4430_keypad_data, struct omap_board_data *bdata)
{
struct platform_device *pdev;
struct omap_hwmod *oh;
struct omap4_keypad_platform_data *keypad_data;
unsigned int id = -1;
char *oh_name = "kbd";
char *name = "omap4-keypad";
oh = omap_hwmod_lookup(oh_name);
if (!oh) {
pr_err("Could not look up %s\n", oh_name);
return -ENODEV;
}
keypad_data = sdp4430_keypad_data;
pdev = omap_device_build(name, id, oh, keypad_data,
sizeof(struct omap4_keypad_platform_data));
if (IS_ERR(pdev)) {
WARN(1, "Can't build omap_device for %s:%s.\n",
name, oh->name);
return PTR_ERR(pdev);
}
oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
return 0;
}
#if defined(CONFIG_OMAP2PLUS_MBOX) || defined(CONFIG_OMAP2PLUS_MBOX_MODULE) #if defined(CONFIG_OMAP2PLUS_MBOX) || defined(CONFIG_OMAP2PLUS_MBOX_MODULE)
static inline void __init omap_init_mbox(void) static inline void __init omap_init_mbox(void)
{ {
......
#ifndef ARCH_ARM_PLAT_OMAP4_KEYPAD_H
#define ARCH_ARM_PLAT_OMAP4_KEYPAD_H
struct omap_board_data;
extern int omap4_keyboard_init(struct omap4_keypad_platform_data *,
struct omap_board_data *);
#endif
...@@ -234,14 +234,6 @@ static void __init goni_radio_init(void) ...@@ -234,14 +234,6 @@ static void __init goni_radio_init(void)
/* TSP */ /* TSP */
static struct mxt_platform_data qt602240_platform_data = { static struct mxt_platform_data qt602240_platform_data = {
.x_line = 17,
.y_line = 11,
.x_size = 800,
.y_size = 480,
.blen = 0x21,
.threshold = 0x28,
.voltage = 2800000, /* 2.8V */
.orient = MXT_DIAGONAL,
.irqflags = IRQF_TRIGGER_FALLING, .irqflags = IRQF_TRIGGER_FALLING,
}; };
......
...@@ -629,12 +629,10 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) ...@@ -629,12 +629,10 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
return copy_to_user(p, str, len) ? -EFAULT : len; return copy_to_user(p, str, len) ? -EFAULT : len;
} }
#define OLD_KEY_MAX 0x1ff
static int handle_eviocgbit(struct input_dev *dev, static int handle_eviocgbit(struct input_dev *dev,
unsigned int type, unsigned int size, unsigned int type, unsigned int size,
void __user *p, int compat_mode) void __user *p, int compat_mode)
{ {
static unsigned long keymax_warn_time;
unsigned long *bits; unsigned long *bits;
int len; int len;
...@@ -652,24 +650,8 @@ static int handle_eviocgbit(struct input_dev *dev, ...@@ -652,24 +650,8 @@ static int handle_eviocgbit(struct input_dev *dev,
default: return -EINVAL; default: return -EINVAL;
} }
/*
* Work around bugs in userspace programs that like to do
* EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len'
* should be in bytes, not in bits.
*/
if (type == EV_KEY && size == OLD_KEY_MAX) {
len = OLD_KEY_MAX;
if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000))
pr_warning("(EVIOCGBIT): Suspicious buffer size %u, "
"limiting output to %zu bytes. See "
"http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n",
OLD_KEY_MAX,
BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long));
}
return bits_to_user(bits, len, size, p, compat_mode); return bits_to_user(bits, len, size, p, compat_mode);
} }
#undef OLD_KEY_MAX
static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p) static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p)
{ {
......
...@@ -147,6 +147,11 @@ static struct attribute_group input_polldev_attribute_group = { ...@@ -147,6 +147,11 @@ static struct attribute_group input_polldev_attribute_group = {
.attrs = sysfs_attrs .attrs = sysfs_attrs
}; };
static const struct attribute_group *input_polldev_attribute_groups[] = {
&input_polldev_attribute_group,
NULL
};
/** /**
* input_allocate_polled_device - allocate memory for polled device * input_allocate_polled_device - allocate memory for polled device
* *
...@@ -171,6 +176,91 @@ struct input_polled_dev *input_allocate_polled_device(void) ...@@ -171,6 +176,91 @@ struct input_polled_dev *input_allocate_polled_device(void)
} }
EXPORT_SYMBOL(input_allocate_polled_device); EXPORT_SYMBOL(input_allocate_polled_device);
struct input_polled_devres {
struct input_polled_dev *polldev;
};
static int devm_input_polldev_match(struct device *dev, void *res, void *data)
{
struct input_polled_devres *devres = res;
return devres->polldev == data;
}
static void devm_input_polldev_release(struct device *dev, void *res)
{
struct input_polled_devres *devres = res;
struct input_polled_dev *polldev = devres->polldev;
dev_dbg(dev, "%s: dropping reference/freeing %s\n",
__func__, dev_name(&polldev->input->dev));
input_put_device(polldev->input);
kfree(polldev);
}
static void devm_input_polldev_unregister(struct device *dev, void *res)
{
struct input_polled_devres *devres = res;
struct input_polled_dev *polldev = devres->polldev;
dev_dbg(dev, "%s: unregistering device %s\n",
__func__, dev_name(&polldev->input->dev));
input_unregister_device(polldev->input);
/*
* Note that we are still holding extra reference to the input
* device so it will stick around until devm_input_polldev_release()
* is called.
*/
}
/**
* devm_input_allocate_polled_device - allocate managed polled device
* @dev: device owning the polled device being created
*
* Returns prepared &struct input_polled_dev or %NULL.
*
* Managed polled input devices do not need to be explicitly unregistered
* or freed as it will be done automatically when owner device unbinds
* from * its driver (or binding fails). Once such managed polled device
* is allocated, it is ready to be set up and registered in the same
* fashion as regular polled input devices (using
* input_register_polled_device() function).
*
* If you want to manually unregister and free such managed polled devices,
* it can be still done by calling input_unregister_polled_device() and
* input_free_polled_device(), although it is rarely needed.
*
* NOTE: the owner device is set up as parent of input device and users
* should not override it.
*/
struct input_polled_dev *devm_input_allocate_polled_device(struct device *dev)
{
struct input_polled_dev *polldev;
struct input_polled_devres *devres;
devres = devres_alloc(devm_input_polldev_release, sizeof(*devres),
GFP_KERNEL);
if (!devres)
return NULL;
polldev = input_allocate_polled_device();
if (!polldev) {
devres_free(devres);
return NULL;
}
polldev->input->dev.parent = dev;
polldev->devres_managed = true;
devres->polldev = polldev;
devres_add(dev, devres);
return polldev;
}
EXPORT_SYMBOL(devm_input_allocate_polled_device);
/** /**
* input_free_polled_device - free memory allocated for polled device * input_free_polled_device - free memory allocated for polled device
* @dev: device to free * @dev: device to free
...@@ -181,7 +271,12 @@ EXPORT_SYMBOL(input_allocate_polled_device); ...@@ -181,7 +271,12 @@ EXPORT_SYMBOL(input_allocate_polled_device);
void input_free_polled_device(struct input_polled_dev *dev) void input_free_polled_device(struct input_polled_dev *dev)
{ {
if (dev) { if (dev) {
input_free_device(dev->input); if (dev->devres_managed)
WARN_ON(devres_destroy(dev->input->dev.parent,
devm_input_polldev_release,
devm_input_polldev_match,
dev));
input_put_device(dev->input);
kfree(dev); kfree(dev);
} }
} }
...@@ -199,26 +294,35 @@ EXPORT_SYMBOL(input_free_polled_device); ...@@ -199,26 +294,35 @@ EXPORT_SYMBOL(input_free_polled_device);
*/ */
int input_register_polled_device(struct input_polled_dev *dev) int input_register_polled_device(struct input_polled_dev *dev)
{ {
struct input_polled_devres *devres = NULL;
struct input_dev *input = dev->input; struct input_dev *input = dev->input;
int error; int error;
if (dev->devres_managed) {
devres = devres_alloc(devm_input_polldev_unregister,
sizeof(*devres), GFP_KERNEL);
if (!devres)
return -ENOMEM;
devres->polldev = dev;
}
input_set_drvdata(input, dev); input_set_drvdata(input, dev);
INIT_DELAYED_WORK(&dev->work, input_polled_device_work); INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
if (!dev->poll_interval) if (!dev->poll_interval)
dev->poll_interval = 500; dev->poll_interval = 500;
if (!dev->poll_interval_max) if (!dev->poll_interval_max)
dev->poll_interval_max = dev->poll_interval; dev->poll_interval_max = dev->poll_interval;
input->open = input_open_polled_device; input->open = input_open_polled_device;
input->close = input_close_polled_device; input->close = input_close_polled_device;
error = input_register_device(input); input->dev.groups = input_polldev_attribute_groups;
if (error)
return error;
error = sysfs_create_group(&input->dev.kobj, error = input_register_device(input);
&input_polldev_attribute_group);
if (error) { if (error) {
input_unregister_device(input); devres_free(devres);
return error; return error;
} }
...@@ -231,6 +335,12 @@ int input_register_polled_device(struct input_polled_dev *dev) ...@@ -231,6 +335,12 @@ int input_register_polled_device(struct input_polled_dev *dev)
*/ */
input_get_device(input); input_get_device(input);
if (dev->devres_managed) {
dev_dbg(input->dev.parent, "%s: registering %s with devres.\n",
__func__, dev_name(&input->dev));
devres_add(input->dev.parent, devres);
}
return 0; return 0;
} }
EXPORT_SYMBOL(input_register_polled_device); EXPORT_SYMBOL(input_register_polled_device);
...@@ -245,8 +355,11 @@ EXPORT_SYMBOL(input_register_polled_device); ...@@ -245,8 +355,11 @@ EXPORT_SYMBOL(input_register_polled_device);
*/ */
void input_unregister_polled_device(struct input_polled_dev *dev) void input_unregister_polled_device(struct input_polled_dev *dev)
{ {
sysfs_remove_group(&dev->input->dev.kobj, if (dev->devres_managed)
&input_polldev_attribute_group); WARN_ON(devres_destroy(dev->input->dev.parent,
devm_input_polldev_unregister,
devm_input_polldev_match,
dev));
input_unregister_device(dev->input); input_unregister_device(dev->input);
} }
......
...@@ -524,6 +524,17 @@ config KEYBOARD_STOWAWAY ...@@ -524,6 +524,17 @@ config KEYBOARD_STOWAWAY
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called stowaway. module will be called stowaway.
config KEYBOARD_ST_KEYSCAN
tristate "STMicroelectronics keyscan support"
depends on ARCH_STI || COMPILE_TEST
select INPUT_MATRIXKMAP
help
Say Y here if you want to use a keypad attached to the keyscan block
on some STMicroelectronics SoC devices.
To compile this driver as a module, choose M here: the
module will be called st-keyscan.
config KEYBOARD_SUNKBD config KEYBOARD_SUNKBD
tristate "Sun Type 4 and Type 5 keyboard" tristate "Sun Type 4 and Type 5 keyboard"
select SERIO select SERIO
...@@ -578,7 +589,7 @@ config KEYBOARD_OMAP ...@@ -578,7 +589,7 @@ config KEYBOARD_OMAP
config KEYBOARD_OMAP4 config KEYBOARD_OMAP4
tristate "TI OMAP4+ keypad support" tristate "TI OMAP4+ keypad support"
depends on ARCH_OMAP2PLUS depends on OF || ARCH_OMAP2PLUS
select INPUT_MATRIXKMAP select INPUT_MATRIXKMAP
help help
Say Y here if you want to use the OMAP4+ keypad. Say Y here if you want to use the OMAP4+ keypad.
......
...@@ -51,6 +51,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o ...@@ -51,6 +51,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o
obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_ST_KEYSCAN) += st-keyscan.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o
obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/mfd/adp5520.h> #include <linux/mfd/adp5520.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h>
struct adp5520_keys { struct adp5520_keys {
struct input_dev *input; struct input_dev *input;
...@@ -81,7 +82,7 @@ static int adp5520_keys_probe(struct platform_device *pdev) ...@@ -81,7 +82,7 @@ static int adp5520_keys_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
if (pdata == NULL) { if (!pdata) {
dev_err(&pdev->dev, "missing platform data\n"); dev_err(&pdev->dev, "missing platform data\n");
return -EINVAL; return -EINVAL;
} }
...@@ -89,17 +90,15 @@ static int adp5520_keys_probe(struct platform_device *pdev) ...@@ -89,17 +90,15 @@ static int adp5520_keys_probe(struct platform_device *pdev)
if (!(pdata->rows_en_mask && pdata->cols_en_mask)) if (!(pdata->rows_en_mask && pdata->cols_en_mask))
return -EINVAL; return -EINVAL;
dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (dev == NULL) { if (!dev) {
dev_err(&pdev->dev, "failed to alloc memory\n"); dev_err(&pdev->dev, "failed to alloc memory\n");
return -ENOMEM; return -ENOMEM;
} }
input = input_allocate_device(); input = devm_input_allocate_device(&pdev->dev);
if (!input) { if (!input)
ret = -ENOMEM; return -ENOMEM;
goto err;
}
dev->master = pdev->dev.parent; dev->master = pdev->dev.parent;
dev->input = input; dev->input = input;
...@@ -135,7 +134,7 @@ static int adp5520_keys_probe(struct platform_device *pdev) ...@@ -135,7 +134,7 @@ static int adp5520_keys_probe(struct platform_device *pdev)
ret = input_register_device(input); ret = input_register_device(input);
if (ret) { if (ret) {
dev_err(&pdev->dev, "unable to register input device\n"); dev_err(&pdev->dev, "unable to register input device\n");
goto err; return ret;
} }
en_mask = pdata->rows_en_mask | pdata->cols_en_mask; en_mask = pdata->rows_en_mask | pdata->cols_en_mask;
...@@ -157,8 +156,7 @@ static int adp5520_keys_probe(struct platform_device *pdev) ...@@ -157,8 +156,7 @@ static int adp5520_keys_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to write\n"); dev_err(&pdev->dev, "failed to write\n");
ret = -EIO; return -EIO;
goto err1;
} }
dev->notifier.notifier_call = adp5520_keys_notifier; dev->notifier.notifier_call = adp5520_keys_notifier;
...@@ -166,19 +164,11 @@ static int adp5520_keys_probe(struct platform_device *pdev) ...@@ -166,19 +164,11 @@ static int adp5520_keys_probe(struct platform_device *pdev)
ADP5520_KP_IEN | ADP5520_KR_IEN); ADP5520_KP_IEN | ADP5520_KR_IEN);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register notifier\n"); dev_err(&pdev->dev, "failed to register notifier\n");
goto err1; return ret;
} }
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
return 0; return 0;
err1:
input_unregister_device(input);
input = NULL;
err:
input_free_device(input);
kfree(dev);
return ret;
} }
static int adp5520_keys_remove(struct platform_device *pdev) static int adp5520_keys_remove(struct platform_device *pdev)
...@@ -188,8 +178,6 @@ static int adp5520_keys_remove(struct platform_device *pdev) ...@@ -188,8 +178,6 @@ static int adp5520_keys_remove(struct platform_device *pdev)
adp5520_unregister_notifier(dev->master, &dev->notifier, adp5520_unregister_notifier(dev->master, &dev->notifier,
ADP5520_KP_IEN | ADP5520_KR_IEN); ADP5520_KP_IEN | ADP5520_KR_IEN);
input_unregister_device(dev->input);
kfree(dev);
return 0; return 0;
} }
......
...@@ -185,7 +185,7 @@ static int clps711x_keypad_remove(struct platform_device *pdev) ...@@ -185,7 +185,7 @@ static int clps711x_keypad_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct of_device_id clps711x_keypad_of_match[] = { static const struct of_device_id clps711x_keypad_of_match[] = {
{ .compatible = "cirrus,clps711x-keypad", }, { .compatible = "cirrus,clps711x-keypad", },
{ } { }
}; };
......
...@@ -424,6 +424,16 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) ...@@ -424,6 +424,16 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void gpio_keys_quiesce_key(void *data)
{
struct gpio_button_data *bdata = data;
if (bdata->timer_debounce)
del_timer_sync(&bdata->timer);
cancel_work_sync(&bdata->work);
}
static int gpio_keys_setup_key(struct platform_device *pdev, static int gpio_keys_setup_key(struct platform_device *pdev,
struct input_dev *input, struct input_dev *input,
struct gpio_button_data *bdata, struct gpio_button_data *bdata,
...@@ -433,7 +443,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -433,7 +443,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
irq_handler_t isr; irq_handler_t isr;
unsigned long irqflags; unsigned long irqflags;
int irq, error; int irq;
int error;
bdata->input = input; bdata->input = input;
bdata->button = button; bdata->button = button;
...@@ -441,7 +452,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -441,7 +452,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
if (gpio_is_valid(button->gpio)) { if (gpio_is_valid(button->gpio)) {
error = gpio_request_one(button->gpio, GPIOF_IN, desc); error = devm_gpio_request_one(&pdev->dev, button->gpio,
GPIOF_IN, desc);
if (error < 0) { if (error < 0) {
dev_err(dev, "Failed to request GPIO %d, error %d\n", dev_err(dev, "Failed to request GPIO %d, error %d\n",
button->gpio, error); button->gpio, error);
...@@ -463,7 +475,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -463,7 +475,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
dev_err(dev, dev_err(dev,
"Unable to get irq number for GPIO %d, error %d\n", "Unable to get irq number for GPIO %d, error %d\n",
button->gpio, error); button->gpio, error);
goto fail; return error;
} }
bdata->irq = irq; bdata->irq = irq;
...@@ -496,6 +508,18 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -496,6 +508,18 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
input_set_capability(input, button->type ?: EV_KEY, button->code); input_set_capability(input, button->type ?: EV_KEY, button->code);
/*
* Install custom action to cancel debounce timer and
* workqueue item.
*/
error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata);
if (error) {
dev_err(&pdev->dev,
"failed to register quiesce action, error: %d\n",
error);
return error;
}
/* /*
* If platform has specified that the button can be disabled, * If platform has specified that the button can be disabled,
* we don't want it to share the interrupt line. * we don't want it to share the interrupt line.
...@@ -503,20 +527,15 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -503,20 +527,15 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
if (!button->can_disable) if (!button->can_disable)
irqflags |= IRQF_SHARED; irqflags |= IRQF_SHARED;
error = request_any_context_irq(bdata->irq, isr, irqflags, desc, bdata); error = devm_request_any_context_irq(&pdev->dev, bdata->irq,
isr, irqflags, desc, bdata);
if (error < 0) { if (error < 0) {
dev_err(dev, "Unable to claim irq %d; error %d\n", dev_err(dev, "Unable to claim irq %d; error %d\n",
bdata->irq, error); bdata->irq, error);
goto fail; return error;
} }
return 0; return 0;
fail:
if (gpio_is_valid(button->gpio))
gpio_free(button->gpio);
return error;
} }
static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata)
...@@ -578,23 +597,18 @@ gpio_keys_get_devtree_pdata(struct device *dev) ...@@ -578,23 +597,18 @@ gpio_keys_get_devtree_pdata(struct device *dev)
int i; int i;
node = dev->of_node; node = dev->of_node;
if (!node) { if (!node)
error = -ENODEV; return ERR_PTR(-ENODEV);
goto err_out;
}
nbuttons = of_get_child_count(node); nbuttons = of_get_child_count(node);
if (nbuttons == 0) { if (nbuttons == 0)
error = -ENODEV; return ERR_PTR(-ENODEV);
goto err_out;
}
pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), pdata = devm_kzalloc(dev,
GFP_KERNEL); sizeof(*pdata) + nbuttons * sizeof(*button),
if (!pdata) { GFP_KERNEL);
error = -ENOMEM; if (!pdata)
goto err_out; return ERR_PTR(-ENOMEM);
}
pdata->buttons = (struct gpio_keys_button *)(pdata + 1); pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
pdata->nbuttons = nbuttons; pdata->nbuttons = nbuttons;
...@@ -619,7 +633,7 @@ gpio_keys_get_devtree_pdata(struct device *dev) ...@@ -619,7 +633,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)
dev_err(dev, dev_err(dev,
"Failed to get gpio flags, error: %d\n", "Failed to get gpio flags, error: %d\n",
error); error);
goto err_free_pdata; return ERR_PTR(error);
} }
button = &pdata->buttons[i++]; button = &pdata->buttons[i++];
...@@ -630,8 +644,7 @@ gpio_keys_get_devtree_pdata(struct device *dev) ...@@ -630,8 +644,7 @@ gpio_keys_get_devtree_pdata(struct device *dev)
if (of_property_read_u32(pp, "linux,code", &button->code)) { if (of_property_read_u32(pp, "linux,code", &button->code)) {
dev_err(dev, "Button without keycode: 0x%x\n", dev_err(dev, "Button without keycode: 0x%x\n",
button->gpio); button->gpio);
error = -EINVAL; return ERR_PTR(-EINVAL);
goto err_free_pdata;
} }
button->desc = of_get_property(pp, "label", NULL); button->desc = of_get_property(pp, "label", NULL);
...@@ -646,20 +659,13 @@ gpio_keys_get_devtree_pdata(struct device *dev) ...@@ -646,20 +659,13 @@ gpio_keys_get_devtree_pdata(struct device *dev)
button->debounce_interval = 5; button->debounce_interval = 5;
} }
if (pdata->nbuttons == 0) { if (pdata->nbuttons == 0)
error = -EINVAL; return ERR_PTR(-EINVAL);
goto err_free_pdata;
}
return pdata; return pdata;
err_free_pdata:
kfree(pdata);
err_out:
return ERR_PTR(error);
} }
static struct of_device_id gpio_keys_of_match[] = { static const struct of_device_id gpio_keys_of_match[] = {
{ .compatible = "gpio-keys", }, { .compatible = "gpio-keys", },
{ }, { },
}; };
...@@ -675,22 +681,13 @@ gpio_keys_get_devtree_pdata(struct device *dev) ...@@ -675,22 +681,13 @@ gpio_keys_get_devtree_pdata(struct device *dev)
#endif #endif
static void gpio_remove_key(struct gpio_button_data *bdata)
{
free_irq(bdata->irq, bdata);
if (bdata->timer_debounce)
del_timer_sync(&bdata->timer);
cancel_work_sync(&bdata->work);
if (gpio_is_valid(bdata->button->gpio))
gpio_free(bdata->button->gpio);
}
static int gpio_keys_probe(struct platform_device *pdev) static int gpio_keys_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
struct gpio_keys_drvdata *ddata; struct gpio_keys_drvdata *ddata;
struct input_dev *input; struct input_dev *input;
size_t size;
int i, error; int i, error;
int wakeup = 0; int wakeup = 0;
...@@ -700,14 +697,18 @@ static int gpio_keys_probe(struct platform_device *pdev) ...@@ -700,14 +697,18 @@ static int gpio_keys_probe(struct platform_device *pdev)
return PTR_ERR(pdata); return PTR_ERR(pdata);
} }
ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + size = sizeof(struct gpio_keys_drvdata) +
pdata->nbuttons * sizeof(struct gpio_button_data), pdata->nbuttons * sizeof(struct gpio_button_data);
GFP_KERNEL); ddata = devm_kzalloc(dev, size, GFP_KERNEL);
input = input_allocate_device(); if (!ddata) {
if (!ddata || !input) {
dev_err(dev, "failed to allocate state\n"); dev_err(dev, "failed to allocate state\n");
error = -ENOMEM; return -ENOMEM;
goto fail1; }
input = devm_input_allocate_device(dev);
if (!input) {
dev_err(dev, "failed to allocate input device\n");
return -ENOMEM;
} }
ddata->pdata = pdata; ddata->pdata = pdata;
...@@ -738,7 +739,7 @@ static int gpio_keys_probe(struct platform_device *pdev) ...@@ -738,7 +739,7 @@ static int gpio_keys_probe(struct platform_device *pdev)
error = gpio_keys_setup_key(pdev, input, bdata, button); error = gpio_keys_setup_key(pdev, input, bdata, button);
if (error) if (error)
goto fail2; return error;
if (button->wakeup) if (button->wakeup)
wakeup = 1; wakeup = 1;
...@@ -748,57 +749,31 @@ static int gpio_keys_probe(struct platform_device *pdev) ...@@ -748,57 +749,31 @@ static int gpio_keys_probe(struct platform_device *pdev)
if (error) { if (error) {
dev_err(dev, "Unable to export keys/switches, error: %d\n", dev_err(dev, "Unable to export keys/switches, error: %d\n",
error); error);
goto fail2; return error;
} }
error = input_register_device(input); error = input_register_device(input);
if (error) { if (error) {
dev_err(dev, "Unable to register input device, error: %d\n", dev_err(dev, "Unable to register input device, error: %d\n",
error); error);
goto fail3; goto err_remove_group;
} }
device_init_wakeup(&pdev->dev, wakeup); device_init_wakeup(&pdev->dev, wakeup);
return 0; return 0;
fail3: err_remove_group:
sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
fail2:
while (--i >= 0)
gpio_remove_key(&ddata->data[i]);
fail1:
input_free_device(input);
kfree(ddata);
/* If we have no platform data, we allocated pdata dynamically. */
if (!dev_get_platdata(&pdev->dev))
kfree(pdata);
return error; return error;
} }
static int gpio_keys_remove(struct platform_device *pdev) static int gpio_keys_remove(struct platform_device *pdev)
{ {
struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
struct input_dev *input = ddata->input;
int i;
sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
device_init_wakeup(&pdev->dev, 0); device_init_wakeup(&pdev->dev, 0);
for (i = 0; i < ddata->pdata->nbuttons; i++)
gpio_remove_key(&ddata->data[i]);
input_unregister_device(input);
/* If we have no platform data, we allocated pdata dynamically. */
if (!dev_get_platdata(&pdev->dev))
kfree(ddata->pdata);
kfree(ddata);
return 0; return 0;
} }
......
...@@ -120,12 +120,10 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct ...@@ -120,12 +120,10 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
if (nbuttons == 0) if (nbuttons == 0)
return NULL; return NULL;
pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons * sizeof(*button),
GFP_KERNEL); GFP_KERNEL);
if (!pdata) { if (!pdata)
error = -ENOMEM; return ERR_PTR(-ENOMEM);
goto err_out;
}
pdata->buttons = (struct gpio_keys_button *)(pdata + 1); pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
pdata->nbuttons = nbuttons; pdata->nbuttons = nbuttons;
...@@ -151,7 +149,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct ...@@ -151,7 +149,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
dev_err(dev, dev_err(dev,
"Failed to get gpio flags, error: %d\n", "Failed to get gpio flags, error: %d\n",
error); error);
goto err_free_pdata; return ERR_PTR(error);
} }
button = &pdata->buttons[i++]; button = &pdata->buttons[i++];
...@@ -162,8 +160,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct ...@@ -162,8 +160,7 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
if (of_property_read_u32(pp, "linux,code", &button->code)) { if (of_property_read_u32(pp, "linux,code", &button->code)) {
dev_err(dev, "Button without keycode: 0x%x\n", dev_err(dev, "Button without keycode: 0x%x\n",
button->gpio); button->gpio);
error = -EINVAL; return ERR_PTR(-EINVAL);
goto err_free_pdata;
} }
button->desc = of_get_property(pp, "label", NULL); button->desc = of_get_property(pp, "label", NULL);
...@@ -178,20 +175,13 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct ...@@ -178,20 +175,13 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
button->debounce_interval = 5; button->debounce_interval = 5;
} }
if (pdata->nbuttons == 0) { if (pdata->nbuttons == 0)
error = -EINVAL; return ERR_PTR(-EINVAL);
goto err_free_pdata;
}
return pdata; return pdata;
err_free_pdata:
kfree(pdata);
err_out:
return ERR_PTR(error);
} }
static struct of_device_id gpio_keys_polled_of_match[] = { static const struct of_device_id gpio_keys_polled_of_match[] = {
{ .compatible = "gpio-keys-polled", }, { .compatible = "gpio-keys-polled", },
{ }, { },
}; };
...@@ -213,6 +203,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) ...@@ -213,6 +203,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
struct gpio_keys_polled_dev *bdev; struct gpio_keys_polled_dev *bdev;
struct input_polled_dev *poll_dev; struct input_polled_dev *poll_dev;
struct input_dev *input; struct input_dev *input;
size_t size;
int error; int error;
int i; int i;
...@@ -228,24 +219,21 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) ...@@ -228,24 +219,21 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
if (!pdata->poll_interval) { if (!pdata->poll_interval) {
dev_err(dev, "missing poll_interval value\n"); dev_err(dev, "missing poll_interval value\n");
error = -EINVAL; return -EINVAL;
goto err_free_pdata;
} }
bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) + size = sizeof(struct gpio_keys_polled_dev) +
pdata->nbuttons * sizeof(struct gpio_keys_button_data), pdata->nbuttons * sizeof(struct gpio_keys_button_data);
GFP_KERNEL); bdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!bdev) { if (!bdev) {
dev_err(dev, "no memory for private data\n"); dev_err(dev, "no memory for private data\n");
error = -ENOMEM; return -ENOMEM;
goto err_free_pdata;
} }
poll_dev = input_allocate_polled_device(); poll_dev = devm_input_allocate_polled_device(&pdev->dev);
if (!poll_dev) { if (!poll_dev) {
dev_err(dev, "no memory for polled device\n"); dev_err(dev, "no memory for polled device\n");
error = -ENOMEM; return -ENOMEM;
goto err_free_bdev;
} }
poll_dev->private = bdev; poll_dev->private = bdev;
...@@ -258,7 +246,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) ...@@ -258,7 +246,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
input->name = pdev->name; input->name = pdev->name;
input->phys = DRV_NAME"/input0"; input->phys = DRV_NAME"/input0";
input->dev.parent = &pdev->dev;
input->id.bustype = BUS_HOST; input->id.bustype = BUS_HOST;
input->id.vendor = 0x0001; input->id.vendor = 0x0001;
...@@ -277,16 +264,15 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) ...@@ -277,16 +264,15 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
if (button->wakeup) { if (button->wakeup) {
dev_err(dev, DRV_NAME " does not support wakeup\n"); dev_err(dev, DRV_NAME " does not support wakeup\n");
error = -EINVAL; return -EINVAL;
goto err_free_gpio;
} }
error = gpio_request_one(gpio, GPIOF_IN, error = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_IN,
button->desc ?: DRV_NAME); button->desc ? : DRV_NAME);
if (error) { if (error) {
dev_err(dev, "unable to claim gpio %u, err=%d\n", dev_err(dev, "unable to claim gpio %u, err=%d\n",
gpio, error); gpio, error);
goto err_free_gpio; return error;
} }
bdata->can_sleep = gpio_cansleep(gpio); bdata->can_sleep = gpio_cansleep(gpio);
...@@ -306,7 +292,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) ...@@ -306,7 +292,7 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
if (error) { if (error) {
dev_err(dev, "unable to register polled device, err=%d\n", dev_err(dev, "unable to register polled device, err=%d\n",
error); error);
goto err_free_gpio; return error;
} }
/* report initial state of the buttons */ /* report initial state of the buttons */
...@@ -315,52 +301,10 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) ...@@ -315,52 +301,10 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
&bdev->data[i]); &bdev->data[i]);
return 0; return 0;
err_free_gpio:
while (--i >= 0)
gpio_free(pdata->buttons[i].gpio);
input_free_polled_device(poll_dev);
err_free_bdev:
kfree(bdev);
err_free_pdata:
/* If we have no platform_data, we allocated pdata dynamically. */
if (!dev_get_platdata(&pdev->dev))
kfree(pdata);
return error;
}
static int gpio_keys_polled_remove(struct platform_device *pdev)
{
struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
const struct gpio_keys_platform_data *pdata = bdev->pdata;
int i;
input_unregister_polled_device(bdev->poll_dev);
for (i = 0; i < pdata->nbuttons; i++)
gpio_free(pdata->buttons[i].gpio);
input_free_polled_device(bdev->poll_dev);
/*
* If we had no platform_data, we allocated pdata dynamically and
* must free it here.
*/
if (!dev_get_platdata(&pdev->dev))
kfree(pdata);
kfree(bdev);
return 0;
} }
static struct platform_driver gpio_keys_polled_driver = { static struct platform_driver gpio_keys_polled_driver = {
.probe = gpio_keys_polled_probe, .probe = gpio_keys_polled_probe,
.remove = gpio_keys_polled_remove,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -415,7 +415,7 @@ static int imx_keypad_open(struct input_dev *dev) ...@@ -415,7 +415,7 @@ static int imx_keypad_open(struct input_dev *dev)
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id imx_keypad_of_match[] = { static const struct of_device_id imx_keypad_of_match[] = {
{ .compatible = "fsl,imx21-kpp", }, { .compatible = "fsl,imx21-kpp", },
{ /* sentinel */ } { /* sentinel */ }
}; };
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <linux/device.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input-polldev.h> #include <linux/input-polldev.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -185,14 +186,15 @@ static int jornada680kbd_probe(struct platform_device *pdev) ...@@ -185,14 +186,15 @@ static int jornada680kbd_probe(struct platform_device *pdev)
struct input_dev *input_dev; struct input_dev *input_dev;
int i, error; int i, error;
jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL); jornadakbd = devm_kzalloc(&pdev->dev, sizeof(struct jornadakbd),
GFP_KERNEL);
if (!jornadakbd) if (!jornadakbd)
return -ENOMEM; return -ENOMEM;
poll_dev = input_allocate_polled_device(); poll_dev = devm_input_allocate_polled_device(&pdev->dev);
if (!poll_dev) { if (!poll_dev) {
error = -ENOMEM; dev_err(&pdev->dev, "failed to allocate polled input device\n");
goto failed; return -ENOMEM;
} }
platform_set_drvdata(pdev, jornadakbd); platform_set_drvdata(pdev, jornadakbd);
...@@ -224,27 +226,10 @@ static int jornada680kbd_probe(struct platform_device *pdev) ...@@ -224,27 +226,10 @@ static int jornada680kbd_probe(struct platform_device *pdev)
input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_capability(input_dev, EV_MSC, MSC_SCAN);
error = input_register_polled_device(jornadakbd->poll_dev); error = input_register_polled_device(jornadakbd->poll_dev);
if (error) if (error) {
goto failed; dev_err(&pdev->dev, "failed to register polled input device\n");
return error;
return 0; }
failed:
printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n",
error);
input_free_polled_device(poll_dev);
kfree(jornadakbd);
return error;
}
static int jornada680kbd_remove(struct platform_device *pdev)
{
struct jornadakbd *jornadakbd = platform_get_drvdata(pdev);
input_unregister_polled_device(jornadakbd->poll_dev);
input_free_polled_device(jornadakbd->poll_dev);
kfree(jornadakbd);
return 0; return 0;
} }
...@@ -255,7 +240,6 @@ static struct platform_driver jornada680kbd_driver = { ...@@ -255,7 +240,6 @@ static struct platform_driver jornada680kbd_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = jornada680kbd_probe, .probe = jornada680kbd_probe,
.remove = jornada680kbd_remove,
}; };
module_platform_driver(jornada680kbd_driver); module_platform_driver(jornada680kbd_driver);
......
...@@ -147,7 +147,7 @@ static int mcs_touchkey_probe(struct i2c_client *client, ...@@ -147,7 +147,7 @@ static int mcs_touchkey_probe(struct i2c_client *client,
} }
dev_info(&client->dev, "Firmware version: %d\n", fw_ver); dev_info(&client->dev, "Firmware version: %d\n", fw_ver);
input_dev->name = "MELPAS MCS Touchkey"; input_dev->name = "MELFAS MCS Touchkey";
input_dev->id.bustype = BUS_I2C; input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev; input_dev->dev.parent = &client->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY); input_dev->evbit[0] = BIT_MASK(EV_KEY);
......
...@@ -28,11 +28,10 @@ ...@@ -28,11 +28,10 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/matrix_keypad.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/platform_data/omap4-keypad.h>
/* OMAP4 registers */ /* OMAP4 registers */
#define OMAP4_KBD_REVISION 0x00 #define OMAP4_KBD_REVISION 0x00
#define OMAP4_KBD_SYSCONFIG 0x10 #define OMAP4_KBD_SYSCONFIG 0x10
...@@ -218,7 +217,6 @@ static void omap4_keypad_close(struct input_dev *input) ...@@ -218,7 +217,6 @@ static void omap4_keypad_close(struct input_dev *input)
pm_runtime_put_sync(input->dev.parent); pm_runtime_put_sync(input->dev.parent);
} }
#ifdef CONFIG_OF
static int omap4_keypad_parse_dt(struct device *dev, static int omap4_keypad_parse_dt(struct device *dev,
struct omap4_keypad *keypad_data) struct omap4_keypad *keypad_data)
{ {
...@@ -235,20 +233,9 @@ static int omap4_keypad_parse_dt(struct device *dev, ...@@ -235,20 +233,9 @@ static int omap4_keypad_parse_dt(struct device *dev,
return 0; return 0;
} }
#else
static inline int omap4_keypad_parse_dt(struct device *dev,
struct omap4_keypad *keypad_data)
{
return -ENOSYS;
}
#endif
static int omap4_keypad_probe(struct platform_device *pdev) static int omap4_keypad_probe(struct platform_device *pdev)
{ {
const struct omap4_keypad_platform_data *pdata =
dev_get_platdata(&pdev->dev);
const struct matrix_keymap_data *keymap_data =
pdata ? pdata->keymap_data : NULL;
struct omap4_keypad *keypad_data; struct omap4_keypad *keypad_data;
struct input_dev *input_dev; struct input_dev *input_dev;
struct resource *res; struct resource *res;
...@@ -277,14 +264,9 @@ static int omap4_keypad_probe(struct platform_device *pdev) ...@@ -277,14 +264,9 @@ static int omap4_keypad_probe(struct platform_device *pdev)
keypad_data->irq = irq; keypad_data->irq = irq;
if (pdata) { error = omap4_keypad_parse_dt(&pdev->dev, keypad_data);
keypad_data->rows = pdata->rows; if (error)
keypad_data->cols = pdata->cols; return error;
} else {
error = omap4_keypad_parse_dt(&pdev->dev, keypad_data);
if (error)
return error;
}
res = request_mem_region(res->start, resource_size(res), pdev->name); res = request_mem_region(res->start, resource_size(res), pdev->name);
if (!res) { if (!res) {
...@@ -363,7 +345,7 @@ static int omap4_keypad_probe(struct platform_device *pdev) ...@@ -363,7 +345,7 @@ static int omap4_keypad_probe(struct platform_device *pdev)
goto err_free_input; goto err_free_input;
} }
error = matrix_keypad_build_keymap(keymap_data, NULL, error = matrix_keypad_build_keymap(NULL, NULL,
keypad_data->rows, keypad_data->cols, keypad_data->rows, keypad_data->cols,
keypad_data->keymap, input_dev); keypad_data->keymap, input_dev);
if (error) { if (error) {
...@@ -434,13 +416,11 @@ static int omap4_keypad_remove(struct platform_device *pdev) ...@@ -434,13 +416,11 @@ static int omap4_keypad_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_OF
static const struct of_device_id omap_keypad_dt_match[] = { static const struct of_device_id omap_keypad_dt_match[] = {
{ .compatible = "ti,omap4-keypad" }, { .compatible = "ti,omap4-keypad" },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, omap_keypad_dt_match); MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
#endif
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int omap4_keypad_suspend(struct device *dev) static int omap4_keypad_suspend(struct device *dev)
...@@ -482,7 +462,7 @@ static struct platform_driver omap4_keypad_driver = { ...@@ -482,7 +462,7 @@ static struct platform_driver omap4_keypad_driver = {
.name = "omap4-keypad", .name = "omap4-keypad",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &omap4_keypad_pm_ops, .pm = &omap4_keypad_pm_ops,
.of_match_table = of_match_ptr(omap_keypad_dt_match), .of_match_table = omap_keypad_dt_match,
}, },
}; };
module_platform_driver(omap4_keypad_driver); module_platform_driver(omap4_keypad_driver);
......
/*
* STMicroelectronics Key Scanning driver
*
* Copyright (c) 2014 STMicroelectonics Ltd.
* Author: Stuart Menefy <stuart.menefy@st.com>
*
* Based on sh_keysc.c, copyright 2008 Magnus Damm
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/input/matrix_keypad.h>
#define ST_KEYSCAN_MAXKEYS 16
#define KEYSCAN_CONFIG_OFF 0x0
#define KEYSCAN_CONFIG_ENABLE 0x1
#define KEYSCAN_DEBOUNCE_TIME_OFF 0x4
#define KEYSCAN_MATRIX_STATE_OFF 0x8
#define KEYSCAN_MATRIX_DIM_OFF 0xc
#define KEYSCAN_MATRIX_DIM_X_SHIFT 0x0
#define KEYSCAN_MATRIX_DIM_Y_SHIFT 0x2
struct st_keyscan {
void __iomem *base;
int irq;
struct clk *clk;
struct input_dev *input_dev;
unsigned long last_state;
unsigned int n_rows;
unsigned int n_cols;
unsigned int debounce_us;
};
static irqreturn_t keyscan_isr(int irq, void *dev_id)
{
struct st_keyscan *keypad = dev_id;
unsigned short *keycode = keypad->input_dev->keycode;
unsigned long state, change;
int bit_nr;
state = readl(keypad->base + KEYSCAN_MATRIX_STATE_OFF) & 0xffff;
change = keypad->last_state ^ state;
keypad->last_state = state;
for_each_set_bit(bit_nr, &change, BITS_PER_LONG)
input_report_key(keypad->input_dev,
keycode[bit_nr], state & BIT(bit_nr));
input_sync(keypad->input_dev);
return IRQ_HANDLED;
}
static int keyscan_start(struct st_keyscan *keypad)
{
int error;
error = clk_enable(keypad->clk);
if (error)
return error;
writel(keypad->debounce_us * (clk_get_rate(keypad->clk) / 1000000),
keypad->base + KEYSCAN_DEBOUNCE_TIME_OFF);
writel(((keypad->n_cols - 1) << KEYSCAN_MATRIX_DIM_X_SHIFT) |
((keypad->n_rows - 1) << KEYSCAN_MATRIX_DIM_Y_SHIFT),
keypad->base + KEYSCAN_MATRIX_DIM_OFF);
writel(KEYSCAN_CONFIG_ENABLE, keypad->base + KEYSCAN_CONFIG_OFF);
return 0;
}
static void keyscan_stop(struct st_keyscan *keypad)
{
writel(0, keypad->base + KEYSCAN_CONFIG_OFF);
clk_disable(keypad->clk);
}
static int keyscan_open(struct input_dev *dev)
{
struct st_keyscan *keypad = input_get_drvdata(dev);
return keyscan_start(keypad);
}
static void keyscan_close(struct input_dev *dev)
{
struct st_keyscan *keypad = input_get_drvdata(dev);
keyscan_stop(keypad);
}
static int keypad_matrix_key_parse_dt(struct st_keyscan *keypad_data)
{
struct device *dev = keypad_data->input_dev->dev.parent;
struct device_node *np = dev->of_node;
int error;
error = matrix_keypad_parse_of_params(dev, &keypad_data->n_rows,
&keypad_data->n_cols);
if (error) {
dev_err(dev, "failed to parse keypad params\n");
return error;
}
of_property_read_u32(np, "st,debounce-us", &keypad_data->debounce_us);
dev_dbg(dev, "n_rows=%d n_col=%d debounce=%d\n",
keypad_data->n_rows, keypad_data->n_cols,
keypad_data->debounce_us);
return 0;
}
static int keyscan_probe(struct platform_device *pdev)
{
struct st_keyscan *keypad_data;
struct input_dev *input_dev;
struct resource *res;
int error;
if (!pdev->dev.of_node) {
dev_err(&pdev->dev, "no DT data present\n");
return -EINVAL;
}
keypad_data = devm_kzalloc(&pdev->dev, sizeof(*keypad_data),
GFP_KERNEL);
if (!keypad_data)
return -ENOMEM;
input_dev = devm_input_allocate_device(&pdev->dev);
if (!input_dev) {
dev_err(&pdev->dev, "failed to allocate the input device\n");
return -ENOMEM;
}
input_dev->name = pdev->name;
input_dev->phys = "keyscan-keys/input0";
input_dev->dev.parent = &pdev->dev;
input_dev->open = keyscan_open;
input_dev->close = keyscan_close;
input_dev->id.bustype = BUS_HOST;
error = keypad_matrix_key_parse_dt(keypad_data);
if (error)
return error;
error = matrix_keypad_build_keymap(NULL, NULL,
keypad_data->n_rows,
keypad_data->n_cols,
NULL, input_dev);
if (error) {
dev_err(&pdev->dev, "failed to build keymap\n");
return error;
}
input_set_drvdata(input_dev, keypad_data);
keypad_data->input_dev = input_dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
keypad_data->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(keypad_data->base))
return PTR_ERR(keypad_data->base);
keypad_data->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(keypad_data->clk)) {
dev_err(&pdev->dev, "cannot get clock\n");
return PTR_ERR(keypad_data->clk);
}
error = clk_enable(keypad_data->clk);
if (error) {
dev_err(&pdev->dev, "failed to enable clock\n");
return error;
}
keyscan_stop(keypad_data);
keypad_data->irq = platform_get_irq(pdev, 0);
if (keypad_data->irq < 0) {
dev_err(&pdev->dev, "no IRQ specified\n");
return -EINVAL;
}
error = devm_request_irq(&pdev->dev, keypad_data->irq, keyscan_isr, 0,
pdev->name, keypad_data);
if (error) {
dev_err(&pdev->dev, "failed to request IRQ\n");
return error;
}
error = input_register_device(input_dev);
if (error) {
dev_err(&pdev->dev, "failed to register input device\n");
return error;
}
platform_set_drvdata(pdev, keypad_data);
device_set_wakeup_capable(&pdev->dev, 1);
return 0;
}
static int keyscan_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct st_keyscan *keypad = platform_get_drvdata(pdev);
struct input_dev *input = keypad->input_dev;
mutex_lock(&input->mutex);
if (device_may_wakeup(dev))
enable_irq_wake(keypad->irq);
else if (input->users)
keyscan_stop(keypad);
mutex_unlock(&input->mutex);
return 0;
}
static int keyscan_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct st_keyscan *keypad = platform_get_drvdata(pdev);
struct input_dev *input = keypad->input_dev;
int retval = 0;
mutex_lock(&input->mutex);
if (device_may_wakeup(dev))
disable_irq_wake(keypad->irq);
else if (input->users)
retval = keyscan_start(keypad);
mutex_unlock(&input->mutex);
return retval;
}
static SIMPLE_DEV_PM_OPS(keyscan_dev_pm_ops, keyscan_suspend, keyscan_resume);
static const struct of_device_id keyscan_of_match[] = {
{ .compatible = "st,sti-keyscan" },
{ },
};
MODULE_DEVICE_TABLE(of, keyscan_of_match);
static struct platform_driver keyscan_device_driver = {
.probe = keyscan_probe,
.driver = {
.name = "st-keyscan",
.pm = &keyscan_dev_pm_ops,
.of_match_table = of_match_ptr(keyscan_of_match),
}
};
module_platform_driver(keyscan_device_driver);
MODULE_AUTHOR("Stuart Menefy <stuart.menefy@st.com>");
MODULE_DESCRIPTION("STMicroelectronics keyscan device driver");
MODULE_LICENSE("GPL");
...@@ -296,6 +296,65 @@ static void tc3589x_keypad_close(struct input_dev *input) ...@@ -296,6 +296,65 @@ static void tc3589x_keypad_close(struct input_dev *input)
tc3589x_keypad_disable(keypad); tc3589x_keypad_disable(keypad);
} }
#ifdef CONFIG_OF
static const struct tc3589x_keypad_platform_data *
tc3589x_keypad_of_probe(struct device *dev)
{
struct device_node *np = dev->of_node;
struct tc3589x_keypad_platform_data *plat;
u32 cols, rows;
u32 debounce_ms;
int proplen;
if (!np)
return ERR_PTR(-ENODEV);
plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL);
if (!plat)
return ERR_PTR(-ENOMEM);
of_property_read_u32(np, "keypad,num-columns", &cols);
of_property_read_u32(np, "keypad,num-rows", &rows);
plat->kcol = (u8) cols;
plat->krow = (u8) rows;
if (!plat->krow || !plat->kcol ||
plat->krow > TC_KPD_ROWS || plat->kcol > TC_KPD_COLUMNS) {
dev_err(dev,
"keypad columns/rows not properly specified (%ux%u)\n",
plat->kcol, plat->krow);
return ERR_PTR(-EINVAL);
}
if (!of_get_property(np, "linux,keymap", &proplen)) {
dev_err(dev, "property linux,keymap not found\n");
return ERR_PTR(-ENOENT);
}
plat->no_autorepeat = of_property_read_bool(np, "linux,no-autorepeat");
plat->enable_wakeup = of_property_read_bool(np, "linux,wakeup");
/* The custom delay format is ms/16 */
of_property_read_u32(np, "debounce-delay-ms", &debounce_ms);
if (debounce_ms)
plat->debounce_period = debounce_ms * 16;
else
plat->debounce_period = TC_KPD_DEBOUNCE_PERIOD;
plat->settle_time = TC_KPD_SETTLE_TIME;
/* FIXME: should be property of the IRQ resource? */
plat->irqtype = IRQF_TRIGGER_FALLING;
return plat;
}
#else
static inline const struct tc3589x_keypad_platform_data *
tc3589x_keypad_of_probe(struct device *dev)
{
return ERR_PTR(-ENODEV);
}
#endif
static int tc3589x_keypad_probe(struct platform_device *pdev) static int tc3589x_keypad_probe(struct platform_device *pdev)
{ {
struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
...@@ -306,8 +365,11 @@ static int tc3589x_keypad_probe(struct platform_device *pdev) ...@@ -306,8 +365,11 @@ static int tc3589x_keypad_probe(struct platform_device *pdev)
plat = tc3589x->pdata->keypad; plat = tc3589x->pdata->keypad;
if (!plat) { if (!plat) {
dev_err(&pdev->dev, "invalid keypad platform data\n"); plat = tc3589x_keypad_of_probe(&pdev->dev);
return -EINVAL; if (IS_ERR(plat)) {
dev_err(&pdev->dev, "invalid keypad platform data\n");
return PTR_ERR(plat);
}
} }
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mfd/88pm860x.h> #include <linux/mfd/88pm860x.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h>
#define PM8607_WAKEUP 0x0b #define PM8607_WAKEUP 0x0b
...@@ -68,7 +69,8 @@ static int pm860x_onkey_probe(struct platform_device *pdev) ...@@ -68,7 +69,8 @@ static int pm860x_onkey_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
info = kzalloc(sizeof(struct pm860x_onkey_info), GFP_KERNEL); info = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_onkey_info),
GFP_KERNEL);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;
info->chip = chip; info->chip = chip;
...@@ -76,11 +78,10 @@ static int pm860x_onkey_probe(struct platform_device *pdev) ...@@ -76,11 +78,10 @@ static int pm860x_onkey_probe(struct platform_device *pdev)
info->dev = &pdev->dev; info->dev = &pdev->dev;
info->irq = irq; info->irq = irq;
info->idev = input_allocate_device(); info->idev = devm_input_allocate_device(&pdev->dev);
if (!info->idev) { if (!info->idev) {
dev_err(chip->dev, "Failed to allocate input dev\n"); dev_err(chip->dev, "Failed to allocate input dev\n");
ret = -ENOMEM; return -ENOMEM;
goto out;
} }
info->idev->name = "88pm860x_on"; info->idev->name = "88pm860x_on";
...@@ -93,42 +94,22 @@ static int pm860x_onkey_probe(struct platform_device *pdev) ...@@ -93,42 +94,22 @@ static int pm860x_onkey_probe(struct platform_device *pdev)
ret = input_register_device(info->idev); ret = input_register_device(info->idev);
if (ret) { if (ret) {
dev_err(chip->dev, "Can't register input device: %d\n", ret); dev_err(chip->dev, "Can't register input device: %d\n", ret);
goto out_reg; return ret;
} }
ret = request_threaded_irq(info->irq, NULL, pm860x_onkey_handler, ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
IRQF_ONESHOT, "onkey", info); pm860x_onkey_handler, IRQF_ONESHOT,
"onkey", info);
if (ret < 0) { if (ret < 0) {
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
info->irq, ret); info->irq, ret);
goto out_irq; return ret;
} }
platform_set_drvdata(pdev, info); platform_set_drvdata(pdev, info);
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
return 0; return 0;
out_irq:
input_unregister_device(info->idev);
kfree(info);
return ret;
out_reg:
input_free_device(info->idev);
out:
kfree(info);
return ret;
}
static int pm860x_onkey_remove(struct platform_device *pdev)
{
struct pm860x_onkey_info *info = platform_get_drvdata(pdev);
free_irq(info->irq, info);
input_unregister_device(info->idev);
kfree(info);
return 0;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
...@@ -161,7 +142,6 @@ static struct platform_driver pm860x_onkey_driver = { ...@@ -161,7 +142,6 @@ static struct platform_driver pm860x_onkey_driver = {
.pm = &pm860x_onkey_pm_ops, .pm = &pm860x_onkey_pm_ops,
}, },
.probe = pm860x_onkey_probe, .probe = pm860x_onkey_probe,
.remove = pm860x_onkey_remove,
}; };
module_platform_driver(pm860x_onkey_driver); module_platform_driver(pm860x_onkey_driver);
......
...@@ -224,7 +224,7 @@ config INPUT_GP2A ...@@ -224,7 +224,7 @@ config INPUT_GP2A
config INPUT_GPIO_BEEPER config INPUT_GPIO_BEEPER
tristate "Generic GPIO Beeper support" tristate "Generic GPIO Beeper support"
depends on OF_GPIO depends on GPIOLIB
help help
Say Y here if you have a beeper connected to a GPIO pin. Say Y here if you have a beeper connected to a GPIO pin.
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* AB8500 Power-On Key handler * AB8500 Power-On Key handler
*/ */
#include <linux/device.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -65,12 +66,14 @@ static int ab8500_ponkey_probe(struct platform_device *pdev) ...@@ -65,12 +66,14 @@ static int ab8500_ponkey_probe(struct platform_device *pdev)
return irq_dbr; return irq_dbr;
} }
ponkey = kzalloc(sizeof(struct ab8500_ponkey), GFP_KERNEL); ponkey = devm_kzalloc(&pdev->dev, sizeof(struct ab8500_ponkey),
input = input_allocate_device(); GFP_KERNEL);
if (!ponkey || !input) { if (!ponkey)
error = -ENOMEM; return -ENOMEM;
goto err_free_mem;
} input = devm_input_allocate_device(&pdev->dev);
if (!input)
return -ENOMEM;
ponkey->idev = input; ponkey->idev = input;
ponkey->ab8500 = ab8500; ponkey->ab8500 = ab8500;
...@@ -82,52 +85,32 @@ static int ab8500_ponkey_probe(struct platform_device *pdev) ...@@ -82,52 +85,32 @@ static int ab8500_ponkey_probe(struct platform_device *pdev)
input_set_capability(input, EV_KEY, KEY_POWER); input_set_capability(input, EV_KEY, KEY_POWER);
error = request_any_context_irq(ponkey->irq_dbf, ab8500_ponkey_handler, error = devm_request_any_context_irq(&pdev->dev, ponkey->irq_dbf,
0, "ab8500-ponkey-dbf", ponkey); ab8500_ponkey_handler, 0,
"ab8500-ponkey-dbf", ponkey);
if (error < 0) { if (error < 0) {
dev_err(ab8500->dev, "Failed to request dbf IRQ#%d: %d\n", dev_err(ab8500->dev, "Failed to request dbf IRQ#%d: %d\n",
ponkey->irq_dbf, error); ponkey->irq_dbf, error);
goto err_free_mem; return error;
} }
error = request_any_context_irq(ponkey->irq_dbr, ab8500_ponkey_handler, error = devm_request_any_context_irq(&pdev->dev, ponkey->irq_dbr,
0, "ab8500-ponkey-dbr", ponkey); ab8500_ponkey_handler, 0,
"ab8500-ponkey-dbr", ponkey);
if (error < 0) { if (error < 0) {
dev_err(ab8500->dev, "Failed to request dbr IRQ#%d: %d\n", dev_err(ab8500->dev, "Failed to request dbr IRQ#%d: %d\n",
ponkey->irq_dbr, error); ponkey->irq_dbr, error);
goto err_free_dbf_irq; return error;
} }
error = input_register_device(ponkey->idev); error = input_register_device(ponkey->idev);
if (error) { if (error) {
dev_err(ab8500->dev, "Can't register input device: %d\n", error); dev_err(ab8500->dev, "Can't register input device: %d\n", error);
goto err_free_dbr_irq; return error;
} }
platform_set_drvdata(pdev, ponkey); platform_set_drvdata(pdev, ponkey);
return 0; return 0;
err_free_dbr_irq:
free_irq(ponkey->irq_dbr, ponkey);
err_free_dbf_irq:
free_irq(ponkey->irq_dbf, ponkey);
err_free_mem:
input_free_device(input);
kfree(ponkey);
return error;
}
static int ab8500_ponkey_remove(struct platform_device *pdev)
{
struct ab8500_ponkey *ponkey = platform_get_drvdata(pdev);
free_irq(ponkey->irq_dbf, ponkey);
free_irq(ponkey->irq_dbr, ponkey);
input_unregister_device(ponkey->idev);
kfree(ponkey);
return 0;
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -144,7 +127,6 @@ static struct platform_driver ab8500_ponkey_driver = { ...@@ -144,7 +127,6 @@ static struct platform_driver ab8500_ponkey_driver = {
.of_match_table = of_match_ptr(ab8500_ponkey_match), .of_match_table = of_match_ptr(ab8500_ponkey_match),
}, },
.probe = ab8500_ponkey_probe, .probe = ab8500_ponkey_probe,
.remove = ab8500_ponkey_remove,
}; };
module_platform_driver(ab8500_ponkey_driver); module_platform_driver(ab8500_ponkey_driver);
......
/* /*
* Generic GPIO beeper driver * Generic GPIO beeper driver
* *
* Copyright (C) 2013 Alexander Shiyan <shc_work@mail.ru> * Copyright (C) 2013-2014 Alexander Shiyan <shc_work@mail.ru>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_gpio.h> #include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -19,14 +20,13 @@ ...@@ -19,14 +20,13 @@
struct gpio_beeper { struct gpio_beeper {
struct work_struct work; struct work_struct work;
int gpio; struct gpio_desc *desc;
bool active_low;
bool beeping; bool beeping;
}; };
static void gpio_beeper_toggle(struct gpio_beeper *beep, bool on) static void gpio_beeper_toggle(struct gpio_beeper *beep, bool on)
{ {
gpio_set_value_cansleep(beep->gpio, on ^ beep->active_low); gpiod_set_value_cansleep(beep->desc, on);
} }
static void gpio_beeper_work(struct work_struct *work) static void gpio_beeper_work(struct work_struct *work)
...@@ -65,18 +65,16 @@ static void gpio_beeper_close(struct input_dev *input) ...@@ -65,18 +65,16 @@ static void gpio_beeper_close(struct input_dev *input)
static int gpio_beeper_probe(struct platform_device *pdev) static int gpio_beeper_probe(struct platform_device *pdev)
{ {
struct gpio_beeper *beep; struct gpio_beeper *beep;
enum of_gpio_flags flags;
struct input_dev *input; struct input_dev *input;
unsigned long gflags;
int err; int err;
beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL); beep = devm_kzalloc(&pdev->dev, sizeof(*beep), GFP_KERNEL);
if (!beep) if (!beep)
return -ENOMEM; return -ENOMEM;
beep->gpio = of_get_gpio_flags(pdev->dev.of_node, 0, &flags); beep->desc = devm_gpiod_get(&pdev->dev, NULL);
if (!gpio_is_valid(beep->gpio)) if (IS_ERR(beep->desc))
return beep->gpio; return PTR_ERR(beep->desc);
input = devm_input_allocate_device(&pdev->dev); input = devm_input_allocate_device(&pdev->dev);
if (!input) if (!input)
...@@ -94,10 +92,7 @@ static int gpio_beeper_probe(struct platform_device *pdev) ...@@ -94,10 +92,7 @@ static int gpio_beeper_probe(struct platform_device *pdev)
input_set_capability(input, EV_SND, SND_BELL); input_set_capability(input, EV_SND, SND_BELL);
beep->active_low = flags & OF_GPIO_ACTIVE_LOW; err = gpiod_direction_output(beep->desc, 0);
gflags = beep->active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
err = devm_gpio_request_one(&pdev->dev, beep->gpio, gflags, pdev->name);
if (err) if (err)
return err; return err;
...@@ -106,17 +101,19 @@ static int gpio_beeper_probe(struct platform_device *pdev) ...@@ -106,17 +101,19 @@ static int gpio_beeper_probe(struct platform_device *pdev)
return input_register_device(input); return input_register_device(input);
} }
static struct of_device_id gpio_beeper_of_match[] = { #ifdef CONFIG_OF
static const struct of_device_id gpio_beeper_of_match[] = {
{ .compatible = BEEPER_MODNAME, }, { .compatible = BEEPER_MODNAME, },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, gpio_beeper_of_match); MODULE_DEVICE_TABLE(of, gpio_beeper_of_match);
#endif
static struct platform_driver gpio_beeper_platform_driver = { static struct platform_driver gpio_beeper_platform_driver = {
.driver = { .driver = {
.name = BEEPER_MODNAME, .name = BEEPER_MODNAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = gpio_beeper_of_match, .of_match_table = of_match_ptr(gpio_beeper_of_match),
}, },
.probe = gpio_beeper_probe, .probe = gpio_beeper_probe,
}; };
......
...@@ -1566,6 +1566,7 @@ static int ims_pcu_buffers_alloc(struct ims_pcu *pcu) ...@@ -1566,6 +1566,7 @@ static int ims_pcu_buffers_alloc(struct ims_pcu *pcu)
if (!pcu->urb_ctrl_buf) { if (!pcu->urb_ctrl_buf) {
dev_err(pcu->dev, dev_err(pcu->dev,
"Failed to allocate memory for read buffer\n"); "Failed to allocate memory for read buffer\n");
error = -ENOMEM;
goto err_free_urb_out_buf; goto err_free_urb_out_buf;
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mfd/max8925.h> #include <linux/mfd/max8925.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h>
#define SW_INPUT (1 << 7) /* 0/1 -- up/down */ #define SW_INPUT (1 << 7) /* 0/1 -- up/down */
#define HARDRESET_EN (1 << 7) #define HARDRESET_EN (1 << 7)
...@@ -81,12 +82,14 @@ static int max8925_onkey_probe(struct platform_device *pdev) ...@@ -81,12 +82,14 @@ static int max8925_onkey_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
info = kzalloc(sizeof(struct max8925_onkey_info), GFP_KERNEL); info = devm_kzalloc(&pdev->dev, sizeof(struct max8925_onkey_info),
input = input_allocate_device(); GFP_KERNEL);
if (!info || !input) { if (!info)
error = -ENOMEM; return -ENOMEM;
goto err_free_mem;
} input = devm_input_allocate_device(&pdev->dev);
if (!input)
return -ENOMEM;
info->idev = input; info->idev = input;
info->i2c = chip->i2c; info->i2c = chip->i2c;
...@@ -100,54 +103,33 @@ static int max8925_onkey_probe(struct platform_device *pdev) ...@@ -100,54 +103,33 @@ static int max8925_onkey_probe(struct platform_device *pdev)
input->dev.parent = &pdev->dev; input->dev.parent = &pdev->dev;
input_set_capability(input, EV_KEY, KEY_POWER); input_set_capability(input, EV_KEY, KEY_POWER);
error = request_threaded_irq(irq[0], NULL, max8925_onkey_handler, error = devm_request_threaded_irq(&pdev->dev, irq[0], NULL,
IRQF_ONESHOT, "onkey-down", info); max8925_onkey_handler, IRQF_ONESHOT,
"onkey-down", info);
if (error < 0) { if (error < 0) {
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
irq[0], error); irq[0], error);
goto err_free_mem; return error;
} }
error = request_threaded_irq(irq[1], NULL, max8925_onkey_handler, error = devm_request_threaded_irq(&pdev->dev, irq[1], NULL,
IRQF_ONESHOT, "onkey-up", info); max8925_onkey_handler, IRQF_ONESHOT,
"onkey-up", info);
if (error < 0) { if (error < 0) {
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
irq[1], error); irq[1], error);
goto err_free_irq0; return error;
} }
error = input_register_device(info->idev); error = input_register_device(info->idev);
if (error) { if (error) {
dev_err(chip->dev, "Can't register input device: %d\n", error); dev_err(chip->dev, "Can't register input device: %d\n", error);
goto err_free_irq1; return error;
} }
platform_set_drvdata(pdev, info); platform_set_drvdata(pdev, info);
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
return 0;
err_free_irq1:
free_irq(irq[1], info);
err_free_irq0:
free_irq(irq[0], info);
err_free_mem:
input_free_device(input);
kfree(info);
return error;
}
static int max8925_onkey_remove(struct platform_device *pdev)
{
struct max8925_onkey_info *info = platform_get_drvdata(pdev);
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
free_irq(info->irq[0] + chip->irq_base, info);
free_irq(info->irq[1] + chip->irq_base, info);
input_unregister_device(info->idev);
kfree(info);
return 0; return 0;
} }
...@@ -190,7 +172,6 @@ static struct platform_driver max8925_onkey_driver = { ...@@ -190,7 +172,6 @@ static struct platform_driver max8925_onkey_driver = {
.pm = &max8925_onkey_pm_ops, .pm = &max8925_onkey_pm_ops,
}, },
.probe = max8925_onkey_probe, .probe = max8925_onkey_probe,
.remove = max8925_onkey_remove,
}; };
module_platform_driver(max8925_onkey_driver); module_platform_driver(max8925_onkey_driver);
......
...@@ -181,11 +181,21 @@ static void max8997_haptic_enable(struct max8997_haptic *chip) ...@@ -181,11 +181,21 @@ static void max8997_haptic_enable(struct max8997_haptic *chip)
} }
if (!chip->enabled) { if (!chip->enabled) {
chip->enabled = true; error = regulator_enable(chip->regulator);
regulator_enable(chip->regulator); if (error) {
dev_err(chip->dev, "Failed to enable regulator\n");
goto out;
}
max8997_haptic_configure(chip); max8997_haptic_configure(chip);
if (chip->mode == MAX8997_EXTERNAL_MODE) if (chip->mode == MAX8997_EXTERNAL_MODE) {
pwm_enable(chip->pwm); error = pwm_enable(chip->pwm);
if (error) {
dev_err(chip->dev, "Failed to enable PWM\n");
regulator_disable(chip->regulator);
goto out;
}
}
chip->enabled = true;
} }
out: out:
......
...@@ -92,15 +92,15 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) ...@@ -92,15 +92,15 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
bool pull_up; bool pull_up;
if (of_property_read_u32(pdev->dev.of_node, "debounce", &kpd_delay)) if (of_property_read_u32(pdev->dev.of_node, "debounce", &kpd_delay))
kpd_delay = 0; kpd_delay = 15625;
pull_up = of_property_read_bool(pdev->dev.of_node, "pull-up"); if (kpd_delay > 62500 || kpd_delay == 0) {
if (kpd_delay > 62500) {
dev_err(&pdev->dev, "invalid power key trigger delay\n"); dev_err(&pdev->dev, "invalid power key trigger delay\n");
return -EINVAL; return -EINVAL;
} }
pull_up = of_property_read_bool(pdev->dev.of_node, "pull-up");
regmap = dev_get_regmap(pdev->dev.parent, NULL); regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!regmap) { if (!regmap) {
dev_err(&pdev->dev, "failed to locate regmap for the device\n"); dev_err(&pdev->dev, "failed to locate regmap for the device\n");
......
...@@ -143,7 +143,7 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id) ...@@ -143,7 +143,7 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id rotary_encoder_of_match[] = { static const struct of_device_id rotary_encoder_of_match[] = {
{ .compatible = "rotary-encoder", }, { .compatible = "rotary-encoder", },
{ }, { },
}; };
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pnp.h> #include <linux/pnp.h>
......
...@@ -262,7 +262,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev) ...@@ -262,7 +262,7 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
struct vibra_info *info; struct vibra_info *info;
int vddvibl_uV = 0; int vddvibl_uV = 0;
int vddvibr_uV = 0; int vddvibr_uV = 0;
int ret; int error;
twl6040_core_node = of_find_node_by_name(twl6040_core_dev->of_node, twl6040_core_node = of_find_node_by_name(twl6040_core_dev->of_node,
"vibra"); "vibra");
...@@ -309,12 +309,12 @@ static int twl6040_vibra_probe(struct platform_device *pdev) ...@@ -309,12 +309,12 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
mutex_init(&info->mutex); mutex_init(&info->mutex);
ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, error = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
twl6040_vib_irq_handler, 0, twl6040_vib_irq_handler, 0,
"twl6040_irq_vib", info); "twl6040_irq_vib", info);
if (ret) { if (error) {
dev_err(info->dev, "VIB IRQ request failed: %d\n", ret); dev_err(info->dev, "VIB IRQ request failed: %d\n", error);
return ret; return error;
} }
info->supplies[0].supply = "vddvibl"; info->supplies[0].supply = "vddvibl";
...@@ -323,40 +323,40 @@ static int twl6040_vibra_probe(struct platform_device *pdev) ...@@ -323,40 +323,40 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
* When booted with Device tree the regulators are attached to the * When booted with Device tree the regulators are attached to the
* parent device (twl6040 MFD core) * parent device (twl6040 MFD core)
*/ */
ret = regulator_bulk_get(twl6040_core_dev, ARRAY_SIZE(info->supplies), error = devm_regulator_bulk_get(twl6040_core_dev,
info->supplies); ARRAY_SIZE(info->supplies),
if (ret) { info->supplies);
dev_err(info->dev, "couldn't get regulators %d\n", ret); if (error) {
return ret; dev_err(info->dev, "couldn't get regulators %d\n", error);
return error;
} }
if (vddvibl_uV) { if (vddvibl_uV) {
ret = regulator_set_voltage(info->supplies[0].consumer, error = regulator_set_voltage(info->supplies[0].consumer,
vddvibl_uV, vddvibl_uV); vddvibl_uV, vddvibl_uV);
if (ret) { if (error) {
dev_err(info->dev, "failed to set VDDVIBL volt %d\n", dev_err(info->dev, "failed to set VDDVIBL volt %d\n",
ret); error);
goto err_regulator; return error;
} }
} }
if (vddvibr_uV) { if (vddvibr_uV) {
ret = regulator_set_voltage(info->supplies[1].consumer, error = regulator_set_voltage(info->supplies[1].consumer,
vddvibr_uV, vddvibr_uV); vddvibr_uV, vddvibr_uV);
if (ret) { if (error) {
dev_err(info->dev, "failed to set VDDVIBR volt %d\n", dev_err(info->dev, "failed to set VDDVIBR volt %d\n",
ret); error);
goto err_regulator; return error;
} }
} }
INIT_WORK(&info->play_work, vibra_play_work); INIT_WORK(&info->play_work, vibra_play_work);
info->input_dev = input_allocate_device(); info->input_dev = devm_input_allocate_device(&pdev->dev);
if (info->input_dev == NULL) { if (!info->input_dev) {
dev_err(info->dev, "couldn't allocate input device\n"); dev_err(info->dev, "couldn't allocate input device\n");
ret = -ENOMEM; return -ENOMEM;
goto err_regulator;
} }
input_set_drvdata(info->input_dev, info); input_set_drvdata(info->input_dev, info);
...@@ -367,44 +367,25 @@ static int twl6040_vibra_probe(struct platform_device *pdev) ...@@ -367,44 +367,25 @@ static int twl6040_vibra_probe(struct platform_device *pdev)
info->input_dev->close = twl6040_vibra_close; info->input_dev->close = twl6040_vibra_close;
__set_bit(FF_RUMBLE, info->input_dev->ffbit); __set_bit(FF_RUMBLE, info->input_dev->ffbit);
ret = input_ff_create_memless(info->input_dev, NULL, vibra_play); error = input_ff_create_memless(info->input_dev, NULL, vibra_play);
if (ret < 0) { if (error) {
dev_err(info->dev, "couldn't register vibrator to FF\n"); dev_err(info->dev, "couldn't register vibrator to FF\n");
goto err_ialloc; return error;
} }
ret = input_register_device(info->input_dev); error = input_register_device(info->input_dev);
if (ret < 0) { if (error) {
dev_err(info->dev, "couldn't register input device\n"); dev_err(info->dev, "couldn't register input device\n");
goto err_iff; return error;
} }
platform_set_drvdata(pdev, info); platform_set_drvdata(pdev, info);
return 0;
err_iff:
input_ff_destroy(info->input_dev);
err_ialloc:
input_free_device(info->input_dev);
err_regulator:
regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
return ret;
}
static int twl6040_vibra_remove(struct platform_device *pdev)
{
struct vibra_info *info = platform_get_drvdata(pdev);
input_unregister_device(info->input_dev);
regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies);
return 0; return 0;
} }
static struct platform_driver twl6040_vibra_driver = { static struct platform_driver twl6040_vibra_driver = {
.probe = twl6040_vibra_probe, .probe = twl6040_vibra_probe,
.remove = twl6040_vibra_remove,
.driver = { .driver = {
.name = "twl6040-vibra", .name = "twl6040-vibra",
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -53,7 +53,7 @@ config MOUSE_PS2_LOGIPS2PP ...@@ -53,7 +53,7 @@ config MOUSE_PS2_LOGIPS2PP
default y default y
depends on MOUSE_PS2 depends on MOUSE_PS2
help help
Say Y here if you have a Logictech PS/2++ mouse connected to Say Y here if you have a Logitech PS/2++ mouse connected to
your system. your system.
If unsure, say Y. If unsure, say Y.
......
...@@ -473,8 +473,15 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, ...@@ -473,8 +473,15 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse,
input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2);
input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3);
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); /* For clickpads map both buttons to BTN_LEFT */
if (etd->fw_version & 0x001000) {
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
} else {
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
}
input_report_abs(dev, ABS_PRESSURE, pres); input_report_abs(dev, ABS_PRESSURE, pres);
input_report_abs(dev, ABS_TOOL_WIDTH, width); input_report_abs(dev, ABS_TOOL_WIDTH, width);
...@@ -484,10 +491,17 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse, ...@@ -484,10 +491,17 @@ static void elantech_report_absolute_v3(struct psmouse *psmouse,
static void elantech_input_sync_v4(struct psmouse *psmouse) static void elantech_input_sync_v4(struct psmouse *psmouse)
{ {
struct input_dev *dev = psmouse->dev; struct input_dev *dev = psmouse->dev;
struct elantech_data *etd = psmouse->private;
unsigned char *packet = psmouse->packet; unsigned char *packet = psmouse->packet;
input_report_key(dev, BTN_LEFT, packet[0] & 0x01); /* For clickpads map both buttons to BTN_LEFT */
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); if (etd->fw_version & 0x001000) {
input_report_key(dev, BTN_LEFT, packet[0] & 0x03);
} else {
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
}
input_mt_report_pointer_emulation(dev, true); input_mt_report_pointer_emulation(dev, true);
input_sync(dev); input_sync(dev);
} }
...@@ -835,7 +849,7 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) ...@@ -835,7 +849,7 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
if (etd->set_hw_resolution) if (etd->set_hw_resolution)
etd->reg_10 = 0x0b; etd->reg_10 = 0x0b;
else else
etd->reg_10 = 0x03; etd->reg_10 = 0x01;
if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) if (elantech_write_reg(psmouse, 0x10, etd->reg_10))
rc = -1; rc = -1;
...@@ -1336,7 +1350,8 @@ static int elantech_reconnect(struct psmouse *psmouse) ...@@ -1336,7 +1350,8 @@ static int elantech_reconnect(struct psmouse *psmouse)
} }
/* /*
* Some hw_version 3 models go into error state when we try to set bit 3 of r10 * Some hw_version 3 models go into error state when we try to set
* bit 3 and/or bit 1 of r10.
*/ */
static const struct dmi_system_id no_hw_res_dmi_table[] = { static const struct dmi_system_id no_hw_res_dmi_table[] = {
#if defined(CONFIG_DMI) && defined(CONFIG_X86) #if defined(CONFIG_DMI) && defined(CONFIG_X86)
......
...@@ -347,15 +347,6 @@ static int synaptics_resolution(struct psmouse *psmouse) ...@@ -347,15 +347,6 @@ static int synaptics_resolution(struct psmouse *psmouse)
unsigned char resp[3]; unsigned char resp[3];
int i; int i;
for (i = 0; min_max_pnpid_table[i].pnp_ids; i++)
if (matches_pnp_id(psmouse, min_max_pnpid_table[i].pnp_ids)) {
priv->x_min = min_max_pnpid_table[i].x_min;
priv->x_max = min_max_pnpid_table[i].x_max;
priv->y_min = min_max_pnpid_table[i].y_min;
priv->y_max = min_max_pnpid_table[i].y_max;
return 0;
}
if (SYN_ID_MAJOR(priv->identity) < 4) if (SYN_ID_MAJOR(priv->identity) < 4)
return 0; return 0;
...@@ -366,6 +357,16 @@ static int synaptics_resolution(struct psmouse *psmouse) ...@@ -366,6 +357,16 @@ static int synaptics_resolution(struct psmouse *psmouse)
} }
} }
for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) {
if (matches_pnp_id(psmouse, min_max_pnpid_table[i].pnp_ids)) {
priv->x_min = min_max_pnpid_table[i].x_min;
priv->x_max = min_max_pnpid_table[i].x_max;
priv->y_min = min_max_pnpid_table[i].y_min;
priv->y_max = min_max_pnpid_table[i].y_max;
return 0;
}
}
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
......
...@@ -203,7 +203,7 @@ static int apbps2_of_remove(struct platform_device *of_dev) ...@@ -203,7 +203,7 @@ static int apbps2_of_remove(struct platform_device *of_dev)
return 0; return 0;
} }
static struct of_device_id apbps2_of_match[] = { static const struct of_device_id apbps2_of_match[] = {
{ .name = "GAISLER_APBPS2", }, { .name = "GAISLER_APBPS2", },
{ .name = "01_060", }, { .name = "01_060", },
{} {}
......
...@@ -262,7 +262,7 @@ static int olpc_apsp_remove(struct platform_device *pdev) ...@@ -262,7 +262,7 @@ static int olpc_apsp_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct of_device_id olpc_apsp_dt_ids[] = { static const struct of_device_id olpc_apsp_dt_ids[] = {
{ .compatible = "olpc,ap-sp", }, { .compatible = "olpc,ap-sp", },
{} {}
}; };
......
...@@ -349,6 +349,7 @@ static int wacom_parse_hid(struct usb_interface *intf, ...@@ -349,6 +349,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
break; break;
case MTTPC: case MTTPC:
case MTTPC_B:
features->pktlen = WACOM_PKGLEN_MTTPC; features->pktlen = WACOM_PKGLEN_MTTPC;
break; break;
...@@ -380,6 +381,16 @@ static int wacom_parse_hid(struct usb_interface *intf, ...@@ -380,6 +381,16 @@ static int wacom_parse_hid(struct usb_interface *intf,
i += 12; i += 12;
break; break;
case MTTPC_B:
features->x_max =
get_unaligned_le16(&report[i + 3]);
features->x_phy =
get_unaligned_le16(&report[i + 6]);
features->unit = report[i - 5];
features->unitExpo = report[i - 3];
i += 9;
break;
default: default:
features->x_max = features->x_max =
get_unaligned_le16(&report[i + 3]); get_unaligned_le16(&report[i + 3]);
...@@ -430,6 +441,14 @@ static int wacom_parse_hid(struct usb_interface *intf, ...@@ -430,6 +441,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
i += 12; i += 12;
break; break;
case MTTPC_B:
features->y_max =
get_unaligned_le16(&report[i + 3]);
features->y_phy =
get_unaligned_le16(&report[i + 6]);
i += 9;
break;
default: default:
features->y_max = features->y_max =
features->x_max; features->x_max;
......
This diff is collapsed.
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#define WACOM_PKGLEN_BBFUN 9 #define WACOM_PKGLEN_BBFUN 9
#define WACOM_PKGLEN_INTUOS 10 #define WACOM_PKGLEN_INTUOS 10
#define WACOM_PKGLEN_TPC1FG 5 #define WACOM_PKGLEN_TPC1FG 5
#define WACOM_PKGLEN_TPC1FG_B 10
#define WACOM_PKGLEN_TPC2FG 14 #define WACOM_PKGLEN_TPC2FG 14
#define WACOM_PKGLEN_BBTOUCH 20 #define WACOM_PKGLEN_BBTOUCH 20
#define WACOM_PKGLEN_BBTOUCH3 64 #define WACOM_PKGLEN_BBTOUCH3 64
...@@ -30,6 +31,7 @@ ...@@ -30,6 +31,7 @@
#define WACOM_PKGLEN_MTOUCH 62 #define WACOM_PKGLEN_MTOUCH 62
#define WACOM_PKGLEN_MTTPC 40 #define WACOM_PKGLEN_MTTPC 40
#define WACOM_PKGLEN_DTUS 68 #define WACOM_PKGLEN_DTUS 68
#define WACOM_PKGLEN_PENABLED 8
/* wacom data size per MT contact */ /* wacom data size per MT contact */
#define WACOM_BYTES_PER_MT_PACKET 11 #define WACOM_BYTES_PER_MT_PACKET 11
...@@ -52,6 +54,7 @@ ...@@ -52,6 +54,7 @@
#define WACOM_REPORT_TPC1FG 6 #define WACOM_REPORT_TPC1FG 6
#define WACOM_REPORT_TPC2FG 13 #define WACOM_REPORT_TPC2FG 13
#define WACOM_REPORT_TPCMT 13 #define WACOM_REPORT_TPCMT 13
#define WACOM_REPORT_TPCMT2 3
#define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCHID 15
#define WACOM_REPORT_TPCST 16 #define WACOM_REPORT_TPCST 16
#define WACOM_REPORT_DTUS 17 #define WACOM_REPORT_DTUS 17
...@@ -105,6 +108,7 @@ enum { ...@@ -105,6 +108,7 @@ enum {
TABLETPC2FG, TABLETPC2FG,
MTSCREEN, MTSCREEN,
MTTPC, MTTPC,
MTTPC_B,
MAX_TYPE MAX_TYPE
}; };
...@@ -118,6 +122,8 @@ struct wacom_features { ...@@ -118,6 +122,8 @@ struct wacom_features {
int type; int type;
int x_resolution; int x_resolution;
int y_resolution; int y_resolution;
int x_min;
int y_min;
int device_type; int device_type;
int x_phy; int x_phy;
int y_phy; int y_phy;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/mfd/88pm860x.h> #include <linux/mfd/88pm860x.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h>
#define MEAS_LEN (8) #define MEAS_LEN (8)
#define ACCURATE_BIT (12) #define ACCURATE_BIT (12)
...@@ -234,16 +235,17 @@ static int pm860x_touch_probe(struct platform_device *pdev) ...@@ -234,16 +235,17 @@ static int pm860x_touch_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL); touch = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_touch),
if (touch == NULL) GFP_KERNEL);
if (!touch)
return -ENOMEM; return -ENOMEM;
platform_set_drvdata(pdev, touch); platform_set_drvdata(pdev, touch);
touch->idev = input_allocate_device(); touch->idev = devm_input_allocate_device(&pdev->dev);
if (touch->idev == NULL) { if (!touch->idev) {
dev_err(&pdev->dev, "Failed to allocate input device!\n"); dev_err(&pdev->dev, "Failed to allocate input device!\n");
ret = -ENOMEM; return -ENOMEM;
goto out;
} }
touch->idev->name = "88pm860x-touch"; touch->idev->name = "88pm860x-touch";
...@@ -258,10 +260,11 @@ static int pm860x_touch_probe(struct platform_device *pdev) ...@@ -258,10 +260,11 @@ static int pm860x_touch_probe(struct platform_device *pdev)
touch->res_x = res_x; touch->res_x = res_x;
input_set_drvdata(touch->idev, touch); input_set_drvdata(touch->idev, touch);
ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler, ret = devm_request_threaded_irq(&pdev->dev, touch->irq, NULL,
IRQF_ONESHOT, "touch", touch); pm860x_touch_handler, IRQF_ONESHOT,
"touch", touch);
if (ret < 0) if (ret < 0)
goto out_irq; return ret;
__set_bit(EV_ABS, touch->idev->evbit); __set_bit(EV_ABS, touch->idev->evbit);
__set_bit(ABS_X, touch->idev->absbit); __set_bit(ABS_X, touch->idev->absbit);
...@@ -279,28 +282,11 @@ static int pm860x_touch_probe(struct platform_device *pdev) ...@@ -279,28 +282,11 @@ static int pm860x_touch_probe(struct platform_device *pdev)
ret = input_register_device(touch->idev); ret = input_register_device(touch->idev);
if (ret < 0) { if (ret < 0) {
dev_err(chip->dev, "Failed to register touch!\n"); dev_err(chip->dev, "Failed to register touch!\n");
goto out_rg; return ret;
} }
platform_set_drvdata(pdev, touch); platform_set_drvdata(pdev, touch);
return 0; return 0;
out_rg:
free_irq(touch->irq, touch);
out_irq:
input_free_device(touch->idev);
out:
kfree(touch);
return ret;
}
static int pm860x_touch_remove(struct platform_device *pdev)
{
struct pm860x_touch *touch = platform_get_drvdata(pdev);
input_unregister_device(touch->idev);
free_irq(touch->irq, touch);
kfree(touch);
return 0;
} }
static struct platform_driver pm860x_touch_driver = { static struct platform_driver pm860x_touch_driver = {
...@@ -309,7 +295,6 @@ static struct platform_driver pm860x_touch_driver = { ...@@ -309,7 +295,6 @@ static struct platform_driver pm860x_touch_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = pm860x_touch_probe, .probe = pm860x_touch_probe,
.remove = pm860x_touch_remove,
}; };
module_platform_driver(pm860x_touch_driver); module_platform_driver(pm860x_touch_driver);
......
...@@ -11,6 +11,10 @@ menuconfig INPUT_TOUCHSCREEN ...@@ -11,6 +11,10 @@ menuconfig INPUT_TOUCHSCREEN
if INPUT_TOUCHSCREEN if INPUT_TOUCHSCREEN
config OF_TOUCHSCREEN
def_tristate INPUT
depends on INPUT && OF
config TOUCHSCREEN_88PM860X config TOUCHSCREEN_88PM860X
tristate "Marvell 88PM860x touchscreen" tristate "Marvell 88PM860x touchscreen"
depends on MFD_88PM860X depends on MFD_88PM860X
...@@ -89,6 +93,7 @@ config TOUCHSCREEN_AD7879_SPI ...@@ -89,6 +93,7 @@ config TOUCHSCREEN_AD7879_SPI
config TOUCHSCREEN_ATMEL_MXT config TOUCHSCREEN_ATMEL_MXT
tristate "Atmel mXT I2C Touchscreen" tristate "Atmel mXT I2C Touchscreen"
depends on I2C depends on I2C
select FW_LOADER
help help
Say Y here if you have Atmel mXT series I2C touchscreen, Say Y here if you have Atmel mXT series I2C touchscreen,
such as AT42QT602240/ATMXT224, connected to your system. such as AT42QT602240/ATMXT224, connected to your system.
...@@ -846,7 +851,7 @@ config TOUCHSCREEN_TSC2007 ...@@ -846,7 +851,7 @@ config TOUCHSCREEN_TSC2007
config TOUCHSCREEN_W90X900 config TOUCHSCREEN_W90X900
tristate "W90P910 touchscreen driver" tristate "W90P910 touchscreen driver"
depends on HAVE_CLK depends on ARCH_W90X900
help help
Say Y here if you have a W90P910 based touchscreen. Say Y here if you have a W90P910 based touchscreen.
...@@ -885,6 +890,17 @@ config TOUCHSCREEN_STMPE ...@@ -885,6 +890,17 @@ config TOUCHSCREEN_STMPE
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called stmpe-ts. module will be called stmpe-ts.
config TOUCHSCREEN_SUN4I
tristate "Allwinner sun4i resistive touchscreen controller support"
depends on ARCH_SUNXI || COMPILE_TEST
depends on HWMON
help
This selects support for the resistive touchscreen controller
found on Allwinner sunxi SoCs.
To compile this driver as a module, choose M here: the
module will be called sun4i-ts.
config TOUCHSCREEN_SUR40 config TOUCHSCREEN_SUR40
tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen" tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
depends on USB depends on USB
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
wm97xx-ts-y := wm97xx-core.o wm97xx-ts-y := wm97xx-core.o
obj-$(CONFIG_OF_TOUCHSCREEN) += of_touchscreen.o
obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o
obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o
obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o
...@@ -53,6 +54,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o ...@@ -53,6 +54,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o
obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o obj-$(CONFIG_TOUCHSCREEN_SUR40) += sur40.o
obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
......
...@@ -210,11 +210,6 @@ static bool gpio3; ...@@ -210,11 +210,6 @@ static bool gpio3;
module_param(gpio3, bool, 0); module_param(gpio3, bool, 0);
MODULE_PARM_DESC(gpio3, "If gpio3 is set to 1 AUX3 acts as GPIO3"); MODULE_PARM_DESC(gpio3, "If gpio3 is set to 1 AUX3 acts as GPIO3");
/*
* ad7877_read/write are only used for initial setup and for sysfs controls.
* The main traffic is done using spi_async() in the interrupt handler.
*/
static int ad7877_read(struct spi_device *spi, u16 reg) static int ad7877_read(struct spi_device *spi, u16 reg)
{ {
struct ser_req *req; struct ser_req *req;
......
...@@ -706,7 +706,7 @@ static void ads7846_read_state(struct ads7846 *ts) ...@@ -706,7 +706,7 @@ static void ads7846_read_state(struct ads7846 *ts)
m = &ts->msg[msg_idx]; m = &ts->msg[msg_idx];
error = spi_sync(ts->spi, m); error = spi_sync(ts->spi, m);
if (error) { if (error) {
dev_err(&ts->spi->dev, "spi_async --> %d\n", error); dev_err(&ts->spi->dev, "spi_sync --> %d\n", error);
packet->tc.ignore = true; packet->tc.ignore = true;
return; return;
} }
......
This diff is collapsed.
...@@ -679,7 +679,7 @@ static const struct i2c_device_id auo_pixcir_idtable[] = { ...@@ -679,7 +679,7 @@ static const struct i2c_device_id auo_pixcir_idtable[] = {
MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable); MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id auo_pixcir_ts_dt_idtable[] = { static const struct of_device_id auo_pixcir_ts_dt_idtable[] = {
{ .compatible = "auo,auo_pixcir_ts" }, { .compatible = "auo,auo_pixcir_ts" },
{}, {},
}; };
......
...@@ -301,10 +301,11 @@ static int da9034_touch_probe(struct platform_device *pdev) ...@@ -301,10 +301,11 @@ static int da9034_touch_probe(struct platform_device *pdev)
struct da9034_touch_pdata *pdata = dev_get_platdata(&pdev->dev); struct da9034_touch_pdata *pdata = dev_get_platdata(&pdev->dev);
struct da9034_touch *touch; struct da9034_touch *touch;
struct input_dev *input_dev; struct input_dev *input_dev;
int ret; int error;
touch = kzalloc(sizeof(struct da9034_touch), GFP_KERNEL); touch = devm_kzalloc(&pdev->dev, sizeof(struct da9034_touch),
if (touch == NULL) { GFP_KERNEL);
if (!touch) {
dev_err(&pdev->dev, "failed to allocate driver data\n"); dev_err(&pdev->dev, "failed to allocate driver data\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -315,18 +316,18 @@ static int da9034_touch_probe(struct platform_device *pdev) ...@@ -315,18 +316,18 @@ static int da9034_touch_probe(struct platform_device *pdev)
touch->interval_ms = pdata->interval_ms; touch->interval_ms = pdata->interval_ms;
touch->x_inverted = pdata->x_inverted; touch->x_inverted = pdata->x_inverted;
touch->y_inverted = pdata->y_inverted; touch->y_inverted = pdata->y_inverted;
} else } else {
/* fallback into default */ /* fallback into default */
touch->interval_ms = 10; touch->interval_ms = 10;
}
INIT_DELAYED_WORK(&touch->tsi_work, da9034_tsi_work); INIT_DELAYED_WORK(&touch->tsi_work, da9034_tsi_work);
touch->notifier.notifier_call = da9034_touch_notifier; touch->notifier.notifier_call = da9034_touch_notifier;
input_dev = input_allocate_device(); input_dev = devm_input_allocate_device(&pdev->dev);
if (!input_dev) { if (!input_dev) {
dev_err(&pdev->dev, "failed to allocate input device\n"); dev_err(&pdev->dev, "failed to allocate input device\n");
ret = -ENOMEM; return -ENOMEM;
goto err_free_touch;
} }
input_dev->name = pdev->name; input_dev->name = pdev->name;
...@@ -346,26 +347,9 @@ static int da9034_touch_probe(struct platform_device *pdev) ...@@ -346,26 +347,9 @@ static int da9034_touch_probe(struct platform_device *pdev)
touch->input_dev = input_dev; touch->input_dev = input_dev;
input_set_drvdata(input_dev, touch); input_set_drvdata(input_dev, touch);
ret = input_register_device(input_dev); error = input_register_device(input_dev);
if (ret) if (error)
goto err_free_input; return error;
platform_set_drvdata(pdev, touch);
return 0;
err_free_input:
input_free_device(input_dev);
err_free_touch:
kfree(touch);
return ret;
}
static int da9034_touch_remove(struct platform_device *pdev)
{
struct da9034_touch *touch = platform_get_drvdata(pdev);
input_unregister_device(touch->input_dev);
kfree(touch);
return 0; return 0;
} }
...@@ -376,7 +360,6 @@ static struct platform_driver da9034_touch_driver = { ...@@ -376,7 +360,6 @@ static struct platform_driver da9034_touch_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = da9034_touch_probe, .probe = da9034_touch_probe,
.remove = da9034_touch_remove,
}; };
module_platform_driver(da9034_touch_driver); module_platform_driver(da9034_touch_driver);
......
...@@ -271,7 +271,7 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, ...@@ -271,7 +271,7 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
wrbuf[0] = addr; wrbuf[0] = addr;
wrbuf[1] = value; wrbuf[1] = value;
return edt_ft5x06_ts_readwrite(tsdata->client, 3, return edt_ft5x06_ts_readwrite(tsdata->client, 2,
wrbuf, 0, NULL); wrbuf, 0, NULL);
default: default:
......
...@@ -262,7 +262,7 @@ static int egalax_ts_resume(struct device *dev) ...@@ -262,7 +262,7 @@ static int egalax_ts_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume); static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume);
static struct of_device_id egalax_ts_dt_ids[] = { static const struct of_device_id egalax_ts_dt_ids[] = {
{ .compatible = "eeti,egalax_ts" }, { .compatible = "eeti,egalax_ts" },
{ /* sentinel */ } { /* sentinel */ }
}; };
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/intel_scu_ipc.h> #include <asm/intel_scu_ipc.h>
#include <linux/device.h>
/* PMIC Interrupt registers */ /* PMIC Interrupt registers */
#define PMIC_REG_ID1 0x00 /* PMIC ID1 register */ #define PMIC_REG_ID1 0x00 /* PMIC ID1 register */
...@@ -580,12 +581,17 @@ static int mrstouch_probe(struct platform_device *pdev) ...@@ -580,12 +581,17 @@ static int mrstouch_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL); tsdev = devm_kzalloc(&pdev->dev, sizeof(struct mrstouch_dev),
input = input_allocate_device(); GFP_KERNEL);
if (!tsdev || !input) { if (!tsdev) {
dev_err(&pdev->dev, "unable to allocate memory\n"); dev_err(&pdev->dev, "unable to allocate memory\n");
err = -ENOMEM; return -ENOMEM;
goto err_free_mem; }
input = devm_input_allocate_device(&pdev->dev);
if (!input) {
dev_err(&pdev->dev, "unable to allocate input device\n");
return -ENOMEM;
} }
tsdev->dev = &pdev->dev; tsdev->dev = &pdev->dev;
...@@ -598,7 +604,7 @@ static int mrstouch_probe(struct platform_device *pdev) ...@@ -598,7 +604,7 @@ static int mrstouch_probe(struct platform_device *pdev)
err = mrstouch_adc_init(tsdev); err = mrstouch_adc_init(tsdev);
if (err) { if (err) {
dev_err(&pdev->dev, "ADC initialization failed\n"); dev_err(&pdev->dev, "ADC initialization failed\n");
goto err_free_mem; return err;
} }
input->name = "mrst_touchscreen"; input->name = "mrst_touchscreen";
...@@ -618,38 +624,20 @@ static int mrstouch_probe(struct platform_device *pdev) ...@@ -618,38 +624,20 @@ static int mrstouch_probe(struct platform_device *pdev)
input_set_abs_params(tsdev->input, ABS_PRESSURE, input_set_abs_params(tsdev->input, ABS_PRESSURE,
MRST_PRESSURE_MIN, MRST_PRESSURE_MAX, 0, 0); MRST_PRESSURE_MIN, MRST_PRESSURE_MAX, 0, 0);
err = request_threaded_irq(tsdev->irq, NULL, mrstouch_pendet_irq, err = devm_request_threaded_irq(&pdev->dev, tsdev->irq, NULL,
IRQF_ONESHOT, "mrstouch", tsdev); mrstouch_pendet_irq, IRQF_ONESHOT,
"mrstouch", tsdev);
if (err) { if (err) {
dev_err(tsdev->dev, "unable to allocate irq\n"); dev_err(tsdev->dev, "unable to allocate irq\n");
goto err_free_mem; return err;
} }
err = input_register_device(tsdev->input); err = input_register_device(tsdev->input);
if (err) { if (err) {
dev_err(tsdev->dev, "unable to register input device\n"); dev_err(tsdev->dev, "unable to register input device\n");
goto err_free_irq; return err;
} }
platform_set_drvdata(pdev, tsdev);
return 0;
err_free_irq:
free_irq(tsdev->irq, tsdev);
err_free_mem:
input_free_device(input);
kfree(tsdev);
return err;
}
static int mrstouch_remove(struct platform_device *pdev)
{
struct mrstouch_dev *tsdev = platform_get_drvdata(pdev);
free_irq(tsdev->irq, tsdev);
input_unregister_device(tsdev->input);
kfree(tsdev);
return 0; return 0;
} }
...@@ -659,7 +647,6 @@ static struct platform_driver mrstouch_driver = { ...@@ -659,7 +647,6 @@ static struct platform_driver mrstouch_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = mrstouch_probe, .probe = mrstouch_probe,
.remove = mrstouch_remove,
}; };
module_platform_driver(mrstouch_driver); module_platform_driver(mrstouch_driver);
......
...@@ -384,7 +384,7 @@ static const struct dev_pm_ops lpc32xx_ts_pm_ops = { ...@@ -384,7 +384,7 @@ static const struct dev_pm_ops lpc32xx_ts_pm_ops = {
#endif #endif
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id lpc32xx_tsc_of_match[] = { static const struct of_device_id lpc32xx_tsc_of_match[] = {
{ .compatible = "nxp,lpc3220-tsc", }, { .compatible = "nxp,lpc3220-tsc", },
{ }, { },
}; };
......
...@@ -161,10 +161,9 @@ static irqreturn_t mcs5000_ts_interrupt(int irq, void *dev_id) ...@@ -161,10 +161,9 @@ static irqreturn_t mcs5000_ts_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data) static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data,
const struct mcs_platform_data *platform_data)
{ {
const struct mcs_platform_data *platform_data =
data->platform_data;
struct i2c_client *client = data->client; struct i2c_client *client = data->client;
/* Touch reset & sleep mode */ /* Touch reset & sleep mode */
...@@ -187,28 +186,32 @@ static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data) ...@@ -187,28 +186,32 @@ static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data)
} }
static int mcs5000_ts_probe(struct i2c_client *client, static int mcs5000_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
const struct mcs_platform_data *pdata;
struct mcs5000_ts_data *data; struct mcs5000_ts_data *data;
struct input_dev *input_dev; struct input_dev *input_dev;
int ret; int error;
if (!dev_get_platdata(&client->dev)) pdata = dev_get_platdata(&client->dev);
if (!pdata)
return -EINVAL; return -EINVAL;
data = kzalloc(sizeof(struct mcs5000_ts_data), GFP_KERNEL); data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
input_dev = input_allocate_device(); if (!data) {
if (!data || !input_dev) {
dev_err(&client->dev, "Failed to allocate memory\n"); dev_err(&client->dev, "Failed to allocate memory\n");
ret = -ENOMEM; return -ENOMEM;
goto err_free_mem;
} }
data->client = client; data->client = client;
data->input_dev = input_dev;
data->platform_data = dev_get_platdata(&client->dev);
input_dev->name = "MELPAS MCS-5000 Touchscreen"; input_dev = devm_input_allocate_device(&client->dev);
if (!input_dev) {
dev_err(&client->dev, "Failed to allocate input device\n");
return -ENOMEM;
}
input_dev->name = "MELFAS MCS-5000 Touchscreen";
input_dev->id.bustype = BUS_I2C; input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev; input_dev->dev.parent = &client->dev;
...@@ -219,43 +222,29 @@ static int mcs5000_ts_probe(struct i2c_client *client, ...@@ -219,43 +222,29 @@ static int mcs5000_ts_probe(struct i2c_client *client,
input_set_abs_params(input_dev, ABS_Y, 0, MCS5000_MAX_YC, 0, 0); input_set_abs_params(input_dev, ABS_Y, 0, MCS5000_MAX_YC, 0, 0);
input_set_drvdata(input_dev, data); input_set_drvdata(input_dev, data);
data->input_dev = input_dev;
if (data->platform_data->cfg_pin) if (pdata->cfg_pin)
data->platform_data->cfg_pin(); pdata->cfg_pin();
ret = request_threaded_irq(client->irq, NULL, mcs5000_ts_interrupt,
IRQF_TRIGGER_LOW | IRQF_ONESHOT, "mcs5000_ts", data);
if (ret < 0) { error = devm_request_threaded_irq(&client->dev, client->irq,
NULL, mcs5000_ts_interrupt,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"mcs5000_ts", data);
if (error) {
dev_err(&client->dev, "Failed to register interrupt\n"); dev_err(&client->dev, "Failed to register interrupt\n");
goto err_free_mem; return error;
} }
ret = input_register_device(data->input_dev); error = input_register_device(data->input_dev);
if (ret < 0) if (error) {
goto err_free_irq; dev_err(&client->dev, "Failed to register input device\n");
return error;
}
mcs5000_ts_phys_init(data); mcs5000_ts_phys_init(data, pdata);
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
return 0;
err_free_irq:
free_irq(client->irq, data);
err_free_mem:
input_free_device(input_dev);
kfree(data);
return ret;
}
static int mcs5000_ts_remove(struct i2c_client *client)
{
struct mcs5000_ts_data *data = i2c_get_clientdata(client);
free_irq(client->irq, data);
input_unregister_device(data->input_dev);
kfree(data);
return 0; return 0;
} }
...@@ -274,14 +263,15 @@ static int mcs5000_ts_resume(struct device *dev) ...@@ -274,14 +263,15 @@ static int mcs5000_ts_resume(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct mcs5000_ts_data *data = i2c_get_clientdata(client); struct mcs5000_ts_data *data = i2c_get_clientdata(client);
const struct mcs_platform_data *pdata = dev_get_platdata(dev);
mcs5000_ts_phys_init(data); mcs5000_ts_phys_init(data, pdata);
return 0; return 0;
} }
#endif
static SIMPLE_DEV_PM_OPS(mcs5000_ts_pm, mcs5000_ts_suspend, mcs5000_ts_resume); static SIMPLE_DEV_PM_OPS(mcs5000_ts_pm, mcs5000_ts_suspend, mcs5000_ts_resume);
#endif
static const struct i2c_device_id mcs5000_ts_id[] = { static const struct i2c_device_id mcs5000_ts_id[] = {
{ "mcs5000_ts", 0 }, { "mcs5000_ts", 0 },
...@@ -291,12 +281,9 @@ MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id); ...@@ -291,12 +281,9 @@ MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id);
static struct i2c_driver mcs5000_ts_driver = { static struct i2c_driver mcs5000_ts_driver = {
.probe = mcs5000_ts_probe, .probe = mcs5000_ts_probe,
.remove = mcs5000_ts_remove,
.driver = { .driver = {
.name = "mcs5000_ts", .name = "mcs5000_ts",
#ifdef CONFIG_PM
.pm = &mcs5000_ts_pm, .pm = &mcs5000_ts_pm,
#endif
}, },
.id_table = mcs5000_ts_id, .id_table = mcs5000_ts_id,
}; };
......
...@@ -456,7 +456,7 @@ static int mms114_probe(struct i2c_client *client, ...@@ -456,7 +456,7 @@ static int mms114_probe(struct i2c_client *client,
data->input_dev = input_dev; data->input_dev = input_dev;
data->pdata = pdata; data->pdata = pdata;
input_dev->name = "MELPAS MMS114 Touchscreen"; input_dev->name = "MELFAS MMS114 Touchscreen";
input_dev->id.bustype = BUS_I2C; input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev; input_dev->dev.parent = &client->dev;
input_dev->open = mms114_input_open; input_dev->open = mms114_input_open;
...@@ -570,7 +570,7 @@ static const struct i2c_device_id mms114_id[] = { ...@@ -570,7 +570,7 @@ static const struct i2c_device_id mms114_id[] = {
MODULE_DEVICE_TABLE(i2c, mms114_id); MODULE_DEVICE_TABLE(i2c, mms114_id);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id mms114_dt_match[] = { static const struct of_device_id mms114_dt_match[] = {
{ .compatible = "melfas,mms114" }, { .compatible = "melfas,mms114" },
{ } { }
}; };
......
/*
* Generic DT helper functions for touchscreen devices
*
* Copyright (c) 2014 Sebastian Reichel <sre@kernel.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
* published by the Free Software Foundation.
*
*/
#include <linux/of.h>
#include <linux/input.h>
#include <linux/input/touchscreen.h>
/**
* touchscreen_parse_of_params - parse common touchscreen DT properties
* @dev: device that should be parsed
*
* This function parses common DT properties for touchscreens and setups the
* input device accordingly. The function keeps previously setuped default
* values if no value is specified via DT.
*/
void touchscreen_parse_of_params(struct input_dev *dev)
{
struct device_node *np = dev->dev.parent->of_node;
struct input_absinfo *absinfo;
input_alloc_absinfo(dev);
if (!dev->absinfo)
return;
absinfo = &dev->absinfo[ABS_X];
of_property_read_u32(np, "touchscreen-size-x", &absinfo->maximum);
of_property_read_u32(np, "touchscreen-fuzz-x", &absinfo->fuzz);
absinfo = &dev->absinfo[ABS_Y];
of_property_read_u32(np, "touchscreen-size-y", &absinfo->maximum);
of_property_read_u32(np, "touchscreen-fuzz-y", &absinfo->fuzz);
absinfo = &dev->absinfo[ABS_PRESSURE];
of_property_read_u32(np, "touchscreen-max-pressure", &absinfo->maximum);
of_property_read_u32(np, "touchscreen-fuzz-pressure", &absinfo->fuzz);
}
EXPORT_SYMBOL(touchscreen_parse_of_params);
...@@ -24,12 +24,13 @@ ...@@ -24,12 +24,13 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/pixcir_ts.h> #include <linux/input/pixcir_ts.h>
#include <linux/gpio.h>
struct pixcir_i2c_ts_data { struct pixcir_i2c_ts_data {
struct i2c_client *client; struct i2c_client *client;
struct input_dev *input; struct input_dev *input;
const struct pixcir_ts_platform_data *chip; const struct pixcir_ts_platform_data *chip;
bool exiting; bool running;
}; };
static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data) static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
...@@ -87,11 +88,12 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data) ...@@ -87,11 +88,12 @@ static void pixcir_ts_poscheck(struct pixcir_i2c_ts_data *data)
static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
{ {
struct pixcir_i2c_ts_data *tsdata = dev_id; struct pixcir_i2c_ts_data *tsdata = dev_id;
const struct pixcir_ts_platform_data *pdata = tsdata->chip;
while (!tsdata->exiting) { while (tsdata->running) {
pixcir_ts_poscheck(tsdata); pixcir_ts_poscheck(tsdata);
if (tsdata->chip->attb_read_val()) if (gpio_get_value(pdata->gpio_attb))
break; break;
msleep(20); msleep(20);
...@@ -100,25 +102,221 @@ static irqreturn_t pixcir_ts_isr(int irq, void *dev_id) ...@@ -100,25 +102,221 @@ static irqreturn_t pixcir_ts_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int pixcir_set_power_mode(struct pixcir_i2c_ts_data *ts,
enum pixcir_power_mode mode)
{
struct device *dev = &ts->client->dev;
int ret;
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE);
if (ret < 0) {
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
__func__, PIXCIR_REG_POWER_MODE, ret);
return ret;
}
ret &= ~PIXCIR_POWER_MODE_MASK;
ret |= mode;
/* Always AUTO_IDLE */
ret |= PIXCIR_POWER_ALLOW_IDLE;
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret);
if (ret < 0) {
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
__func__, PIXCIR_REG_POWER_MODE, ret);
return ret;
}
return 0;
}
/*
* Set the interrupt mode for the device i.e. ATTB line behaviour
*
* @polarity : 1 for active high, 0 for active low.
*/
static int pixcir_set_int_mode(struct pixcir_i2c_ts_data *ts,
enum pixcir_int_mode mode, bool polarity)
{
struct device *dev = &ts->client->dev;
int ret;
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
if (ret < 0) {
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
__func__, PIXCIR_REG_INT_MODE, ret);
return ret;
}
ret &= ~PIXCIR_INT_MODE_MASK;
ret |= mode;
if (polarity)
ret |= PIXCIR_INT_POL_HIGH;
else
ret &= ~PIXCIR_INT_POL_HIGH;
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
if (ret < 0) {
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
__func__, PIXCIR_REG_INT_MODE, ret);
return ret;
}
return 0;
}
/*
* Enable/disable interrupt generation
*/
static int pixcir_int_enable(struct pixcir_i2c_ts_data *ts, bool enable)
{
struct device *dev = &ts->client->dev;
int ret;
ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE);
if (ret < 0) {
dev_err(dev, "%s: can't read reg 0x%x : %d\n",
__func__, PIXCIR_REG_INT_MODE, ret);
return ret;
}
if (enable)
ret |= PIXCIR_INT_ENABLE;
else
ret &= ~PIXCIR_INT_ENABLE;
ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret);
if (ret < 0) {
dev_err(dev, "%s: can't write reg 0x%x : %d\n",
__func__, PIXCIR_REG_INT_MODE, ret);
return ret;
}
return 0;
}
static int pixcir_start(struct pixcir_i2c_ts_data *ts)
{
struct device *dev = &ts->client->dev;
int error;
/* LEVEL_TOUCH interrupt with active low polarity */
error = pixcir_set_int_mode(ts, PIXCIR_INT_LEVEL_TOUCH, 0);
if (error) {
dev_err(dev, "Failed to set interrupt mode: %d\n", error);
return error;
}
ts->running = true;
mb(); /* Update status before IRQ can fire */
/* enable interrupt generation */
error = pixcir_int_enable(ts, true);
if (error) {
dev_err(dev, "Failed to enable interrupt generation: %d\n",
error);
return error;
}
return 0;
}
static int pixcir_stop(struct pixcir_i2c_ts_data *ts)
{
int error;
/* Disable interrupt generation */
error = pixcir_int_enable(ts, false);
if (error) {
dev_err(&ts->client->dev,
"Failed to disable interrupt generation: %d\n",
error);
return error;
}
/* Exit ISR if running, no more report parsing */
ts->running = false;
mb(); /* update status before we synchronize irq */
/* Wait till running ISR is complete */
synchronize_irq(ts->client->irq);
return 0;
}
static int pixcir_input_open(struct input_dev *dev)
{
struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
return pixcir_start(ts);
}
static void pixcir_input_close(struct input_dev *dev)
{
struct pixcir_i2c_ts_data *ts = input_get_drvdata(dev);
pixcir_stop(ts);
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int pixcir_i2c_ts_suspend(struct device *dev) static int pixcir_i2c_ts_suspend(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
struct input_dev *input = ts->input;
int ret = 0;
mutex_lock(&input->mutex);
if (device_may_wakeup(&client->dev)) {
if (!input->users) {
ret = pixcir_start(ts);
if (ret) {
dev_err(dev, "Failed to start\n");
goto unlock;
}
}
if (device_may_wakeup(&client->dev))
enable_irq_wake(client->irq); enable_irq_wake(client->irq);
} else if (input->users) {
ret = pixcir_stop(ts);
}
return 0; unlock:
mutex_unlock(&input->mutex);
return ret;
} }
static int pixcir_i2c_ts_resume(struct device *dev) static int pixcir_i2c_ts_resume(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
struct pixcir_i2c_ts_data *ts = i2c_get_clientdata(client);
struct input_dev *input = ts->input;
int ret = 0;
mutex_lock(&input->mutex);
if (device_may_wakeup(&client->dev)) if (device_may_wakeup(&client->dev)) {
disable_irq_wake(client->irq); disable_irq_wake(client->irq);
return 0; if (!input->users) {
ret = pixcir_stop(ts);
if (ret) {
dev_err(dev, "Failed to stop\n");
goto unlock;
}
}
} else if (input->users) {
ret = pixcir_start(ts);
}
unlock:
mutex_unlock(&input->mutex);
return ret;
} }
#endif #endif
...@@ -130,6 +328,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, ...@@ -130,6 +328,7 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
{ {
const struct pixcir_ts_platform_data *pdata = const struct pixcir_ts_platform_data *pdata =
dev_get_platdata(&client->dev); dev_get_platdata(&client->dev);
struct device *dev = &client->dev;
struct pixcir_i2c_ts_data *tsdata; struct pixcir_i2c_ts_data *tsdata;
struct input_dev *input; struct input_dev *input;
int error; int error;
...@@ -139,12 +338,19 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, ...@@ -139,12 +338,19 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
return -EINVAL; return -EINVAL;
} }
tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL); if (!gpio_is_valid(pdata->gpio_attb)) {
input = input_allocate_device(); dev_err(dev, "Invalid gpio_attb in pdata\n");
if (!tsdata || !input) { return -EINVAL;
dev_err(&client->dev, "Failed to allocate driver data!\n"); }
error = -ENOMEM;
goto err_free_mem; tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
if (!tsdata)
return -ENOMEM;
input = devm_input_allocate_device(dev);
if (!input) {
dev_err(dev, "Failed to allocate input device\n");
return -ENOMEM;
} }
tsdata->client = client; tsdata->client = client;
...@@ -153,6 +359,8 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, ...@@ -153,6 +359,8 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
input->name = client->name; input->name = client->name;
input->id.bustype = BUS_I2C; input->id.bustype = BUS_I2C;
input->open = pixcir_input_open;
input->close = pixcir_input_close;
input->dev.parent = &client->dev; input->dev.parent = &client->dev;
__set_bit(EV_KEY, input->evbit); __set_bit(EV_KEY, input->evbit);
...@@ -165,44 +373,47 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client, ...@@ -165,44 +373,47 @@ static int pixcir_i2c_ts_probe(struct i2c_client *client,
input_set_drvdata(input, tsdata); input_set_drvdata(input, tsdata);
error = request_threaded_irq(client->irq, NULL, pixcir_ts_isr, error = devm_gpio_request_one(dev, pdata->gpio_attb,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, GPIOF_DIR_IN, "pixcir_i2c_attb");
client->name, tsdata);
if (error) { if (error) {
dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); dev_err(dev, "Failed to request ATTB gpio\n");
goto err_free_mem; return error;
} }
error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
client->name, tsdata);
if (error) {
dev_err(dev, "failed to request irq %d\n", client->irq);
return error;
}
/* Always be in IDLE mode to save power, device supports auto wake */
error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
if (error) {
dev_err(dev, "Failed to set IDLE mode\n");
return error;
}
/* Stop device till opened */
error = pixcir_stop(tsdata);
if (error)
return error;
error = input_register_device(input); error = input_register_device(input);
if (error) if (error)
goto err_free_irq; return error;
i2c_set_clientdata(client, tsdata); i2c_set_clientdata(client, tsdata);
device_init_wakeup(&client->dev, 1); device_init_wakeup(&client->dev, 1);
return 0; return 0;
err_free_irq:
free_irq(client->irq, tsdata);
err_free_mem:
input_free_device(input);
kfree(tsdata);
return error;
} }
static int pixcir_i2c_ts_remove(struct i2c_client *client) static int pixcir_i2c_ts_remove(struct i2c_client *client)
{ {
struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(client);
device_init_wakeup(&client->dev, 0); device_init_wakeup(&client->dev, 0);
tsdata->exiting = true;
mb();
free_irq(client->irq, tsdata);
input_unregister_device(tsdata->input);
kfree(tsdata);
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -25,11 +25,15 @@ ...@@ -25,11 +25,15 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/input/touchscreen.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/tsc2005.h> #include <linux/spi/tsc2005.h>
#include <linux/regulator/consumer.h>
/* /*
* The touchscreen interface operates as follows: * The touchscreen interface operates as follows:
...@@ -100,6 +104,11 @@ ...@@ -100,6 +104,11 @@
TSC2005_CFR2_AVG_7) TSC2005_CFR2_AVG_7)
#define MAX_12BIT 0xfff #define MAX_12BIT 0xfff
#define TSC2005_DEF_X_FUZZ 4
#define TSC2005_DEF_Y_FUZZ 8
#define TSC2005_DEF_P_FUZZ 2
#define TSC2005_DEF_RESISTOR 280
#define TSC2005_SPI_MAX_SPEED_HZ 10000000 #define TSC2005_SPI_MAX_SPEED_HZ 10000000
#define TSC2005_PENUP_TIME_MS 40 #define TSC2005_PENUP_TIME_MS 40
...@@ -143,6 +152,9 @@ struct tsc2005 { ...@@ -143,6 +152,9 @@ struct tsc2005 {
bool pen_down; bool pen_down;
struct regulator *vio;
int reset_gpio;
void (*set_reset)(bool enable); void (*set_reset)(bool enable);
}; };
...@@ -337,6 +349,14 @@ static void tsc2005_stop_scan(struct tsc2005 *ts) ...@@ -337,6 +349,14 @@ static void tsc2005_stop_scan(struct tsc2005 *ts)
tsc2005_cmd(ts, TSC2005_CMD_STOP); tsc2005_cmd(ts, TSC2005_CMD_STOP);
} }
static void tsc2005_set_reset(struct tsc2005 *ts, bool enable)
{
if (ts->reset_gpio >= 0)
gpio_set_value(ts->reset_gpio, enable);
else if (ts->set_reset)
ts->set_reset(enable);
}
/* must be called with ts->mutex held */ /* must be called with ts->mutex held */
static void __tsc2005_disable(struct tsc2005 *ts) static void __tsc2005_disable(struct tsc2005 *ts)
{ {
...@@ -355,7 +375,7 @@ static void __tsc2005_enable(struct tsc2005 *ts) ...@@ -355,7 +375,7 @@ static void __tsc2005_enable(struct tsc2005 *ts)
{ {
tsc2005_start_scan(ts); tsc2005_start_scan(ts);
if (ts->esd_timeout && ts->set_reset) { if (ts->esd_timeout && (ts->set_reset || ts->reset_gpio)) {
ts->last_valid_interrupt = jiffies; ts->last_valid_interrupt = jiffies;
schedule_delayed_work(&ts->esd_work, schedule_delayed_work(&ts->esd_work,
round_jiffies_relative( round_jiffies_relative(
...@@ -414,9 +434,9 @@ static ssize_t tsc2005_selftest_show(struct device *dev, ...@@ -414,9 +434,9 @@ static ssize_t tsc2005_selftest_show(struct device *dev,
} }
/* hardware reset */ /* hardware reset */
ts->set_reset(false); tsc2005_set_reset(ts, false);
usleep_range(100, 500); /* only 10us required */ usleep_range(100, 500); /* only 10us required */
ts->set_reset(true); tsc2005_set_reset(ts, true);
if (!success) if (!success)
goto out; goto out;
...@@ -459,7 +479,7 @@ static umode_t tsc2005_attr_is_visible(struct kobject *kobj, ...@@ -459,7 +479,7 @@ static umode_t tsc2005_attr_is_visible(struct kobject *kobj,
umode_t mode = attr->mode; umode_t mode = attr->mode;
if (attr == &dev_attr_selftest.attr) { if (attr == &dev_attr_selftest.attr) {
if (!ts->set_reset) if (!ts->set_reset && !ts->reset_gpio)
mode = 0; mode = 0;
} }
...@@ -509,9 +529,9 @@ static void tsc2005_esd_work(struct work_struct *work) ...@@ -509,9 +529,9 @@ static void tsc2005_esd_work(struct work_struct *work)
tsc2005_update_pen_state(ts, 0, 0, 0); tsc2005_update_pen_state(ts, 0, 0, 0);
ts->set_reset(false); tsc2005_set_reset(ts, false);
usleep_range(100, 500); /* only 10us required */ usleep_range(100, 500); /* only 10us required */
ts->set_reset(true); tsc2005_set_reset(ts, true);
enable_irq(ts->spi->irq); enable_irq(ts->spi->irq);
tsc2005_start_scan(ts); tsc2005_start_scan(ts);
...@@ -572,29 +592,47 @@ static void tsc2005_setup_spi_xfer(struct tsc2005 *ts) ...@@ -572,29 +592,47 @@ static void tsc2005_setup_spi_xfer(struct tsc2005 *ts)
static int tsc2005_probe(struct spi_device *spi) static int tsc2005_probe(struct spi_device *spi)
{ {
const struct tsc2005_platform_data *pdata = dev_get_platdata(&spi->dev); const struct tsc2005_platform_data *pdata = dev_get_platdata(&spi->dev);
struct device_node *np = spi->dev.of_node;
struct tsc2005 *ts; struct tsc2005 *ts;
struct input_dev *input_dev; struct input_dev *input_dev;
unsigned int max_x, max_y, max_p; unsigned int max_x = MAX_12BIT;
unsigned int fudge_x, fudge_y, fudge_p; unsigned int max_y = MAX_12BIT;
unsigned int max_p = MAX_12BIT;
unsigned int fudge_x = TSC2005_DEF_X_FUZZ;
unsigned int fudge_y = TSC2005_DEF_Y_FUZZ;
unsigned int fudge_p = TSC2005_DEF_P_FUZZ;
unsigned int x_plate_ohm = TSC2005_DEF_RESISTOR;
unsigned int esd_timeout;
int error; int error;
if (!pdata) { if (!np && !pdata) {
dev_dbg(&spi->dev, "no platform data\n"); dev_err(&spi->dev, "no platform data\n");
return -ENODEV; return -ENODEV;
} }
fudge_x = pdata->ts_x_fudge ? : 4;
fudge_y = pdata->ts_y_fudge ? : 8;
fudge_p = pdata->ts_pressure_fudge ? : 2;
max_x = pdata->ts_x_max ? : MAX_12BIT;
max_y = pdata->ts_y_max ? : MAX_12BIT;
max_p = pdata->ts_pressure_max ? : MAX_12BIT;
if (spi->irq <= 0) { if (spi->irq <= 0) {
dev_dbg(&spi->dev, "no irq\n"); dev_err(&spi->dev, "no irq\n");
return -ENODEV; return -ENODEV;
} }
if (pdata) {
fudge_x = pdata->ts_x_fudge;
fudge_y = pdata->ts_y_fudge;
fudge_p = pdata->ts_pressure_fudge;
max_x = pdata->ts_x_max;
max_y = pdata->ts_y_max;
max_p = pdata->ts_pressure_max;
x_plate_ohm = pdata->ts_x_plate_ohm;
esd_timeout = pdata->esd_timeout_ms;
} else {
x_plate_ohm = TSC2005_DEF_RESISTOR;
of_property_read_u32(np, "ti,x-plate-ohms", &x_plate_ohm);
esd_timeout = 0;
of_property_read_u32(np, "ti,esd-recovery-timeout-ms",
&esd_timeout);
}
spi->mode = SPI_MODE_0; spi->mode = SPI_MODE_0;
spi->bits_per_word = 8; spi->bits_per_word = 8;
if (!spi->max_speed_hz) if (!spi->max_speed_hz)
...@@ -604,19 +642,48 @@ static int tsc2005_probe(struct spi_device *spi) ...@@ -604,19 +642,48 @@ static int tsc2005_probe(struct spi_device *spi)
if (error) if (error)
return error; return error;
ts = kzalloc(sizeof(*ts), GFP_KERNEL); ts = devm_kzalloc(&spi->dev, sizeof(*ts), GFP_KERNEL);
input_dev = input_allocate_device(); if (!ts)
if (!ts || !input_dev) { return -ENOMEM;
error = -ENOMEM;
goto err_free_mem; input_dev = devm_input_allocate_device(&spi->dev);
} if (!input_dev)
return -ENOMEM;
ts->spi = spi; ts->spi = spi;
ts->idev = input_dev; ts->idev = input_dev;
ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 280; ts->x_plate_ohm = x_plate_ohm;
ts->esd_timeout = pdata->esd_timeout_ms; ts->esd_timeout = esd_timeout;
ts->set_reset = pdata->set_reset;
if (np) {
ts->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
if (ts->reset_gpio == -EPROBE_DEFER)
return ts->reset_gpio;
if (ts->reset_gpio < 0) {
dev_err(&spi->dev, "error acquiring reset gpio: %d\n",
ts->reset_gpio);
return ts->reset_gpio;
}
error = devm_gpio_request_one(&spi->dev, ts->reset_gpio, 0,
"reset-gpios");
if (error) {
dev_err(&spi->dev, "error requesting reset gpio: %d\n",
error);
return error;
}
ts->vio = devm_regulator_get(&spi->dev, "vio");
if (IS_ERR(ts->vio)) {
error = PTR_ERR(ts->vio);
dev_err(&spi->dev, "vio regulator missing (%d)", error);
return error;
}
} else {
ts->reset_gpio = -1;
ts->set_reset = pdata->set_reset;
}
mutex_init(&ts->mutex); mutex_init(&ts->mutex);
...@@ -641,6 +708,9 @@ static int tsc2005_probe(struct spi_device *spi) ...@@ -641,6 +708,9 @@ static int tsc2005_probe(struct spi_device *spi)
input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0); input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0); input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
if (np)
touchscreen_parse_of_params(input_dev);
input_dev->open = tsc2005_open; input_dev->open = tsc2005_open;
input_dev->close = tsc2005_close; input_dev->close = tsc2005_close;
...@@ -649,12 +719,20 @@ static int tsc2005_probe(struct spi_device *spi) ...@@ -649,12 +719,20 @@ static int tsc2005_probe(struct spi_device *spi)
/* Ensure the touchscreen is off */ /* Ensure the touchscreen is off */
tsc2005_stop_scan(ts); tsc2005_stop_scan(ts);
error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread, error = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
IRQF_TRIGGER_RISING | IRQF_ONESHOT, tsc2005_irq_thread,
"tsc2005", ts); IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"tsc2005", ts);
if (error) { if (error) {
dev_err(&spi->dev, "Failed to request irq, err: %d\n", error); dev_err(&spi->dev, "Failed to request irq, err: %d\n", error);
goto err_free_mem; return error;
}
/* enable regulator for DT */
if (ts->vio) {
error = regulator_enable(ts->vio);
if (error)
return error;
} }
spi_set_drvdata(spi, ts); spi_set_drvdata(spi, ts);
...@@ -662,7 +740,7 @@ static int tsc2005_probe(struct spi_device *spi) ...@@ -662,7 +740,7 @@ static int tsc2005_probe(struct spi_device *spi)
if (error) { if (error) {
dev_err(&spi->dev, dev_err(&spi->dev,
"Failed to create sysfs attributes, err: %d\n", error); "Failed to create sysfs attributes, err: %d\n", error);
goto err_clear_drvdata; goto disable_regulator;
} }
error = input_register_device(ts->idev); error = input_register_device(ts->idev);
...@@ -677,11 +755,9 @@ static int tsc2005_probe(struct spi_device *spi) ...@@ -677,11 +755,9 @@ static int tsc2005_probe(struct spi_device *spi)
err_remove_sysfs: err_remove_sysfs:
sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group); sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
err_clear_drvdata: disable_regulator:
free_irq(spi->irq, ts); if (ts->vio)
err_free_mem: regulator_disable(ts->vio);
input_free_device(input_dev);
kfree(ts);
return error; return error;
} }
...@@ -689,11 +765,10 @@ static int tsc2005_remove(struct spi_device *spi) ...@@ -689,11 +765,10 @@ static int tsc2005_remove(struct spi_device *spi)
{ {
struct tsc2005 *ts = spi_get_drvdata(spi); struct tsc2005 *ts = spi_get_drvdata(spi);
sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group); sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
free_irq(ts->spi->irq, ts); if (ts->vio)
input_unregister_device(ts->idev); regulator_disable(ts->vio);
kfree(ts);
return 0; return 0;
} }
......
...@@ -880,7 +880,7 @@ static struct i2c_device_id zforce_idtable[] = { ...@@ -880,7 +880,7 @@ static struct i2c_device_id zforce_idtable[] = {
MODULE_DEVICE_TABLE(i2c, zforce_idtable); MODULE_DEVICE_TABLE(i2c, zforce_idtable);
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id zforce_dt_idtable[] = { static const struct of_device_id zforce_dt_idtable[] = {
{ .compatible = "neonode,zforce" }, { .compatible = "neonode,zforce" },
{}, {},
}; };
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -48,9 +48,12 @@ struct input_polled_dev { ...@@ -48,9 +48,12 @@ struct input_polled_dev {
/* private: */ /* private: */
struct delayed_work work; struct delayed_work work;
bool devres_managed;
}; };
struct input_polled_dev *input_allocate_polled_device(void); struct input_polled_dev *input_allocate_polled_device(void);
struct input_polled_dev *devm_input_allocate_polled_device(struct device *dev);
void input_free_polled_device(struct input_polled_dev *dev); void input_free_polled_device(struct input_polled_dev *dev);
int input_register_polled_device(struct input_polled_dev *dev); int input_register_polled_device(struct input_polled_dev *dev);
void input_unregister_polled_device(struct input_polled_dev *dev); void input_unregister_polled_device(struct input_polled_dev *dev);
......
This diff is collapsed.
This diff is collapsed.
#ifndef __LINUX_INPUT_OMAP4_KEYPAD_H
#define __LINUX_INPUT_OMAP4_KEYPAD_H
#include <linux/input/matrix_keypad.h>
struct omap4_keypad_platform_data {
const struct matrix_keymap_data *keymap_data;
u8 rows;
u8 cols;
};
#endif /* __LINUX_INPUT_OMAP4_KEYPAD_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment