]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'v3.14-rc4' into next
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 1 Mar 2014 18:31:53 +0000 (10:31 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 1 Mar 2014 18:31:53 +0000 (10:31 -0800)
Merge with Linux 3.14-rc4 to bring devm_request_any_context_irq().

Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt [new file with mode: 0644]
drivers/input/keyboard/imx_keypad.c
drivers/input/misc/ims-pcu.c
drivers/input/misc/sirfsoc-onkey.c
drivers/input/misc/uinput.c
drivers/input/misc/wistron_btns.c
drivers/input/tablet/gtco.c
drivers/input/touchscreen/zforce_ts.c
include/linux/platform_data/touchscreen-s3c2410.h
include/linux/uinput.h
include/uapi/linux/uinput.h

diff --git a/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt
new file mode 100644 (file)
index 0000000..2faf1f1
--- /dev/null
@@ -0,0 +1,30 @@
+* Neonode infrared touchscreen controller
+
+Required properties:
+- compatible: must be "neonode,zforce"
+- reg: I2C address of the chip
+- interrupts: interrupt to which the chip is connected
+- gpios: gpios the chip is connected to
+  first one is the interrupt gpio and second one the reset gpio
+- x-size: horizontal resolution of touchscreen
+- y-size: vertical resolution of touchscreen
+
+Example:
+
+       i2c@00000000 {
+               /* ... */
+
+               zforce_ts@50 {
+                       compatible = "neonode,zforce";
+                       reg = <0x50>;
+                       interrupts = <2 0>;
+
+                       gpios = <&gpio5 6 0>, /* INT */
+                               <&gpio5 9 0>; /* RST */
+
+                       x-size = <800>;
+                       y-size = <600>;
+               };
+
+               /* ... */
+       };
index cbf4f8038cbae434998e9aaa4f6120ed6f5f3c9a..97ec33572e563fce0ab5dfedf0aeaa966462f05c 100644 (file)
@@ -439,7 +439,7 @@ static int imx_keypad_probe(struct platform_device *pdev)
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(&pdev->dev, "no irq defined in platform data\n");
-               return -EINVAL;
+               return irq;
        }
 
        input_dev = devm_input_allocate_device(&pdev->dev);
