Merge tag 'v4.3-rc4' into next
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 6 Oct 2015 00:36:38 +0000 (17:36 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 6 Oct 2015 00:36:38 +0000 (17:36 -0700)
Merge with mainline to sync up with changes to parkbd driver.

33 files changed:
Documentation/devicetree/bindings/input/da9062-onkey.txt [new file with mode: 0644]
Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt
Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
arch/arm/boot/dts/am437x-sk-evm.dts
arch/arm/boot/dts/imx28-tx28.dts
arch/arm/boot/dts/imx53-tx53-x03x.dts
arch/arm/boot/dts/imx6qdl-tx6.dtsi
drivers/input/ff-core.c
drivers/input/joydev.c
drivers/input/joystick/db9.c
drivers/input/joystick/gamecon.c
drivers/input/joystick/turbografx.c
drivers/input/joystick/walkera0701.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/gpio_keys.c
drivers/input/misc/Kconfig
drivers/input/misc/ad714x-i2c.c
drivers/input/misc/ad714x-spi.c
drivers/input/misc/ad714x.c
drivers/input/misc/ad714x.h
drivers/input/misc/da9063_onkey.c
drivers/input/misc/kxtj9.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/auo-pixcir-ts.c
drivers/input/touchscreen/cyttsp4_i2c.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/input/touchscreen/ft6236.c [new file with mode: 0644]
drivers/input/touchscreen/tps6507x-ts.c
drivers/input/touchscreen/zforce_ts.c
include/linux/input/edt-ft5x06.h [deleted file]

diff --git a/Documentation/devicetree/bindings/input/da9062-onkey.txt b/Documentation/devicetree/bindings/input/da9062-onkey.txt
new file mode 100644 (file)
index 0000000..ab0e048
--- /dev/null
@@ -0,0 +1,32 @@
+* Dialog DA9062/63 OnKey Module
+
+This module is part of the DA9062/DA9063. For more details about entire
+chips see Documentation/devicetree/bindings/mfd/da9062.txt and
+Documentation/devicetree/bindings/mfd/da9063.txt
+
+This module provides KEY_POWER, KEY_SLEEP and events.
+
+Required properties:
+
+- compatible: should be one of:
+       dlg,da9062-onkey
+       dlg,da9063-onkey
+
+Optional properties:
+
+  - dlg,disable-key-power : Disable power-down using a long key-press. If this
+    entry exists the OnKey driver will remove support for the KEY_POWER key
+    press. If this entry does not exist then by default the key-press
+    triggered power down is enabled and the OnKey will support both KEY_POWER
+    and KEY_SLEEP.
+
+Example:
+
+       pmic0: da9062@58 {
+
+               onkey {
+                       compatible = "dlg,da9063-onkey";
+                       dlg,disable-key-power;
+               };
+
+       };
index 76db96704a602e823fc6d09a04ddfd000a5949a7..bedd7ddc56aabee435bcaebb3bb67d72289d14fc 100644 (file)
@@ -49,7 +49,7 @@ Example:
                pinctrl-names = "default";
                pinctrl-0 = <&edt_ft5x06_pins>;
                interrupt-parent = <&gpio2>;
-               interrupts = <5 0>;
-               reset-gpios = <&gpio2 6 1>;
-               wake-gpios = <&gpio4 9 0>;
+               interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+               reset-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
+               wake-gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>;
        };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt b/Documentation/devicetree/bindings/input/touchscreen/focaltech-ft6236.txt
new file mode 100644 (file)
index 0000000..777521d
--- /dev/null
@@ -0,0 +1,35 @@
+* FocalTech FT6236 I2C touchscreen controller
+
+Required properties:
+ - compatible            : "focaltech,ft6236"
+ - reg                   : I2C slave address of the chip (0x38)
+ - interrupt-parent      : a phandle pointing to the interrupt controller
+                           serving the interrupt for this chip
+ - interrupts            : interrupt specification for the touch controller
+                           interrupt
+ - reset-gpios           : GPIO specification for the RSTN input
+ - touchscreen-size-x    : horizontal resolution of touchscreen (in pixels)
+ - touchscreen-size-y    : vertical resolution of touchscreen (in pixels)
+
+Optional properties:
+ - 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-inverted-x : X axis is inverted (boolean)
+ - touchscreen-inverted-y : Y axis is inverted (boolean)
+ - touchscreen-swapped-x-y: X and Y axis are swapped (boolean)
+                           Swapping is done after inverting the axis
+
+Example:
+
+       ft6x06@38 {
+               compatible = "focaltech,ft6236";
+               reg = <0x38>;
+               interrupt-parent = <&gpio>;
+               interrupts = <23 2>;
+               touchscreen-size-x = <320>;
+               touchscreen-size-y = <480>;
+               touchscreen-inverted-x;
+               touchscreen-swapped-x-y;
+       };
index 82d2ac97af74b2a8e5569576cf92f15f1236c036..3222b2ff475e9cc64425debe6db6e1fc20ae3ba5 100644 (file)
@@ -82,6 +82,7 @@ everspin      Everspin Technologies, Inc.
 excito Excito
 fcs    Fairchild Semiconductor
 firefly        Firefly
+focaltech      FocalTech Systems Co.,Ltd
 fsl    Freescale Semiconductor
 GEFanuc        GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 gef    GE Fanuc Intelligent Platforms Embedded Systems, Inc.
index 7da7c2da4af13b3bc711f15a9098c10da80d56fa..0bb36e9af93623e6f3a6e4ee96ae64ce8c215e53 100644 (file)
 
                reg = <0x38>;
                interrupt-parent = <&gpio0>;
-               interrupts = <31 0>;
+               interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
 
                reset-gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
 
index a5b27c85a91c8b14464feabd30d2af7ec03b9d8c..4ea89344a5fff51115160fad9e34b16a4a4377eb 100644 (file)
@@ -13,6 +13,7 @@
 /dts-v1/;
 #include "imx28.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        model = "Ka-Ro electronics TX28 module";
                pinctrl-names = "default";
                pinctrl-0 = <&tx28_edt_ft5x06_pins>;
                interrupt-parent = <&gpio2>;
-               interrupts = <5 0>;
+               interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
                reset-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
                wake-gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>;
        };
index 3b73e81dc3f0df58507a7a6a3ae0556f9abee7dd..13e842b0c7857b1050c73319842113d6bf08dbb3 100644 (file)
@@ -12,6 +12,7 @@
 /dts-v1/;
 #include "imx53-tx53.dtsi"
 #include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pwm/pwm.h>
 
 / {
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_edt_ft5x06_1>;
                interrupt-parent = <&gpio6>;
-               interrupts = <15 0>;
+               interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
                reset-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
                wake-gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
        };
index da08de324e9eb595db45c7cae308327d77bd33a9..13cb7ccfea44dd653e8100669d415b88699c7831 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pwm/pwm.h>
 
 / {
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_edt_ft5x06>;
                interrupt-parent = <&gpio6>;
-               interrupts = <15 0>;
+               interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
                reset-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
                wake-gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
                linux,wakeup;
index c642082671987f98963ff7b07758a678aaffc480..eab56c0aacd5d9433338341b731a242c9370e1bd 100644 (file)
@@ -273,14 +273,14 @@ int input_ff_event(struct input_dev *dev, unsigned int type,
 
        switch (code) {
        case FF_GAIN:
-               if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffff)
+               if (!test_bit(FF_GAIN, dev->ffbit) || value > 0xffffU)
                        break;
 
                ff->set_gain(dev, value);
                break;
 
        case FF_AUTOCENTER:
-               if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffff)
+               if (!test_bit(FF_AUTOCENTER, dev->ffbit) || value > 0xffffU)
                        break;
 
                ff->set_autocenter(dev, value);
index 6cb5a3e5f9a106321aa73de1a4d4265df1022575..e3dcd4abae182e1f4758cc556d274cfeb09b381c 100644 (file)
@@ -444,12 +444,9 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev,
        len = min(len, sizeof(joydev->abspam));
 
        /* Validate the map. */
-       abspam = kmalloc(len, GFP_KERNEL);
-       if (!abspam)
-               return -ENOMEM;
-
-       if (copy_from_user(abspam, argp, len)) {
-               retval = -EFAULT;
+       abspam = memdup_user(argp, len);
+       if (IS_ERR(abspam)) {
+               retval = PTR_ERR(abspam);
                goto out;
        }
 
@@ -480,12 +477,9 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev,
        len = min(len, sizeof(joydev->keypam));
 
        /* Validate the map. */
-       keypam = kmalloc(len, GFP_KERNEL);
-       if (!keypam)
-               return -ENOMEM;
-
-       if (copy_from_user(keypam, argp, len)) {
-               retval = -EFAULT;
+       keypam = memdup_user(argp, len);
+       if (IS_ERR(keypam)) {
+               retval = PTR_ERR(keypam);
                goto out;
        }
 
index 8e7de5c7754ffa98ef0fb869e7668b00b9a32be4..932d07307454bd47441da61ff06e3ef03ea93cd4 100644 (file)
@@ -48,7 +48,7 @@ struct db9_config {
 };
 
 #define DB9_MAX_PORTS          3
-static struct db9_config db9_cfg[DB9_MAX_PORTS] __initdata;
+static struct db9_config db9_cfg[DB9_MAX_PORTS];
 
 module_param_array_named(dev, db9_cfg[0].args, int, &db9_cfg[0].nargs, 0);
 MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
@@ -106,6 +106,7 @@ struct db9 {
        struct pardevice *pd;
        int mode;
        int used;
+       int parportno;
        struct mutex mutex;
        char phys[DB9_MAX_DEVICES][32];
 };
@@ -553,54 +554,60 @@ static void db9_close(struct input_dev *dev)
        mutex_unlock(&db9->mutex);
 }
 
-static struct db9 __init *db9_probe(int parport, int mode)
+static void db9_attach(struct parport *pp)
 {
        struct db9 *db9;
        const struct db9_mode_data *db9_mode;
-       struct parport *pp;
        struct pardevice *pd;
        struct input_dev *input_dev;
-       int i, j;
-       int err;
+       int i, j, port_idx;
+       int mode;
+       struct pardev_cb db9_parport_cb;
+
+       for (port_idx = 0; port_idx < DB9_MAX_PORTS; port_idx++) {
+               if (db9_cfg[port_idx].nargs == 0 ||
+                   db9_cfg[port_idx].args[DB9_ARG_PARPORT] < 0)
+                       continue;
+
+               if (db9_cfg[port_idx].args[DB9_ARG_PARPORT] == pp->number)
+                       break;
+       }
+
+       if (port_idx == DB9_MAX_PORTS) {
+               pr_debug("Not using parport%d.\n", pp->number);
+               return;
+       }
+
+       mode = db9_cfg[port_idx].args[DB9_ARG_MODE];
 
        if (mode < 1 || mode >= DB9_MAX_PAD || !db9_modes[mode].n_buttons) {
                printk(KERN_ERR "db9.c: Bad device type %d\n", mode);
-               err = -EINVAL;
-               goto err_out;
+               return;
        }
 
        db9_mode = &db9_modes[mode];
 
-       pp = parport_find_number(parport);
-       if (!pp) {
-               printk(KERN_ERR "db9.c: no such parport\n");
-               err = -ENODEV;
-               goto err_out;
-       }
-
        if (db9_mode->bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) {
                printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
-               err = -EINVAL;
-               goto err_put_pp;
+               return;
        }
 
-       pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+       db9_parport_cb.flags = PARPORT_FLAG_EXCL;
+
+       pd = parport_register_dev_model(pp, "db9", &db9_parport_cb, port_idx);
        if (!pd) {
                printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
-               err = -EBUSY;
-               goto err_put_pp;
+               return;
        }
 
        db9 = kzalloc(sizeof(struct db9), GFP_KERNEL);
-       if (!db9) {
-               printk(KERN_ERR "db9.c: Not enough memory\n");
-               err = -ENOMEM;
+       if (!db9)
                goto err_unreg_pardev;
-       }
 
        mutex_init(&db9->mutex);
        db9->pd = pd;
        db9->mode = mode;
+       db9->parportno = pp->number;
        init_timer(&db9->timer);
        db9->timer.data = (long) db9;
        db9->timer.function = db9_timer;
@@ -610,7 +617,6 @@ static struct db9 __init *db9_probe(int parport, int mode)
                db9->dev[i] = input_dev = input_allocate_device();
                if (!input_dev) {
                        printk(KERN_ERR "db9.c: Not enough memory for input device\n");
-                       err = -ENOMEM;
                        goto err_unreg_devs;
                }
 
@@ -639,13 +645,12 @@ static struct db9 __init *db9_probe(int parport, int mode)
                                input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0);
                }
 
-               err = input_register_device(input_dev);
-               if (err)
+               if (input_register_device(input_dev))
                        goto err_free_dev;
        }
 
