forklift of touch screen from
authormgross <mark.gross@intel.com>
Wed, 26 Oct 2011 23:16:35 +0000 (16:16 -0700)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 21:17:38 +0000 (13:17 -0800)
git://jfumg-gcrmirror.jf.intel.com/a/bsp/hardware/intel/linux-2.6.git
commit 3d9f0662a963acad6de0dc2b2c3fb44c07956fbf

Change-Id: Iaced0c8177afcb5f34f75024317c43eae4aff02c

arch/x86/platform/mfld/Makefile
arch/x86/platform/mfld/blackbay_pr2.c [new file with mode: 0644]
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/atmel_mxt224.c [new file with mode: 0644]
include/linux/atmel_mxt224.h [new file with mode: 0644]

index 2b3a25c..7c64d28 100644 (file)
@@ -1 +1,2 @@
 obj-$(CONFIG_X86_MDFLD)                += pmu.o
+obj-$(CONFIG_X86_MDFLD)                += blackbay_pr2.o
diff --git a/arch/x86/platform/mfld/blackbay_pr2.c b/arch/x86/platform/mfld/blackbay_pr2.c
new file mode 100644 (file)
index 0000000..f959452
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * blackbay_pr2.c: Intel Medfield platform BlackBay PR2 specific setup code
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * Note:
+ *
+ */
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/pci.h>
+#include <linux/sfi.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <asm/mrst.h>
+#include <linux/atmel_mxt224.h>
+
+static u8 mxt_valid_interrupt(void)
+{
+       return 1;
+}
+
+static void mxt_init_platform_hw(void)
+{
+       /* maXTouch wants 40mSec minimum after reset to get organized */
+       /*
+       gpio_set_value(mxt_reset_gpio, 1);
+       msleep(40);
+       */
+}
+
+static void mxt_exit_platform_hw(void)
+{
+       /*
+       printk(KERN_INFO "In %s.", __func__);
+       gpio_set_value(mxt_reset_gpio, 0);
+       gpio_set_value(mxt_intr_gpio, 0);
+       */
+}
+
+static struct mxt_platform_data mxt_pdata = {
+       .numtouch       = 2,
+       .init_platform_hw = &mxt_init_platform_hw,
+       .exit_platform_hw = &mxt_exit_platform_hw,
+       .max_x          = 1023,
+       .max_y          = 975,
+       .orientation    = MXT_MSGB_T9_ORIENT_HORZ_FLIP,
+       .valid_interrupt = &mxt_valid_interrupt,
+       .reset          = 129,
+       .irq            = 62,
+};
+
+static struct i2c_board_info pr2_i2c_bus0_devs[] = {
+       {
+               .type       = "atmel_mxt224",
+               .addr       = 0x4A,
+               .platform_data = &mxt_pdata,
+       },
+};
+
+
+static struct gpio_keys_button gpio_button[] = {
+       {KEY_VOLUMEUP,          32, 1, "vol_up",        EV_KEY, 0, 20},
+       {KEY_VOLUMEDOWN,        31, 1, "vol_down",      EV_KEY, 0, 20},
+       {KEY_CAMERA,            43, 1, "cam_capture",   EV_KEY, 0, 20, 0, 0, 0, 1},
+       {KEY_CAMERA_FOCUS,      36, 1, "cam_focus",     EV_KEY, 0, 20},
+};
+
+static struct gpio_keys_platform_data mrst_gpio_keys = {
+       .buttons        = gpio_button,
+       .rep            = 1,
+       .nbuttons       = 4,
+};
+
+static struct platform_device pb_device = {
+       .name           = "gpio-keys",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &mrst_gpio_keys,
+       },
+};
+
+static void bkbpr2_gpio_keys_init()
+{
+       platform_device_register(&pb_device);
+}
+
+static void register_board_i2c_devs()
+{
+       i2c_register_board_info(0, pr2_i2c_bus0_devs,
+                               ARRAY_SIZE(pr2_i2c_bus0_devs));
+}
+static int __init platform_bkbpr2_subsys_init(void)
+{
+       register_board_i2c_devs();
+#if 0
+       switch (mfld_board_id()) {
+       case MFLD_BID_PR2_PROTO:
+       case MFLD_BID_PR2_PNP:
+       case MFLD_BID_PR2_VOLUME:
+       case MFLD_BID_PR3:
+               register_board_i2c_devs();
+               bkbpr2_gpio_keys_init();
+               return 0;
+       default:
+               return 1;
+       }
+#endif
+}
+device_initcall(platform_bkbpr2_subsys_init);
+
index 2ecd1b8..23ef376 100644 (file)
@@ -752,4 +752,12 @@ config TOUCHSCREEN_CYTTSP_CORE
        help
          Always activated for Cypress TTSP touchscreen
 
+config TOUCHSCREEN_ATMEL_MXT224
+       tristate "ATMEL mXT224 touchscreen"
+       depends on I2C
+       default n
+       help
+               Say Y here if you have a mXT224 touchscreen
+               If unsure, say N.
+          
 endif
index dba4130..3933daa 100644 (file)
@@ -63,3 +63,4 @@ obj-$(CONFIG_TOUCHSCREEN_W90X900)     += w90p910_ts.o
 obj-$(CONFIG_TOUCHSCREEN_TPS6507X)     += tps6507x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE)  += cyttsp_core.o
 obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C)   += cyttsp_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT224) += atmel_mxt224.o