@@ -449,7 +449,7 @@ static int imx_keypad_probe(struct platform_device *pdev)
        }
 
        keypad = devm_kzalloc(&pdev->dev, sizeof(struct imx_keypad),
-                            GFP_KERNEL);
+                             GFP_KERNEL);
        if (!keypad) {
                dev_err(&pdev->dev, "not enough memory for driver data\n");
                return -ENOMEM;
index e204f26b0011ae0f5ecfff4e6c28cd8e32481806..5a736397d9c8ee3f540ce9cc7b7f77710ff6b787 100644 (file)
@@ -51,6 +51,8 @@ struct ims_pcu_backlight {
 #define IMS_PCU_BL_VERSION_LEN         (9 + 1)
 #define IMS_PCU_BL_RESET_REASON_LEN    (2 + 1)
 
+#define IMS_PCU_PCU_B_DEVICE_ID                5
+
 #define IMS_PCU_BUF_SIZE               128
 
 struct ims_pcu {
@@ -68,6 +70,9 @@ struct ims_pcu {
        char bl_version[IMS_PCU_BL_VERSION_LEN];
        char reset_reason[IMS_PCU_BL_RESET_REASON_LEN];
        int update_firmware_status;
+       u8 device_id;
+
+       u8 ofn_reg_addr;
 
        struct usb_interface *ctrl_intf;
 
@@ -371,6 +376,8 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu)
 #define IMS_PCU_CMD_GET_DEVICE_ID      0xae
 #define IMS_PCU_CMD_SPECIAL_INFO       0xb0
 #define IMS_PCU_CMD_BOOTLOADER         0xb1    /* Pass data to bootloader */
+#define IMS_PCU_CMD_OFN_SET_CONFIG     0xb3
+#define IMS_PCU_CMD_OFN_GET_CONFIG     0xb4
 
 /* PCU responses */
 #define IMS_PCU_RSP_STATUS             0xc0
@@ -389,6 +396,9 @@ static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu)
 #define IMS_PCU_RSP_GET_DEVICE_ID      0xce
 #define IMS_PCU_RSP_SPECIAL_INFO       0xd0
 #define IMS_PCU_RSP_BOOTLOADER         0xd1    /* Bootloader response */
+#define IMS_PCU_RSP_OFN_SET_CONFIG     0xd2
+#define IMS_PCU_RSP_OFN_GET_CONFIG     0xd3
+
 
 #define IMS_PCU_RSP_EVNT_BUTTONS       0xe0    /* Unsolicited, button state */
 #define IMS_PCU_GAMEPAD_MASK           0x0001ff80UL    /* Bits 7 through 16 */
@@ -1256,6 +1266,225 @@ static struct attribute_group ims_pcu_attr_group = {
        .attrs          = ims_pcu_attrs,
 };
 
+/* Support for a separate OFN attribute group */
+
+#define OFN_REG_RESULT_OFFSET  2
+
+static int ims_pcu_read_ofn_config(struct ims_pcu *pcu, u8 addr, u8 *data)
+{
+       int error;
+       s16 result;
+
+       error = ims_pcu_execute_command(pcu, OFN_GET_CONFIG,
+                                       &addr, sizeof(addr));
+       if (error)
+               return error;
+
+       result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET);
+       if (result < 0)
+               return -EIO;
+
+       /* We only need LSB */
+       *data = pcu->cmd_buf[OFN_REG_RESULT_OFFSET];
+       return 0;
+}
+
+static int ims_pcu_write_ofn_config(struct ims_pcu *pcu, u8 addr, u8 data)
+{
+       u8 buffer[] = { addr, data };
+       int error;
+       s16 result;
+
+       error = ims_pcu_execute_command(pcu, OFN_SET_CONFIG,
+                                       &buffer, sizeof(buffer));
+       if (error)
+               return error;
+
+       result = (s16)get_unaligned_le16(pcu->cmd_buf + OFN_REG_RESULT_OFFSET);
+       if (result < 0)
+               return -EIO;
+
+       return 0;
+}
+
+static ssize_t ims_pcu_ofn_reg_data_show(struct device *dev,
+                                        struct device_attribute *dattr,
+                                        char *buf)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct ims_pcu *pcu = usb_get_intfdata(intf);
+       int error;
+       u8 data;
+
+       mutex_lock(&pcu->cmd_mutex);
+       error = ims_pcu_read_ofn_config(pcu, pcu->ofn_reg_addr, &data);
+       mutex_unlock(&pcu->cmd_mutex);
+
+       if (error)
+               return error;
+
+       return scnprintf(buf, PAGE_SIZE, "%x\n", data);
+}
+
+static ssize_t ims_pcu_ofn_reg_data_store(struct device *dev,
+                                         struct device_attribute *dattr,
+                                         const char *buf, size_t count)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct ims_pcu *pcu = usb_get_intfdata(intf);
+       int error;
+       u8 value;
+
+       error = kstrtou8(buf, 0, &value);
+       if (error)
+               return error;
+
+       mutex_lock(&pcu->cmd_mutex);
+       error = ims_pcu_write_ofn_config(pcu, pcu->ofn_reg_addr, value);
+       mutex_unlock(&pcu->cmd_mutex);
+
+       return error ?: count;
+}
+
+static DEVICE_ATTR(reg_data, S_IRUGO | S_IWUSR,
+                  ims_pcu_ofn_reg_data_show, ims_pcu_ofn_reg_data_store);
+
+static ssize_t ims_pcu_ofn_reg_addr_show(struct device *dev,
+                                        struct device_attribute *dattr,
+                                        char *buf)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct ims_pcu *pcu = usb_get_intfdata(intf);
+       int error;
+
+       mutex_lock(&pcu->cmd_mutex);
+       error = scnprintf(buf, PAGE_SIZE, "%x\n", pcu->ofn_reg_addr);
+       mutex_unlock(&pcu->cmd_mutex);
+
+       return error;
+}
+
+static ssize_t ims_pcu_ofn_reg_addr_store(struct device *dev,
+                                         struct device_attribute *dattr,
+                                         const char *buf, size_t count)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct ims_pcu *pcu = usb_get_intfdata(intf);
+       int error;
+       u8 value;
+
+       error = kstrtou8(buf, 0, &value);
+       if (error)
+               return error;
+
+       mutex_lock(&pcu->cmd_mutex);
+       pcu->ofn_reg_addr = value;
+       mutex_unlock(&pcu->cmd_mutex);
+
+       return error ?: count;
+}
+
+static DEVICE_ATTR(reg_addr, S_IRUGO | S_IWUSR,
+                  ims_pcu_ofn_reg_addr_show, ims_pcu_ofn_reg_addr_store);
+
+struct ims_pcu_ofn_bit_attribute {
+       struct device_attribute dattr;
+       u8 addr;
+       u8 nr;
+};
+
+static ssize_t ims_pcu_ofn_bit_show(struct device *dev,
+                                   struct device_attribute *dattr,
+                                   char *buf)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct ims_pcu *pcu = usb_get_intfdata(intf);
+       struct ims_pcu_ofn_bit_attribute *attr =
+               container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr);
+       int error;
+       u8 data;
+
+       mutex_lock(&pcu->cmd_mutex);
+       error = ims_pcu_read_ofn_config(pcu, attr->addr, &data);
+       mutex_unlock(&pcu->cmd_mutex);
+
+       if (error)
+               return error;
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", !!(data & (1 << attr->nr)));
+}
+
+static ssize_t ims_pcu_ofn_bit_store(struct device *dev,
+                                    struct device_attribute *dattr,
+                                    const char *buf, size_t count)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct ims_pcu *pcu = usb_get_intfdata(intf);
+       struct ims_pcu_ofn_bit_attribute *attr =
+               container_of(dattr, struct ims_pcu_ofn_bit_attribute, dattr);
+       int error;
+       int value;
+       u8 data;
+
+       error = kstrtoint(buf, 0, &value);
+       if (error)
+               return error;
+
+       if (value > 1)
+               return -EINVAL;
+
+       mutex_lock(&pcu->cmd_mutex);
+
+       error = ims_pcu_read_ofn_config(pcu, attr->addr, &data);
+       if (!error) {
+               if (value)
+                       data |= 1U << attr->nr;
+               else
+                       data &= ~(1U << attr->nr);
+
+               error = ims_pcu_write_ofn_config(pcu, attr->addr, data);
+       }
+
+       mutex_unlock(&pcu->cmd_mutex);
+
+       return error ?: count;
+}
+
+#define IMS_PCU_OFN_BIT_ATTR(_field, _addr, _nr)                       \
+struct ims_pcu_ofn_bit_attribute ims_pcu_ofn_attr_##_field = {         \
+       .dattr = __ATTR(_field, S_IWUSR | S_IRUGO,                      \
+                       ims_pcu_ofn_bit_show, ims_pcu_ofn_bit_store),   \
+       .addr = _addr,                                                  \
+       .nr = _nr,                                                      \
+}
+
+static IMS_PCU_OFN_BIT_ATTR(engine_enable,   0x60, 7);
+static IMS_PCU_OFN_BIT_ATTR(speed_enable,    0x60, 6);
+static IMS_PCU_OFN_BIT_ATTR(assert_enable,   0x60, 5);
+static IMS_PCU_OFN_BIT_ATTR(xyquant_enable,  0x60, 4);
+static IMS_PCU_OFN_BIT_ATTR(xyscale_enable,  0x60, 1);
+
+static IMS_PCU_OFN_BIT_ATTR(scale_x2,        0x63, 6);
+static IMS_PCU_OFN_BIT_ATTR(scale_y2,        0x63, 7);
+
+static struct attribute *ims_pcu_ofn_attrs[] = {
+       &dev_attr_reg_data.attr,
+       &dev_attr_reg_addr.attr,
+       &ims_pcu_ofn_attr_engine_enable.dattr.attr,
+       &ims_pcu_ofn_attr_speed_enable.dattr.attr,
+       &ims_pcu_ofn_attr_assert_enable.dattr.attr,
+       &ims_pcu_ofn_attr_xyquant_enable.dattr.attr,
+       &ims_pcu_ofn_attr_xyscale_enable.dattr.attr,
+       &ims_pcu_ofn_attr_scale_x2.dattr.attr,
+       &ims_pcu_ofn_attr_scale_y2.dattr.attr,
+       NULL
+};
+
+static struct attribute_group ims_pcu_ofn_attr_group = {
+       .name   = "ofn",
+       .attrs  = ims_pcu_ofn_attrs,
+};
+
 static void ims_pcu_irq(struct urb *urb)
 {
        struct ims_pcu *pcu = urb->context;
@@ -1624,7 +1853,6 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
        static atomic_t device_no = ATOMIC_INIT(0);
 
        const struct ims_pcu_device_info *info;
-       u8 device_id;
        int error;
 
        error = ims_pcu_get_device_info(pcu);
@@ -1633,7 +1861,7 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
                return error;
        }
 