-       parport_put_port(pp);
-       return db9;
+       db9_base[port_idx] = db9;
+       return;
 
  err_free_dev:
        input_free_device(db9->dev[i]);
@@ -655,15 +660,23 @@ static struct db9 __init *db9_probe(int parport, int mode)
        kfree(db9);
  err_unreg_pardev:
        parport_unregister_device(pd);
- err_put_pp:
-       parport_put_port(pp);
- err_out:
-       return ERR_PTR(err);
 }
 
-static void db9_remove(struct db9 *db9)
+static void db9_detach(struct parport *port)
 {
        int i;
+       struct db9 *db9;
+
+       for (i = 0; i < DB9_MAX_PORTS; i++) {
+               if (db9_base[i] && db9_base[i]->parportno == port->number)
+                       break;
+       }
+
+       if (i == DB9_MAX_PORTS)
+               return;
+
+       db9 = db9_base[i];
+       db9_base[i] = NULL;
 
        for (i = 0; i < min(db9_modes[db9->mode].n_pads, DB9_MAX_DEVICES); i++)
                input_unregister_device(db9->dev[i]);
@@ -671,11 +684,17 @@ static void db9_remove(struct db9 *db9)
        kfree(db9);
 }
 
+static struct parport_driver db9_parport_driver = {
+       .name = "db9",
+       .match_port = db9_attach,
+       .detach = db9_detach,
+       .devmodel = true,
+};
+
 static int __init db9_init(void)
 {
        int i;
        int have_dev = 0;
-       int err = 0;
 
        for (i = 0; i < DB9_MAX_PORTS; i++) {
                if (db9_cfg[i].nargs == 0 || db9_cfg[i].args[DB9_ARG_PARPORT] < 0)
@@ -683,37 +702,21 @@ static int __init db9_init(void)
 
                if (db9_cfg[i].nargs < 2) {
                        printk(KERN_ERR "db9.c: Device type must be specified.\n");
-                       err = -EINVAL;
-                       break;
-               }
-
-               db9_base[i] = db9_probe(db9_cfg[i].args[DB9_ARG_PARPORT],
-                                       db9_cfg[i].args[DB9_ARG_MODE]);
-               if (IS_ERR(db9_base[i])) {
-                       err = PTR_ERR(db9_base[i]);
-                       break;
+                       return -EINVAL;
                }
 
                have_dev = 1;
        }
 
-       if (err) {
-               while (--i >= 0)
-                       if (db9_base[i])
-                               db9_remove(db9_base[i]);
-               return err;
-       }
+       if (!have_dev)
+               return -ENODEV;
 
-       return have_dev ? 0 : -ENODEV;
+       return parport_register_driver(&db9_parport_driver);
 }
 
 static void __exit db9_exit(void)
 {
-       int i;
-
-       for (i = 0; i < DB9_MAX_PORTS; i++)
-               if (db9_base[i])
-                       db9_remove(db9_base[i]);
+       parport_unregister_driver(&db9_parport_driver);
 }
 
 module_init(db9_init);
index e68e497864830f63a9dfa72ee7d5a4948bfb733a..5a672dcac0d8174a151254ac31b591f0189f9d91 100644 (file)
@@ -53,7 +53,7 @@ struct gc_config {
        unsigned int nargs;
 };
 
-static struct gc_config gc_cfg[GC_MAX_PORTS] __initdata;
+static struct gc_config gc_cfg[GC_MAX_PORTS];
 
 module_param_array_named(map, gc_cfg[0].args, int, &gc_cfg[0].nargs, 0);
 MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
@@ -92,6 +92,7 @@ struct gc {
        struct timer_list timer;
        int pad_count[GC_MAX];
        int used;
+       int parportno;
        struct mutex mutex;
 };
 
@@ -304,7 +305,7 @@ static int gc_n64_play_effect(struct input_dev *dev, void *data,
        return 0;
 }
 
-static int __init gc_n64_init_ff(struct input_dev *dev, int i)
+static int gc_n64_init_ff(struct input_dev *dev, int i)
 {
        struct gc_subdev *sdev;
        int err;
@@ -811,7 +812,7 @@ static void gc_close(struct input_dev *dev)
        mutex_unlock(&gc->mutex);
 }
 
-static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
+static int gc_setup_pad(struct gc *gc, int idx, int pad_type)
 {
        struct gc_pad *pad = &gc->pads[idx];
        struct input_dev *input_dev;
@@ -926,46 +927,55 @@ err_free_dev:
        return err;
 }
 
-static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
+static void gc_attach(struct parport *pp)
 {
        struct gc *gc;
-       struct parport *pp;
        struct pardevice *pd;
-       int i;
+       int i, port_idx;
        int count = 0;
-       int err;
+       int *pads, n_pads;
+       struct pardev_cb gc_parport_cb;
+
+       for (port_idx = 0; port_idx < GC_MAX_PORTS; port_idx++) {
+               if (gc_cfg[port_idx].nargs == 0 || gc_cfg[port_idx].args[0] < 0)
+                       continue;
+
+               if (gc_cfg[port_idx].args[0] == pp->number)
+                       break;
+       }
 
-       pp = parport_find_number(parport);
-       if (!pp) {
-               pr_err("no such parport %d\n", parport);
-               err = -EINVAL;
-               goto err_out;
+       if (port_idx == GC_MAX_PORTS) {
+               pr_debug("Not using parport%d.\n", pp->number);
+               return;
        }
+       pads = gc_cfg[port_idx].args + 1;
+       n_pads = gc_cfg[port_idx].nargs - 1;
 
-       pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+       gc_parport_cb.flags = PARPORT_FLAG_EXCL;
+
+       pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb,
+                                       port_idx);
        if (!pd) {
                pr_err("parport busy already - lp.o loaded?\n");
-               err = -EBUSY;
-               goto err_put_pp;
+               return;
        }
 
        gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
        if (!gc) {
                pr_err("Not enough memory\n");
-               err = -ENOMEM;
                goto err_unreg_pardev;
        }
 
        mutex_init(&gc->mutex);
        gc->pd = pd;
+       gc->parportno = pp->number;
        setup_timer(&gc->timer, gc_timer, (long) gc);
 
        for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) {
                if (!pads[i])
                        continue;
 
-               err = gc_setup_pad(gc, i, pads[i]);
-               if (err)
+               if (gc_setup_pad(gc, i, pads[i]))
                        goto err_unreg_devs;
 
                count++;
@@ -973,12 +983,11 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
 
        if (count == 0) {
                pr_err("No valid devices specified\n");
-               err = -EINVAL;
                goto err_free_gc;
        }
 
-       parport_put_port(pp);
-       return gc;
+       gc_base[port_idx] = gc;
+       return;
 
  err_unreg_devs:
        while (--i >= 0)
@@ -988,15 +997,23 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
        kfree(gc);
  err_unreg_pardev:
        parport_unregister_device(pd);
- err_put_pp:
-       parport_put_port(pp);
- err_out:
-       return ERR_PTR(err);
 }
 
-static void gc_remove(struct gc *gc)
+static void gc_detach(struct parport *port)
 {
        int i;
+       struct gc *gc;
+
+       for (i = 0; i < GC_MAX_PORTS; i++) {
+               if (gc_base[i] && gc_base[i]->parportno == port->number)
+                       break;
+       }
+
+       if (i == GC_MAX_PORTS)
+               return;
+
+       gc = gc_base[i];
+       gc_base[i] = NULL;
 
        for (i = 0; i < GC_MAX_DEVICES; i++)
                if (gc->pads[i].dev)
@@ -1005,11 +1022,17 @@ static void gc_remove(struct gc *gc)
        kfree(gc);
 }
 
+static struct parport_driver gc_parport_driver = {
+       .name = "gamecon",
+       .match_port = gc_attach,
+       .detach = gc_detach,
+       .devmodel = true,
+};
+
 static int __init gc_init(void)
 {
        int i;
        int have_dev = 0;
-       int err = 0;
 
        for (i = 0; i < GC_MAX_PORTS; i++) {
                if (gc_cfg[i].nargs == 0 || gc_cfg[i].args[0] < 0)
@@ -1017,37 +1040,21 @@ static int __init gc_init(void)
 
                if (gc_cfg[i].nargs < 2) {
                        pr_err("at least one device must be specified\n");
-                       err = -EINVAL;
-                       break;
-               }
-
-               gc_base[i] = gc_probe(gc_cfg[i].args[0],
-                                     gc_cfg[i].args + 1, gc_cfg[i].nargs - 1);
-               if (IS_ERR(gc_base[i])) {
-                       err = PTR_ERR(gc_base[i]);
-                       break;
+                       return -EINVAL;
                }
 
                have_dev = 1;
        }
 
-       if (err) {
-               while (--i >= 0)
-                       if (gc_base[i])
-                               gc_remove(gc_base[i]);
-               return err;
-       }
+       if (!have_dev)
+               return -ENODEV;
 
-       return have_dev ? 0 : -ENODEV;
+       return parport_register_driver(&gc_parport_driver);
 }
 
 static void __exit gc_exit(void)
 {
-       int i;
-
-       for (i = 0; i < GC_MAX_PORTS; i++)
-               if (gc_base[i])
-                       gc_remove(gc_base[i]);
+       parport_unregister_driver(&gc_parport_driver);
 }
 
 module_init(gc_init);
