]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00274247: touch: add egalax touch driver support on i.MX6Q/DL AUTO/SD
authorLuwei <b45643@freescale.com>
Thu, 8 Aug 2013 08:35:24 +0000 (16:35 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Mon, 16 Jun 2014 14:07:30 +0000 (16:07 +0200)
Copy the egalax touch screen driver from linux3.5.7.Make some
modification.Remove the __devinit __devexit __devexit_p out
of the file, because 3.10 does not support.

Signed-off-by: Luwei Zhou <b45643@freescale.com>
drivers/input/touchscreen/egalax_ts.c

index c8057847d71d475a02450cb294d08b9cc17419bc..db214af0ebd21aa19fbf081c132988b0639f5242 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Driver for EETI eGalax Multiple Touch Controller
  *
- * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
  *
  * based on max11801_ts.c
  *
@@ -34,7 +34,7 @@
  * which can only report one point at a given time.
  * This driver will ignore events in this mode.
  */
-#define REPORT_MODE_MOUSE              0x1
+#define REPORT_MODE_SINGLE             0x1
 /*
  * Vendor Mode: this mode is used to transfer some vendor specific
  * messages.
@@ -46,6 +46,8 @@
 
 #define MAX_SUPPORT_POINTS             5
 
+#define EVENT_MODE             0
+#define EVENT_STATUS           1
 #define EVENT_VALID_OFFSET     7
 #define EVENT_VALID_MASK       (0x1 << EVENT_VALID_OFFSET)
 #define EVENT_ID_OFFSET                2
 
 #define MAX_I2C_DATA_LEN       10
 
-#define EGALAX_MAX_X   32760
-#define EGALAX_MAX_Y   32760
+#define EGALAX_MAX_X   32767
+#define EGALAX_MAX_Y   32767
 #define EGALAX_MAX_TRIES 100
 
+struct egalax_pointer {
+       bool valid;
+       bool status;
+       u16 x;
+       u16 y;
+};
+
 struct egalax_ts {
        struct i2c_client               *client;
        struct input_dev                *input_dev;
+       struct egalax_pointer           events[MAX_SUPPORT_POINTS];
 };
 
 static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
@@ -69,8 +79,9 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
        struct egalax_ts *ts = dev_id;
        struct input_dev *input_dev = ts->input_dev;
        struct i2c_client *client = ts->client;
+       struct egalax_pointer *events = ts->events;
        u8 buf[MAX_I2C_DATA_LEN];
-       int id, ret, x, y, z;
+       int i, id, ret, x, y;
        int tries = 0;
        bool down, valid;
        u8 state;
@@ -82,15 +93,38 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
        if (ret < 0)
                return IRQ_HANDLED;
 
-       if (buf[0] != REPORT_MODE_MTTOUCH) {
-               /* ignore mouse events and vendor events */
+       dev_dbg(&client->dev, "recv ret:%d", ret);
+       for (i = 0; i < MAX_I2C_DATA_LEN; i++)
+               dev_dbg(&client->dev, " %x ", buf[i]);
+
+       if (buf[0] != REPORT_MODE_VENDOR
+           && buf[0] != REPORT_MODE_SINGLE
+           && buf[0] != REPORT_MODE_MTTOUCH) {
+               /* invalid point */
+               return IRQ_HANDLED;
+       }
+
+       if (buf[0] == REPORT_MODE_VENDOR) {
+               dev_dbg(&client->dev, "vendor message, ignored\n");
                return IRQ_HANDLED;
        }
 
        state = buf[1];
        x = (buf[3] << 8) | buf[2];
        y = (buf[5] << 8) | buf[4];
-       z = (buf[7] << 8) | buf[6];
+
+       /* Currently, the panel Freescale using on SMD board _NOT_
+        * support single pointer mode. All event are going to
+        * multiple pointer mode.  Add single pointer mode according
+        * to EETI eGalax I2C programming manual.
+        */
+       if (buf[0] == REPORT_MODE_SINGLE) {
+               input_report_abs(input_dev, ABS_X, x);
+               input_report_abs(input_dev, ABS_Y, y);
+               input_report_key(input_dev, BTN_TOUCH, !!state);
+               input_sync(input_dev);
+               return IRQ_HANDLED;
+       }
 
        valid = state & EVENT_VALID_MASK;
        id = (state & EVENT_ID_MASK) >> EVENT_ID_OFFSET;
@@ -101,19 +135,50 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
                return IRQ_HANDLED;
        }
 