-       error = ims_pcu_identify_type(pcu, &device_id);
+       error = ims_pcu_identify_type(pcu, &pcu->device_id);
        if (error) {
                dev_err(pcu->dev,
                        "Failed to identify device, error: %d\n", error);
@@ -1645,9 +1873,9 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
                return 0;
        }
 
-       if (device_id >= ARRAY_SIZE(ims_pcu_device_info) ||
-           !ims_pcu_device_info[device_id].keymap) {
-               dev_err(pcu->dev, "Device ID %d is not valid\n", device_id);
+       if (pcu->device_id >= ARRAY_SIZE(ims_pcu_device_info) ||
+           !ims_pcu_device_info[pcu->device_id].keymap) {
+               dev_err(pcu->dev, "Device ID %d is not valid\n", pcu->device_id);
                /* Same as above, punt to userspace */
                return 0;
        }
@@ -1655,11 +1883,21 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
        /* Device appears to be operable, complete initialization */
        pcu->device_no = atomic_inc_return(&device_no) - 1;
 
+       /*
+        * PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor
+        */
+       if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) {
+               error = sysfs_create_group(&pcu->dev->kobj,
+                                          &ims_pcu_ofn_attr_group);
+               if (error)
+                       return error;
+       }
+
        error = ims_pcu_setup_backlight(pcu);
        if (error)
                return error;
 
-       info = &ims_pcu_device_info[device_id];
+       info = &ims_pcu_device_info[pcu->device_id];
        error = ims_pcu_setup_buttons(pcu, info->keymap, info->keymap_len);
        if (error)
                goto err_destroy_backlight;
@@ -1674,10 +1912,10 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
 
        return 0;
 
-err_destroy_backlight:
-       ims_pcu_destroy_backlight(pcu);
 err_destroy_buttons:
        ims_pcu_destroy_buttons(pcu);
+err_destroy_backlight:
+       ims_pcu_destroy_backlight(pcu);
        return error;
 }
 
@@ -1691,6 +1929,10 @@ static void ims_pcu_destroy_application_mode(struct ims_pcu *pcu)
                        ims_pcu_destroy_gamepad(pcu);
                ims_pcu_destroy_buttons(pcu);
                ims_pcu_destroy_backlight(pcu);
+
+               if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID)
+                       sysfs_remove_group(&pcu->dev->kobj,
+                                          &ims_pcu_ofn_attr_group);
        }
 }
 
index e8897c36d21b022ce7d4d0ccb128c962db5aa78f..4d66c723cf084ac4fc3bac72e6bde5482c7ea664 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * Power key driver for SiRF PrimaII
  *