index 891797ad76bccda3ae132e1fc59483b539e522ee..9f5bca26bd2fb85a90ed4fd91bbdcf1a83e84162 100644 (file)
@@ -49,7 +49,7 @@ struct tgfx_config {
        unsigned int nargs;
 };
 
-static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS] __initdata;
+static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS];
 
 module_param_array_named(map, tgfx_cfg[0].args, int, &tgfx_cfg[0].nargs, 0);
 MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
@@ -81,6 +81,7 @@ static struct tgfx {
        char phys[TGFX_MAX_DEVICES][32];
        int sticks;
        int used;
+       int parportno;
        struct mutex sem;
 } *tgfx_base[TGFX_MAX_PORTS];
 
@@ -156,38 +157,48 @@ static void tgfx_close(struct input_dev *dev)
  * tgfx_probe() probes for tg gamepads.
  */
 
-static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
+static void tgfx_attach(struct parport *pp)
 {
        struct tgfx *tgfx;
        struct input_dev *input_dev;
-       struct parport *pp;
        struct pardevice *pd;
-       int i, j;
-       int err;
+       int i, j, port_idx;
+       int *n_buttons, n_devs;
+       struct pardev_cb tgfx_parport_cb;
+
+       for (port_idx = 0; port_idx < TGFX_MAX_PORTS; port_idx++) {
+               if (tgfx_cfg[port_idx].nargs == 0 ||
+                   tgfx_cfg[port_idx].args[0] < 0)
+                       continue;
+               if (tgfx_cfg[port_idx].args[0] == pp->number)
+                       break;
+       }
 
-       pp = parport_find_number(parport);
-       if (!pp) {
-               printk(KERN_ERR "turbografx.c: no such parport\n");
-               err = -EINVAL;
-               goto err_out;
+       if (port_idx == TGFX_MAX_PORTS) {
+               pr_debug("Not using parport%d.\n", pp->number);
+               return;
        }
+       n_buttons = tgfx_cfg[port_idx].args + 1;
+       n_devs = tgfx_cfg[port_idx].nargs - 1;
+
+       tgfx_parport_cb.flags = PARPORT_FLAG_EXCL;
 
-       pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+       pd = parport_register_dev_model(pp, "turbografx", &tgfx_parport_cb,
+                                       port_idx);
        if (!pd) {
-               printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
-               err = -EBUSY;
-               goto err_put_pp;
+               pr_err("parport busy already - lp.o loaded?\n");
+               return;
        }
 
        tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL);
        if (!tgfx) {
                printk(KERN_ERR "turbografx.c: Not enough memory\n");
-               err = -ENOMEM;
                goto err_unreg_pardev;
        }
 
        mutex_init(&tgfx->sem);
        tgfx->pd = pd;
+       tgfx->parportno = pp->number;
        init_timer(&tgfx->timer);
        tgfx->timer.data = (long) tgfx;
        tgfx->timer.function = tgfx_timer;
@@ -198,14 +209,12 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
 
                if (n_buttons[i] > ARRAY_SIZE(tgfx_buttons)) {
                        printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]);
-                       err = -EINVAL;
                        goto err_unreg_devs;
                }
 
                tgfx->dev[i] = input_dev = input_allocate_device();
                if (!input_dev) {
                        printk(KERN_ERR "turbografx.c: Not enough memory for input device\n");
-                       err = -ENOMEM;
                        goto err_unreg_devs;
                }
 
@@ -234,19 +243,17 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
                for (j = 0; j < n_buttons[i]; j++)
                        set_bit(tgfx_buttons[j], input_dev->keybit);
 
-               err = input_register_device(tgfx->dev[i]);
-               if (err)
+               if (input_register_device(tgfx->dev[i]))
                        goto err_free_dev;
        }
 
         if (!tgfx->sticks) {
                printk(KERN_ERR "turbografx.c: No valid devices specified\n");
-               err = -EINVAL;
                goto err_free_tgfx;
         }
 
-       parport_put_port(pp);
-       return tgfx;
+       tgfx_base[port_idx] = tgfx;
+       return;
 
  err_free_dev:
        input_free_device(tgfx->dev[i]);
@@ -258,15 +265,23 @@ static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
        kfree(tgfx);
  err_unreg_pardev:
        parport_unregister_device(pd);
- err_put_pp:
-       parport_put_port(pp);
- err_out:
-       return ERR_PTR(err);
 }
 
-static void tgfx_remove(struct tgfx *tgfx)
+static void tgfx_detach(struct parport *port)
 {
        int i;
+       struct tgfx *tgfx;
+
+       for (i = 0; i < TGFX_MAX_PORTS; i++) {
+               if (tgfx_base[i] && tgfx_base[i]->parportno == port->number)
+                       break;
+       }
+
+       if (i == TGFX_MAX_PORTS)
+               return;
+
+       tgfx = tgfx_base[i];
+       tgfx_base[i] = NULL;
 
        for (i = 0; i < TGFX_MAX_DEVICES; i++)
                if (tgfx->dev[i])
@@ -275,11 +290,17 @@ static void tgfx_remove(struct tgfx *tgfx)
        kfree(tgfx);
 }
 
+static struct parport_driver tgfx_parport_driver = {
+       .name = "turbografx",
+       .match_port = tgfx_attach,
+       .detach = tgfx_detach,
+       .devmodel = true,
+};
+
 static int __init tgfx_init(void)
 {
        int i;
        int have_dev = 0;
-       int err = 0;
 
        for (i = 0; i < TGFX_MAX_PORTS; i++) {
                if (tgfx_cfg[i].nargs == 0 || tgfx_cfg[i].args[0] < 0)
@@ -287,38 +308,21 @@ static int __init tgfx_init(void)
 
                if (tgfx_cfg[i].nargs < 2) {
                        printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
-                       err = -EINVAL;
-                       break;
-               }
-
-               tgfx_base[i] = tgfx_probe(tgfx_cfg[i].args[0],
-                                         tgfx_cfg[i].args + 1,
-                                         tgfx_cfg[i].nargs - 1);
-               if (IS_ERR(tgfx_base[i])) {
-                       err = PTR_ERR(tgfx_base[i]);
-                       break;
+                       return -EINVAL;
                }
 
                have_dev = 1;
        }
 
-       if (err) {
-               while (--i >= 0)
-                       if (tgfx_base[i])
-                               tgfx_remove(tgfx_base[i]);
-               return err;
-       }
+       if (!have_dev)
+               return -ENODEV;
 
-       return have_dev ? 0 : -ENODEV;
+       return parport_register_driver(&tgfx_parport_driver);
 }
 
 static void __exit tgfx_exit(void)
 {
-       int i;
-
-       for (i = 0; i < TGFX_MAX_PORTS; i++)
-               if (tgfx_base[i])
-                       tgfx_remove(tgfx_base[i]);
+       parport_unregister_driver(&tgfx_parport_driver);
 }
 
 module_init(tgfx_init);
index a8bc2fe170dd83e12ff78706f97f9bc32a72e5cd..d88f5dd3c9d9e9a7080cbd9bacecb740e0791488 100644 (file)
@@ -200,35 +200,38 @@ static void walkera0701_close(struct input_dev *dev)
        parport_release(w->pardevice);
 }
 
-static int walkera0701_connect(struct walkera_dev *w, int parport)
+static void walkera0701_attach(struct parport *pp)
 {
-       int error;
+       struct pardev_cb walkera0701_parport_cb;
+       struct walkera_dev *w = &w_dev;
 
-       w->parport = parport_find_number(parport);
-       if (!w->parport) {
-               pr_err("parport %d does not exist\n", parport);
-               return -ENODEV;
+       if (pp->number != walkera0701_pp_no) {
+               pr_debug("Not using parport%d.\n", pp->number);
+               return;
        }
 
-       if (w->parport->irq == -1) {
+       if (pp->irq == -1) {
                pr_err("parport %d does not have interrupt assigned\n",
-                       parport);
-               error = -EINVAL;
-               goto err_put_parport;
+                       pp->number);
+               return;
        }
 
-       w->pardevice = parport_register_device(w->parport, "walkera0701",
-                                   NULL, NULL, walkera0701_irq_handler,
-                                   PARPORT_DEV_EXCL, w);
+       w->parport = pp;
+
+       walkera0701_parport_cb.flags = PARPORT_FLAG_EXCL;
+       walkera0701_parport_cb.irq_func = walkera0701_irq_handler;
+       walkera0701_parport_cb.private = w;
+
+       w->pardevice = parport_register_dev_model(pp, "walkera0701",
+                                                 &walkera0701_parport_cb, 0);
+
        if (!w->pardevice) {
                pr_err("failed to register parport device\n");
-               error = -EIO;
-               goto err_put_parport;
+               return;
        }
 
        if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT)) {
                pr_err("failed to negotiate parport mode\n");
-               error = -EIO;
                goto err_unregister_device;
        }
 
@@ -238,7 +241,6 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
        w->input_dev = input_allocate_device();
        if (!w->input_dev) {
                pr_err("failed to allocate input device\n");
-               error = -ENOMEM;
                goto err_unregister_device;
        }
 
@@ -265,38 +267,46 @@ static int walkera0701_connect(struct walkera_dev *w, int parport)
        input_set_abs_params(w->input_dev, ABS_RUDDER, -512, 512, 0, 0);
        input_set_abs_params(w->input_dev, ABS_MISC, -512, 512, 0, 0);
 
-       error = input_register_device(w->input_dev);
-       if (error) {
+       if (input_register_device(w->input_dev)) {
                pr_err("failed to register input device\n");
                goto err_free_input_dev;
        }
 
-       return 0;
+       return;
 
 err_free_input_dev:
        input_free_device(w->input_dev);
 err_unregister_device:
        parport_unregister_device(w->pardevice);
-err_put_parport:
-       parport_put_port(w->parport);
-       return error;
 }
 
-static void walkera0701_disconnect(struct walkera_dev *w)
+static void walkera0701_detach(struct parport *port)
 {
+       struct walkera_dev *w = &w_dev;
+
+       if (!w->pardevice || w->parport->number != port->number)
+               return;
+
        input_unregister_device(w->input_dev);
        parport_unregister_device(w->pardevice);
-       parport_put_port(w->parport);
+       w->parport = NULL;
 }
 
