--- v4
+++ v2
@@ -1,53 +1,190 @@
-Write each object using a single bulk i2c write transfer.
+Instead of carrying around per-finger state in the driver instance, just
+report each finger as it arrives to the input layer, and let the input
+layer (evdev) hold the event state (which it does anyway).
+
+Also, the atmel pad reports "amplitude", which is reported to userspace
+using the "PRESSURE" event type. The variables now reflect this.
+
+Note: this driver does not really do MT-B properly. Each input report
+(a goup of input events followed by a SYN_REPORT) only contains data for
+a single contact. When multiple fingers are present on a device, each is
+properly reported in its own MT_SLOT. However, there is only ever one
+MT_SLOT per SYN_REPORT. This is fixed in a subsequent patch.
+
+This patch was tested with an mXT224E.
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
-Reviewed-by: Joonyoung Shim <jy0922.shim@samsung.com>
---
- drivers/input/touchscreen/atmel_mxt_ts.c | 24 ++++++++++++------------
- 1 files changed, 12 insertions(+), 12 deletions(-)
+ drivers/input/touchscreen/atmel_mxt_ts.c | 121 +++++++++---------------------
+ 1 files changed, 35 insertions(+), 86 deletions(-)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
-index 2e49488..efce50f 100644
+index 0d0dab6..731293b 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
-@@ -653,7 +653,8 @@ static int mxt_check_reg_init(struct mxt_data *data)
- struct mxt_object *object;
+@@ -195,6 +195,7 @@
+ #define MXT_BOOT_STATUS_MASK 0x3f
+
+ /* Touch status */
++#define MXT_UNGRIP (1 << 0)
+ #define MXT_SUPPRESS (1 << 1)
+ #define MXT_AMP (1 << 2)
+ #define MXT_VECTOR (1 << 3)
+@@ -239,14 +240,6 @@ struct mxt_message {
+ u8 message[7];
+ };
+
+-struct mxt_finger {
+- int status;
+- int x;
+- int y;
+- int area;
+- int pressure;
+-};
+-
+ /* Each client has this additional data */
+ struct mxt_data {
+ struct i2c_client *client;
+@@ -254,7 +247,6 @@ struct mxt_data {
+ const struct mxt_platform_data *pdata;
+ struct mxt_object *object_table;
+ struct mxt_info info;
+- struct mxt_finger finger[MXT_MAX_FINGER];
+ unsigned int irq;
+ unsigned int max_x;
+ unsigned int max_y;
+@@ -488,97 +480,54 @@ static int mxt_write_object(struct mxt_data *data,
+ return mxt_write_reg(data->client, reg + offset, 1, &val);
+ }
+
+-static void mxt_input_report(struct mxt_data *data, int single_id)
+-{
+- struct mxt_finger *finger = data->finger;
+- struct input_dev *input_dev = data->input_dev;
+- int status = finger[single_id].status;
+- int finger_num = 0;
+- int id;
+-
+- for (id = 0; id < MXT_MAX_FINGER; id++) {
+- if (!finger[id].status)
+- continue;
+-
+- input_mt_slot(input_dev, id);
+- input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
+- finger[id].status != MXT_RELEASE);
+-
+- if (finger[id].status != MXT_RELEASE) {
+- finger_num++;
+- input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
+- finger[id].area);
+- input_report_abs(input_dev, ABS_MT_POSITION_X,
+- finger[id].x);
+- input_report_abs(input_dev, ABS_MT_POSITION_Y,
+- finger[id].y);
+- input_report_abs(input_dev, ABS_MT_PRESSURE,
+- finger[id].pressure);
+- } else {
+- finger[id].status = 0;
+- }
+- }
+-
+- input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
+-
+- if (status != MXT_RELEASE) {
+- input_report_abs(input_dev, ABS_X, finger[single_id].x);
+- input_report_abs(input_dev, ABS_Y, finger[single_id].y);
+- input_report_abs(input_dev,
+- ABS_PRESSURE, finger[single_id].pressure);
+- }
+-
+- input_sync(input_dev);
+-}
+-
+ static void mxt_input_touchevent(struct mxt_data *data,
+- struct mxt_message *message, int id)
++ struct mxt_message *message, int id)
+ {
+- struct mxt_finger *finger = data->finger;
struct device *dev = &data->client->dev;
- int index = 0;
-- int i, j, config_offset;
-+ int i, size;
-+ int ret;
+- u8 status = message->message[0];
++ struct input_dev *input_dev = data->input_dev;
++ u8 status;
+ int x;
+ int y;
+ int area;
+- int pressure;
+-
+- /* Check the touch is present on the screen */
+- if (!(status & MXT_DETECT)) {
+- if (status & MXT_RELEASE) {
+- dev_dbg(dev, "[%d] released\n", id);
+-
+- finger[id].status = MXT_RELEASE;
+- mxt_input_report(data, id);
+- }
+- return;
+- }
+-
+- /* Check only AMP detection */
+- if (!(status & (MXT_PRESS | MXT_MOVE)))
+- return;
++ int amplitude;
- if (!pdata->config) {
- dev_dbg(dev, "No cfg data defined, skipping reg init\n");
-@@ -666,18 +667,17 @@ static int mxt_check_reg_init(struct mxt_data *data)
- if (!mxt_object_writable(object->type))
- continue;
++ status = message->message[0];
+ x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
+ y = (message->message[2] << 4) | ((message->message[3] & 0xf));
+ if (data->max_x < 1024)
+- x = x >> 2;
++ x >>= 2;
+ if (data->max_y < 1024)
+- y = y >> 2;
++ y >>= 2;
-- for (j = 0;
-- j < (object->size + 1) * (object->instances + 1);
-- j++) {
-- config_offset = index + j;
-- if (config_offset > pdata->config_length) {
-- dev_err(dev, "Not enough config data!\n");
-- return -EINVAL;
-- }
-- mxt_write_object(data, object->type, j,
-- pdata->config[config_offset]);
-+ size = (object->size + 1) * (object->instances + 1);
-+ if (index + size > pdata->config_length) {
-+ dev_err(dev, "Not enough config data!\n");
-+ return -EINVAL;
- }
-- index += (object->size + 1) * (object->instances + 1);
+ area = message->message[4];
+- pressure = message->message[5];
+-
+- dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
+- status & MXT_MOVE ? "moved" : "pressed",
+- x, y, area);
+-
+- finger[id].status = status & MXT_MOVE ?
+- MXT_MOVE : MXT_PRESS;
+- finger[id].x = x;
+- finger[id].y = y;
+- finger[id].area = area;
+- finger[id].pressure = pressure;
++ amplitude = message->message[5];
+
-+ ret = __mxt_write_reg(data->client, object->start_address,
-+ size, &pdata->config[index]);
-+ if (ret)
-+ return ret;
-+ index += size;
- }
++ dev_dbg(dev,
++ "[%d] %c%c%c%c%c%c%c%c x: %d y: %d area: %d amp: %d\n",
++ id,
++ (status & MXT_DETECT) ? 'D' : '.',
++ (status & MXT_PRESS) ? 'P' : '.',
++ (status & MXT_RELEASE) ? 'R' : '.',
++ (status & MXT_MOVE) ? 'M' : '.',
++ (status & MXT_VECTOR) ? 'V' : '.',
++ (status & MXT_AMP) ? 'A' : '.',
++ (status & MXT_SUPPRESS) ? 'S' : '.',
++ (status & MXT_UNGRIP) ? 'U' : '.',
++ x, y, area, amplitude);
++
++ input_mt_slot(input_dev, id);
++ input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
++ status & MXT_DETECT);
++
++ if (status & MXT_DETECT) {
++ 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, amplitude);
++ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, area);
++ }
- return 0;
+- mxt_input_report(data, id);
++ input_mt_report_pointer_emulation(input_dev, false);
++ input_sync(input_dev);
+ }
+
+ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
--
1.7.7.3
+