- * Copyright (c) 2013 Cambridge Silicon Radio Limited, a CSR plc group company.
+ * Copyright (c) 2013 - 2014 Cambridge Silicon Radio Limited, a CSR plc group
+ * company.
  *
  * Licensed under GPLv2 or later.
  */
 #include <linux/input.h>
 #include <linux/rtc/sirfsoc_rtciobrg.h>
 #include <linux/of.h>
+#include <linux/workqueue.h>
 
 struct sirfsoc_pwrc_drvdata {
        u32                     pwrc_base;
        struct input_dev        *input;
+       struct delayed_work     work;
 };
 
 #define PWRC_ON_KEY_BIT                        (1 << 0)
 
 #define PWRC_INT_STATUS                        0xc
 #define PWRC_INT_MASK                  0x10
+#define PWRC_PIN_STATUS                        0x14
+#define PWRC_KEY_DETECT_UP_TIME                20      /* ms*/
+
+static int sirfsoc_pwrc_is_on_key_down(struct sirfsoc_pwrc_drvdata *pwrcdrv)
+{
+       u32 state = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base +
+                                                       PWRC_PIN_STATUS);
+       return !(state & PWRC_ON_KEY_BIT); /* ON_KEY is active low */
+}
+
+static void sirfsoc_pwrc_report_event(struct work_struct *work)
+{
+       struct sirfsoc_pwrc_drvdata *pwrcdrv =
+               container_of(work, struct sirfsoc_pwrc_drvdata, work.work);
+
+       if (sirfsoc_pwrc_is_on_key_down(pwrcdrv)) {
+               schedule_delayed_work(&pwrcdrv->work,
+                       msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME));
+       } else {
+               input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 0);
+               input_sync(pwrcdrv->input);
+       }
+}
 
 static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)
 {
@@ -34,21 +60,44 @@ static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)
        sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT,
                                 pwrcdrv->pwrc_base + PWRC_INT_STATUS);
 
-       /*
-        * For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c
-        * to queue a SUSPEND APM event
-        */
-       input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1);
+       input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 1);
        input_sync(pwrcdrv->input);
-
-       /*
-        * Todo: report KEY_POWER event for Android platforms, Android PowerManager
-        * will handle the suspend and powerdown/hibernation
-        */
+       schedule_delayed_work(&pwrcdrv->work,
+                             msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME));
 
        return IRQ_HANDLED;
 }
 
+static void sirfsoc_pwrc_toggle_interrupts(struct sirfsoc_pwrc_drvdata *pwrcdrv,
+                                          bool enable)
+{
+       u32 int_mask;
+
+       int_mask = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK);
+       if (enable)
+               int_mask |= PWRC_ON_KEY_BIT;
+       else
+               int_mask &= ~PWRC_ON_KEY_BIT;
+       sirfsoc_rtc_iobrg_writel(int_mask, pwrcdrv->pwrc_base + PWRC_INT_MASK);
+}
+
+static int sirfsoc_pwrc_open(struct input_dev *input)
+{
+       struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input);
+
+       sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
+
+       return 0;
+}
+
+static void sirfsoc_pwrc_close(struct input_dev *input)
+{
+       struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input);
+
+       sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false);
+       cancel_delayed_work_sync(&pwrcdrv->work);
+}
+
 static const struct of_device_id sirfsoc_pwrc_of_match[] = {
        { .compatible = "sirf,prima2-pwrc" },
        {},
@@ -70,7 +119,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
        }
 
        /*
-        * we can't use of_iomap because pwrc is not mapped in memory,
+        * We can't use of_iomap because pwrc is not mapped in memory,
         * the so-called base address is only offset in rtciobrg
         */
        error = of_property_read_u32(np, "reg", &pwrcdrv->pwrc_base);
@@ -86,11 +135,21 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
 
        pwrcdrv->input->name = "sirfsoc pwrckey";
        pwrcdrv->input->phys = "pwrc/input0";