-       input_mt_slot(input_dev, id);
-       input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, down);
-
-       dev_dbg(&client->dev, "%s id:%d x:%d y:%d z:%d",
-               down ? "down" : "up", id, x, y, z);
-
        if (down) {
-               input_report_abs(input_dev, ABS_MT_POSITION_X, x);
-               input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
-               input_report_abs(input_dev, ABS_MT_PRESSURE, z);
+               events[id].valid = valid;
+               events[id].status = down;
+               events[id].x = x;
+               events[id].y = y;
+
+#ifdef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH
+               input_report_abs(input_dev, ABS_X, x);
+               input_report_abs(input_dev, ABS_Y, y);
+               input_event(ts->input_dev, EV_KEY, BTN_TOUCH, 1);
+               input_report_abs(input_dev, ABS_PRESSURE, 1);
+#endif
+       } else {
+               dev_dbg(&client->dev, "release id:%d\n", id);
+               events[id].valid = 0;
+               events[id].status = 0;
+#ifdef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH
+               input_report_key(input_dev, BTN_TOUCH, 0);
+               input_report_abs(input_dev, ABS_PRESSURE, 0);
+#else
+               input_report_abs(input_dev, ABS_MT_TRACKING_ID, id);
+               input_event(input_dev, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
+               input_mt_sync(input_dev);
+#endif
        }
 
-       input_mt_report_pointer_emulation(input_dev, true);
+#ifndef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH
+       /* report all pointers */
+       for (i = 0; i < MAX_SUPPORT_POINTS; i++) {
+               if (!events[i].valid)
+                       continue;
+               dev_dbg(&client->dev, "report id:%d valid:%d x:%d y:%d",
+                       i, valid, x, y);
+                       input_report_abs(input_dev,
+                                ABS_MT_TRACKING_ID, i);
+               input_report_abs(input_dev,
+                                ABS_MT_TOUCH_MAJOR, 1);
+               input_report_abs(input_dev,
+                                ABS_MT_POSITION_X, events[i].x);
+               input_report_abs(input_dev,
+                                ABS_MT_POSITION_Y, events[i].y);
+               input_mt_sync(input_dev);
+       }
+#endif
        input_sync(input_dev);
 
        return IRQ_HANDLED;
@@ -199,21 +264,34 @@ static int egalax_ts_probe(struct i2c_client *client,
                return error;
        }
 
-       input_dev->name = "EETI eGalax Touch Screen";
+       input_dev->name = "eGalax Touch Screen";
+       input_dev->phys = "I2C",
        input_dev->id.bustype = BUS_I2C;
+       input_dev->id.vendor = 0x0EEF;
+       input_dev->id.product = 0x0020;
+       input_dev->id.version = 0x0001;
+       input_dev->dev.parent = &client->dev;
 
        __set_bit(EV_ABS, input_dev->evbit);
        __set_bit(EV_KEY, input_dev->evbit);
        __set_bit(BTN_TOUCH, input_dev->keybit);
-
+       __set_bit(ABS_X, input_dev->absbit);
+       __set_bit(ABS_Y, input_dev->absbit);
+       __set_bit(ABS_PRESSURE, input_dev->absbit);
        input_set_abs_params(input_dev, ABS_X, 0, EGALAX_MAX_X, 0, 0);
        input_set_abs_params(input_dev, ABS_Y, 0, EGALAX_MAX_Y, 0, 0);
-       input_set_abs_params(input_dev,
-                            ABS_MT_POSITION_X, 0, EGALAX_MAX_X, 0, 0);
-       input_set_abs_params(input_dev,
-                            ABS_MT_POSITION_Y, 0, EGALAX_MAX_Y, 0, 0);
-       input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS, 0);
-
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0);
+
+#ifndef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH
+       input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+                               0, EGALAX_MAX_X, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+                               0, EGALAX_MAX_Y, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
+                            MAX_SUPPORT_POINTS, 0, 0);
+#endif
        input_set_drvdata(input_dev, ts);
 
        error = devm_request_threaded_irq(&client->dev, client->irq, NULL,