+static struct parport_driver walkera0701_parport_driver = {
+       .name = "walkera0701",
+       .match_port = walkera0701_attach,
+       .detach = walkera0701_detach,
+       .devmodel = true,
+};
+
 static int __init walkera0701_init(void)
 {
-       return walkera0701_connect(&w_dev, walkera0701_pp_no);
+       return parport_register_driver(&walkera0701_parport_driver);
 }
 
 static void __exit walkera0701_exit(void)
 {
-       walkera0701_disconnect(&w_dev);
+       parport_unregister_driver(&walkera0701_parport_driver);
 }
 
 module_init(walkera0701_init);
index 2e80107ff630384739ec23d497e9d14321be25c5..ddd8148d51d70cf5994c53190110ae9c35adadfb 100644 (file)
@@ -516,7 +516,7 @@ config KEYBOARD_SAMSUNG
          module will be called samsung-keypad.
 
 config KEYBOARD_GOLDFISH_EVENTS
-       depends on GOLDFISH
+       depends on GOLDFISH || COMPILE_TEST
        tristate "Generic Input Event device for Goldfish"
        help
          Say Y here to get an input event device for the Goldfish virtual
index 9d517ca7eb5aad432249d34ed8a710588510bd21..bef317ff7352ffd73885ea6a11efd58efba9663d 100644 (file)
@@ -341,8 +341,14 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
        const struct gpio_keys_button *button = bdata->button;
        struct input_dev *input = bdata->input;
        unsigned int type = button->type ?: EV_KEY;
-       int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low;
+       int state = gpio_get_value_cansleep(button->gpio);
 
+       if (state < 0) {
+               dev_err(input->dev.parent, "failed to get gpio state\n");
+               return;
+       }
+
+       state = (state ? 1 : 0) ^ button->active_low;
        if (type == EV_ABS) {
                if (state)
                        input_event(input, type, button->code, button->value);
index 906dd1b25e41b7efc0aa12f70e37bb977fa61c76..d1ef61c2decd190490bee743b1688fc4b35208ca 100644 (file)
@@ -599,11 +599,11 @@ config INPUT_DA9055_ONKEY
          will be called da9055_onkey.
 
 config INPUT_DA9063_ONKEY
-       tristate "Dialog DA9063 OnKey"
-       depends on MFD_DA9063
+       tristate "Dialog DA9062/63 OnKey"
+       depends on MFD_DA9063 || MFD_DA9062
        help
-         Support the ONKEY of Dialog DA9063 Power Management IC as an
-         input device reporting power button statue.
+         Support the ONKEY of Dialog DA9063 and DA9062 Power Management ICs
+         as an input device capable of reporting the power button status.
 
          To compile this driver as a module, choose M here: the module
          will be called da9063_onkey.
index 189bdc8e91a5d2d116cda4d429ca8474eb071c26..2f047738bc0bd85f1ff21459a0b9709fa6a422b9 100644 (file)
@@ -85,15 +85,6 @@ static int ad714x_i2c_probe(struct i2c_client *client,
        return 0;
 }
 
-static int ad714x_i2c_remove(struct i2c_client *client)
-{
-       struct ad714x_chip *chip = i2c_get_clientdata(client);
-
-       ad714x_remove(chip);
-
-       return 0;
-}
-
 static const struct i2c_device_id ad714x_id[] = {
        { "ad7142_captouch", 0 },
        { "ad7143_captouch", 0 },
@@ -110,7 +101,6 @@ static struct i2c_driver ad714x_i2c_driver = {
                .pm   = &ad714x_i2c_pm,
        },
        .probe    = ad714x_i2c_probe,
-       .remove   = ad714x_i2c_remove,
        .id_table = ad714x_id,
 };
 
index a79e50b58bf5d3f2c0b3f12d7eb3d62b527686a4..c8170f0829624a111f1d8a3a68ad1abe6d6b7445 100644 (file)
@@ -101,15 +101,6 @@ static int ad714x_spi_probe(struct spi_device *spi)
        return 0;
 }
 