-       pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR);
+       pwrcdrv->input->evbit[0] = BIT_MASK(EV_KEY);
+
+       INIT_DELAYED_WORK(&pwrcdrv->work, sirfsoc_pwrc_report_event);
+
+       pwrcdrv->input->open = sirfsoc_pwrc_open;
+       pwrcdrv->input->close = sirfsoc_pwrc_close;
+
+       input_set_drvdata(pwrcdrv->input, pwrcdrv);
+
+       /* Make sure the device is quiesced */
+       sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false);
 
        irq = platform_get_irq(pdev, 0);
        error = devm_request_irq(&pdev->dev, irq,
-                                sirfsoc_pwrc_isr, IRQF_SHARED,
+                                sirfsoc_pwrc_isr, 0,
                                 "sirfsoc_pwrc_int", pwrcdrv);
        if (error) {
                dev_err(&pdev->dev, "unable to claim irq %d, error: %d\n",
@@ -98,11 +157,6 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
                return error;
        }
 
-       sirfsoc_rtc_iobrg_writel(
-               sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + PWRC_INT_MASK) |
-                       PWRC_ON_KEY_BIT,
-               pwrcdrv->pwrc_base + PWRC_INT_MASK);
-
        error = input_register_device(pwrcdrv->input);
        if (error) {
                dev_err(&pdev->dev,
@@ -111,7 +165,7 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
                return error;
        }
 
-       platform_set_drvdata(pdev, pwrcdrv);
+       dev_set_drvdata(&pdev->dev, pwrcdrv);
        device_init_wakeup(&pdev->dev, 1);
 
        return 0;
@@ -125,25 +179,25 @@ static int sirfsoc_pwrc_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int pwrc_resume(struct device *dev)
+static int sirfsoc_pwrc_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct sirfsoc_pwrc_drvdata *pwrcdrv = platform_get_drvdata(pdev);
+       struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(dev);
+       struct input_dev *input = pwrcdrv->input;
 
        /*
         * Do not mask pwrc interrupt as we want pwrc work as a wakeup source
         * if users touch X_ONKEY_B, see arch/arm/mach-prima2/pm.c
         */
-       sirfsoc_rtc_iobrg_writel(
-               sirfsoc_rtc_iobrg_readl(
-               pwrcdrv->pwrc_base + PWRC_INT_MASK) | PWRC_ON_KEY_BIT,
-               pwrcdrv->pwrc_base + PWRC_INT_MASK);
+       mutex_lock(&input->mutex);
+       if (input->users)
+               sirfsoc_pwrc_toggle_interrupts(pwrcdrv, true);
+       mutex_unlock(&input->mutex);
 
        return 0;
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, pwrc_resume);
+static SIMPLE_DEV_PM_OPS(sirfsoc_pwrc_pm_ops, NULL, sirfsoc_pwrc_resume);
 
 static struct platform_driver sirfsoc_pwrc_driver = {
        .probe          = sirfsoc_pwrc_probe,
index 772835938a526ed2575f6bc187619fe962ac0e6c..8569362475004d7230de2c982b965bfbad099d0a 100644 (file)
@@ -20,6 +20,8 @@
  * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
  *
  * Changes/Revisions:
+ *     0.4     01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
+ *             - add UI_GET_SYSNAME ioctl
  *     0.3     09/04/2006 (Anssi Hannula <anssi.hannula@gmail.com>)
  *             - updated ff support for the changes in kernel interface
  *             - added MODULE_VERSION
@@ -670,6 +672,31 @@ static int uinput_ff_upload_from_user(const char __user *buffer,
        __ret;                                          \
 })
 
+static int uinput_str_to_user(void __user *dest, const char *str,
+                             unsigned int maxlen)
+{
+       char __user *p = dest;
+       int len, ret;
+
+       if (!str)
+               return -ENOENT;
+
+       if (maxlen == 0)
+               return -EINVAL;
+
+       len = strlen(str) + 1;
+       if (len > maxlen)
+               len = maxlen;
+
+       ret = copy_to_user(p, str, len);
+       if (ret)
+               return -EFAULT;
+
+       /* force terminating '\0' */
+       ret = put_user(0, p + len - 1);
+       return ret ? -EFAULT : len;
+}
+
 static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
                                 unsigned long arg, void __user *p)
 {
@@ -679,6 +706,8 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
        struct uinput_ff_erase  ff_erase;
        struct uinput_request   *req;
        char                    *phys;
+       const char              *name;
+       unsigned int            size;
 
        retval = mutex_lock_interruptible(&udev->mutex);
        if (retval)
@@ -693,51 +722,51 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
        switch (cmd) {
                case UI_DEV_CREATE:
                        retval = uinput_create_device(udev);
-                       break;
+                       goto out;
 
                case UI_DEV_DESTROY:
                        uinput_destroy_device(udev);
-                       break;
+                       goto out;
 
                case UI_SET_EVBIT:
                        retval = uinput_set_bit(arg, evbit, EV_MAX);
-                       break;
+                       goto out;
 
                case UI_SET_KEYBIT:
                        retval = uinput_set_bit(arg, keybit, KEY_MAX);
-                       break;
+                       goto out;
 
                case UI_SET_RELBIT:
                        retval = uinput_set_bit(arg, relbit, REL_MAX);
-                       break;
+                       goto out;
 
                case UI_SET_ABSBIT:
                        retval = uinput_set_bit(arg, absbit, ABS_MAX);
-                       break;
+                       goto out;
 
                case UI_SET_MSCBIT:
                        retval = uinput_set_bit(arg, mscbit, MSC_MAX);
-                       break;
+                       goto out;
 
                case UI_SET_LEDBIT:
                        retval = uinput_set_bit(arg, ledbit, LED_MAX);
-                       break;
+                       goto out;
 
                case UI_SET_SNDBIT:
                        retval = uinput_set_bit(arg, sndbit, SND_MAX);
-                       break;
+                       goto out;
 
                case UI_SET_FFBIT:
                        retval = uinput_set_bit(arg, ffbit, FF_MAX);
-                       break;
+                       goto out;
 
                case UI_SET_SWBIT:
                        retval = uinput_set_bit(arg, swbit, SW_MAX);
-                       break;
+                       goto out;
 
                case UI_SET_PROPBIT:
                        retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
-                       break;
+                       goto out;
 
                case UI_SET_PHYS:
                        if (udev->state == UIST_CREATED) {
@@ -753,18 +782,18 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 
                        kfree(udev->dev->phys);
                        udev->dev->phys = phys;
-                       break;
+                       goto out;
 
                case UI_BEGIN_FF_UPLOAD:
                        retval = uinput_ff_upload_from_user(p, &ff_up);
                        if (retval)
-                               break;
+                               goto out;
 
                        req = uinput_request_find(udev, ff_up.request_id);
                        if (!req || req->code != UI_FF_UPLOAD ||
                            !req->u.upload.effect) {
                                retval = -EINVAL;
-                               break;
+                               goto out;
                        }
 
                        ff_up.retval = 0;
@@ -775,65 +804,77 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
                                memset(&ff_up.old, 0, sizeof(struct ff_effect));
 
                        retval = uinput_ff_upload_to_user(p, &ff_up);
-                       break;
+                       goto out;
 
                case UI_BEGIN_FF_ERASE:
                        if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
                                retval = -EFAULT;
-                               break;
+                               goto out;
                        }
 
                        req = uinput_request_find(udev, ff_erase.request_id);
                        if (!req || req->code != UI_FF_ERASE) {
                                retval = -EINVAL;
-                               break;
+                               goto out;
                        }
 
                        ff_erase.retval = 0;
                        ff_erase.effect_id = req->u.effect_id;
                        if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
                                retval = -EFAULT;
-                               break;
+                               goto out;
                        }
 
-                       break;
+                       goto out;
 
                case UI_END_FF_UPLOAD:
                        retval = uinput_ff_upload_from_user(p, &ff_up);
                        if (retval)
-                               break;
+                               goto out;
 
                        req = uinput_request_find(udev, ff_up.request_id);
                        if (!req || req->code != UI_FF_UPLOAD ||
                            !req->u.upload.effect) {
                                retval = -EINVAL;
-                               break;
+                               goto out;
                        }
 
                        req->retval = ff_up.retval;
                        uinput_request_done(udev, req);
-                       break;
+                       goto out;
 
                case UI_END_FF_ERASE:
                        if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
                                retval = -EFAULT;
-                               break;
+                               goto out;
                        }
 
                        req = uinput_request_find(udev, ff_erase.request_id);
                        if (!req || req->code != UI_FF_ERASE) {
                                retval = -EINVAL;
-                               break;
+                               goto out;
                        }
 
                        req->retval = ff_erase.retval;
                        uinput_request_done(udev, req);