\ No newline at end of file
diff --git a/drivers/input/touchscreen/atmel_mxt224.c b/drivers/input/touchscreen/atmel_mxt224.c
new file mode 100644 (file)
index 0000000..568a3d9
--- /dev/null
@@ -0,0 +1,2486 @@
+/*
+ *  Atmel maXTouch Touchscreen Controller Driver
+ *
+ *
+ *  Copyright (C) 2010 Atmel Corporation
+ *  Copyright (C) 2010 Ulf Samuelsson (ulf@atmel.com)
+ *  Copyright (C) 2009 Raphael Derosso Pereira <raphaelpereira@gmail.com>
+ *  Contains changes by Wind River Systems, 2010-09-29
+ *
+ *  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.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Modified by Richard Zhu(jianxin.zhu@borqs.com) 05/19/2011
+ */
+
+/*
+ *
+ * Driver for Atmel maXTouch family of touch controllers.
+ *
+ */
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/debugfs.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/earlysuspend.h>
+#include <linux/atmel_mxt224.h>
+
+/* Routines for memory access within a 16 bit address space */
+
+static int mxt_read_block(struct i2c_client *client, u16 addr, u16 length,
+                         u8 *value);
+static int mxt_write_byte(struct i2c_client *client, u16 addr, u8 value);
+static int mxt_write_block(struct i2c_client *client, u16 addr, u16 length,
+                          u8 *value);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+void mxt_early_suspend(struct early_suspend *h);
+void mxt_late_resume(struct early_suspend *h);
+#endif
+
+#define DRIVER_VERSION "0.9a"
+#define MXT_CONFIG_VERSION 5
+
+#define MXT_BACKNVM_DELAY 25 /* ms */
+#define MXT_RESET_DELAY   65 /* ms */
+
+static int debug = DEBUG_TRACE;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activate debugging output");
+
+static int stored_size[MXT_MAX_NUM_TOUCHES];
+static int stored_x[MXT_MAX_NUM_TOUCHES];
+static int stored_y[MXT_MAX_NUM_TOUCHES];
+
+static struct mxt_data *mxt_es;
+
+/* Device Info descriptor */
+/* Parsed from maXTouch "Id information" inside device */
+struct mxt_device_info {
+       u8   family_id;
+       u8   variant_id;
+       u8   major;
+       u8   minor;
+       u8   build;
+       u8   num_objs;
+       u8   x_size;
+       u8   y_size;
+       char family_name[16];    /* Family name */
+       char variant_name[16];    /* Variant name */
+       u16  num_nodes;           /* Number of sensor nodes */
+};
+
+/* object descriptor table, parsed from maXTouch "object table" */
+struct mxt_object {
+       u16 chip_addr;
+       u8  type;
+       u8  size;
+       u8  instances;
+       u8  num_report_ids;
+};
+
+
+/* Mapping from report id to object type and instance */
+struct report_id_map {
+       u8  object;
+       u8  instance;
+/*
+ * This is the first report ID belonging to object. It enables us to
+ * find out easily the touch number: each touch has different report
+ * ID (which are assigned to touches in increasing order). By
+ * subtracting the first report ID from current, we get the touch
+ * number.
+ */
+       u8  first_rid;
+};
+
+
+/* Driver datastructure */
+struct mxt_data {
+       struct i2c_client    *client;
+       struct mutex         dev_mutex;
+       struct input_dev     *touch_input;
+       struct input_dev     *key_input;
+       char                 touch_phys_name[32];
+       char                 key_phys_name[32];
+       int                  irq;
+
+       u16                  last_read_addr;
+       bool                 new_msgs;
+
+       int                  valid_irq_counter;
+       int                  invalid_irq_counter;
+       int                  irq_counter;
+       int                  message_counter;
+       int                  read_fail_counter;
+
+
+       int                  bytes_to_read;
+
+       u8                   xpos_format;
+       u8                   ypos_format;
+
+       u8                   numtouch;
+
+       struct mxt_device_info  device_info;
+
+       u32                  info_block_crc;
+       u32                  configuration_crc;
+       u16                  report_id_count;
+       struct report_id_map *rid_map;
+       struct mxt_object    *object_table;
+
+       u16                  msg_proc_addr;
+       u8                   message_size;
+
+       u16                  max_x_val;
+       u16                  max_y_val;
+       u16                  orientation;
+
+       void                 (*init_hw)(void);
+       void                 (*exit_hw)(void);
+       u8                   (*valid_interrupt)(void);
+       u8                   (*read_chg)(void);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       u8                   T7[3];
+       struct early_suspend es;
+       bool                 suspended;
+#endif
+
+#ifdef DEBUG
+       u8                   *last_message;
+       /* debugfs variables */
+       struct dentry        *debug_dir;
+       int                  current_debug_datap;
+
+       struct mutex         debug_mutex;
+       u16                  *debug_data;
+
+       /* Character device variables */
+       struct cdev          cdev;
+       struct cdev          cdev_messages;  /* 2nd Char dev for messages */
+       dev_t                dev_num;
+       struct class         *mxt_class;
+       struct mutex         msg_mutex;
+       int                  msg_buffer_startp, msg_buffer_endp;
+       /* Message buffer & pointers */
+       char                 *messages;
+       u16                  address_pointer;
+       bool                 valid_ap;
+#endif
+
+       /* Put only non-touch messages to buffer if this is set */
+       char                 nontouch_msg_only;
+
+       int                  prev_key;
+
+       int                  mxt_intr_gpio;
+       int                  mxt_reset_gpio;
+};
+
+/*
+ * This struct is used for i2c transfers.
+ */
+struct mxt_i2c_byte_transfer {
+       __le16 le_addr;
+       u8     data;
+} __attribute__ ((packed));
+
+#define I2C_RETRY_COUNT 5
+#define I2C_PAYLOAD_SIZE 254
+
+/*
+ * Check whether we have multi-touch enabled kernel; if not, report just the
+ * first touch (on mXT224, the maximum is 10 simultaneous touches).
+ * Because just the 1st one is reported, it might seem that the screen is not
+ * responding to touch if the first touch is removed while the screen is being
+ * touched by another finger, so beware.
+ *
+ * TODO: investigate if there is any standard set of input events that upper
+ * layers are expecting from a touchscreen? These can however be different for
+ * different platforms, and customers may have different opinions too about
+ * what should be interpreted as right-click, for example.
+ *
+ */
+
+static const u8        *obj_typ_name[] = {
+       [0]  = "Reserved",
+       [5]  = "GEN_MESSAGEPROCESSOR_T5",
+       [6]  = "GEN_COMMANDPROCESSOR_T6",
+       [7]  = "GEN_POWERCONFIG_T7",
+       [8]  = "GEN_ACQUIRECONFIG_T8",
+       [9]  = "TOUCH_MULTITOUCHSCREEN_T9",
+       [15] = "TOUCH_KEYARRAY_T15",
+       [17] = "SPT_COMMSCONFIG_T18",
+       [19] = "SPT_GPIOPWM_T19",
+       [20] = "PROCI_GRIPFACESUPPRESSION_T20",
+       [22] = "PROCG_NOISESUPPRESSION_T22",
+       [23] = "TOUCH_PROXIMITY_T23",
+       [24] = "PROCI_ONETOUCHGESTUREPROCESSOR_T24",
+       [25] = "SPT_SELFTEST_T25",
+       [27] = "PROCI_TWOTOUCHGESTUREPROCESSOR_T27",
+       [28] = "SPT_CTECONFIG_T28",
+       [37] = "DEBUG_DIAGNOSTICS_T37",
+       [38] = "SPT_USER_DATA_T38",
+       [40] = "PROCI_GRIPSUPPRESSION_T40",
+       [41] = "PROCI_PALMSUPPRESSION_T41",
+       [42] = "PROCI_FACESUPPRESSION_T42",
+       [43] = "SPT_DIGITIZER_T43",
+       [44] = "SPT_MESSAGECOUNT_T44",
+};
+
+void mxt_config_init(struct mxt_data *mxt)
+{
+       /*
+        * Please refer to "mXT224 Firmware 2.x Protocol Guide" for
+        * the meaning of the config data for each object.
+        */
+       u8 v20_T7[]  = { 32, 255, 50 };
+       u8 v20_T8[]  = { 10, 0, 5, 5, 0, 0, 5, 50, 5, 192 };
+       u8 v20_T9[]  = { 143, 0, 0, 18, 11, 1, 32, 80, 3, 1, 0, 5, 5,
+                        0, 2, 10, 10, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 64, 0, 10, 10 };
+       u8 v20_T15[] = { 131, 0, 11, 11, 1, 1, 32, 80, 3, 0, 0 };
+       u8 v20_T18[] = { 0, 0 };
+       u8 v20_T19[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+       u8 v20_T20[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+       u8 v20_T22[] = { 7, 0, 0, 0, 0, 0, 0, 0, 65, 0, 1, 12, 17, 22, 255,
+                        255, 0 };
+       u8 v20_T23[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+       u8 v20_T24[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        0, 0, 0 };
+       u8 v20_T25[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+       u8 v20_T28[] = { 0, 0, 2, 16, 16, 30 };
+
+       u8 i= 0, max_objs= 0;
+       u16 addr;
+       struct mxt_object *obj_index;
+
+       dev_dbg(&mxt->client->dev, "In function %s", __func__);
+       max_objs = mxt->device_info.num_objs;
+       obj_index = mxt->object_table;
+
+       for (i=0; i<max_objs; i++) {
+               addr = obj_index->chip_addr;
+               switch(obj_index->type) {
+               case MXT_GEN_POWERCONFIG_T7:
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T7), v20_T7);
+                       break;
+               case MXT_GEN_ACQUIRECONFIG_T8:
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T8), v20_T8);
+                       break;
+               case MXT_TOUCH_MULTITOUCHSCREEN_T9:
+                       if (v20_T9[MXT_ADR_T9_NUMTOUCH] != mxt->numtouch)
+                               v20_T9[MXT_ADR_T9_NUMTOUCH] = mxt->numtouch;
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T9), v20_T9);
+                       dev_dbg(&mxt->client->dev, "init multitouch object");
+                       break;
+               case MXT_TOUCH_KEYARRAY_T15:
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T15), v20_T15);
+                       break;
+               case MXT_SPT_COMCONFIG_T18:
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T18), v20_T18);
+                       break;
+               case MXT_SPT_GPIOPWM_T19:
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T19), v20_T19);
+                       break;
+               case MXT_PROCI_GRIPFACESUPPRESSION_T20:
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T20), v20_T20);
+                       break;
+               case MXT_PROCG_NOISESUPPRESSION_T22:
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T22), v20_T22);
+                       break;
+               case MXT_TOUCH_PROXIMITY_T23:
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T23), v20_T23);
+                       break;
+               case MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24:
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T24), v20_T24);
+                       break;
+               case MXT_SPT_SELFTEST_T25:
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T25), v20_T25);
+                       break;
+               case MXT_SPT_CTECONFIG_T28:
+                       mxt_write_block(mxt->client, addr,
+                                       sizeof(v20_T28), v20_T28);
+                       break;
+               default:
+                       break;
+               }
+               obj_index++;
+       }
+       dev_dbg(&mxt->client->dev, "config init Done.");
+}
+
+/* Returns object address in mXT chip, or zero if object is not found */
+static u16 get_object_address(uint8_t object_type,
+                             uint8_t instance,
+                             struct mxt_object *object_table,
+                             int max_objs)
+{
+       uint8_t object_table_index = 0;
+       uint8_t address_found = 0;
+       uint16_t address = 0;
+       struct mxt_object *obj;
+
+       while ((object_table_index < max_objs) && !address_found) {
+               obj = &object_table[object_table_index];
+               if (obj->type == object_type) {
+                       address_found = 1;
+                       /* Are there enough instances defined in the FW? */
+                       if (obj->instances >= instance) {
+                               address = obj->chip_addr +
+                                         (obj->size + 1) * instance;
+                       } else {
+                               break;
+                       }
+               }
+               object_table_index++;
+       }
+       return address;
+}
+
+#ifdef DEBUG
+/* Writes the address pointer (to set up following reads). */
+static int mxt_write_ap(struct mxt_data *mxt, u16 ap)
+{
+       struct i2c_client *client;
+       int err;
+       __le16  le_ap = cpu_to_le16(ap);
+       client = mxt->client;
+       if (mxt != NULL)
+               mxt->last_read_addr = -1;
+       if (i2c_master_send(client, (u8 *) &le_ap, 2) == 2) {
+               dev_dbg(&mxt->client->dev, "Address pointer set to %d\n", ap);
+               err = 0;
+       } else {
+               dev_dbg(&mxt->client->dev, "Error writing address pointer!\n");
+               err = -EIO;
+       }
+       return err;
+}
+
+/* Reads a block of bytes from current address from mXT chip. */
+static int mxt_read_block_wo_addr(struct i2c_client *client,
+                          u16 length,
+                          u8 *value)
+{
+       int err;
+       struct mxt_data *mxt;
+
+       mxt = i2c_get_clientdata(client);
+       if  (i2c_master_recv(client, value, length) == length) {
+               dev_dbg(&client->dev, "I2C block read ok\n");
+               err = length;
+       } else {
+               dev_dbg(&client->dev, "I2C block read failed\n");
+               err = -EIO;
+       }
+       return err;
+}
+
+ssize_t debug_data_read(struct mxt_data *mxt, char *buf, size_t count,
+                       loff_t *ppos, u8 debug_command){
+       int i;
+       u16 *data;
+       u16 diagnostics_reg;
+       int offset = 0;
+       int size;
+       int read_size;
+       int error;
+       char *buf_start;
+       u16 debug_data_addr;
+       u16 page_address;
+       u8 page;
+       u8 debug_command_reg;
+
+       data = mxt->debug_data;
+       if (data == NULL)
+               return -EIO;
+
+       /* If first read after open, read all data to buffer. */
+       if (mxt->current_debug_datap == 0) {
+
+               diagnostics_reg =
+                       get_object_address(MXT_GEN_COMMANDPROCESSOR_T6,
+                       0,
+                       mxt->object_table,
+                       mxt->device_info.num_objs) + MXT_ADR_T6_DIAGNOSTIC;
+
+               if (count > (mxt->device_info.num_nodes * 2))
+                       count = mxt->device_info.num_nodes;
+
+               debug_data_addr =
+                       get_object_address(MXT_DEBUG_DIAGNOSTIC_T37,
+                       0,
+                       mxt->object_table,
+                       mxt->device_info.num_objs) + MXT_ADR_T37_DATA;
+
+               page_address =
+                       get_object_address(MXT_DEBUG_DIAGNOSTIC_T37,
+                       0,
+                       mxt->object_table,
+                       mxt->device_info.num_objs) + MXT_ADR_T37_PAGE;
+
+               error = mxt_read_block(mxt->client, page_address, 1, &page);
+               if (error < 0)
+                       return error;
+
+               dev_dbg(&mxt->client->dev, "debug data page = %d\n", page);
+
+               while (page != 0) {
+                       error = mxt_write_byte(mxt->client,
+                                       diagnostics_reg,
+                                       MXT_CMD_T6_PAGE_DOWN);
+                       if (error < 0)
+                               return error;
+                       /* Wait for command to be handled; when it has, the
+                          register will be cleared. */
+                       debug_command_reg = 1;
+                       while (debug_command_reg != 0) {
+                               error = mxt_read_block(mxt->client,
+                                               diagnostics_reg, 1,
+                                               &debug_command_reg);
+                               if (error < 0)
+                                       return error;
+                               dev_dbg(&mxt->client->dev,
+                                       "Waiting for debug diag command "
+                                       "to propagate...\n");
+
+                       }
+                       error = mxt_read_block(mxt->client, page_address, 1,
+                                       &page);
+                       if (error < 0)
+                               return error;
+
+                       dev_dbg(&mxt->client->dev,
+                                       "debug data page = %d\n", page);
+               }
+
+               /*
+                * Lock mutex to prevent writing some unwanted data to debug
+                * command register. User can still write through the char
+                * device interface though. TODO: fix?
+                */
+               mutex_lock(&mxt->debug_mutex);
+               /* Configure Debug Diagnostics object to show deltas/refs */
+               error = mxt_write_byte(mxt->client, diagnostics_reg,
+                               debug_command);
+
+               /* Wait for command to be handled; when it has, the
+                * register will be cleared. */
+               debug_command_reg = 1;
+               while (debug_command_reg != 0) {
+                       error = mxt_read_block(mxt->client,
+                                       diagnostics_reg, 1,
+                                       &debug_command_reg);
+                       if (error < 0)
+                               goto error;
+                       dev_dbg(&mxt->client->dev,
+                               "Waiting for debug diag command "
+                               "to propagate...\n");
+
+               }
+
+               if (error < 0) {
+                       printk(KERN_WARNING
+                               "Error writing to maXTouch device!\n");
+                       goto error;
+               }
+
+               size = mxt->device_info.num_nodes * sizeof(u16);
+
+               while (size > 0) {
+
+                       read_size = size > 128 ? 128 : size;
+
+                       dev_dbg(&mxt->client->dev,
+                               "Debug data read loop, reading %d bytes...\n",
+                               read_size);
+                       error = mxt_read_block(mxt->client,
+                                              debug_data_addr,
+                                              read_size,
+                                              (u8 *) &data[offset]);
+                       if (error < 0) {
+                               printk(KERN_WARNING
+                                      "Error reading debug data\n");
+                               goto error;
+                       }
+                       offset += read_size/2;
+                       size -= read_size;
+
+                       /* Select next page */
+                       error = mxt_write_byte(mxt->client, diagnostics_reg,
+                                       MXT_CMD_T6_PAGE_UP);
+                       if (error < 0) {
+                               printk(KERN_WARNING
+                                       "Error writing to maXTouch device!\n");
+                               goto error;
+                       }
+               }
+               mutex_unlock(&mxt->debug_mutex);
+       }
+
+       buf_start = buf;
+       i = mxt->current_debug_datap;
+
+       while (((buf - buf_start) < (count - 6)) &&
+               (i < mxt->device_info.num_nodes)) {
+
+               mxt->current_debug_datap++;
+               if (debug_command == MXT_CMD_T6_REFERENCES_MODE)
+                       buf += sprintf(buf, "%d: %5d\n", i,
+                                      (u16) le16_to_cpu(data[i]));
+               else if (debug_command == MXT_CMD_T6_DELTAS_MODE)
+                       buf += sprintf(buf, "%d: %5d\n", i,
+                                      (s16) le16_to_cpu(data[i]));
+               i++;
+       }
+
+       return buf - buf_start;
+error:
+       mutex_unlock(&mxt->debug_mutex);
+       return error;
+}
+
+ssize_t deltas_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+       return debug_data_read(file->private_data, buf, count, ppos,
+                              MXT_CMD_T6_DELTAS_MODE);
+}
+
+ssize_t refs_read(struct file *file, char *buf, size_t count,
+                       loff_t *ppos)
+{
+       return debug_data_read(file->private_data, buf, count, ppos,
+                              MXT_CMD_T6_REFERENCES_MODE);
+}
+
+int debug_data_open(struct inode *inode, struct file *file)
+{
+       struct mxt_data *mxt;
+       int i;
+
+       mxt = inode->i_private;
+       if (mxt == NULL)
+               return -EIO;
+
+       mxt->current_debug_datap = 0;
+       mxt->debug_data = kmalloc(mxt->device_info.num_nodes * sizeof(u16),
+                                 GFP_KERNEL);
+       if (mxt->debug_data == NULL)
+               return -ENOMEM;
+
+
+       for (i = 0; i < mxt->device_info.num_nodes; i++)
+               mxt->debug_data[i] = 7777;
+
+
+       file->private_data = mxt;
+       return 0;
+}
+
+int debug_data_release(struct inode *inode, struct file *file)
+{
+       struct mxt_data *mxt;
+       mxt = file->private_data;
+       kfree(mxt->debug_data);
+       return 0;
+}
+
+static const struct file_operations delta_fops = {
+       .owner = THIS_MODULE,
+       .open = debug_data_open,
+       .release = debug_data_release,
+       .read = deltas_read,
+};
+
+static const struct file_operations refs_fops = {
+       .owner = THIS_MODULE,
+       .open = debug_data_open,
+       .release = debug_data_release,
+       .read = refs_read,
+};
+
+
+int mxt_memory_open(struct inode *inode, struct file *file)
+{
+       struct mxt_data *mxt;
+       mxt = container_of(inode->i_cdev, struct mxt_data, cdev);
+       if (mxt == NULL)
+               return -EIO;
+       file->private_data = mxt;
+       return 0;
+}
+
+int mxt_message_open(struct inode *inode, struct file *file)
+{
+       struct mxt_data *mxt;
+       mxt = container_of(inode->i_cdev, struct mxt_data, cdev_messages);
+       if (mxt == NULL)
+               return -EIO;
+       file->private_data = mxt;
+       return 0;
+}
+
+
+ssize_t mxt_memory_read(struct file *file, char *buf, size_t count,
+                       loff_t *ppos)
+{
+       int i;
+       struct mxt_data *mxt;
+       mxt = file->private_data;
+
+       if (mxt == NULL)
+               return -EIO;
+
+       if (mxt->valid_ap) {
+               dev_dbg(&mxt->client->dev,
+                       "Reading %d bytes from current ap\n",
+                       (int) count);
+               i = mxt_read_block_wo_addr(mxt->client, count, (u8 *) buf);
+       } else {
+               dev_dbg(&mxt->client->dev, "Address pointer changed since set;"
+                         "writing AP (%d) before reading %d bytes",
+                         mxt->address_pointer, (int) count);
+               i = mxt_read_block(mxt->client, mxt->address_pointer, count,
+                                  buf);
+       }
+
+       return i;
+}
+
+ssize_t mxt_memory_write(struct file *file, const char *buf, size_t count,
+                        loff_t *ppos)
+{
+       int i;
+       int whole_blocks;
+       int last_block_size;
+       struct mxt_data *mxt;
+       u16 address;
+       mxt = file->private_data;
+       address = mxt->address_pointer;
+
+       dev_dbg(&mxt->client->dev, "mxt_memory_write entered\n");
+       whole_blocks = count / I2C_PAYLOAD_SIZE;
+       last_block_size = count % I2C_PAYLOAD_SIZE;
+
+       for (i = 0; i < whole_blocks; i++) {
+               dev_dbg(&mxt->client->dev, "About to write to %d...",
+                       address);
+               mxt_write_block(mxt->client, address, I2C_PAYLOAD_SIZE,
+                               (u8 *) buf);
+               address += I2C_PAYLOAD_SIZE;
+               buf += I2C_PAYLOAD_SIZE;
+       }
+
+       mxt_write_block(mxt->client, address, last_block_size, (u8 *) buf);
+
+       return count;
+}
+
+static int mxt_ioctl(struct inode *inode, struct file *file,
+                    unsigned int cmd, unsigned long arg)
+{
+       int retval;
+       struct mxt_data *mxt;
+       u8 data[6];
+       u16 base_addr;
+
+       retval = 0;
+       mxt = file->private_data;
+
+       if (mxt == NULL)
+               return -1;
+
+       switch (cmd) {
+       case MXT_SET_ADDRESS_IOCTL:
+               retval = mxt_write_ap(mxt, (u16) arg);
+               if (retval >= 0) {
+                       mxt->address_pointer = (u16) arg;
+                       mxt->valid_ap = 1;
+               }
+               break;
+       case MXT_RESET_IOCTL:
+               base_addr = get_object_address(MXT_GEN_COMMANDPROCESSOR_T6,
+                       0,
+                       mxt->object_table,
+                       mxt->device_info.num_objs) + MXT_ADR_T6_RESET;
+
+               retval = mxt_write_byte(mxt->client, base_addr, 1);
+               break;
+
+       case MXT_CALIBRATE_IOCTL:
+               base_addr = get_object_address(MXT_GEN_COMMANDPROCESSOR_T6,
+                       0,
+                       mxt->object_table,
+                       mxt->device_info.num_objs) + MXT_ADR_T6_CALIBRATE;
+
+               retval = mxt_write_byte(mxt->client, base_addr, 1);
+               break;
+
+       case MXT_BACKUP_IOCTL:
+               base_addr = get_object_address(MXT_GEN_COMMANDPROCESSOR_T6,
+                       0,
+                       mxt->object_table,
+                       mxt->device_info.num_objs) + MXT_ADR_T6_BACKUPNV;
+
+               retval = mxt_write_byte(mxt->client,
+                               base_addr, MXT_CMD_T6_BACKUP);
+
+               break;
+
+       case MXT_NONTOUCH_MSG_IOCTL:
+               mxt->nontouch_msg_only = 1;
+               break;
+       case MXT_ALL_MSG_IOCTL:
+               mxt->nontouch_msg_only = 0;
+               break;
+       case MXT_SELF_TEST_IOCTL:
+
+               base_addr = get_object_address(MXT_SPT_SELFTEST_T25,
+                       0,
+                       mxt->object_table,
+                       mxt->device_info.num_objs) + MXT_ADR_T25_CTRL;
+
+               retval = mxt_write_byte(mxt->client, base_addr, 0x03);
+
+               if (retval < 0)
+                       return -1;
+
+               base_addr = get_object_address(MXT_SPT_SELFTEST_T25,
+                       0,
+                       mxt->object_table,
+                       mxt->device_info.num_objs) + MXT_ADR_T25_CMD;
+
+               retval = mxt_write_byte(mxt->client, base_addr,
+                       MXT_MSGR_T25_RUN_ALL_TESTS);
+
+               if (retval < 0)
+                       return -1;
+
+               /* Read back to verify update. */
+               memset(&data[0], 0x00, sizeof(data));
+
+               base_addr = get_object_address(MXT_SPT_SELFTEST_T25,
+                       0,
+                       mxt->object_table,
+                       mxt->device_info.num_objs);
+
+               retval = mxt_read_block(mxt->client, base_addr,
+                               sizeof(data),
+                               (u8 *)&data);
+               if (retval < 0)
+                       return -1;
+               else if ((retval > 0) && (data[1] !=
+                               MXT_MSGR_T25_RUN_ALL_TESTS))
+                       return -1;
+               retval = 0;
+               break;
+       default:
+               return -1;
+       }
+       return retval;
+}
+
+/*
+ * Copies messages from buffer to user space.
+ *
+ * NOTE: if less than (mxt->message_size * 5 + 1) bytes requested,
+ * this will return 0!
+ *
+ */
+ssize_t mxt_message_read(struct file *file, char *buf, size_t count,
+                        loff_t *ppos)
+{
+       int i;
+       struct mxt_data *mxt;
+       char *buf_start;
+       mxt = file->private_data;
+       if (mxt == NULL)
+               return -EIO;
+       buf_start = buf;
+
+       mutex_lock(&mxt->msg_mutex);
+       /* Copy messages until buffer empty, or 'count' bytes written */
+       while ((mxt->msg_buffer_startp != mxt->msg_buffer_endp) &&
+              ((buf - buf_start) < (count - 5 * mxt->message_size - 1))) {
+
+               for (i = 0; i < mxt->message_size; i++) {
+                       buf += sprintf(buf, "[%2X] ",
+                               *(mxt->messages + mxt->msg_buffer_endp *
+                                       mxt->message_size + i));
+               }
+               buf += sprintf(buf, "\n");
+               if (mxt->msg_buffer_endp < MXT_MESSAGE_BUFFER_SIZE)
+                       mxt->msg_buffer_endp++;
+               else
+                       mxt->msg_buffer_endp = 0;
+       }
+       mutex_unlock(&mxt->msg_mutex);
+       return buf - buf_start;
+}
+
+static const struct file_operations mxt_message_fops = {
+       .owner = THIS_MODULE,
+       .open = mxt_message_open,
+       .read = mxt_message_read,
+};
+
+static const struct file_operations mxt_memory_fops = {
+       .owner = THIS_MODULE,
+       .open = mxt_memory_open,
+       .read = mxt_memory_read,
+       .write = mxt_memory_write,
+       .ioctl = mxt_ioctl,
+};
+#endif
+
+/* Calculates the 24-bit CRC sum. */
+static u32 CRC_24(u32 crc, u8 byte1, u8 byte2)
+{
+       static const u32 crcpoly = 0x80001B;
+       u32 result;
+       u32 data_word;
+
+       data_word = ((((u16) byte2) << 8u) | byte1);
+       result = ((crc << 1u) ^ data_word);
+       if (result & 0x1000000)
+               result ^= crcpoly;
+       return result;
+}
+
+static void mxt_reset(struct mxt_data *mxt)
+{
+       u16 base_addr;
+
+       dev_dbg(&mxt->client->dev, "mxt reset\n");
+
+       base_addr = get_object_address(MXT_GEN_COMMANDPROCESSOR_T6,
+                       0,
+                       mxt->object_table,
+                       mxt->device_info.num_objs) + MXT_ADR_T6_RESET;
+
+       mxt_write_byte(mxt->client, base_addr, 1);
+       msleep(MXT_RESET_DELAY);
+}
+
+static void mxt_gpio_reset(struct mxt_data *mxt)
+{
+       /*
+        * When RESET pin asserted, it returns the device to its reset state.
+        * The RESET pin must be asserted low for at least 90 ns to cause a
+        * reset. After releasing the RESET pin the device takes 40 ms before
+        * it is ready to start communications.
+        */
+       gpio_set_value(mxt->mxt_reset_gpio, 0);
+       usleep_range(1000, 2000);
+       gpio_set_value(mxt->mxt_reset_gpio, 1);
+       msleep(40);
+}
+
+/*
+ * Reads a block of bytes from given address from mXT chip. If we are
+ * reading from message window, and previous read was from message window,
+ * there's no need to write the address pointer: the mXT chip will
+ * automatically set the address pointer back to message window start.
+ */
+
+static int mxt_read_block(struct i2c_client *client,
+                         u16 addr, u16 length, u8 *value)
+{
+       struct mxt_data *mxt;
+       int ret = 0;
+       __le16  le_addr;
+
+       mxt = i2c_get_clientdata(client);
+       if (mxt &&
+           (mxt->last_read_addr == addr) &&
+           (addr == mxt->msg_proc_addr)) {
+               ret = i2c_master_recv(client, value, length);
+               if (ret < 0)
+                       goto out_err;
+               return 0;
+       }
+
+       dev_dbg(&client->dev, "Writing address pointer & reading %d bytes"
+               " in on i2c transaction...\n", length);
+
+       /*
+        * block read must be split into two i2c transactions:
+        * 1st: set the 16bit address pointer
+        * 2nd: read data
+        *
+        * need STOP on the i2c bus between write and read:
+        */
+       le_addr = cpu_to_le16(addr);
+       ret = i2c_master_send(client, (u8 *)&le_addr, sizeof(le_addr));
+       if (ret < 0)
+               goto out_err;
+
+       ret = i2c_master_recv(client, value, length);
+       if (ret < 0)
+               goto out_err;
+
+       if (mxt)
+               mxt->last_read_addr = addr;
+       return 0;
+
+out_err:
+       if (mxt)
+               mxt->last_read_addr = -1;
+       return ret;
+}
+
+
+/* Writes one byte to given address in mXT chip. */
+
+static int mxt_write_byte(struct i2c_client *client, u16 addr, u8 value)
+{
+
+       struct mxt_data *mxt;
+       struct mxt_i2c_byte_transfer i2c_byte_transfer;
+       int err;
+
+       mxt = i2c_get_clientdata(client);
+       if (mxt != NULL)
+               mxt->last_read_addr = -1;
+       i2c_byte_transfer.le_addr = cpu_to_le16(addr);
+       i2c_byte_transfer.data = value;
+       if  (i2c_master_send(client, (u8 *) &i2c_byte_transfer, 3) == 3)
+               err = 0;
+       else
+               err = -EIO;
+       return err;
+}
+
+
+/* Writes a block of bytes (max 256) to given address in mXT chip. */
+static int mxt_write_block(struct i2c_client *client,
+                   u16 addr,
+                   u16 length,
+                   u8 *value)
+{
+       int i;
+       struct {
+               __le16  le_addr;
+               u8      data[256];
+
+       } i2c_block_transfer;
+
+       struct mxt_data *mxt;
+       dev_dbg(&client->dev, "Writing %d bytes to %d...", length, addr);
+       if (length > 256)
+               return -EINVAL;
+       mxt = i2c_get_clientdata(client);
+       if (mxt != NULL)
+               mxt->last_read_addr = -1;
+       for (i = 0; i < length; i++)
+               i2c_block_transfer.data[i] = *value++;
+       i2c_block_transfer.le_addr = cpu_to_le16(addr);
+       i = i2c_master_send(client, (u8 *) &i2c_block_transfer, length + 2);
+       if (i == (length + 2))
+               return length;
+       else
+               return -EIO;
+}
+
+/* Calculates the CRC value for mXT infoblock. */
+static int calculate_infoblock_crc(u32 *crc_result, u8 *data, int crc_area_size)
+{
+       u32 crc = 0;
+       int i;
+
+       pr_debug("atmel_mxt224 In function %s", __func__);
+       for (i = 0; i < (crc_area_size - 1); i = i + 2)
+               crc = CRC_24(crc, *(data + i), *(data + i + 1));
+       /* If uneven size, pad with zero */
+       if (crc_area_size & 0x0001)
+               crc = CRC_24(crc, *(data + i), 0);
+       /* Return only 24 bits of CRC. */
+       *crc_result = (crc & 0x00FFFFFF);
+
+       return 0;
+}
+
+static void report_mt(struct mxt_data *mxt)
+{
+       int i;
+       /* origin from atmel */
+       int active_touches = 0;
+
+       for (i = 0; i < mxt->numtouch; i++) {
+               if (!stored_size[i])
+                       continue;
+
+               active_touches++;
+               input_report_abs(mxt->touch_input,
+                               ABS_MT_TRACKING_ID,
+                               i);
+               input_report_abs(mxt->touch_input,
+                               ABS_MT_TOUCH_MAJOR,
+                               stored_size[i]);
+               input_report_abs(mxt->touch_input,
+                               ABS_MT_POSITION_X,
+                               stored_x[i]);
+               input_report_abs(mxt->touch_input,
+                               ABS_MT_POSITION_Y,
+                               stored_y[i]);
+               input_mt_sync(mxt->touch_input);
+       }
+
+       if (active_touches == 0)
+               input_mt_sync(mxt->touch_input);
+       input_sync(mxt->touch_input);
+}
+
+static void process_T9_message(u8 *message, struct mxt_data *mxt)
+{
+       struct input_dev *input;
+       struct device *dev = &mxt->client->dev;
+       u8  status;
+       u16 xpos = 0xFFFF;
+       u16 ypos = 0xFFFF;
+       u8  touch_size = 255;
+       u8  touch_number;
+       u8  amplitude;
+       u8  report_id;
+       input = mxt->touch_input;
+       status = message[MXT_MSG_T9_STATUS];
+       report_id = message[0];
+
+       if (status & MXT_MSGB_T9_SUPPRESS) {
+               /* Touch has been suppressed by grip/face */
+               /* detection                              */
+               dev_dbg(dev, "SUPRESS");
+       } else {
+               xpos = message[MXT_MSG_T9_XPOSMSB] * 16 +
+                       ((message[MXT_MSG_T9_XYPOSLSB] >> 4) & 0xF);
+               ypos = message[MXT_MSG_T9_YPOSMSB] * 16 +
+                       ((message[MXT_MSG_T9_XYPOSLSB] >> 0) & 0xF);
+
+               xpos >>= 2;
+               ypos >>= 2;
+
+               touch_number = message[MXT_MSG_REPORTID] -
+                       mxt->rid_map[report_id].first_rid;
+
+               stored_x[touch_number] = xpos;
+               stored_y[touch_number] = ypos;
+
+               if (status & MXT_MSGB_T9_DETECT) {
+                       /*
+                        * TODO: more precise touch size calculation?
+                        * mXT224 reports the number of touched nodes,
+                        * so the exact value for touch ellipse major
+                        * axis length would be 2*sqrt(touch_size/pi)
+                        * (assuming round touch shape).
+                        */
+                       touch_size = message[MXT_MSG_T9_TCHAREA];
+                       touch_size = touch_size >> 2;
+                       if (!touch_size)
+                               touch_size = 1;
+                       stored_size[touch_number] = touch_size;
+                       if (status & MXT_MSGB_T9_AMP)
+                               /* Amplitude of touch has changed */
+                               amplitude = message[MXT_MSG_T9_TCHAMPLITUDE];
+
+                       dev_dbg(dev, "DETECT:%s%s%s%s",
+                               ((status & MXT_MSGB_T9_PRESS) ? " PRESS" : ""),
+                               ((status & MXT_MSGB_T9_MOVE) ? " MOVE" : ""),
+                               ((status & MXT_MSGB_T9_AMP) ? " AMP" : ""),
+                               ((status & MXT_MSGB_T9_VECTOR) ? " VECT" : ""));
+               } else if (status & MXT_MSGB_T9_RELEASE) {
+                       dev_dbg(dev, "RELEASE");
+
+                       /* The previously reported touch has been removed.*/
+                       stored_size[touch_number] = 0;
+               }
+
+               dev_dbg(dev, "X=%d, Y=%d, touch number=%d, TOUCHSIZE=%d",
+                       xpos, ypos, touch_number, stored_size[touch_number]);
+       }
+}
+
+void process_key_message(u8 *message, struct mxt_data *mxt)
+{
+       /*key up*/
+       if( message[1] == 0 && message[2] == 0 && message[3] == 0 && message[4] == 0) {
+               if( mxt->prev_key == 0){
+                       dev_dbg(&mxt->client->dev, "No previous key");
+               } else {
+                       input_report_key(mxt->key_input, mxt->prev_key, 0);
+                       dev_dbg(&mxt->client->dev,
+                                "Report key %d up", mxt->prev_key);
+                       mxt->prev_key = 0;
+               }
+               return;
+       }
+
+       /*key down*/
+       if (message[1] == 128 && message[2] == 1 && message[3] == 0 && message[4] == 0) {
+               input_report_key(mxt->key_input, KEY_BACK, 1);
+               dev_dbg(&mxt->client->dev,
+                       "Report BACK(%d) key DOWN.", KEY_BACK);
+               mxt->prev_key = KEY_BACK;
+       }else if (message[1] == 128 && message[2] == 2 && message[3] == 0 && message[4] == 0) {
+               input_report_key(mxt->key_input, KEY_MENU, 1);
+               dev_dbg(&mxt->client->dev,
+                        "Report MENU(%d) key DOWN.", KEY_MENU);
+               mxt->prev_key = KEY_MENU;
+       }else if (message[1] == 128 && message[2] == 0 && message[3] == 4 && message[4] == 0) {
+               input_report_key(mxt->key_input, KEY_HOME, 1);
+               dev_dbg(&mxt->client->dev,
+                       "Report HOME(%d) key DOWN.", KEY_HOME);
+               mxt->prev_key = KEY_HOME;
+       }else if (message[1] == 128 && message[2] == 0 && message[3] == 2 && message[4] == 0) {
+               input_report_key(mxt->key_input, KEY_SEARCH, 1);
+               dev_dbg(&mxt->client->dev,
+                       "Report SEARCH(%d) key DOWN.", KEY_SEARCH);
+               mxt->prev_key = KEY_SEARCH;
+       }
+}
+
+static int process_message(u8 *message, u8 object, struct mxt_data *mxt)
+{
+       struct i2c_client *client;
+       u8  status;
+       u16 xpos = 0xFFFF;
+       u16 ypos = 0xFFFF;
+       u8  event;
+       u8  direction;
+       u16 distance;
+       u8  length;
+       u8  report_id;
+       static u8 error_cond;
+       client = mxt->client;
+       length = mxt->message_size;
+       report_id = message[0];
+
+       if ((mxt->nontouch_msg_only == 0) ||
+               ((object != MXT_TOUCH_MULTITOUCHSCREEN_T9) &&
+               (object != MXT_TOUCH_KEYARRAY_T15) &&
+               (object != MXT_TOUCH_PROXIMITY_T23) &&
+               (object != MXT_TOUCH_SINGLETOUCHSCREEN_T10) &&
+               (object != MXT_TOUCH_XSLIDER_T11) &&
+               (object != MXT_TOUCH_YSLIDER_T12) &&
+               (object != MXT_TOUCH_XWHEEL_T13) &&
+               (object != MXT_TOUCH_YWHEEL_T14) &&
+               (object != MXT_TOUCH_KEYSET_T31) &&
+               (object != MXT_TOUCH_XSLIDERSET_T32))) {
+
+#ifdef DEBUG
+               mutex_lock(&mxt->msg_mutex);
+               /* Copy the message to buffer */
+               if (mxt->msg_buffer_startp < MXT_MESSAGE_BUFFER_SIZE)
+                       mxt->msg_buffer_startp++;
+               else
+                       mxt->msg_buffer_startp = 0;
+
+               if (mxt->msg_buffer_startp == mxt->msg_buffer_endp) {
+                       dev_dbg(&mxt->client->dev,
+                                 "Message buf full, discard last entry.\n");
+                       if (mxt->msg_buffer_endp < MXT_MESSAGE_BUFFER_SIZE)
+                               mxt->msg_buffer_endp++;
+                       else
+                               mxt->msg_buffer_endp = 0;
+               }
+               memcpy((mxt->messages + mxt->msg_buffer_startp * length),
+                      message,
+                      length);
+               mutex_unlock(&mxt->msg_mutex);
+#endif
+       }
+
+       switch (object) {
+       case MXT_GEN_COMMANDPROCESSOR_T6:
+               status = message[1];
+
+               if (status & MXT_MSGB_T6_COMSERR) {
+                       if ((!error_cond) & MXT_MSGB_T6_COMSERR) {
+                               dev_err(&client->dev,
+                                       "maXTouch checksum error\n");
+                               error_cond |= MXT_MSGB_T6_COMSERR;
+                       }
+               }
+               if (status & MXT_MSGB_T6_CFGERR) {
+                       /*
+                        * Configuration error. A proper configuration
+                        * needs to be written to chip and backed up. Refer
+                        * to protocol document for further info.
+                        */
+                       if ((!error_cond) & MXT_MSGB_T6_CFGERR) {
+                               dev_err(&client->dev,
+                                       "maXTouch configuration error\n");
+                               error_cond |= MXT_MSGB_T6_CFGERR;
+                       }
+               }
+               if (status & MXT_MSGB_T6_CAL) {
+                       /* Calibration in action, no need to react */
+                       dev_info(&client->dev,
+                               "maXTouch calibration in progress\n");
+               }
+               if (status & MXT_MSGB_T6_SIGERR) {
+                       /*
+                        * Signal acquisition error, something is seriously
+                        * wrong, not much we can in the driver to correct
+                        * this
+                        */
+                       if ((!error_cond) & MXT_MSGB_T6_SIGERR) {
+                               dev_err(&client->dev,
+                                       "maXTouch acquisition error\n");
+                               error_cond |= MXT_MSGB_T6_SIGERR;
+                       }
+               }
+               if (status & MXT_MSGB_T6_OFL) {
+                       /*
+                        * Cycle overflow, the acquisition is too short.
+                        * Can happen temporarily when there's a complex
+                        * touch shape on the screen requiring lots of
+                        * processing.
+                        */
+                       dev_err(&client->dev, "maXTouch cycle overflow\n");
+                       mxt_gpio_reset(mxt);
+               }
+               if (status & MXT_MSGB_T6_RESET) {
+                       /* Chip has reseted, no need to react. */
+                       dev_info(&client->dev,
+                               "maXTouch chip reset\n");
+               }
+               if (status == 0) {
+                       /* Chip status back to normal. */
+                       dev_info(&client->dev,
+                               "maXTouch status normal\n");
+                       error_cond = 0;
+               }
+               break;
+
+       case MXT_TOUCH_KEYARRAY_T15:
+               dev_dbg(&client->dev, "key value, message[1]=%d, "
+                       "message[2]=%d, message[3]=%d, message[4]=%d",
+                        message[1], message[2], message[3], message[4]);
+               process_key_message(message, mxt);
+               break;
+
+       case MXT_TOUCH_MULTITOUCHSCREEN_T9:
+               process_T9_message(message, mxt);
+               report_mt(mxt);
+               break;
+
+       case MXT_SPT_GPIOPWM_T19:
+               if (debug >= DEBUG_TRACE)
+                       dev_info(&client->dev,
+                               "Receiving GPIO message\n");
+               break;
+
+       case MXT_PROCI_GRIPFACESUPPRESSION_T20:
+               if (debug >= DEBUG_TRACE)
+                       dev_info(&client->dev,
+                               "Receiving face suppression msg\n");
+               break;
+
+       case MXT_PROCG_NOISESUPPRESSION_T22:
+               if (debug >= DEBUG_TRACE)
+                       dev_info(&client->dev,
+                               "Receiving noise suppression msg\n");
+               status = message[MXT_MSG_T22_STATUS];
+               if (status & MXT_MSGB_T22_FHCHG) {
+                       if (debug >= DEBUG_TRACE)
+                               dev_info(&client->dev,
+                                       "maXTouch: Freq changed\n");
+               }
+               if (status & MXT_MSGB_T22_GCAFERR) {
+                       if (debug >= DEBUG_TRACE)
+                               dev_info(&client->dev,
+                                       "maXTouch: High noise "
+                                       "level\n");
+               }
+               if (status & MXT_MSGB_T22_FHERR) {
+                       if (debug >= DEBUG_TRACE)
+                               dev_info(&client->dev,
+                                       "maXTouch: Freq changed - "
+                                       "Noise level too high\n");
+               }
+               break;
+
+       case MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24:
+               if (debug >= DEBUG_TRACE)
+                       dev_info(&client->dev,
+                               "Receiving one-touch gesture msg\n");
+
+               event = message[MXT_MSG_T24_STATUS] & 0x0F;
+               xpos = message[MXT_MSG_T24_XPOSMSB] * 16 +
+                       ((message[MXT_MSG_T24_XYPOSLSB] >> 4) & 0x0F);
+               ypos = message[MXT_MSG_T24_YPOSMSB] * 16 +
+                       ((message[MXT_MSG_T24_XYPOSLSB] >> 0) & 0x0F);
+               xpos >>= 2;
+               ypos >>= 2;
+               direction = message[MXT_MSG_T24_DIR];
+               distance = message[MXT_MSG_T24_DIST] +
+                          (message[MXT_MSG_T24_DIST + 1] << 16);
+
+               input_event(mxt->touch_input, EV_MSC, MSC_GESTURE,
+                               (event << 24) | (direction << 16) | distance);
+               input_event(mxt->touch_input, EV_MSC, MSC_GESTURE,
+                               (xpos << 16) | ypos);
+               break;
+
+       case MXT_SPT_SELFTEST_T25:
+               if (debug >= DEBUG_TRACE)
+                       dev_info(&client->dev,
+                               "Receiving Self-Test msg\n");
+
+               if (message[MXT_MSG_T25_STATUS] == MXT_MSGR_T25_RUN_ALL_TESTS) {
+                       if (debug >= DEBUG_TRACE)
+                               dev_info(&client->dev,
+                                       "maXTouch: Self-Test OK\n");
+
+               } else  {
+                       dev_err(&client->dev,
+                               "maXTouch: Self-Test Failed [%02x]:"
+                               "{%02x,%02x,%02x,%02x,%02x}\n",
+                               message[MXT_MSG_T25_STATUS],
+                               message[MXT_MSG_T25_STATUS + 0],
+                               message[MXT_MSG_T25_STATUS + 1],
+                               message[MXT_MSG_T25_STATUS + 2],
+                               message[MXT_MSG_T25_STATUS + 3],
+                               message[MXT_MSG_T25_STATUS + 4]
+                               );
+               }
+               break;
+
+       case MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27:
+               if (debug >= DEBUG_TRACE)
+                       dev_info(&client->dev,
+                               "Receiving 2-touch gesture message\n");
+
+               event = message[MXT_MSG_T27_STATUS] & 0xF0;
+               xpos = message[MXT_MSG_T27_XPOSMSB] * 16 +
+                       ((message[MXT_MSG_T27_XYPOSLSB] >> 4) & 0x0F);
+               ypos = message[MXT_MSG_T27_YPOSMSB] * 16 +
+                       ((message[MXT_MSG_T27_XYPOSLSB] >> 0) & 0x0F);
+               xpos >>= 2;
+               ypos >>= 2;
+               direction = message[MXT_MSG_T27_ANGLE];
+               distance = message[MXT_MSG_T27_SEPARATION] +
+                          (message[MXT_MSG_T27_SEPARATION + 1] << 16);
+
+               input_event(mxt->touch_input, EV_MSC, MSC_GESTURE,
+                               (event << 24) | (direction << 16) | distance);
+               input_event(mxt->touch_input, EV_MSC, MSC_GESTURE,
+                               (xpos << 16) | ypos);
+               break;
+
+       case MXT_SPT_CTECONFIG_T28:
+               if (debug >= DEBUG_TRACE)
+                       dev_info(&client->dev,
+                               "Receiving CTE message...\n");
+               status = message[MXT_MSG_T28_STATUS];
+               if (status & MXT_MSGB_T28_CHKERR)
+                       dev_err(&client->dev,
+                               "maXTouch: Power-Up CRC failure\n");
+
+               break;
+       default:
+               if (debug >= DEBUG_TRACE)
+                       dev_info(&client->dev,
+                               "maXTouch: Unknown message!\n");
+
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * Processes messages when the interrupt line (CHG) is asserted. Keeps
+ * reading messages until a message with report ID 0xFF is received,
+ * which indicates that there is no more new messages.
+ *
+ */
+static void mxt_worker(struct mxt_data *mxt)
+{
+       struct i2c_client *client;
+       u8      *message;
+       u16     message_length;
+       u16     message_addr;
+       u8      report_id = 0;
+       u8      object;
+       int     error;
+       int     i;
+
+       message = NULL;
+       client = mxt->client;
+       message_addr = mxt->msg_proc_addr;
+       message_length = mxt->message_size;
+
+       if (message_length < 256) {
+               message = kmalloc(message_length, GFP_KERNEL);
+               if (message == NULL) {
+                       dev_err(&client->dev, "Error allocating memory\n");
+                       return;
+               }
+       } else {
+               dev_err(&client->dev,
+                       "Message length > 256 bytes not supported\n");
+               return;
+       }
+
+       dev_dbg(&client->dev, "maXTouch worker active:\n");
+       do {
+               /* Read next message, reread on failure. */
+               mxt->message_counter++;
+               for (i = 1; i < I2C_RETRY_COUNT; i++) {
+                       error = mxt_read_block(client, message_addr,
+                                       message_length, message);
+                       if (error >= 0)
+                               break;
+                       mxt->read_fail_counter++;
+                       dev_err(&client->dev,
+                                       "Failure reading maxTouch device\n");
+               }
+               if (error < 0) {
+                       /*
+                        * Reset device if we fail to read message
+                        * I2C_RETRY_COUNT-1 times, the touch i2c
+                        * interface may die.
+                        */
+                       mxt_gpio_reset(mxt);
+                       continue;
+               }
+
+               report_id = message[0];
+
+/* FIXME! this is broken if enabled */
+#ifdef DEBUG
+               if (mxt->address_pointer != message_addr)
+                       mxt->valid_ap = 0;
+
+               char *message_string;
+               char *message_start;
+
+               if (report_id == 0xFF)
+                       dev_dbg(&client->dev,
+                               "Reoport ID is undefined\n");
+               else {
+                       dev_dbg(&client->dev,
+                               "%s message [msg count: %08x]:",
+                               obj_typ_name[mxt->rid_map[report_id].object],
+                               mxt->message_counter);
+               }
+               /* 5 characters per one byte */
+               message_string = kmalloc(message_length * 5,
+                               GFP_KERNEL);
+               if (message_string == NULL) {
+                       dev_err(&client->dev,
+                                       "Error allocating memory\n");
+                       kfree(message);
+                       return;
+               }
+               message_start = message_string;
+               for (i = 0; i < message_length; i++) {
+                       message_string +=
+                       sprintf(message_string,
+                                       "0x%02X ", message[i]);
+               }
+               dev_dbg(&client->dev, "%s", message_start);
+               kfree(message_start);
+#endif
+
+               if ((report_id != MXT_END_OF_MESSAGES) && (report_id != 0)) {
+#ifdef DEBUG
+                       memcpy(mxt->last_message, message, message_length);
+                       mxt->new_msgs = 1;
+                       smp_wmb();
+#endif
+                       /* Get type of object and process the message */
+                       object = mxt->rid_map[report_id].object;
+                       process_message(message, object, mxt);
+               }
+               dev_dbg(&client->dev, "chgline: %d\n", mxt->read_chg());
+       } while ((report_id != MXT_END_OF_MESSAGES));
+
+       kfree(message);
+}
+
+/*
+ * The maXTouch device will signal the host about a new message by asserting
+ * the CHG line. This ISR schedules a worker routine to read the message when
+ * that happens.
+ */
+static irqreturn_t mxt_irq_handler(int irq, void *_mxt)
+{
+       struct mxt_data *mxt = _mxt;
+
+       mxt->irq_counter++;
+       if (mxt->valid_interrupt()) {
+               mxt->valid_irq_counter++;
+
+               mutex_lock(&mxt->dev_mutex);
+               mxt_worker(mxt);
+               mutex_unlock(&mxt->dev_mutex);
+       } else {
+               mxt->invalid_irq_counter++;
+               return IRQ_NONE;
+       }
+
+       return IRQ_HANDLED;
+}
+
+/******************************************************************************/
+/* Initialization of driver                                                   */
+/******************************************************************************/
+
+static int __devinit mxt_identify(struct i2c_client *client,
+                                 struct mxt_data *mxt,
+                                 u8 *id_block_data)
+{
+       u8 buf[7];
+       int error;
+       int identified;
+
+       identified = 0;
+
+       /* Read Device info to check if chip is valid */
+       error = mxt_read_block(client, MXT_ADDR_INFO_BLOCK, MXT_ID_BLOCK_SIZE,
+                              (u8 *) buf);
+
+       if (error < 0) {
+               mxt->read_fail_counter++;
+               dev_err(&client->dev, "Failure accessing maXTouch device\n");
+               return -EIO;
+       }
+
+       memcpy(id_block_data, buf, MXT_ID_BLOCK_SIZE);
+
+       mxt->device_info.family_id  = buf[0];
+       mxt->device_info.variant_id = buf[1];
+       mxt->device_info.major      = ((buf[2] >> 4) & 0x0F);
+       mxt->device_info.minor      = (buf[2] & 0x0F);
+       mxt->device_info.build      = buf[3];
+       mxt->device_info.x_size     = buf[4];
+       mxt->device_info.y_size     = buf[5];
+       mxt->device_info.num_objs   = buf[6];
+       mxt->device_info.num_nodes  = mxt->device_info.x_size *
+                                     mxt->device_info.y_size;
+
+       /*
+        * Check Family & Variant Info; warn if not recognized but
+        * still continue.
+        */
+
+       /* MXT224 */
+       if (mxt->device_info.family_id == MXT224_FAMILYID) {
+               strcpy(mxt->device_info.family_name, "atmel_mxt224");
+
+               if (mxt->device_info.variant_id == MXT224_CAL_VARIANTID) {
+                       strcpy(mxt->device_info.variant_name, "Calibrated");
+               } else if (mxt->device_info.variant_id ==
+                       MXT224_UNCAL_VARIANTID) {
+                       strcpy(mxt->device_info.variant_name, "Uncalibrated");
+               } else {
+                       dev_err(&client->dev,
+                               "Warning: maXTouch Variant ID [%d] not "
+                               "supported\n",
+                               mxt->device_info.variant_id);
+                       strcpy(mxt->device_info.variant_name, "UNKNOWN");
+                       /* identified = -ENXIO; */
+               }
+
+       /* MXT1386 */
+       } else if (mxt->device_info.family_id == MXT1386_FAMILYID) {
+               strcpy(mxt->device_info.family_name, "mXT1386");
+
+               if (mxt->device_info.variant_id == MXT1386_CAL_VARIANTID) {
+                       strcpy(mxt->device_info.variant_name, "Calibrated");
+               } else {
+                       dev_err(&client->dev,
+                               "Warning: maXTouch Variant ID [%d] not "
+                               "supported\n",
+                               mxt->device_info.variant_id);
+                       strcpy(mxt->device_info.variant_name, "UNKNOWN");
+                       /* identified = -ENXIO; */
+               }
+       /* Unknown family ID! */
+       } else {
+               dev_err(&client->dev,
+                       "Warning: maXTouch Family ID [%d] not supported\n",
+                       mxt->device_info.family_id);
+               strcpy(mxt->device_info.family_name, "UNKNOWN");
+               strcpy(mxt->device_info.variant_name, "UNKNOWN");
+               /* identified = -ENXIO; */
+       }
+
+       dev_info(
+               &client->dev,
+               "Atmel maXTouch (Family %s (%X), Variant %s (%X)) Firmware "
+               "version [%d.%d] Build %d\n",
+               mxt->device_info.family_name,
+               mxt->device_info.family_id,
+               mxt->device_info.variant_name,
+               mxt->device_info.variant_id,
+               mxt->device_info.major,
+               mxt->device_info.minor,
+               mxt->device_info.build
+       );
+       dev_info(
+               &client->dev,
+               "Atmel maXTouch Configuration "
+               "[X: %d] x [Y: %d]\n",
+               mxt->device_info.x_size,
+               mxt->device_info.y_size
+       );
+       return identified;
+}
+
+/*
+ * Reads the object table from maXTouch chip to get object data like
+ * address, size, report id. For Info Block CRC calculation, already read
+ * id data is passed to this function too (Info Block consists of the ID
+ * block and object table).
+ *
+ */
+static int __devinit mxt_read_object_table(struct i2c_client *client,
+                                          struct mxt_data *mxt,
+                                          u8 *raw_id_data)
+{
+       u16     report_id_count;
+       u8      buf[MXT_OBJECT_TABLE_ELEMENT_SIZE];
+       u8      *raw_ib_data;
+       u8      object_type;
+       u16     object_address;
+       u16     object_size;
+       u8      object_instances;
+       u8      object_report_ids;
+       u16     object_info_address;
+       u32     crc;
+       u32     calculated_crc;
+       int     i;
+       int     error;
+
+       u8      object_instance;
+       u8      object_report_id;
+       u8      report_id;
+       int     first_report_id;
+       int     ib_pointer;
+       struct mxt_object *object_table;
+       dev_dbg(&mxt->client->dev, "maXTouch driver reading configuration\n");
+
+       object_table = kzalloc(sizeof(struct mxt_object) *
+                              mxt->device_info.num_objs,
+                              GFP_KERNEL);
+       if (object_table == NULL) {
+               printk(KERN_WARNING "maXTouch: Memory allocation failed!\n");
+               error = -ENOMEM;
+               goto err_object_table_alloc;
+       }
+
+       raw_ib_data = kmalloc(MXT_OBJECT_TABLE_ELEMENT_SIZE *
+                       mxt->device_info.num_objs + MXT_ID_BLOCK_SIZE,
+                       GFP_KERNEL);
+       if (raw_ib_data == NULL) {
+               printk(KERN_WARNING "maXTouch: Memory allocation failed!\n");
+               error = -ENOMEM;
+               goto err_ib_alloc;
+       }
+
+       /* Copy the ID data for CRC calculation. */
+       memcpy(raw_ib_data, raw_id_data, MXT_ID_BLOCK_SIZE);
+       ib_pointer = MXT_ID_BLOCK_SIZE;
+
+       mxt->object_table = object_table;
+
+       dev_dbg(&mxt->client->dev, "maXTouch driver Memory allocated\n");
+
+       object_info_address = MXT_ADDR_OBJECT_TABLE;
+
+       report_id_count = 0;
+       for (i = 0; i < mxt->device_info.num_objs; i++) {
+               dev_dbg(&mxt->client->dev, "Reading maXTouch at [0x%04x]: ",
+                         object_info_address);
+
+               error = mxt_read_block(client, object_info_address,
+                                      MXT_OBJECT_TABLE_ELEMENT_SIZE, buf);
+
+               if (error < 0) {
+                       mxt->read_fail_counter++;
+                       dev_err(&client->dev,
+                               "maXTouch Object %d could not be read\n", i);
+                       error = -EIO;
+                       goto err_object_read;
+               }
+
+               memcpy(raw_ib_data + ib_pointer, buf,
+                      MXT_OBJECT_TABLE_ELEMENT_SIZE);
+               ib_pointer += MXT_OBJECT_TABLE_ELEMENT_SIZE;
+
+               object_type       =  buf[0];
+               object_address    = (buf[2] << 8) + buf[1];
+               object_size       =  buf[3] + 1;
+               object_instances  =  buf[4] + 1;
+               object_report_ids =  buf[5];
+               dev_dbg(&mxt->client->dev, "Type=%03d, Address=0x%04x, "
+                         "Size=0x%02x, %d instances, %d report id's\n",
+                         object_type,
+                         object_address,
+                         object_size,
+                         object_instances,
+                         object_report_ids
+               );
+
+               /* TODO: check whether object is known and supported? */
+
+               /* Save frequently needed info. */
+               if (object_type == MXT_GEN_MESSAGEPROCESSOR_T5) {
+                       mxt->msg_proc_addr = object_address;
+                       mxt->message_size = object_size;
+               }
+
+               object_table[i].type            = object_type;
+               object_table[i].chip_addr       = object_address;
+               object_table[i].size            = object_size;
+               object_table[i].instances       = object_instances;
+               object_table[i].num_report_ids  = object_report_ids;
+               report_id_count += object_instances * object_report_ids;
+
+               object_info_address += MXT_OBJECT_TABLE_ELEMENT_SIZE;
+       }
+
+       mxt->rid_map =
+               kzalloc(sizeof(struct report_id_map) * (report_id_count + 1),
+                       /* allocate for report_id 0, even if not used */
+                       GFP_KERNEL);
+       if (mxt->rid_map == NULL) {
+               printk(KERN_WARNING "maXTouch: Can't allocate memory!\n");
+               error = -ENOMEM;
+               goto err_rid_map_alloc;
+       }
+
+#ifdef DEBUG
+       mxt->messages = kzalloc(mxt->message_size * MXT_MESSAGE_BUFFER_SIZE,
+                               GFP_KERNEL);
+       if (mxt->messages == NULL) {
+               printk(KERN_WARNING "maXTouch: Can't allocate memory!\n");
+               error = -ENOMEM;
+               goto err_msg_alloc1;
+       }
+
+       mxt->last_message = kzalloc(mxt->message_size, GFP_KERNEL);
+       if (mxt->last_message == NULL) {
+               printk(KERN_WARNING "maXTouch: Can't allocate memory!\n");
+               error = -ENOMEM;
+               goto err_msg_alloc2;
+       }
+#endif
+
+       mxt->report_id_count = report_id_count;
+       if (report_id_count > 254) {    /* 0 & 255 are reserved */
+                       dev_err(&client->dev,
+                               "Too many maXTouch report id's [%d]\n",
+                               report_id_count);
+                       error = -ENXIO;
+                       goto err_max_rid;
+       }
+
+       /* Create a mapping from report id to object type */
+       report_id = 1; /* Start from 1, 0 is reserved. */
+
+       /* Create table associating report id's with objects & instances */
+       for (i = 0; i < mxt->device_info.num_objs; i++) {
+               for (object_instance = 0;
+                    object_instance < object_table[i].instances;
+                    object_instance++){
+                       first_report_id = report_id;
+                       for (object_report_id = 0;
+                            object_report_id < object_table[i].num_report_ids;
+                            object_report_id++) {
+                               mxt->rid_map[report_id].object =
+                                       object_table[i].type;
+                               mxt->rid_map[report_id].instance =
+                                       object_instance;
+                               mxt->rid_map[report_id].first_rid =
+                                       first_report_id;
+                               report_id++;
+                       }
+               }
+       }
+
+       /* Read 3 byte CRC */
+       error = mxt_read_block(client, object_info_address, 3, buf);
+       if (error < 0) {
+               mxt->read_fail_counter++;
+               dev_err(&client->dev, "Error reading CRC\n");
+       }
+
+       crc = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+       if (calculate_infoblock_crc(&calculated_crc, raw_ib_data,
+                                   ib_pointer)) {
+               printk(KERN_WARNING "Error while calculating CRC!\n");
+               calculated_crc = 0;
+       }
+       kfree(raw_ib_data);
+
+       dev_dbg(&mxt->client->dev, "\nReported info block CRC = 0x%6X\n", crc);
+       dev_dbg(&mxt->client->dev, "Calculated info block CRC = 0x%6X\n\n",
+                      calculated_crc);
+
+       if (crc == calculated_crc) {
+               mxt->info_block_crc = crc;
+       } else {
+               mxt->info_block_crc = 0;
+               printk(KERN_ALERT "maXTouch: Info block CRC invalid!\n");
+       }
+
+       if (debug >= DEBUG_VERBOSE) {
+
+               dev_info(&client->dev, "maXTouch: %d Objects\n",
+                               mxt->device_info.num_objs);
+
+               for (i = 0; i < mxt->device_info.num_objs; i++) {
+                       dev_info(&client->dev, "Type:\t\t\t[%d]: %s\n",
+                                object_table[i].type,
+                                obj_typ_name[object_table[i].type]);
+                       dev_info(&client->dev, "\tAddress:\t0x%04X\n",
+                               object_table[i].chip_addr);
+                       dev_info(&client->dev, "\tSize:\t\t%d Bytes\n",
+                                object_table[i].size);
+                       dev_info(&client->dev, "\tInstances:\t%d\n",
+                                object_table[i].instances);
+                       dev_info(&client->dev, "\tReport Id's:\t%d\n",
+                                object_table[i].num_report_ids);
+               }
+       }
+
+       return 0;
+
+err_max_rid:
+#ifdef DEBUG
+       kfree(mxt->last_message);
+err_msg_alloc2:
+       kfree(mxt->messages);
+err_msg_alloc1:
+#endif
+       kfree(mxt->rid_map);
+err_rid_map_alloc:
+err_object_read:
+       kfree(raw_ib_data);
+err_ib_alloc:
+       kfree(object_table);
+err_object_table_alloc:
+       return error;
+}
+
+static u8 mxt_valid_interrupt_dummy(void)
+{
+       return 1;
+}
+
+static int mxt_get_config_version(struct mxt_data *mxt)
+{
+       int ret;
+       u32 t38[2] = { 0 };
+       u16 addr;
+
+       addr = get_object_address(MXT_USER_INFO_T38,
+                       0, mxt->object_table,
+                       mxt->device_info.num_objs);
+       ret = mxt_read_block(mxt->client, addr, sizeof(t38), (u8 *)t38);
+       if (ret < 0)
+               return ret;
+
+       return t38[0];
+}
+
+static int mxt_set_config_version(struct mxt_data *mxt, int version)
+{
+       int ret;
+       u32 t38[2] = { 0 };
+       u16 addr;
+
+       addr = get_object_address(MXT_USER_INFO_T38,
+                       0, mxt->object_table,
+                       mxt->device_info.num_objs);
+
+       t38[0] = version;
+       ret = mxt_write_block(mxt->client, addr, sizeof(t38), (u8 *)t38);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static void mxt_initialize(struct mxt_data *mxt)
+{
+       int config_version = mxt_get_config_version(mxt);
+       u16 addr;
+
+       dev_info(&mxt->client->dev, "version nvm:%d, current:%d\n",
+                config_version, MXT_CONFIG_VERSION);
+
+#ifdef MXT_CHECK_VERSION
+       if (config_version >= MXT_CONFIG_VERSION)
+               goto out_reset;
+#endif
+
+       mxt_config_init(mxt);
+       mxt_set_config_version(mxt, MXT_CONFIG_VERSION);
+
+       addr = get_object_address(MXT_GEN_COMMANDPROCESSOR_T6,
+                       0, mxt->object_table,
+                       mxt->device_info.num_objs) + MXT_ADR_T6_BACKUPNV;
+       mxt_write_byte(mxt->client, addr, MXT_CMD_T6_BACKUP);
+       msleep(MXT_BACKNVM_DELAY);
+
+#ifdef MXT_CHECK_VERSION
+out_reset:
+#endif
+       mxt_reset(mxt);
+}
+
+static int __devinit mxt_probe(struct i2c_client *client,
+                              const struct i2c_device_id *id)
+{
+       struct mxt_data          *mxt;
+       struct mxt_platform_data *pdata;
+       struct input_dev         *touch_input;
+       struct input_dev         *key_input;
+       u8 *id_data;
+       int error;
+
+       printk(KERN_INFO "atmel_mxt224: mxt_probe\n");
+
+       if (client == NULL) {
+               pr_debug("maXTouch: client == NULL\n");
+               return  -EINVAL;
+       } else if (client->adapter == NULL) {
+               pr_debug("maXTouch: client->adapter == NULL\n");
+               return  -EINVAL;
+       } else if (&client->dev == NULL) {
+               pr_debug("maXTouch: client->dev == NULL\n");
+               return  -EINVAL;
+       } else if (&client->adapter->dev == NULL) {
+               pr_debug("maXTouch: client->adapter->dev == NULL\n");
+               return  -EINVAL;
+       } else if (id == NULL) {
+               pr_debug("maXTouch: id == NULL\n");
+               return  -EINVAL;
+       }
+
+       dev_dbg(&client->dev, "maXTouch driver v. %s\n", DRIVER_VERSION);
+       dev_dbg(&client->dev, "\t \"%s\"\n", client->name);
+       dev_dbg(&client->dev, "\taddr:\t0x%04x\n", client->addr);
+       dev_dbg(&client->dev, "\tirq:\t%d\n", client->irq);
+       dev_dbg(&client->dev, "\tflags:\t0x%04x\n", client->flags);
+       dev_dbg(&client->dev, "\tadapter:\"%s\"\n", client->adapter->name);
+       dev_dbg(&client->dev, "\tdevice:\t\"%s\"\n", client->dev.init_name);
+
+       /* Check if the I2C bus supports BYTE transfer */
+       error = i2c_check_functionality(client->adapter,
+                       I2C_FUNC_SMBUS_BYTE);
+       if (!error) {
+               dev_err(&client->dev, "%s adapter not supported\n",
+                               dev_driver_string(&client->adapter->dev));
+               return -ENODEV;
+       }
+       dev_dbg(&client->dev, "maXTouch driver functionality OK\n");
+
+       /* Allocate structure - we need it to identify device */
+       mxt = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
+       if (mxt == NULL) {
+               dev_err(&client->dev, "insufficient memory\n");
+               error = -ENOMEM;
+               goto err_mxt_alloc;
+       }
+
+       id_data = kmalloc(MXT_ID_BLOCK_SIZE, GFP_KERNEL);
+       if (id_data == NULL) {
+               dev_err(&client->dev, "insufficient memory\n");
+               error = -ENOMEM;
+               goto err_id_alloc;
+       }
+
+       touch_input = input_allocate_device();
+       if (!touch_input) {
+               dev_err(&client->dev, "error allocating touch input device\n");
+               error = -ENOMEM;
+               goto err_touch_input_dev_alloc;
+       }
+
+       key_input = input_allocate_device();
+       if(!key_input) {
+               dev_err(&client->dev, "error allocating key input device");
+               error = -ENOMEM;
+               goto err_key_input_dev_alloc;
+       }
+
+       /* Initialize Platform data */
+       pdata = client->dev.platform_data;
+       if (pdata == NULL) {
+               dev_err(&client->dev, "platform data is required!\n");
+               error = -EINVAL;
+               goto err_pdata;
+       }
+       if (debug >= DEBUG_TRACE)
+               printk(KERN_INFO "Platform OK: pdata = 0x%08x\n",
+                      (unsigned int) pdata);
+
+       mutex_init(&mxt->dev_mutex);
+       mxt->read_fail_counter = 0;
+       mxt->message_counter   = 0;
+       mxt->max_x_val         = pdata->max_x;
+       mxt->max_y_val         = pdata->max_y;
+       mxt->orientation       = pdata->orientation;
+
+       mxt->mxt_intr_gpio = pdata->irq;
+       mxt->mxt_reset_gpio = pdata->reset;
+
+       /*init INTERRUPT pin*/
+       error = gpio_request(mxt->mxt_intr_gpio, 0);
+       if(error < 0)
+               printk(KERN_ERR "Failed to request GPIO%d (MaxTouch-interrupt) error=%d\n",
+                       mxt->mxt_intr_gpio, error);
+
+       error = gpio_direction_input(mxt->mxt_intr_gpio);
+       if (error){
+               printk(KERN_ERR "Failed to set interrupt direction, error=%d\n", error);
+               gpio_free(mxt->mxt_intr_gpio);
+       }
+
+       /*init RESET pin*/
+       error = gpio_request(mxt->mxt_reset_gpio, "MaxTouch-reset");
+       if (error < 0)
+               printk(KERN_ERR "Failed to request GPIO%d (MaxTouch-reset) error=%d\n",
+                       mxt->mxt_reset_gpio, error);
+
+       error = gpio_direction_output(mxt->mxt_reset_gpio, 1);
+       if (error){
+               printk(KERN_ERR "Failed to set reset direction, error=%d\n", error);
+               gpio_free(mxt->mxt_reset_gpio);
+       }
+
+       /* maXTouch wants 40mSec minimum after reset to get organized */
+       gpio_set_value(mxt->mxt_reset_gpio, 1);
+       msleep(40);
+
+       /* Get data that is defined in board specific code. */
+       mxt->init_hw = pdata->init_platform_hw;
+       mxt->exit_hw = pdata->exit_platform_hw;
+       mxt->read_chg = pdata->read_chg;
+
+       if (pdata->valid_interrupt != NULL)
+               mxt->valid_interrupt = pdata->valid_interrupt;
+       else
+               mxt->valid_interrupt = mxt_valid_interrupt_dummy;
+
+       if (mxt->init_hw != NULL)
+               mxt->init_hw();
+
+       if (debug >= DEBUG_TRACE)
+               printk(KERN_INFO "maXTouch driver identifying chip\n");
+
+       if (mxt_identify(client, mxt, id_data) < 0) {
+               dev_err(&client->dev, "Chip could not be identified\n");
+               error = -ENODEV;
+               goto err_identify;
+       }
+       /* Chip is valid and active. */
+       if (debug >= DEBUG_TRACE)
+               printk(KERN_INFO "maXTouch driver allocating input device\n");
+
+       mxt->client = client;
+       mxt->touch_input = touch_input;
+       mxt->key_input = key_input;
+
+       dev_dbg(&mxt->client->dev, "maXTouch driver creating device name\n");
+
+       snprintf(mxt->touch_phys_name, sizeof(mxt->touch_phys_name),
+                "%s/input0", dev_name(&client->dev));
+
+       snprintf(mxt->key_phys_name, sizeof(mxt->key_phys_name),
+                "%s/input1", dev_name(&client->dev));
+
+       /*touch input parameter*/
+       touch_input->name = "mxt224_touchscreen_0";
+       touch_input->phys = mxt->touch_phys_name;
+       touch_input->id.bustype = BUS_I2C;
+       touch_input->dev.parent = &client->dev;
+
+       dev_dbg(&client->dev, "maXTouch name: \"%s\"\n", touch_input->name);
+       dev_dbg(&client->dev, "maXTouch phys: \"%s\"\n", touch_input->phys);
+
+       /*key input parameter*/
+       key_input->name = "mxt224_key_0";
+       key_input->phys = mxt->key_phys_name;
+
+       dev_dbg(&client->dev, "maxTouch name: \"%s\"\n", key_input->name);
+       dev_dbg(&client->dev, "maxTouch phys: \"%s\"\n", key_input->phys);
+       dev_dbg(&client->dev, "maXTouch driver setting abs parameters\n");
+
+       /* Multitouch */
+       input_set_abs_params(touch_input, ABS_MT_POSITION_X, TS_MIN_X, TS_MAX_X, 0, 0);
+       input_set_abs_params(touch_input, ABS_MT_POSITION_Y, TS_MIN_Y, TS_MAX_Y, 0, 0);
+       input_set_abs_params(touch_input, ABS_MT_TOUCH_MAJOR, 0, MXT_MAX_TOUCH_SIZE,
+                            0, 0);
+       input_set_abs_params(touch_input, ABS_MT_TRACKING_ID, 0,
+                            MXT_MAX_NUM_TOUCHES, 0, 0);
+
+       __set_bit(EV_ABS, touch_input->evbit);
+       __set_bit(EV_SYN, touch_input->evbit);
+
+       /* Function key*/
+       __set_bit(EV_KEY, key_input->evbit);
+       __set_bit(KEY_HOME, key_input->keybit);
+       __set_bit(KEY_MENU, key_input->keybit);
+       __set_bit(KEY_BACK, key_input->keybit);
+       __set_bit(KEY_SEARCH, key_input->keybit);
+
+       dev_dbg(&mxt->client->dev, "maXTouch driver setting client data\n");
+       i2c_set_clientdata(client, mxt);
+       dev_dbg(&mxt->client->dev, "maXTouch driver setting drv data\n");
+       input_set_drvdata(touch_input, mxt);
+       input_set_drvdata(key_input, mxt);
+
+       dev_dbg(&mxt->client->dev, "maXTouch driver input register device\n");
+       error = input_register_device(mxt->touch_input);
+       if (error < 0) {
+               dev_err(&client->dev,
+                       "Failed to register touch input device\n");
+               goto err_register_touch_device;
+       }
+       error = input_register_device(mxt->key_input);
+       if (error < 0) {
+               dev_err(&client->dev,
+                       "Failed to register key input device in mxt224\n");
+               goto err_register_key_device;
+       }
+
+       error = mxt_read_object_table(client, mxt, id_data);
+       if (error < 0)
+               goto err_read_ot;
+
+#ifdef DEBUG
+       mutex_init(&mxt->debug_mutex);
+       mutex_init(&mxt->msg_mutex);
+       /* Create debugfs entries. */
+       mxt->debug_dir = debugfs_create_dir("maXTouch", NULL);
+       if ((int)mxt->debug_dir == -ENODEV) {
+               /* debugfs is not enabled. */
+               printk(KERN_WARNING "debugfs not enabled in kernel\n");
+       } else if (mxt->debug_dir == NULL) {
+               printk(KERN_WARNING "error creating debugfs dir\n");
+       } else {
+               dev_dbg(&mxt->client->dev,
+                       "created \"maXTouch\" debugfs dir\n");
+
+               debugfs_create_file("deltas", S_IRUSR, mxt->debug_dir, mxt,
+                                   &delta_fops);
+               debugfs_create_file("refs", S_IRUSR, mxt->debug_dir, mxt,
+                                   &refs_fops);
+       }
+
+       /* Create character device nodes for reading & writing registers */
+       mxt->mxt_class = class_create(THIS_MODULE, "maXTouch_memory");
+       /* 2 numbers; one for memory and one for messages */
+       error = alloc_chrdev_region(&mxt->dev_num, 0, 2,
+                                   "maXTouch_memory");
+       dev_info(&mxt->client->dev,
+               "device number %d allocated!\n", MAJOR(mxt->dev_num));
+       if (error)
+               printk(KERN_WARNING "Error registering device\n");
+       cdev_init(&mxt->cdev, &mxt_memory_fops);
+       cdev_init(&mxt->cdev_messages, &mxt_message_fops);
+
+       dev_info(&mxt->client->dev, "cdev initialized\n");
+       mxt->cdev.owner = THIS_MODULE;
+       mxt->cdev_messages.owner = THIS_MODULE;
+
+       error = cdev_add(&mxt->cdev, mxt->dev_num, 1);
+       if (error)
+               printk(KERN_WARNING "Bad cdev\n");
+
+       error = cdev_add(&mxt->cdev_messages, mxt->dev_num + 1, 1);
+       if (error)
+               printk(KERN_WARNING "Bad cdev\n");
+
+       dev_info(&mxt->client->dev, "cdev added\n");
+
+       device_create(mxt->mxt_class, NULL, MKDEV(MAJOR(mxt->dev_num), 0),
+                       NULL,
+                       "maXTouch");
+
+       device_create(mxt->mxt_class, NULL, MKDEV(MAJOR(mxt->dev_num), 1),
+                       NULL,
+                       "maXTouch_messages");
+
+       mxt->msg_buffer_startp = 0;
+       mxt->msg_buffer_endp = 0;
+#endif
+
+       mxt->prev_key = 0;
+
+       if (pdata->numtouch)
+               mxt->numtouch = pdata->numtouch;
+
+       mxt_initialize(mxt);
+
+       /* Allocate the interrupt */
+       dev_dbg(&mxt->client->dev,
+                       "maXTouch driver allocating interrupt...\n");
+       mxt->irq = gpio_to_irq(mxt->mxt_intr_gpio);
+       mxt->valid_irq_counter = 0;
+       mxt->invalid_irq_counter = 0;
+       mxt->irq_counter = 0;
+
+       if (mxt->irq) {
+               error = request_threaded_irq(mxt->irq, NULL,
+                                   mxt_irq_handler,
+                                   IRQF_TRIGGER_FALLING,
+                                   client->dev.driver->name,
+                                   mxt);
+               if (error < 0) {
+                       dev_err(&client->dev,
+                               "failed to allocate irq %d\n", mxt->irq);
+                       goto err_irq;
+               }
+       }
+
+       mutex_lock(&mxt->dev_mutex);
+       mxt_worker(mxt);
+       mutex_unlock(&mxt->dev_mutex);
+
+       kfree(id_data);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       mxt->suspended = FALSE;
+       mxt->T7[0] = 32;
+       mxt->T7[1] = 10;
+       mxt->T7[2] = 50;
+       mxt->es.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+       mxt->es.suspend = mxt_early_suspend;
+       mxt->es.resume = mxt_late_resume;
+
+       register_early_suspend(&mxt->es);
+       mxt_es = mxt;
+#endif
+
+       return 0;
+
+err_irq:
+       kfree(mxt->rid_map);
+       kfree(mxt->object_table);
+#ifdef DEBUG
+       kfree(mxt->last_message);
+#endif
+err_read_ot:
+err_register_key_device:
+err_register_touch_device:
+err_identify:
+err_pdata:
+       input_free_device(key_input);
+err_key_input_dev_alloc:
+       input_free_device(touch_input);
+err_touch_input_dev_alloc:
+       kfree(id_data);
+err_id_alloc:
+       if (mxt->exit_hw != NULL)
+               mxt->exit_hw();
+       kfree(mxt);
+err_mxt_alloc:
+       return error;
+}
+
+static int __devexit mxt_remove(struct i2c_client *client)
+{
+       struct mxt_data *mxt;
+
+       mxt = i2c_get_clientdata(client);
+
+       if (mxt != NULL) {
+               if (mxt->exit_hw != NULL)
+                       mxt->exit_hw();
+
+               if (mxt->irq)
+                       free_irq(mxt->irq, mxt);
+#ifdef DEBUG
+               /* Remove debug dir entries */
+               debugfs_remove_recursive(mxt->debug_dir);
+               unregister_chrdev_region(mxt->dev_num, 2);
+               device_destroy(mxt->mxt_class, MKDEV(MAJOR(mxt->dev_num), 0));
+               device_destroy(mxt->mxt_class, MKDEV(MAJOR(mxt->dev_num), 1));
+               cdev_del(&mxt->cdev);
+               cdev_del(&mxt->cdev_messages);
+               class_destroy(mxt->mxt_class);
+               debugfs_remove(mxt->debug_dir);
+               kfree(mxt->last_message);
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+               unregister_early_suspend(&mxt->es);
+#endif
+               input_unregister_device(mxt->key_input);
+               input_unregister_device(mxt->touch_input);
+               kfree(mxt->rid_map);
+               kfree(mxt->object_table);
+       }
+       kfree(mxt);
+
+       if (debug >= DEBUG_TRACE)
+               dev_info(&client->dev, "Touchscreen unregistered\n");
+
+       return 0;
+}
+
+#if defined(CONFIG_PM)
+static int mxt_suspend(struct device *dev)
+{
+       struct mxt_data *mxt = dev_get_drvdata(dev);
+
+       dev_dbg(&mxt->client->dev, "In function %s", __func__);
+
+       if (device_may_wakeup(dev))
+               enable_irq_wake(mxt->irq);
+
+       return 0;
+}
+
+static int mxt_resume(struct device *dev)
+{
+       struct mxt_data *mxt = dev_get_drvdata(dev);
+
+       dev_dbg(&mxt->client->dev, "In function %s", __func__);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(mxt->irq);
+
+       return 0;
+}
+#else
+#define mxt_suspend NULL
+#define mxt_resume NULL
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+void mxt_early_suspend(struct early_suspend *h)
+{
+       u16 addr;
+       u8 buf[3] = { 0 };
+       u8 err;
+
+       disable_irq(mxt_es->irq);
+
+       mutex_lock(&mxt_es->dev_mutex);
+
+       addr = get_object_address(MXT_GEN_POWERCONFIG_T7,
+                               0,
+                               mxt_es->object_table,
+                               mxt_es->device_info.num_objs);
+       mxt_read_block(mxt_es->client, addr, 3, mxt_es->T7);
+       err = mxt_write_block(mxt_es->client, addr, 3, buf);
+       if (err < 0)
+               dev_err(&mxt_es->client->dev, "fail to stop scan.\n");
+
+       /* clear touch state when suspending */
+       memset(stored_size, 0, mxt_es->numtouch * sizeof(stored_size[0]));
+       report_mt(mxt_es);
+
+       mxt_es->suspended = TRUE;
+
+       mutex_unlock(&mxt_es->dev_mutex);
+}
+
+void mxt_late_resume(struct early_suspend *h)
+{
+       int gpio_intr;
+
+       enable_irq(mxt_es->irq);
+
+       mutex_lock(&mxt_es->dev_mutex);
+       mxt_reset(mxt_es);
+
+       gpio_intr = gpio_get_value(mxt_es->mxt_intr_gpio);
+       if (gpio_intr == 0)
+               mxt_worker(mxt_es);
+
+       mxt_es->suspended = FALSE;
+       mutex_unlock(&mxt_es->dev_mutex);
+}
+#endif
+
+static const struct dev_pm_ops mxt_pm_ops = {
+       .suspend = mxt_suspend,
+       .resume = mxt_resume,
+};
+
+static const struct i2c_device_id mxt_idtable[] = {
+       {TOUCH_DEVICE_NAME, 1,},
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, mxt_idtable);
+
+static struct i2c_driver mxt_driver = {
+       .driver = {
+               .name   = TOUCH_DEVICE_NAME,
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm = &mxt_pm_ops,
+#endif
+       },
+
+       .id_table       = mxt_idtable,
+       .probe          = mxt_probe,
+       .remove         = __devexit_p(mxt_remove),
+};
+
+static int __init mxt_init(void)
+{
+       int err;
+
+       err = i2c_add_driver(&mxt_driver);
+       if (err) {
+               printk(KERN_WARNING "Adding maXTouch driver(Here for mxt224) failed "
+                      "(errno = %d)\n", err);
+       } else {
+               printk(KERN_INFO "Successfully added driver %s\n",
+                         mxt_driver.driver.name);
+       }
+       return err;
+}
+
+static void __exit mxt_cleanup(void)
+{
+       i2c_del_driver(&mxt_driver);
+}
+
+module_init(mxt_init);
+module_exit(mxt_cleanup);
+
+MODULE_AUTHOR("Iiro Valkonen");
+MODULE_DESCRIPTION("Driver for Atmel maXTouch Touchscreen Controller");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/atmel_mxt224.h b/include/linux/atmel_mxt224.h
new file mode 100644 (file)
index 0000000..7a3b99c
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ *  Atmel maXTouch header file
+ *
+ *  Copyright (c) 2010 Atmel Corporation
+ *  Copyright (C) 2010 Ulf Samuelsson (ulf@atmel.com)
+ *  Contains changes by Wind River Systems, 2010-09-29
+ *
+ *  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.
+ *
+ *  See the file "COPYING" in the main directory of this archive
+ *  for more details.
+ *
+ *  Modified by Richard Zhu(jianxin.zhu@borqs.com) 05/19/2011
+ */
+#include <linux/ioctl.h>
+
+#define        MXT224_I2C_ADDR1                                0x4A
+#define        MXT224_I2C_ADDR2                                0x4B
+#define        MXT1386_I2C_ADDR1                               0x4C
+#define        MXT1386_I2C_ADDR2                               0x4D
+#define        MXT1386_I2C_ADDR3                               0x5A
+#define        MXT1386_I2C_ADDR4                               0x5B
+
+/*
+ * Select this address from above depending on what maXTouch
+ * chip you have and how it's address pins are configured;
+ * see datasheet.
+ */
+
+#define MXT_I2C_ADDRESS                                 MXT224_I2C_ADDR1
+
+#define MXT_BL_ADDRESS                                  0x25
+
+#define        MXT224_FAMILYID                                 0x80
+#define MXT1386_FAMILYID                                0xA0
+
+#define        MXT224_CAL_VARIANTID                            0x01
+#define MXT224_UNCAL_VARIANTID                          0x00
+#define MXT1386_CAL_VARIANTID                           0x00
+
+#define MXT_MAX_REPORTED_WIDTH                          255
+#define MXT_MAX_REPORTED_PRESSURE                       255
+#define MXT_MAX_TOUCH_SIZE                              255
+#define MXT_MAX_NUM_TOUCHES                             10
+
+/* Fixed addresses inside maXTouch device */
+#define        MXT_ADDR_INFO_BLOCK                             0
+#define        MXT_ADDR_OBJECT_TABLE                           7
+#define MXT_ID_BLOCK_SIZE                               7
+#define        MXT_OBJECT_TABLE_ELEMENT_SIZE                   6
+
+/* Object types */
+#define        MXT_DEBUG_DELTAS_T2                             2
+#define        MXT_DEBUG_REFERENCES_T3                         3
+#define        MXT_GEN_MESSAGEPROCESSOR_T5                     5
+#define        MXT_GEN_COMMANDPROCESSOR_T6                     6
+#define        MXT_GEN_POWERCONFIG_T7                          7
+#define        MXT_GEN_ACQUIRECONFIG_T8                        8
+#define        MXT_TOUCH_MULTITOUCHSCREEN_T9                   9
+#define MXT_TOUCH_SINGLETOUCHSCREEN_T10                 10
+#define MXT_TOUCH_XSLIDER_T11                           11
+#define MXT_TOUCH_YSLIDER_T12                           12
+#define MXT_TOUCH_XWHEEL_T13                            13
+#define MXT_TOUCH_YWHEEL_T14                            14
+#define        MXT_TOUCH_KEYARRAY_T15                          15
+#define MXT_SPT_COMCONFIG_T18                          18
+#define        MXT_SPT_GPIOPWM_T19                             19
+#define        MXT_PROCI_GRIPFACESUPPRESSION_T20               20
+#define        MXT_PROCG_NOISESUPPRESSION_T22                  22
+#define        MXT_TOUCH_PROXIMITY_T23                         23
+#define        MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24          24
+#define        MXT_SPT_SELFTEST_T25                            25
+#define MXT_DEBUG_CTERANGE_T26                         26
+#define        MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27          27
+#define        MXT_SPT_CTECONFIG_T28                           28
+#define        MXT_TOUCH_KEYSET_T31                            31
+#define        MXT_TOUCH_XSLIDERSET_T32                        32
+#define        MXT_DEBUG_DIAGNOSTIC_T37                        37
+#define        MXT_USER_INFO_T38                               38
+
+
+/*
+ * If a message is read from mXT when there's no new messages available,
+ * the report ID of the message will be 0xFF.
+ */
+#define        MXT_END_OF_MESSAGES                             0xFF
+
+
+/* GEN_COMMANDPROCESSOR_T6 Register offsets from T6 base address */
+#define        MXT_ADR_T6_RESET                                0x00
+#define        MXT_ADR_T6_BACKUPNV                             0x01
+#define        MXT_ADR_T6_CALIBRATE                            0x02
+#define        MXT_ADR_T6_REPORTALL                            0x03
+#define        MXT_ADR_T6_RESERVED                             0x04
+#define        MXT_ADR_T6_DIAGNOSTIC                           0x05
+
+/* T6 Debug Diagnostics Commands */
+#define        MXT_CMD_T6_PAGE_UP          0x01
+#define        MXT_CMD_T6_PAGE_DOWN        0x02
+#define        MXT_CMD_T6_DELTAS_MODE      0x10
+#define        MXT_CMD_T6_REFERENCES_MODE  0x11
+#define        MXT_CMD_T6_CTE_MODE         0x31
+
+/* T6 Backup Command */
+#define MXT_CMD_T6_BACKUP           0x55
+
+/* SPT_DEBUG_DIAGNOSTIC_T37 Register offsets from T37 base address */
+#define MXT_ADR_T37_PAGE                                0x01
+#define        MXT_ADR_T37_DATA                                0x02
+
+
+
+/************************************************************************
+ * MESSAGE OBJECTS ADDRESS FIELDS
+ *
+ ************************************************************************/
+#define MXT_MSG_REPORTID                                0x00
+
+
+/* MXT_GEN_MESSAGEPROCESSOR_T5 Message address definitions             */
+#define        MXT_MSG_T5_REPORTID                             0x00
+#define        MXT_MSG_T5_MESSAGE                              0x01
+#define        MXT_MSG_T5_CHECKSUM                             0x08
+
+/* MXT_GEN_COMMANDPROCESSOR_T6 Message address definitions             */
+#define        MXT_MSG_T6_STATUS                               0x01
+#define                MXT_MSGB_T6_COMSERR             0x04
+#define                MXT_MSGB_T6_CFGERR              0x08
+#define                MXT_MSGB_T6_CAL                 0x10
+#define                MXT_MSGB_T6_SIGERR              0x20
+#define                MXT_MSGB_T6_OFL                 0x40
+#define                MXT_MSGB_T6_RESET               0x80
+/* Three bytes */
+#define        MXT_MSG_T6_CHECKSUM                             0x02
+
+/* MXT_GEN_POWERCONFIG_T7 NO Message address definitions               */
+/* MXT_GEN_ACQUIRECONFIG_T8 Message address definitions                        */
+/* MXT_TOUCH_MULTITOUCHSCREEN_T9 Message address definitions           */
+
+#define        MXT_MSG_T9_STATUS                               0x01
+/* Status bit field */
+#define                MXT_MSGB_T9_SUPPRESS            0x02
+#define                MXT_MSGB_T9_AMP                 0x04
+#define                MXT_MSGB_T9_VECTOR              0x08
+#define                MXT_MSGB_T9_MOVE                0x10
+#define                MXT_MSGB_T9_RELEASE             0x20
+#define                MXT_MSGB_T9_PRESS               0x40
+#define                MXT_MSGB_T9_DETECT              0x80
+
+#define        MXT_MSG_T9_XPOSMSB                              0x02
+#define        MXT_MSG_T9_YPOSMSB                              0x03
+#define        MXT_MSG_T9_XYPOSLSB                             0x04
+#define        MXT_MSG_T9_TCHAREA                              0x05
+#define        MXT_MSG_T9_TCHAMPLITUDE                         0x06
+#define        MXT_MSG_T9_TCHVECTOR                            0x07
+#define MXT_MSG_T9_ORIENT                              0x09
+/* ORIENT field settings. */
+#define MXT_MSGB_T9_ORIENT_NORMAL_ORIENT               0X00
+#define MXT_MSGB_T9_ORIENT_HORZ_FLIP                   0x02
+#define MXT_MSGB_T9_ORIENT_VERT_FLIP                   0x04
+#define MXT_MSGB_T9_ORIENT_ROTATE_180                  0x06
+#define MXT_MSGB_T9_ORIENT_DIAG_X0_Y0_XMAX_YMAX                0x01
+#define MXT_MSGB_T9_ORIENT_ROTATE_90_CCWISE            0x03
+#define MXT_MSGB_T9_ORIENT_ROTATE_90_CWISE             0x05
+#define MXT_MSGB_T9_ORIENT_DIAG_X0_YMAX_XMAX_Y0                0x07
+
+#define        MXT_ADR_T9_NUMTOUCH                             0x0e
+
+/* MXT_SPT_GPIOPWM_T19 Message address definitions                     */
+#define        MXT_MSG_T19_STATUS                              0x01
+
+/* MXT_PROCI_GRIPFACESUPPRESSION_T20 Message address definitions       */
+#define        MXT_MSG_T20_STATUS                              0x01
+#define                MXT_MSGB_T20_FACE_SUPPRESS      0x01
+/* MXT_PROCG_NOISESUPPRESSION_T22 Message address definitions          */
+#define        MXT_MSG_T22_STATUS                              0x01
+#define                MXT_MSGB_T22_FHCHG              0x01
+#define                MXT_MSGB_T22_GCAFERR            0x04
+#define                MXT_MSGB_T22_FHERR              0x08
+#define        MXT_MSG_T22_GCAFDEPTH                           0x02
+
+/* MXT_TOUCH_PROXIMITY_T23 Message address definitions                 */
+#define        MXT_MSG_T23_STATUS                              0x01
+#define                MXT_MSGB_T23_FALL               0x20
+#define                MXT_MSGB_T23_RISE               0x40
+#define                MXT_MSGB_T23_DETECT             0x80
+/* 16 bit */
+#define        MXT_MSG_T23_PROXDELTA                           0x02
+
+/* MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24 Message address definitions  */
+#define        MXT_MSG_T24_STATUS                              0x01
+#define        MXT_MSG_T24_XPOSMSB                             0x02
+#define        MXT_MSG_T24_YPOSMSB                             0x03
+#define        MXT_MSG_T24_XYPOSLSB                            0x04
+#define        MXT_MSG_T24_DIR                                 0x05
+/* 16 bit */
+#define        MXT_MSG_T24_DIST                                0x06
+
+/* MXT_SPT_SELFTEST_T25 Message address definitions                    */
+#define        MXT_ADR_T25_CTRL                                0x00
+#define        MXT_MSG_T25_STATUS                              0x01
+#define        MXT_ADR_T25_CMD                                 0x01
+
+/* 5 Bytes */
+#define                MXT_MSGR_T25_INVALID_TEST       0xFD
+#define                MXT_MSGR_T25_PIN_FAULT          0x11
+#define                MXT_MSGR_T25_SIGNAL_LIMIT_FAULT 0x17
+#define                MXT_MSGR_T25_GAIN_ERROR         0x20
+#define                MXT_MSGR_T25_RUN_ALL_TESTS      0xFE
+#define        MXT_MSG_T25_INFO                                0x02
+
+/* MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27 Message address definitions  */
+#define        MXT_MSG_T27_STATUS                      0x01
+#define                MXT_MSGB_T27_ROTATEDIR          0x10
+#define                MXT_MSGB_T27_PINCH              0x20
+#define                MXT_MSGB_T27_ROTATE             0x40
+#define                MXT_MSGB_T27_STRETCH            0x80
+#define        MXT_MSG_T27_XPOSMSB                     0x02
+#define        MXT_MSG_T27_YPOSMSB                     0x03
+#define        MXT_MSG_T27_XYPOSLSB                    0x04
+#define        MXT_MSG_T27_ANGLE                       0x05
+
+/* 16 bit */
+#define        MXT_MSG_T27_SEPARATION                          0x06
+
+/* MXT_SPT_CTECONFIG_T28 Message address definitions                   */
+#define        MXT_MSG_T28_STATUS                              0x01
+#define        MXT_MSGB_T28_CHKERR             0x01
+
+
+/* One Touch Events */
+#define        MXT_GESTURE_RESERVED            0x00
+#define        MXT_GESTURE_PRESS               0x01
+#define        MXT_GESTURE_RELEASE             0x02
+#define        MXT_GESTURE_TAP                 0x03
+#define        MXT_GESTURE_DOUBLE_TAP          0x04
+#define        MXT_GESTURE_FLICK               0x05
+#define        MXT_GESTURE_DRAG                0x06
+#define        MXT_GESTURE_SHORT_PRESS         0x07
+#define        MXT_GESTURE_LONG_PRESS          0x08
+#define        MXT_GESTURE_REPEAT_PRESS        0x09
+#define        MXT_GESTURE_TAP_AND_PRESS       0x0a
+#define        MXT_GESTURE_THROW               0x0b
+
+/* Two-touch events */
+#define MXT_GESTURE_STRETCH             (1 << 7)
+#define MXT_GESTURE_ROTATE              (1 << 6)
+#define MXT_GESTURE_PINCH               (1 << 5)
+#define MXT_GESTURE_ROTATEDIR           (1 << 4)
+
+
+
+/* Bootloader states */
+#define WAITING_BOOTLOAD_COMMAND   0xC0
+#define WAITING_FRAME_DATA         0x80
+#define APP_CRC_FAIL               0x40
+#define FRAME_CRC_CHECK            0x02
+#define FRAME_CRC_PASS             0x04
+#define FRAME_CRC_FAIL             0x03
+
+#define MXT_MAX_FRAME_SIZE         276
+
+/* Debug levels */
+#define DEBUG_INFO     1
+#define DEBUG_VERBOSE  2
+#define DEBUG_MESSAGES 5
+#define DEBUG_RAW      8
+#define DEBUG_TRACE   10
+
+/* IOCTL commands */
+/* TODO: get correct numbers! */
+#define MXT_IOC_MAGIC 'x'
+
+/* Sets the internal address pointer */
+#define MXT_SET_ADDRESS_IOCTL  _IO(MXT_IOC_MAGIC, 1)
+/* Resets the device */
+#define MXT_RESET_IOCTL        _IO(MXT_IOC_MAGIC, 2)
+/* Calibrates the device */
+#define MXT_CALIBRATE_IOCTL    _IO(MXT_IOC_MAGIC, 3)
+/* Backups the current state of registers to NVM */
+#define MXT_BACKUP_IOCTL       _IO(MXT_IOC_MAGIC, 4)
+/* Only non-touch messages can be read from the message buffer
+ * (/dev/maXTouch_messages)*/
+#define MXT_NONTOUCH_MSG_IOCTL _IO(MXT_IOC_MAGIC, 5)
+/* All messages can be read from the message buffer */
+#define MXT_ALL_MSG_IOCTL      _IO(MXT_IOC_MAGIC, 6)
+/* self test */
+#define MXT_SELF_TEST_IOCTL    _IO(MXT_IOC_MAGIC, 7)
+
+/* Message buffer size. This is a ring buffer, and when full, the oldest entry
+   will be overwritten. */
+#define MXT_MESSAGE_BUFFER_SIZE  128
+
+/* TODO: */
+/* Bootloader specific function prototypes. */
+#if 0
+static int mxt_read_byte_bl(struct i2c_client *client, u8 *value);
+static int mxt_read_block_bl(struct i2c_client *client, u16 length, u8 *value);
+static int mxt_write_byte_bl(struct i2c_client *client, u8 value);
+static int mxt_write_block_bl(struct i2c_client *client, u16 length, u8 *value);
+#endif
+
+/**
+ * struct mxt_platform_data - includes platform specific information
+ * related to Atmel maXTouch touchscreen controller.
+ *
+ * @numtouch:           Number of simultaneous touches supported
+ * @init_platform_hw(): Initialization function, which can for example
+ *                      trigger a hardware reset by toggling a GPIO pin
+ * @exit_platform_hw(): Function to run when the driver is unloaded.
+ * @valid_interrupt():  Function that checks the validity of the interrupt -
+ *                      function that check the validity of a interrupt (by
+ *                      reading the changeline interrupt pin and checking that
+ *                      it really is low for example).
+ * @max_x:              Reported X range
+ * @max_y:              Reported Y range
+ */
+
+struct mxt_platform_data {
+       u8    numtouch; /* Number of touches to report  */
+       void  (*init_platform_hw)(void);
+       void  (*exit_platform_hw)(void);
+       int   max_x;    /* The default reported X range   */
+       int   max_y;    /* The default reported Y range   */
+       int   orientation; /* The default orientation */
+       u8    (*valid_interrupt) (void);
+       u8    (*read_chg) (void);
+
+       u16   reset;
+       u16   irq;
+
+};
+
+void   mxt_hw_reset(void);
+
+#define TOUCH_DEVICE_NAME                              "atmel_mxt224"
+#define FALSE                           0
+#define TRUE                            1
+#define TS_MAX_X                                               1023
+#define TS_MIN_X                                               0
+#define TS_MAX_Y                                               1023
+#define TS_MIN_Y                                               0
+
+struct point_info{
+       int x;
+       int y;
+       int num;
+       int first_area;
+       int last_area;
+};
+
+enum touch_state {
+       NO_TOUCH = 0,
+       PRESS_TOUCH_AREA,
+};