-static int ad714x_spi_remove(struct spi_device *spi)
-{
-       struct ad714x_chip *chip = spi_get_drvdata(spi);
-
-       ad714x_remove(chip);
-
-       return 0;
-}
-
 static struct spi_driver ad714x_spi_driver = {
        .driver = {
                .name   = "ad714x_captouch",
@@ -117,7 +108,6 @@ static struct spi_driver ad714x_spi_driver = {
                .pm     = &ad714x_spi_pm,
        },
        .probe          = ad714x_spi_probe,
-       .remove         = ad714x_spi_remove,
 };
 
 module_spi_driver(ad714x_spi_driver);
index 7a61e9ee682cff92c7b445c8fbc660f31286088b..84b51dd51f6e9147396d43bc002833e670d24764 100644 (file)
@@ -960,13 +960,12 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-#define MAX_DEVICE_NUM 8
 struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
                                 ad714x_read_t read, ad714x_write_t write)
 {
-       int i, alloc_idx;
+       int i;
        int error;
-       struct input_dev *input[MAX_DEVICE_NUM];
+       struct input_dev *input;
 
        struct ad714x_platform_data *plat_data = dev_get_platdata(dev);
        struct ad714x_chip *ad714x;
@@ -982,25 +981,25 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
        if (irq <= 0) {
                dev_err(dev, "IRQ not configured!\n");
                error = -EINVAL;
-               goto err_out;
+               return ERR_PTR(error);
        }
 
        if (dev_get_platdata(dev) == NULL) {
                dev_err(dev, "platform data for ad714x doesn't exist\n");
                error = -EINVAL;
-               goto err_out;
+               return ERR_PTR(error);
        }
 
-       ad714x = kzalloc(sizeof(*ad714x) + sizeof(*ad714x->sw) +
-                        sizeof(*sd_drv) * plat_data->slider_num +
-                        sizeof(*wl_drv) * plat_data->wheel_num +
-                        sizeof(*tp_drv) * plat_data->touchpad_num +
-                        sizeof(*bt_drv) * plat_data->button_num, GFP_KERNEL);
+       ad714x = devm_kzalloc(dev, sizeof(*ad714x) + sizeof(*ad714x->sw) +
+                                  sizeof(*sd_drv) * plat_data->slider_num +
+                                  sizeof(*wl_drv) * plat_data->wheel_num +
+                                  sizeof(*tp_drv) * plat_data->touchpad_num +
+                                  sizeof(*bt_drv) * plat_data->button_num,
+                             GFP_KERNEL);
        if (!ad714x) {
                error = -ENOMEM;
-               goto err_out;
+               return ERR_PTR(error);
        }
-
        ad714x->hw = plat_data;
 
        drv_mem = ad714x + 1;
@@ -1022,47 +1021,40 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
 
        error = ad714x_hw_detect(ad714x);
        if (error)
-               goto err_free_mem;
+               return ERR_PTR(error);
 
        /* initialize and request sw/hw resources */
 
        ad714x_hw_init(ad714x);
        mutex_init(&ad714x->mutex);
 
-       /*
-        * Allocate and register AD714X input device
-        */
-       alloc_idx = 0;
-
        /* a slider uses one input_dev instance */
        if (ad714x->hw->slider_num > 0) {
                struct ad714x_slider_plat *sd_plat = ad714x->hw->slider;
 
                for (i = 0; i < ad714x->hw->slider_num; i++) {
-                       sd_drv[i].input = input[alloc_idx] = input_allocate_device();
-                       if (!input[alloc_idx]) {
-                               error = -ENOMEM;
-                               goto err_free_dev;
-                       }
-
-                       __set_bit(EV_ABS, input[alloc_idx]->evbit);
-                       __set_bit(EV_KEY, input[alloc_idx]->evbit);
-                       __set_bit(ABS_X, input[alloc_idx]->absbit);
-                       __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
-                       input_set_abs_params(input[alloc_idx],
+                       input = devm_input_allocate_device(dev);
+                       if (!input)
+                               return ERR_PTR(-ENOMEM);
+
+                       __set_bit(EV_ABS, input->evbit);
+                       __set_bit(EV_KEY, input->evbit);
+                       __set_bit(ABS_X, input->absbit);
+                       __set_bit(BTN_TOUCH, input->keybit);
+                       input_set_abs_params(input,
                                ABS_X, 0, sd_plat->max_coord, 0, 0);
 
-                       input[alloc_idx]->id.bustype = bus_type;
-                       input[alloc_idx]->id.product = ad714x->product;
-                       input[alloc_idx]->id.version = ad714x->version;
-                       input[alloc_idx]->name = "ad714x_captouch_slider";
-                       input[alloc_idx]->dev.parent = dev;
+                       input->id.bustype = bus_type;
+                       input->id.product = ad714x->product;
+                       input->id.version = ad714x->version;
+                       input->name = "ad714x_captouch_slider";
+                       input->dev.parent = dev;
 
-                       error = input_register_device(input[alloc_idx]);
+                       error = input_register_device(input);
                        if (error)
-                               goto err_free_dev;
+                               return ERR_PTR(error);
 
-                       alloc_idx++;
+                       sd_drv[i].input = input;
                }
        }
 
@@ -1071,30 +1063,28 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
                struct ad714x_wheel_plat *wl_plat = ad714x->hw->wheel;
 
                for (i = 0; i < ad714x->hw->wheel_num; i++) {
-                       wl_drv[i].input = input[alloc_idx] = input_allocate_device();
-                       if (!input[alloc_idx]) {
-                               error = -ENOMEM;
-                               goto err_free_dev;
-                       }
-
-                       __set_bit(EV_KEY, input[alloc_idx]->evbit);
-                       __set_bit(EV_ABS, input[alloc_idx]->evbit);
-                       __set_bit(ABS_WHEEL, input[alloc_idx]->absbit);
-                       __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
-                       input_set_abs_params(input[alloc_idx],
+                       input = devm_input_allocate_device(dev);
+                       if (!input)
+                               return ERR_PTR(-ENOMEM);
+
+                       __set_bit(EV_KEY, input->evbit);
+                       __set_bit(EV_ABS, input->evbit);
+                       __set_bit(ABS_WHEEL, input->absbit);
+                       __set_bit(BTN_TOUCH, input->keybit);
+                       input_set_abs_params(input,
                                ABS_WHEEL, 0, wl_plat->max_coord, 0, 0);
 
-                       input[alloc_idx]->id.bustype = bus_type;
-                       input[alloc_idx]->id.product = ad714x->product;
-                       input[alloc_idx]->id.version = ad714x->version;
-                       input[alloc_idx]->name = "ad714x_captouch_wheel";
-                       input[alloc_idx]->dev.parent = dev;
+                       input->id.bustype = bus_type;
+                       input->id.product = ad714x->product;
+                       input->id.version = ad714x->version;
+                       input->name = "ad714x_captouch_wheel";
+                       input->dev.parent = dev;
 
-                       error = input_register_device(input[alloc_idx]);
+                       error = input_register_device(input);
                        if (error)
-                               goto err_free_dev;
+                               return ERR_PTR(error);
 
-                       alloc_idx++;
+                       wl_drv[i].input = input;
                }
        }
 
@@ -1103,33 +1093,31 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
                struct ad714x_touchpad_plat *tp_plat = ad714x->hw->touchpad;
 
                for (i = 0; i < ad714x->hw->touchpad_num; i++) {
-                       tp_drv[i].input = input[alloc_idx] = input_allocate_device();
-                       if (!input[alloc_idx]) {
-                               error = -ENOMEM;
-                               goto err_free_dev;
-                       }
-
-                       __set_bit(EV_ABS, input[alloc_idx]->evbit);
-                       __set_bit(EV_KEY, input[alloc_idx]->evbit);
-                       __set_bit(ABS_X, input[alloc_idx]->absbit);
-                       __set_bit(ABS_Y, input[alloc_idx]->absbit);
-                       __set_bit(BTN_TOUCH, input[alloc_idx]->keybit);
-                       input_set_abs_params(input[alloc_idx],
+                       input = devm_input_allocate_device(dev);
+                       if (!input)
+                               return ERR_PTR(-ENOMEM);
+
+                       __set_bit(EV_ABS, input->evbit);
+                       __set_bit(EV_KEY, input->evbit);
+                       __set_bit(ABS_X, input->absbit);
+                       __set_bit(ABS_Y, input->absbit);
+                       __set_bit(BTN_TOUCH, input->keybit);
+                       input_set_abs_params(input,
                                ABS_X, 0, tp_plat->x_max_coord, 0, 0);
-                       input_set_abs_params(input[alloc_idx],
+                       input_set_abs_params(input,
                                ABS_Y, 0, tp_plat->y_max_coord, 0, 0);
 
-                       input[alloc_idx]->id.bustype = bus_type;
-                       input[alloc_idx]->id.product = ad714x->product;
-                       input[alloc_idx]->id.version = ad714x->version;
-                       input[alloc_idx]->name = "ad714x_captouch_pad";
-                       input[alloc_idx]->dev.parent = dev;
+                       input->id.bustype = bus_type;
+                       input->id.product = ad714x->product;
+                       input->id.version = ad714x->version;
+                       input->name = "ad714x_captouch_pad";
+                       input->dev.parent = dev;
 
-                       error = input_register_device(input[alloc_idx]);
+                       error = input_register_device(input);
                        if (error)
-                               goto err_free_dev;
+                               return ERR_PTR(error);
 
-                       alloc_idx++;
+                       tp_drv[i].input = input;
                }
        }
 
@@ -1137,82 +1125,44 @@ struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
        if (ad714x->hw->button_num > 0) {
                struct ad714x_button_plat *bt_plat = ad714x->hw->button;
 
-               input[alloc_idx] = input_allocate_device();
-               if (!input[alloc_idx]) {
+               input = devm_input_allocate_device(dev);
+               if (!input) {
                        error = -ENOMEM;
-                       goto err_free_dev;
+                       return ERR_PTR(error);
                }
 
-               __set_bit(EV_KEY, input[alloc_idx]->evbit);
+               __set_bit(EV_KEY, input->evbit);
                for (i = 0; i < ad714x->hw->button_num; i++) {
-                       bt_drv[i].input = input[alloc_idx];
-                       __set_bit(bt_plat[i].keycode, input[alloc_idx]->keybit);
+                       bt_drv[i].input = input;
+                       __set_bit(bt_plat[i].keycode, input->keybit);
                }
 
-               input[alloc_idx]->id.bustype = bus_type;
-               input[alloc_idx]->id.product = ad714x->product;
-               input[alloc_idx]->id.version = ad714x->version;
-               input[alloc_idx]->name = "ad714x_captouch_button";
-               input[alloc_idx]->dev.parent = dev;
+               input->id.bustype = bus_type;
+               input->id.product = ad714x->product;
+               input->id.version = ad714x->version;
+               input->name = "ad714x_captouch_button";
+               input->dev.parent = dev;
 
-               error = input_register_device(input[alloc_idx]);
+               error = input_register_device(input);
                if (error)
-                       goto err_free_dev;
-
-               alloc_idx++;
+                       return ERR_PTR(error);
        }
 
        irqflags = plat_data->irqflags ?: IRQF_TRIGGER_FALLING;
        irqflags |= IRQF_ONESHOT;
 
-       error = request_threaded_irq(ad714x->irq, NULL, ad714x_interrupt_thread,
-                                    irqflags, "ad714x_captouch", ad714x);
+       error = devm_request_threaded_irq(dev, ad714x->irq, NULL,
+                                         ad714x_interrupt_thread,
+                                         irqflags, "ad714x_captouch", ad714x);
        if (error) {
                dev_err(dev, "can't allocate irq %d\n", ad714x->irq);
-               goto err_unreg_dev;
+               return ERR_PTR(error);
        }
 
        return ad714x;
-
- err_free_dev:
-       dev_err(dev, "failed to setup AD714x input device %i\n", alloc_idx);
-       input_free_device(input[alloc_idx]);
- err_unreg_dev:
-       while (--alloc_idx >= 0)
-               input_unregister_device(input[alloc_idx]);
- err_free_mem:
-       kfree(ad714x);
- err_out:
-       return ERR_PTR(error);
 }
 EXPORT_SYMBOL(ad714x_probe);
 
-void ad714x_remove(struct ad714x_chip *ad714x)
-{
-       struct ad714x_platform_data *hw = ad714x->hw;
-       struct ad714x_driver_data *sw = ad714x->sw;
-       int i;
-
-       free_irq(ad714x->irq, ad714x);
-
-       /* unregister and free all input devices */
-
-       for (i = 0; i < hw->slider_num; i++)
-               input_unregister_device(sw->slider[i].input);
-
-       for (i = 0; i < hw->wheel_num; i++)
-               input_unregister_device(sw->wheel[i].input);
-
-       for (i = 0; i < hw->touchpad_num; i++)
-               input_unregister_device(sw->touchpad[i].input);
-
-       if (hw->button_num)
-               input_unregister_device(sw->button[0].input);
-
-       kfree(ad714x);
-}
-EXPORT_SYMBOL(ad714x_remove);
-
 #ifdef CONFIG_PM
 int ad714x_disable(struct ad714x_chip *ad714x)
 {
index 3c85455aa66d23329d3605fb367d400d320e4976..5d65d303b9bfa9d41f936ffd6908fe4f6f38ce8d 100644 (file)
@@ -50,6 +50,5 @@ int ad714x_disable(struct ad714x_chip *ad714x);
 int ad714x_enable(struct ad714x_chip *ad714x);
 struct ad714x_chip *ad714x_probe(struct device *dev, u16 bus_type, int irq,
                                 ad714x_read_t read, ad714x_write_t write);
-void ad714x_remove(struct ad714x_chip *ad714x);
 
 #endif
index f577585ef999af29425531b9cc75fe494f1c62ba..8eb697db82d03606839e0002c5232513cfb80477 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * OnKey device driver for DA9063
+ * OnKey device driver for DA9063 and DA9062 PMICs
  * Copyright (C) 2015  Dialog Semiconductor Ltd.
  *
  * This program is free software; you can redistribute it and/or
 #include <linux/mfd/da9063/core.h>
 #include <linux/mfd/da9063/pdata.h>
 #include <linux/mfd/da9063/registers.h>
+#include <linux/mfd/da9062/core.h>
+#include <linux/mfd/da9062/registers.h>
+
+struct da906x_chip_config {
+       /* REGS */
+       int onkey_status;
+       int onkey_pwr_signalling;
+       int onkey_fault_log;
+       int onkey_shutdown;
+       /* MASKS */
+       int onkey_nonkey_mask;
+       int onkey_nonkey_lock_mask;
+       int onkey_key_reset_mask;
+       int onkey_shutdown_mask;
+       /* NAMES */
+       const char *name;
+};
 
 struct da9063_onkey {
-       struct da9063 *hw;
        struct delayed_work work;
        struct input_dev *input;
        struct device *dev;
+       struct regmap *regmap;
+       const struct da906x_chip_config *config;
+       char phys[32];
        bool key_power;
 };
 
+static const struct da906x_chip_config da9063_regs = {
+       /* REGS */
+       .onkey_status = DA9063_REG_STATUS_A,
+       .onkey_pwr_signalling = DA9063_REG_CONTROL_B,
+       .onkey_fault_log = DA9063_REG_FAULT_LOG,
+       .onkey_shutdown = DA9063_REG_CONTROL_F,
+       /* MASKS */
+       .onkey_nonkey_mask = DA9063_NONKEY,
+       .onkey_nonkey_lock_mask = DA9063_NONKEY_LOCK,
+       .onkey_key_reset_mask = DA9063_KEY_RESET,
+       .onkey_shutdown_mask = DA9063_SHUTDOWN,
+       /* NAMES */
+       .name = DA9063_DRVNAME_ONKEY,
+};
+
+static const struct da906x_chip_config da9062_regs = {
+       /* REGS */
+       .onkey_status = DA9062AA_STATUS_A,
+       .onkey_pwr_signalling = DA9062AA_CONTROL_B,
+       .onkey_fault_log = DA9062AA_FAULT_LOG,
+       .onkey_shutdown = DA9062AA_CONTROL_F,
+       /* MASKS */
+       .onkey_nonkey_mask = DA9062AA_NONKEY_MASK,
+       .onkey_nonkey_lock_mask = DA9062AA_NONKEY_LOCK_MASK,
+       .onkey_key_reset_mask = DA9062AA_KEY_RESET_MASK,
+       .onkey_shutdown_mask = DA9062AA_SHUTDOWN_MASK,
+       /* NAMES */
+       .name = "da9062-onkey",
+};
+
+static const struct of_device_id da9063_compatible_reg_id_table[] = {
+       { .compatible = "dlg,da9063-onkey", .data = &da9063_regs },
+       { .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
+       { },
+};
+
 static void da9063_poll_on(struct work_struct *work)
 {
-       struct da9063_onkey *onkey = container_of(work, struct da9063_onkey,
-                                                 work.work);
+       struct da9063_onkey *onkey = container_of(work,
+                                               struct da9063_onkey,
+                                               work.work);
+       const struct da906x_chip_config *config = onkey->config;
        unsigned int val;
        int fault_log = 0;
        bool poll = true;
        int error;
 
        /* Poll to see when the pin is released */
-       error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val);
+       error = regmap_read(onkey->regmap,
+                           config->onkey_status,
+                           &val);
        if (error) {
                dev_err(onkey->dev,
                        "Failed to read ON status: %d\n", error);
                goto err_poll;
        }
 
-       if (!(val & DA9063_NONKEY)) {
-               error = regmap_update_bits(onkey->hw->regmap,
-                                          DA9063_REG_CONTROL_B,
-                                          DA9063_NONKEY_LOCK, 0);
+       if (!(val & config->onkey_nonkey_mask)) {
+               error = regmap_update_bits(onkey->regmap,
+                                          config->onkey_pwr_signalling,
+                                          config->onkey_nonkey_lock_mask,
+                                          0);
                if (error) {
                        dev_err(onkey->dev,
                                "Failed to reset the Key Delay %d\n", error);
@@ -70,15 +130,16 @@ static void da9063_poll_on(struct work_struct *work)
         * If the fault log KEY_RESET is detected, then clear it
         * and shut down the system.
         */
-       error = regmap_read(onkey->hw->regmap,
-                           DA9063_REG_FAULT_LOG, &fault_log);
+       error = regmap_read(onkey->regmap,
+                           config->onkey_fault_log,
+                           &fault_log);
        if (error) {
                dev_warn(&onkey->input->dev,
                         "Cannot read FAULT_LOG: %d\n", error);
-       } else if (fault_log & DA9063_KEY_RESET) {
-               error = regmap_write(onkey->hw->regmap,
-                                    DA9063_REG_FAULT_LOG,
-                                    DA9063_KEY_RESET);
+       } else if (fault_log & config->onkey_key_reset_mask) {
+               error = regmap_write(onkey->regmap,
+                                    config->onkey_fault_log,
+                                    config->onkey_key_reset_mask);
                if (error) {
                        dev_warn(&onkey->input->dev,
                                 "Cannot reset KEY_RESET fault log: %d\n",
@@ -88,10 +149,10 @@ static void da9063_poll_on(struct work_struct *work)
                         * and then send shutdown command
                         */
                        dev_dbg(&onkey->input->dev,
-                                "Sending SHUTDOWN to DA9063 ...\n");
-                       error = regmap_write(onkey->hw->regmap,
-                                            DA9063_REG_CONTROL_F,
-                                            DA9063_SHUTDOWN);
+                               "Sending SHUTDOWN to DA9063 ...\n");
+                       error = regmap_write(onkey->regmap,
+                                            config->onkey_shutdown,
+                                            config->onkey_shutdown_mask);
                        if (error)
                                dev_err(&onkey->input->dev,
                                        "Cannot SHUTDOWN DA9063: %d\n",
@@ -107,11 +168,14 @@ err_poll:
 static irqreturn_t da9063_onkey_irq_handler(int irq, void *data)
 {
        struct da9063_onkey *onkey = data;
+       const struct da906x_chip_config *config = onkey->config;
        unsigned int val;
        int error;
 
-       error = regmap_read(onkey->hw->regmap, DA9063_REG_STATUS_A, &val);
-       if (onkey->key_power && !error && (val & DA9063_NONKEY)) {
+       error = regmap_read(onkey->regmap,
+                           config->onkey_status,
+                           &val);
+       if (onkey->key_power && !error && (val & config->onkey_nonkey_mask)) {
                input_report_key(onkey->input, KEY_POWER, 1);
                input_sync(onkey->input);
                schedule_delayed_work(&onkey->work, 0);
@@ -139,9 +203,15 @@ static int da9063_onkey_probe(struct platform_device *pdev)
        struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
        struct da9063_pdata *pdata = dev_get_platdata(da9063->dev);
        struct da9063_onkey *onkey;
+       const struct of_device_id *match;
        int irq;
        int error;
 
+       match = of_match_node(da9063_compatible_reg_id_table,
+                             pdev->dev.of_node);
+       if (!match)
+               return -ENXIO;
+
        onkey = devm_kzalloc(&pdev->dev, sizeof(struct da9063_onkey),
                             GFP_KERNEL);
        if (!onkey) {
@@ -149,8 +219,14 @@ static int da9063_onkey_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+       onkey->config = match->data;
        onkey->dev = &pdev->dev;
-       onkey->hw = da9063;
+
+       onkey->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+       if (!onkey->regmap) {
+               dev_err(&pdev->dev, "Parent regmap unavailable.\n");
+               return -ENXIO;
+       }
 
        if (pdata)
                onkey->key_power = pdata->key_power;
@@ -165,8 +241,10 @@ static int da9063_onkey_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       onkey->input->name = DA9063_DRVNAME_ONKEY;
-       onkey->input->phys = DA9063_DRVNAME_ONKEY "/input0";
+       onkey->input->name = onkey->config->name;
+       snprintf(onkey->phys, sizeof(onkey->phys), "%s/input0",
+                onkey->config->name);
+       onkey->input->phys = onkey->phys;
        onkey->input->dev.parent = &pdev->dev;
 
        if (onkey->key_power)
@@ -216,11 +294,12 @@ static struct platform_driver da9063_onkey_driver = {
        .probe  = da9063_onkey_probe,
        .driver = {
                .name   = DA9063_DRVNAME_ONKEY,
+               .of_match_table = da9063_compatible_reg_id_table,
        },
 };
 module_platform_driver(da9063_onkey_driver);
 
 MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
-MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063");
+MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063 and DA9062");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY);
index e058d711256a203c97f8018824cba877fbdc0f05..efaffcc57e36cb58050a009830b5953bd08cb744 100644 (file)
@@ -635,7 +635,6 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
        struct i2c_client *client = to_i2c_client(dev);
        struct kxtj9_data *tj9 = i2c_get_clientdata(client);
        struct input_dev *input_dev = tj9->input_dev;
-       int retval = 0;
 
        mutex_lock(&input_dev->mutex);
 
@@ -643,7 +642,7 @@ static int __maybe_unused kxtj9_resume(struct device *dev)
                kxtj9_enable(tj9);
 
        mutex_unlock(&input_dev->mutex);
-       return retval;
+       return 0;
 }
 
 static SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume);
index 600dcceff5426aaf4f6fc7b20ce966960bf0aa92..eda89b6b7e11569748cef18d7845df0d5ef19e31 100644 (file)
@@ -295,6 +295,19 @@ config TOUCHSCREEN_EGALAX
          To compile this driver as a module, choose M here: the
          module will be called egalax_ts.
 
+config TOUCHSCREEN_FT6236
+       tristate "FT6236 I2C touchscreen"
+       depends on I2C
+       depends on GPIOLIB || COMPILE_TEST
+       help
+         Say Y here to enable support for the I2C connected FT6x06 and
+         FT6x36 family of capacitive touchscreen drivers.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ft6236.
+
 config TOUCHSCREEN_FUJITSU
        tristate "Fujitsu serial touchscreen"
        select SERIO
index 1b79cc09744af93b02ecabe958c24fc47bd189f3..baba189e3e160f5090a60d47103b2600ded75d8c 100644 (file)
@@ -35,6 +35,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI)                += eeti_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ELAN)         += elants_i2c.o
 obj-$(CONFIG_TOUCHSCREEN_ELO)          += elo.o
 obj-$(CONFIG_TOUCHSCREEN_EGALAX)       += egalax_ts.o
+obj-$(CONFIG_TOUCHSCREEN_FT6236)       += ft6236.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)      += fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GOODIX)       += goodix.o
 obj-$(CONFIG_TOUCHSCREEN_ILI210X)      += ili210x.o
index 0f5f968592bd02afd9c5381a8839b3428c3bcbea..727d88c900c1da57f9922d0eeafc0d579cf050f2 100644 (file)
@@ -529,10 +529,8 @@ static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
 
        ts->hwmon = hwmon_device_register_with_groups(&spi->dev, spi->modalias,
                                                      ts, ads7846_attr_groups);
-       if (IS_ERR(ts->hwmon))
-               return PTR_ERR(ts->hwmon);
 
-       return 0;
+       return PTR_ERR_OR_ZERO(ts->hwmon);
 }
 
 static void ads784x_hwmon_unregister(struct spi_device *spi,
index 38c06f754acd69abeb45ff3fbba766c9e01a09d6..6592fc5d48b489ee5cc6c7ea2fe797c7e19683b4 100644 (file)
@@ -399,13 +399,8 @@ static int auo_pixcir_stop(struct auo_pixcir_ts *ts)
 static int auo_pixcir_input_open(struct input_dev *dev)
 {
        struct auo_pixcir_ts *ts = input_get_drvdata(dev);
-       int ret;
-
-       ret = auo_pixcir_start(ts);
-       if (ret)
-               return ret;
 
-       return 0;
+       return auo_pixcir_start(ts);
 }
 
 static void auo_pixcir_input_close(struct input_dev *dev)
index a9f95c7d3c0066cbd257b80755efdbe683340dbf..564e49002d5d61ae5632ac830a4bb0f3f05c32e2 100644 (file)
@@ -50,10 +50,7 @@ static int cyttsp4_i2c_probe(struct i2c_client *client,
        ts = cyttsp4_probe(&cyttsp4_i2c_bus_ops, &client->dev, client->irq,
                          CYTTSP4_I2C_DATA_SIZE);
 
-       if (IS_ERR(ts))
-               return PTR_ERR(ts);
-
-       return 0;
+       return PTR_ERR_OR_ZERO(ts);
 }
 
 static int cyttsp4_i2c_remove(struct i2c_client *client)
index 48de1e8b3c93578cf4c1faf88c220c008a75569c..7239c314c9e9bf398620ee98a11461b9050987ea 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <linux/module.h>
 #include <linux/ratelimit.h>
+#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/input/mt.h>
 #include <linux/input/touchscreen.h>
-#include <linux/input/edt-ft5x06.h>
 
 #define MAX_SUPPORT_POINTS             5
 
@@ -91,9 +90,8 @@ struct edt_ft5x06_ts_data {
        u16 num_x;
        u16 num_y;
 
-       int reset_pin;
-       int irq_pin;
-       int wake_pin;
+       struct gpio_desc *reset_gpio;
+       struct gpio_desc *wake_gpio;
 
 #if defined(CONFIG_DEBUG_FS)
        struct dentry *debug_dir;
@@ -752,45 +750,6 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
 
 #endif /* CONFIG_DEBUGFS */
 
-static int edt_ft5x06_ts_reset(struct i2c_client *client,
-                       struct edt_ft5x06_ts_data *tsdata)
-{
-       int error;
-
-       if (gpio_is_valid(tsdata->wake_pin)) {
-               error = devm_gpio_request_one(&client->dev,
-                                       tsdata->wake_pin, GPIOF_OUT_INIT_LOW,
-                                       "edt-ft5x06 wake");
-               if (error) {
-                       dev_err(&client->dev,
-                               "Failed to request GPIO %d as wake pin, error %d\n",
-                               tsdata->wake_pin, error);
-                       return error;
-               }
-
-               msleep(5);
-               gpio_set_value(tsdata->wake_pin, 1);
-       }
-       if (gpio_is_valid(tsdata->reset_pin)) {
-               /* this pulls reset down, enabling the low active reset */
-               error = devm_gpio_request_one(&client->dev,
-                                       tsdata->reset_pin, GPIOF_OUT_INIT_LOW,
-                                       "edt-ft5x06 reset");
-               if (error) {
-                       dev_err(&client->dev,
-                               "Failed to request GPIO %d as reset pin, error %d\n",
-                               tsdata->reset_pin, error);
-                       return error;
-               }
-
-               msleep(5);
-               gpio_set_value(tsdata->reset_pin, 1);
-               msleep(300);
-       }
-
-       return 0;
-}
-
 static int edt_ft5x06_ts_identify(struct i2c_client *client,
                                        struct edt_ft5x06_ts_data *tsdata,
                                        char *fw_version)
@@ -850,44 +809,24 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
        return 0;
 }
 
-#define EDT_ATTR_CHECKSET(name, reg) \
-do {                                                           \
-       if (pdata->name >= edt_ft5x06_attr_##name.limit_low &&          \
-           pdata->name <= edt_ft5x06_attr_##name.limit_high)           \
-               edt_ft5x06_register_write(tsdata, reg, pdata->name);    \
-} while (0)
-
-#define EDT_GET_PROP(name, reg) {                              \
-       u32 val;                                                \
-       if (of_property_read_u32(np, #name, &val) == 0)         \
-               edt_ft5x06_register_write(tsdata, reg, val);    \
-}
-
-static void edt_ft5x06_ts_get_dt_defaults(struct device_node *np,
-                                       struct edt_ft5x06_ts_data *tsdata)
+static void edt_ft5x06_ts_get_defaults(struct device *dev,
+                                      struct edt_ft5x06_ts_data *tsdata)
 {
        struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
+       u32 val;
+       int error;
 
-       EDT_GET_PROP(threshold, reg_addr->reg_threshold);
-       EDT_GET_PROP(gain, reg_addr->reg_gain);
-       EDT_GET_PROP(offset, reg_addr->reg_offset);
-}
-
-static void
-edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata,
-                          const struct edt_ft5x06_platform_data *pdata)
-{
-       struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
+       error = device_property_read_u32(dev, "threshold", &val);
+       if (!error)
+               reg_addr->reg_threshold = val;
 
-       if (!pdata->use_parameters)
-               return;
+       error = device_property_read_u32(dev, "gain", &val);
+       if (!error)
+               reg_addr->reg_gain = val;
 
-       /* pick up defaults from the platform data */
-       EDT_ATTR_CHECKSET(threshold, reg_addr->reg_threshold);
-       EDT_ATTR_CHECKSET(gain, reg_addr->reg_gain);
-       EDT_ATTR_CHECKSET(offset, reg_addr->reg_offset);
-       if (reg_addr->reg_report_rate != NO_REGISTER)
-               EDT_ATTR_CHECKSET(report_rate, reg_addr->reg_report_rate);
+       error = device_property_read_u32(dev, "offset", &val);
+       if (!error)
+               reg_addr->reg_offset = val;
 }
 
 static void
@@ -931,37 +870,12 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
        }
 }
 
-#ifdef CONFIG_OF
-static int edt_ft5x06_i2c_ts_probe_dt(struct device *dev,
-                               struct edt_ft5x06_ts_data *tsdata)
-{
-       struct device_node *np = dev->of_node;
-
-       /*
-        * irq_pin is not needed for DT setup.
-        * irq is associated via 'interrupts' property in DT
-        */
-       tsdata->irq_pin = -EINVAL;
-       tsdata->reset_pin = of_get_named_gpio(np, "reset-gpios", 0);
-       tsdata->wake_pin = of_get_named_gpio(np, "wake-gpios", 0);
-
-       return 0;
-}
-#else
-static inline int edt_ft5x06_i2c_ts_probe_dt(struct device *dev,
-                                       struct edt_ft5x06_ts_data *tsdata)
-{
-       return -ENODEV;
-}
-#endif
-
 static int edt_ft5x06_ts_probe(struct i2c_client *client,
                                         const struct i2c_device_id *id)
 {
-       const struct edt_ft5x06_platform_data *pdata =
-                                               dev_get_platdata(&client->dev);
        struct edt_ft5x06_ts_data *tsdata;
        struct input_dev *input;
+       unsigned long irq_flags;
        int error;
        char fw_version[EDT_NAME_LEN];
 
@@ -973,32 +887,33 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
                return -ENOMEM;
        }
 
-       if (!pdata) {
-               error = edt_ft5x06_i2c_ts_probe_dt(&client->dev, tsdata);
-               if (error) {
-                       dev_err(&client->dev,
-                               "DT probe failed and no platform data present\n");
-                       return error;
-               }
-       } else {
-               tsdata->reset_pin = pdata->reset_pin;
-               tsdata->irq_pin = pdata->irq_pin;
-               tsdata->wake_pin = -EINVAL;
+       tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev,
+                                                    "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(tsdata->reset_gpio)) {
+               error = PTR_ERR(tsdata->reset_gpio);
+               dev_err(&client->dev,
+                       "Failed to request GPIO reset pin, error %d\n", error);
+               return error;
        }
 
-       error = edt_ft5x06_ts_reset(client, tsdata);
-       if (error)
+       tsdata->wake_gpio = devm_gpiod_get_optional(&client->dev,
+                                                   "wake", GPIOD_OUT_LOW);
+       if (IS_ERR(tsdata->wake_gpio)) {
+               error = PTR_ERR(tsdata->wake_gpio);
+               dev_err(&client->dev,
+                       "Failed to request GPIO wake pin, error %d\n", error);
                return error;
+       }
 
-       if (gpio_is_valid(tsdata->irq_pin)) {
-               error = devm_gpio_request_one(&client->dev, tsdata->irq_pin,
-                                       GPIOF_IN, "edt-ft5x06 irq");
-               if (error) {
-                       dev_err(&client->dev,
-                               "Failed to request GPIO %d, error %d\n",
-                               tsdata->irq_pin, error);
-                       return error;
-               }
+       if (tsdata->wake_gpio) {
+               usleep_range(5000, 6000);
+               gpiod_set_value_cansleep(tsdata->wake_gpio, 1);
+       }
+
+       if (tsdata->reset_gpio) {
+               usleep_range(5000, 6000);
+               gpiod_set_value_cansleep(tsdata->reset_gpio, 0);
+               msleep(300);
        }
 
        input = devm_input_allocate_device(&client->dev);
@@ -1019,12 +934,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
        }
 
        edt_ft5x06_ts_set_regs(tsdata);
-
-       if (!pdata)
-               edt_ft5x06_ts_get_dt_defaults(client->dev.of_node, tsdata);
-       else
-               edt_ft5x06_ts_get_defaults(tsdata, pdata);
-
+       edt_ft5x06_ts_get_defaults(&client->dev, tsdata);
        edt_ft5x06_ts_get_parameters(tsdata);
 
        dev_dbg(&client->dev,
@@ -1040,8 +950,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
        input_set_abs_params(input, ABS_MT_POSITION_Y,
                             0, tsdata->num_y * 64 - 1, 0, 0);
 
-       if (!pdata)
-               touchscreen_parse_properties(input, true);
+       touchscreen_parse_properties(input, true);
 
        error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, INPUT_MT_DIRECT);
        if (error) {
@@ -1052,9 +961,13 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
        input_set_drvdata(input, tsdata);
        i2c_set_clientdata(client, tsdata);
 
-       error = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-                                       edt_ft5x06_ts_isr,
-                                       IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+       irq_flags = irq_get_trigger_type(client->irq);
+       if (irq_flags == IRQF_TRIGGER_NONE)
+               irq_flags = IRQF_TRIGGER_FALLING;
+       irq_flags |= IRQF_ONESHOT;
+
+       error = devm_request_threaded_irq(&client->dev, client->irq,
+                                       NULL, edt_ft5x06_ts_isr, irq_flags,
                                        client->name, tsdata);
        if (error) {
                dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
@@ -1074,7 +987,8 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
 
        dev_dbg(&client->dev,
                "EDT FT5x06 initialized: IRQ %d, WAKE pin %d, Reset pin %d.\n",
-               client->irq, tsdata->wake_pin, tsdata->reset_pin);
+               client->irq, desc_to_gpio(tsdata->wake_gpio),
+               desc_to_gpio(tsdata->reset_gpio));
 
        return 0;
 
diff --git a/drivers/input/touchscreen/ft6236.c b/drivers/input/touchscreen/ft6236.c
new file mode 100644 (file)
index 0000000..cccae19
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * FocalTech FT6236 TouchScreen driver.
+ *
+ * Copyright (c) 2010  Focal tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/property.h>
+
+#define FT6236_MAX_TOUCH_POINTS                2
+
+#define FT6236_REG_TH_GROUP            0x80
+#define FT6236_REG_PERIODACTIVE                0x88
+#define FT6236_REG_LIB_VER_H           0xa1
+#define FT6236_REG_LIB_VER_L           0xa2
+#define FT6236_REG_CIPHER              0xa3
+#define FT6236_REG_FIRMID              0xa6
+#define FT6236_REG_FOCALTECH_ID                0xa8
+#define FT6236_REG_RELEASE_CODE_ID     0xaf
+
+#define FT6236_EVENT_PRESS_DOWN                0
+#define FT6236_EVENT_LIFT_UP           1
+#define FT6236_EVENT_CONTACT           2
+#define FT6236_EVENT_NO_EVENT          3
+
+struct ft6236_data {
+       struct i2c_client *client;
+       struct input_dev *input;
+       struct gpio_desc *reset_gpio;
+       u32 max_x;
+       u32 max_y;
+       bool invert_x;
+       bool invert_y;
+       bool swap_xy;
+};
+
+/*
+ * This struct is a touchpoint as stored in hardware.  Note that the id,
+ * as well as the event, are stored in the upper nybble of the hi byte.
+ */
+struct ft6236_touchpoint {
+       union {
+               u8 xhi;
+               u8 event;
+       };
+       u8 xlo;
+       union {
+               u8 yhi;
+               u8 id;
+       };
+       u8 ylo;
+       u8 weight;
+       u8 misc;
+} __packed;
+
+/* This packet represents the register map as read from offset 0 */
+struct ft6236_packet {
+       u8 dev_mode;
+       u8 gest_id;
+       u8 touches;
+       struct ft6236_touchpoint points[FT6236_MAX_TOUCH_POINTS];
+} __packed;
+
+static int ft6236_read(struct i2c_client *client, u8 reg, u8 len, void *data)
+{
+       int error;
+
+       error = i2c_smbus_read_i2c_block_data(client, reg, len, data);
+       if (error < 0)
+               return error;
+
+       if (error != len)
+               return -EIO;
+
+       return 0;
+}
+
+static irqreturn_t ft6236_interrupt(int irq, void *dev_id)
+{
+       struct ft6236_data *ft6236 = dev_id;
+       struct device *dev = &ft6236->client->dev;
+       struct input_dev *input = ft6236->input;
+       struct ft6236_packet buf;
+       u8 touches;
+       int i, error;
+
+       error = ft6236_read(ft6236->client, 0, sizeof(buf), &buf);
+       if (error) {
+               dev_err(dev, "read touchdata failed %d\n", error);
+               return IRQ_HANDLED;
+       }
+
+       touches = buf.touches & 0xf;
+       if (touches > FT6236_MAX_TOUCH_POINTS) {
+               dev_dbg(dev,
+                       "%d touch points reported, only %d are supported\n",
+                       touches, FT6236_MAX_TOUCH_POINTS);
+               touches = FT6236_MAX_TOUCH_POINTS;
+       }
+
+       for (i = 0; i < touches; i++) {
+               struct ft6236_touchpoint *point = &buf.points[i];
+               u16 x = ((point->xhi & 0xf) << 8) | buf.points[i].xlo;
+               u16 y = ((point->yhi & 0xf) << 8) | buf.points[i].ylo;
+               u8 event = point->event >> 6;
+               u8 id = point->id >> 4;
+               bool act = (event == FT6236_EVENT_PRESS_DOWN ||
+                           event == FT6236_EVENT_CONTACT);
+
+               input_mt_slot(input, id);
+               input_mt_report_slot_state(input, MT_TOOL_FINGER, act);
+               if (!act)
+                       continue;
+
+               if (ft6236->invert_x)
+                       x = ft6236->max_x - x;
+
+               if (ft6236->invert_y)
+                       y = ft6236->max_y - y;
+
+               if (ft6236->swap_xy) {
+                       input_report_abs(input, ABS_MT_POSITION_X, y);
+                       input_report_abs(input, ABS_MT_POSITION_Y, x);
+               } else {
+                       input_report_abs(input, ABS_MT_POSITION_X, x);
+                       input_report_abs(input, ABS_MT_POSITION_Y, y);
+               }
+       }
+
+       input_mt_sync_frame(input);
+       input_sync(input);
+
+       return IRQ_HANDLED;
+}
+
+static u8 ft6236_debug_read_byte(struct ft6236_data *ft6236, u8 reg)
+{
+       struct i2c_client *client = ft6236->client;
+       u8 val = 0;
+       int error;
+
+       error = ft6236_read(client, reg, 1, &val);
+       if (error)
+               dev_dbg(&client->dev,
+                       "error reading register 0x%02x: %d\n", reg, error);
+
+       return val;
+}
+
+static void ft6236_debug_info(struct ft6236_data *ft6236)
+{
+       struct device *dev = &ft6236->client->dev;
+
+       dev_dbg(dev, "Touch threshold is %d\n",
+               ft6236_debug_read_byte(ft6236, FT6236_REG_TH_GROUP) * 4);
+       dev_dbg(dev, "Report rate is %dHz\n",
+               ft6236_debug_read_byte(ft6236, FT6236_REG_PERIODACTIVE) * 10);
+       dev_dbg(dev, "Firmware library version 0x%02x%02x\n",
+               ft6236_debug_read_byte(ft6236, FT6236_REG_LIB_VER_H),
+               ft6236_debug_read_byte(ft6236, FT6236_REG_LIB_VER_L));
+       dev_dbg(dev, "Firmware version 0x%02x\n",
+               ft6236_debug_read_byte(ft6236, FT6236_REG_FIRMID));
+       dev_dbg(dev, "Chip vendor ID 0x%02x\n",
+               ft6236_debug_read_byte(ft6236, FT6236_REG_CIPHER));
+       dev_dbg(dev, "CTPM vendor ID 0x%02x\n",
+               ft6236_debug_read_byte(ft6236, FT6236_REG_FOCALTECH_ID));
+       dev_dbg(dev, "Release code version 0x%02x\n",
+               ft6236_debug_read_byte(ft6236, FT6236_REG_RELEASE_CODE_ID));
+}
+
+static void ft6236_reset(struct ft6236_data *ft6236)
+{
+       if (!ft6236->reset_gpio)
+               return;
+
+       gpiod_set_value_cansleep(ft6236->reset_gpio, 1);
+       usleep_range(5000, 20000);
+       gpiod_set_value_cansleep(ft6236->reset_gpio, 0);
+       msleep(300);
+}
+
+static int ft6236_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct device *dev = &client->dev;
+       struct ft6236_data *ft6236;
+       struct input_dev *input;
+       u32 fuzz_x = 0, fuzz_y = 0;
+       u8 val;
+       int error;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+               return -ENXIO;
+
+       if (!client->irq) {
+               dev_err(dev, "irq is missing\n");
+               return -EINVAL;
+       }
+
+       ft6236 = devm_kzalloc(dev, sizeof(*ft6236), GFP_KERNEL);
+       if (!ft6236)
+               return -ENOMEM;
+
+       ft6236->client = client;
+       ft6236->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+                                                    GPIOD_OUT_LOW);
+       if (IS_ERR(ft6236->reset_gpio)) {
+               error = PTR_ERR(ft6236->reset_gpio);
+               if (error != -EPROBE_DEFER)
+                       dev_err(dev, "error getting reset gpio: %d\n", error);
+               return error;
+       }
+
+       ft6236_reset(ft6236);
+
+       /* verify that the controller is present */
+       error = ft6236_read(client, 0x00, 1, &val);
+       if (error) {
+               dev_err(dev, "failed to read from controller: %d\n", error);
+               return error;
+       }
+
+       ft6236_debug_info(ft6236);
+
+       input = devm_input_allocate_device(dev);
+       if (!input)
+               return -ENOMEM;
+
+       ft6236->input = input;
+       input->name = client->name;
+       input->id.bustype = BUS_I2C;
+
+       if (device_property_read_u32(dev, "touchscreen-size-x",
+                                    &ft6236->max_x) ||
+           device_property_read_u32(dev, "touchscreen-size-y",
+                                    &ft6236->max_y)) {
+               dev_err(dev, "touchscreen-size-x and/or -y missing\n");
+               return -EINVAL;
+       }
+
+       device_property_read_u32(dev, "touchscreen-fuzz-x", &fuzz_x);
+       device_property_read_u32(dev, "touchscreen-fuzz-y", &fuzz_y);
+       ft6236->invert_x = device_property_read_bool(dev,
+                                                    "touchscreen-inverted-x");
+       ft6236->invert_y = device_property_read_bool(dev,
+                                                    "touchscreen-inverted-y");
+       ft6236->swap_xy = device_property_read_bool(dev,
+                                                   "touchscreen-swapped-x-y");
+
+       if (ft6236->swap_xy) {
+               input_set_abs_params(input, ABS_MT_POSITION_X, 0,
+                                    ft6236->max_y, fuzz_y, 0);
+               input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
+                                    ft6236->max_x, fuzz_x, 0);
+       } else {
+               input_set_abs_params(input, ABS_MT_POSITION_X, 0,
+                                    ft6236->max_x, fuzz_x, 0);
+               input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
+                                    ft6236->max_y, fuzz_y, 0);
+       }
+
+       error = input_mt_init_slots(input, FT6236_MAX_TOUCH_POINTS,
+                                   INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+       if (error)
+               return error;
+
+       error = devm_request_threaded_irq(dev, client->irq, NULL,
+                                         ft6236_interrupt, IRQF_ONESHOT,
+                                         client->name, ft6236);
+       if (error) {
+               dev_err(dev, "request irq %d failed: %d\n", client->irq, error);
+               return error;
+       }
+
+       error = input_register_device(input);
+       if (error) {
+               dev_err(dev, "failed to register input device: %d\n", error);
+               return error;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id ft6236_of_match[] = {
+       { .compatible = "focaltech,ft6236", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ft6236_of_match);
+#endif
+
+static const struct i2c_device_id ft6236_id[] = {
+       { "ft6236", },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ft6236_id);
+
+static struct i2c_driver ft6236_driver = {
+       .driver = {
+               .name = "ft6236",
+               .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(ft6236_of_match),
+       },
+       .probe = ft6236_probe,
+       .id_table = ft6236_id,
+};
+module_i2c_driver(ft6236_driver);
+
+MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>");
+MODULE_AUTHOR("Noralf Trønnes <noralf@tronnes.org>");
+MODULE_DESCRIPTION("FocalTech FT6236 TouchScreen driver");
+MODULE_LICENSE("GPL");
index 4ffd829d1990a2d0e66d8c7fdf0fa2151f6c0504..a340bfccdfb6697fb033dca488f310559ba91fd6 100644 (file)
@@ -50,14 +50,7 @@ struct tps6507x_ts {
 
 static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data)
 {
-       int err;
-
-       err = tsc->mfd->read_dev(tsc->mfd, reg, 1, data);
-
-       if (err)
-               return err;
-
-       return 0;
+       return tsc->mfd->read_dev(tsc->mfd, reg, 1, data);
 }
 
 static int tps6507x_write_u8(struct tps6507x_ts *tsc, u8 reg, u8 data)
index 781d0f83050ab005ef4917188f2df0e3995aad72..9bbadaaf6bc3723f044a9c44e8619773d242ec8f 100644 (file)
@@ -599,13 +599,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
 static int zforce_input_open(struct input_dev *dev)
 {
        struct zforce_ts *ts = input_get_drvdata(dev);
-       int ret;
 
-       ret = zforce_start(ts);
-       if (ret)
-               return ret;
-
-       return 0;
+       return zforce_start(ts);
 }
 
 static void zforce_input_close(struct input_dev *dev)
diff --git a/include/linux/input/edt-ft5x06.h b/include/linux/input/edt-ft5x06.h
deleted file mode 100644 (file)
index 8a1e0d1..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _EDT_FT5X06_H
-#define _EDT_FT5X06_H
-
-/*
- * Copyright (c) 2012 Simon Budig, <simon.budig@kernelconcepts.de>
- *
- * 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.
- */
-
-struct edt_ft5x06_platform_data {
-       int irq_pin;
-       int reset_pin;
-
-       /* startup defaults for operational parameters */
-       bool use_parameters;
-       u8 gain;
-       u8 threshold;
-       u8 offset;
-       u8 report_rate;
-};
-
-#endif /* _EDT_FT5X06_H */