-                       break;
+                       goto out;
+       }
 
-               default:
-                       retval = -EINVAL;
+       size = _IOC_SIZE(cmd);
+
+       /* Now check variable-length commands */
+       switch (cmd & ~IOCSIZE_MASK) {
+       case UI_GET_SYSNAME(0):
+               if (udev->state != UIST_CREATED) {
+                       retval = -ENOENT;
+                       goto out;
+               }
+               name = dev_name(&udev->dev->dev);
+               retval = uinput_str_to_user(p, name, size);
+               goto out;
        }
 
+       retval = -EINVAL;
  out:
        mutex_unlock(&udev->mutex);
        return retval;
index b6505454bcc4575f810b468d81c419a6f8ff611c..7b7add5061a5ab3459a5aa2331b2e9bd76e6a18c 100644 (file)
@@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v3505[] __initdata = {
        { KE_END,       0 }
 };
 
+static struct key_entry keymap_fs_amilo_pro_v8210[] __initdata = {
+       { KE_KEY,       0x01, {KEY_HELP} },          /* Fn+F1 */
+       { KE_KEY,       0x06, {KEY_DISPLAYTOGGLE} }, /* Fn+F4 */
+       { KE_BLUETOOTH, 0x30 },                      /* Fn+F10 */
+       { KE_KEY,       0x31, {KEY_MAIL} },          /* mail button */
+       { KE_KEY,       0x36, {KEY_WWW} },           /* www button */
+       { KE_WIFI,      0x78 },                      /* satelite dish button */
+       { KE_END,       FE_WIFI_LED }
+};
+
 static struct key_entry keymap_fujitsu_n3510[] __initdata = {
        { KE_KEY, 0x11, {KEY_PROG1} },
        { KE_KEY, 0x12, {KEY_PROG2} },
@@ -653,6 +663,15 @@ static const struct dmi_system_id dmi_ids[] __initconst = {
                },
                .driver_data = keymap_fs_amilo_pro_v3505
        },
+       {
+               /* Fujitsu-Siemens Amilo Pro Edition V8210 */
+               .callback = dmi_matched,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Series V8210"),
+               },
+               .driver_data = keymap_fs_amilo_pro_v8210
+       },
        {
                /* Fujitsu-Siemens Amilo M7400 */
                .callback = dmi_matched,
index caecffe8caff3e3742e08d9531b3f4eea3ae5ac7..858045694e9d73f8ade7fe9d2327ec6594cb12c6 100644 (file)
@@ -848,7 +848,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
        gtco->inputdevice = input_dev;
 
        /* Save interface information */
-       gtco->usbdev = usb_get_dev(interface_to_usbdev(usbinterface));
+       gtco->usbdev = interface_to_usbdev(usbinterface);
        gtco->intf = usbinterface;
 
        /* Allocate some data for incoming reports */
index 2175f341900204f8ba0c3ba42c99973603fc6b09..01d30cedde460f7f54f49ac72ad744b080fcfcb6 100644 (file)
 #include <linux/sysfs.h>
 #include <linux/input/mt.h>
 #include <linux/platform_data/zforce_ts.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 #define WAIT_TIMEOUT           msecs_to_jiffies(1000)
 
 #define FRAME_START            0xee
+#define FRAME_MAXSIZE          257
 
 /* Offsets of the different parts of the payload the controller sends */
 #define PAYLOAD_HEADER         0
@@ -64,7 +67,7 @@
 #define RESPONSE_STATUS                0X1e
 
 /*
- * Notifications are send by the touch controller without
+ * Notifications are sent by the touch controller without
  * being requested by the driver and include for example
  * touch indications
  */
@@ -103,8 +106,8 @@ struct zforce_point {
  * @suspended          device suspended
  * @access_mutex       serialize i2c-access, to keep multipart reads together
  * @command_done       completion to wait for the command result
- * @command_mutex      serialize commands send to the ic
- * @command_waiting    the id of the command that that is currently waiting
+ * @command_mutex      serialize commands sent to the ic
+ * @command_waiting    the id of the command that is currently waiting
  *                     for a result
  * @command_result     returned result of the command
  */
@@ -235,7 +238,8 @@ static int zforce_scan_frequency(struct zforce_ts *ts, u16 idle, u16 finger,
                        (finger & 0xff), ((finger >> 8) & 0xff),
                        (stylus & 0xff), ((stylus >> 8) & 0xff) };
 
-       dev_dbg(&client->dev, "set scan frequency to (idle: %d, finger: %d, stylus: %d)\n",
+       dev_dbg(&client->dev,
+               "set scan frequency to (idle: %d, finger: %d, stylus: %d)\n",
                idle, finger, stylus);
 
        return zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf));
@@ -255,7 +259,7 @@ static int zforce_setconfig(struct zforce_ts *ts, char b1)
 static int zforce_start(struct zforce_ts *ts)
 {
        struct i2c_client *client = ts->client;
-       const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
+       const struct zforce_ts_platdata *pdata = ts->pdata;
        int ret;
 
        dev_dbg(&client->dev, "starting device\n");
@@ -326,13 +330,14 @@ static int zforce_stop(struct zforce_ts *ts)
 static int zforce_touch_event(struct zforce_ts *ts, u8 *payload)
 {
        struct i2c_client *client = ts->client;
-       const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
+       const struct zforce_ts_platdata *pdata = ts->pdata;
        struct zforce_point point;
        int count, i, num = 0;
 
        count = payload[0];
        if (count > ZFORCE_REPORT_POINTS) {
-               dev_warn(&client->dev, "to many coordinates %d, expected max %d\n",
+               dev_warn(&client->dev,
+                        "too many coordinates %d, expected max %d\n",
                         count, ZFORCE_REPORT_POINTS);
                count = ZFORCE_REPORT_POINTS;
        }
@@ -421,7 +426,7 @@ static int zforce_read_packet(struct zforce_ts *ts, u8 *buf)
                goto unlock;
        }
 
-       if (buf[PAYLOAD_LENGTH] <= 0 || buf[PAYLOAD_LENGTH] > 255) {
+       if (buf[PAYLOAD_LENGTH] == 0) {
                dev_err(&client->dev, "invalid payload length: %d\n",
                        buf[PAYLOAD_LENGTH]);
                ret = -EIO;
@@ -471,9 +476,9 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
 {
        struct zforce_ts *ts = dev_id;
        struct i2c_client *client = ts->client;
-       const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev);
+       const struct zforce_ts_platdata *pdata = ts->pdata;
        int ret;
-       u8 payload_buffer[512];
+       u8 payload_buffer[FRAME_MAXSIZE];
        u8 *payload;
 
        /*
@@ -494,8 +499,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
        while (!gpio_get_value(pdata->gpio_int)) {
                ret = zforce_read_packet(ts, payload_buffer);
                if (ret < 0) {
-                       dev_err(&client->dev, "could not read packet, ret: %d\n",
-                               ret);
+                       dev_err(&client->dev,
+                               "could not read packet, ret: %d\n", ret);
                        break;
                }
 
@@ -539,7 +544,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
                                                payload[RESPONSE_DATA + 4];
                        ts->version_rev   = (payload[RESPONSE_DATA + 7] << 8) |
                                                payload[RESPONSE_DATA + 6];
-                       dev_dbg(&ts->client->dev, "Firmware Version %04x:%04x %04x:%04x\n",
+                       dev_dbg(&ts->client->dev,
+                               "Firmware Version %04x:%04x %04x:%04x\n",
                                ts->version_major, ts->version_minor,
                                ts->version_build, ts->version_rev);
 
@@ -552,7 +558,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id)
                        break;
 
                default:
-                       dev_err(&ts->client->dev, "unrecognized response id: 0x%x\n",
+                       dev_err(&ts->client->dev,
+                               "unrecognized response id: 0x%x\n",
                                payload[RESPONSE_ID]);
                        break;
                }
@@ -618,7 +625,8 @@ static int zforce_suspend(struct device *dev)
 
                enable_irq_wake(client->irq);
        } else if (input->users) {
-               dev_dbg(&client->dev, "suspend without being a wakeup source\n");
+               dev_dbg(&client->dev,
+                       "suspend without being a wakeup source\n");
 
                ret = zforce_stop(ts);
                if (ret)
@@ -684,6 +692,45 @@ static void zforce_reset(void *data)
        gpio_set_value(ts->pdata->gpio_rst, 0);
 }
 
+static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev)
+{
+       struct zforce_ts_platdata *pdata;
+       struct device_node *np = dev->of_node;
+
+       if (!np)
+               return ERR_PTR(-ENOENT);
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               dev_err(dev, "failed to allocate platform data\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       pdata->gpio_int = of_get_gpio(np, 0);
+       if (!gpio_is_valid(pdata->gpio_int)) {
+               dev_err(dev, "failed to get interrupt gpio\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       pdata->gpio_rst = of_get_gpio(np, 1);
+       if (!gpio_is_valid(pdata->gpio_rst)) {
+               dev_err(dev, "failed to get reset gpio\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(np, "x-size", &pdata->x_max)) {
+               dev_err(dev, "failed to get x-size property\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (of_property_read_u32(np, "y-size", &pdata->y_max)) {
+               dev_err(dev, "failed to get y-size property\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       return pdata;
+}
+
 static int zforce_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
@@ -692,8 +739,11 @@ static int zforce_probe(struct i2c_client *client,
        struct input_dev *input_dev;
        int ret;
 
-       if (!pdata)
-               return -EINVAL;
+       if (!pdata) {
+               pdata = zforce_parse_dt(&client->dev);
+               if (IS_ERR(pdata))
+                       return PTR_ERR(pdata);
+       }
 
        ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL);
        if (!ts)
@@ -798,7 +848,7 @@ static int zforce_probe(struct i2c_client *client,
                return ret;
        }
 
-       /* this gets the firmware version among other informations */
+       /* this gets the firmware version among other information */
        ret = zforce_command_wait(ts, COMMAND_STATUS);
        if (ret < 0) {
                dev_err(&client->dev, "couldn't get status, %d\n", ret);
@@ -829,11 +879,20 @@ static struct i2c_device_id zforce_idtable[] = {
 };
 MODULE_DEVICE_TABLE(i2c, zforce_idtable);
 
+#ifdef CONFIG_OF
+static struct of_device_id zforce_dt_idtable[] = {
+       { .compatible = "neonode,zforce" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, zforce_dt_idtable);
+#endif
+
 static struct i2c_driver zforce_driver = {
        .driver = {
                .owner  = THIS_MODULE,
                .name   = "zforce-ts",
                .pm     = &zforce_pm_ops,
+               .of_match_table = of_match_ptr(zforce_dt_idtable),
        },
        .probe          = zforce_probe,
        .id_table       = zforce_idtable,
index 26fdb22e0fc239e62d318aa3b1f0edf6e8d84c42..58dc7c5ae63b610f8092c0d21d6548a4ba7598bc 100644 (file)
@@ -1,5 +1,4 @@
-/* arch/arm/plat-samsung/include/plat/ts.h
- *
+/*
  * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -7,14 +6,14 @@
  * published by the Free Software Foundation.
 */
 
-#ifndef __ASM_ARM_TS_H
-#define __ASM_ARM_TS_H
+#ifndef __TOUCHSCREEN_S3C2410_H
+#define __TOUCHSCREEN_S3C2410_H
 
 struct s3c2410_ts_mach_info {
-       int             delay;
-       int             presc;
-       int             oversampling_shift;
-       void    (*cfg_gpio)(struct platform_device *dev);
+       int delay;
+       int presc;
+       int oversampling_shift;
+       void (*cfg_gpio)(struct platform_device *dev);
 };
 
 extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *);
@@ -22,4 +21,4 @@ extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *);
 /* defined by architecture to configure gpio */
 extern void s3c24xx_ts_cfg_gpio(struct platform_device *dev);
 
-#endif /* __ASM_ARM_TS_H */
+#endif /*__TOUCHSCREEN_S3C2410_H */
index 0a4487d3fb1ee43d436c37712f76403006c86dc4..0994c0d01a09295eefc672f6d31a0f34d69bc9ad 100644 (file)
@@ -20,6 +20,8 @@
  * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
  *
  * Changes/Revisions:
+ *     0.4     01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
+ *             - add UI_GET_SYSNAME ioctl
  *     0.3     24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>)
  *             - update ff support for the changes in kernel interface
  *             - add UINPUT_VERSION
index fe46431593f9a431e8e24712af36b98b3f78293a..0389b489bbba0041cd0ecd7cff58c24d746b2147 100644 (file)
@@ -20,6 +20,8 @@
  * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
  *
  * Changes/Revisions:
+ *     0.4     01/09/2014 (Benjamin Tissoires <benjamin.tissoires@redhat.com>)
+ *             - add UI_GET_SYSNAME ioctl
  *     0.3     24/05/2006 (Anssi Hannula <anssi.hannulagmail.com>)
  *             - update ff support for the changes in kernel interface
  *             - add UINPUT_VERSION
@@ -35,7 +37,7 @@
 #include <linux/types.h>
 #include <linux/input.h>
 
-#define UINPUT_VERSION         3
+#define UINPUT_VERSION         4
 
 
 struct uinput_ff_upload {
@@ -73,6 +75,15 @@ struct uinput_ff_erase {
 #define UI_BEGIN_FF_ERASE      _IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
 #define UI_END_FF_ERASE                _IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
 
+/**
+ * UI_GET_SYSNAME - get the sysfs name of the created uinput device
+ *
+ * @return the sysfs name of the created virtual input device.
+ * The complete sysfs path is then /sys/devices/virtual/input/--NAME--
+ * Usually, it is in the form "inputN"
+ */
+#define UI_GET_SYSNAME(len)    _IOC(_IOC_READ, UINPUT_IOCTL_BASE, 300, len)
+
 /*
  * To write a force-feedback-capable driver, the upload_effect
  * and erase_effect callbacks in input_dev must be implemented.