MFLD_DV10: display and touchscreen support components
authorshenghua.lu <shenghua.lu@intel.com>
Thu, 5 Jan 2012 09:35:27 +0000 (17:35 +0800)
committerbuildbot <buildbot@intel.com>
Fri, 10 Feb 2012 23:39:29 +0000 (15:39 -0800)
BZ:20808

This commit contains the display and touchscreen driver
component changes necessary to support the MFLD DV10
tablet device..

Signed-off-by: Lu Shenghua <shenghua.lu@intel.com>
Change-Id: Ibb09c5de4144e8673c1a580f22ab376f08bbe90d
Reviewed-on: http://android.intel.com:8080/32093
Reviewed-by: Wood, Brian J <brian.j.wood@intel.com>
Reviewed-by: Seibel, Eric <eric.seibel@intel.com>
Tested-by: Seibel, Eric <eric.seibel@intel.com>
Tested-by: Wood, Brian J <brian.j.wood@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
23 files changed:
arch/x86/Kconfig
arch/x86/platform/mfld/Makefile
arch/x86/platform/mfld/board-redridge.c [new file with mode: 0644]
arch/x86/platform/mrst/mrst.c
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/staging/mrst/Kconfig
drivers/staging/mrst/drv/mdfld_dsi_dbi.c [changed mode: 0755->0644]
drivers/staging/mrst/drv/mdfld_dsi_dpi.c [changed mode: 0755->0644]
drivers/staging/mrst/drv/mdfld_dsi_dpi.h [changed mode: 0755->0644]
drivers/staging/mrst/drv/mdfld_dsi_lvds_bridge.c [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_lvds_bridge.h [new file with mode: 0644]
drivers/staging/mrst/drv/mdfld_dsi_output.c
drivers/staging/mrst/drv/mdfld_dsi_output.h [changed mode: 0755->0644]
drivers/staging/mrst/drv/mdfld_dsi_pkg_sender.c [changed mode: 0755->0644]
drivers/staging/mrst/drv/psb_drv.c
drivers/staging/mrst/drv/psb_intel_display2.c [changed mode: 0755->0644]
drivers/staging/mrst/drv/psb_intel_dsi.c
drivers/staging/mrst/drv/psb_powermgmt.c
drivers/staging/mrst/drv/tmd_vid.c
drivers/staging/mrst/drv/tpo_cmd.c [changed mode: 0755->0644]
drivers/staging/mrst/medfield/Makefile
include/linux/atmel_mxt_ts.h [new file with mode: 0644]
include/linux/i2c/tc35876x.h [new file with mode: 0644]

index 29f0c28..7cc3ce5 100644 (file)
@@ -435,6 +435,13 @@ config X86_MDFLD
          nor standard legacy replacement devices/features. e.g. Medfield does
          not contain i8259, i8254, HPET, legacy BIOS, most of the io ports.
 
+config BOARD_REDRIDGE
+   bool "Medfield redridge board type"
+   depends on X86_MDFLD
+   default n
+   ---help---
+     This option adds support for the Medfield RedRidge board type.
+
 endif
 
 config X86_RDC321X
index 8ebaaf4..beab5e6 100644 (file)
@@ -1,4 +1,8 @@
 CFLAGS_pmu.o        := -Werror
 
 obj-$(CONFIG_INTEL_MID_MDFLD_POWER)            += pmu.o
+ifneq ($(strip $(CONFIG_BOARD_REDRIDGE)),)
+obj-$(CONFIG_BOARD_REDRIDGE)   += board-redridge.o
+else
 obj-$(CONFIG_X86_MDFLD)                += blackbay_pr2.o
+endif
diff --git a/arch/x86/platform/mfld/board-redridge.c b/arch/x86/platform/mfld/board-redridge.c
new file mode 100644 (file)
index 0000000..54ccd6d
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * board-redridge.c: Intel Medfield platform RedRidge DV10 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/input/lis3dh.h>
+#include <linux/ms5607.h>
+#include <linux/a1026.h>
+#include <linux/i2c-gpio.h>
+#include <linux/lnw_gpio.h>
+#include <linux/atmel_mxt_ts.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       = 10,
+       .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       = "mxt1386",
+               .addr       = 0x4C,
+               .platform_data = &mxt_pdata,
+       },
+};
+
+static struct lis3dh_acc_platform_data lis3dh_pdata = {
+       .poll_interval = 200,
+       .negate_x = 1,
+       .negate_y = 0,
+       .negate_z = 0,
+       .axis_map_x = 0,
+       .axis_map_y = 1,
+       .axis_map_z = 2,
+       .gpio_int1 = 60,
+       .gpio_int2 = 61,
+};
+
+/* AUDIENCE es305 PLATFORM DATA */
+#define AUDIENCE_WAKEUP_GPIO               "audience-wakeup"
+#define AUDIENCE_RESET_GPIO                 "audience-reset"
+/* FIXME: Although a1026_platform_data has defined gpio number, but don't know
+ * why add reset/wakeup function in the platform_data structure.
+ * Currently set the gpio a fixed number, after changed driver code,
+ * will remove below global define */
+#define A1026_WAKEUP_GPIO      159
+#define A1026_RESET_GPIO       111
+
+static int audience_request_resources(struct i2c_client *client)
+{
+       struct a1026_platform_data *pdata = (struct a1026_platform_data *)
+               client->dev.platform_data;
+       int ret;
+
+       pr_debug("Audience: request ressource audience\n");
+       if (!pdata)
+               return -1;
+       ret = gpio_request(pdata->gpio_a1026_wakeup, AUDIENCE_WAKEUP_GPIO);
+       if (ret) {
+               dev_err(&client->dev, "Request AUDIENCE WAKEUP GPIO %d fails %d\n",
+                       pdata->gpio_a1026_wakeup, ret);
+               return -1;
+       }
+       ret = gpio_direction_output(pdata->gpio_a1026_wakeup, 0);
+       if (ret) {
+               dev_err(&client->dev, "Set GPIO Direction fails %d\n", ret);
+               goto err_wake;
+       }
+
+       ret = gpio_request(pdata->gpio_a1026_reset, AUDIENCE_RESET_GPIO);
+       if (ret) {
+               dev_err(&client->dev,
+                               "Request for Audience reset GPIO %d fails %d\n",
+                                       pdata->gpio_a1026_reset, ret);
+               goto err_wake;
+       }
+       ret = gpio_direction_output(pdata->gpio_a1026_reset, 0);
+       if (ret) {
+               dev_err(&client->dev, "Set GPIO Direction fails %d\n", ret);
+               goto err_reset;
+       }
+       if (mfld_board_id() == MFLD_BID_PR3 ||
+                       mfld_board_id() == MFLD_BID_PR3_PNP)
+               sprintf(pdata->firmware_name, "%s", "vpimg_es305b.bin");
+       else
+               sprintf(pdata->firmware_name, "%s", "vpimg.bin");
+
+       return 0;
+err_reset:
+       gpio_free(pdata->gpio_a1026_reset);
+err_wake:
+       gpio_free(pdata->gpio_a1026_wakeup);
+       return -1;
+}
+
+static void audience_free_resources(struct i2c_client *client)
+{
+       struct a1026_platform_data *pdata = (struct a1026_platform_data *)
+               &client->dev.platform_data;
+
+       gpio_free(pdata->gpio_a1026_wakeup);
+       gpio_free(pdata->gpio_a1026_reset);
+}
+
+static void audience_wake_up(bool state)
+{
+       gpio_set_value(A1026_WAKEUP_GPIO, state);
+       pr_debug("Audience: WAKE UP %d\n", state);
+}
+
+static void audience_reset(bool state)
+{
+       gpio_set_value(A1026_RESET_GPIO, state);
+       pr_debug("Audience: RESET %d\n", state);
+}
+
+static struct a1026_platform_data mfld_audience_platform_data = {
+       .gpio_a1026_wakeup      = A1026_WAKEUP_GPIO,
+       .gpio_a1026_reset       = A1026_RESET_GPIO,
+       .request_resources      = audience_request_resources,
+       .wakeup                 = audience_wake_up,
+       .reset                  = audience_reset,
+};
+
+static struct ms5607_platform_data baro_pdata = {
+       .poll_interval = 100,
+       .min_interval  = 0,
+};
+
+#define LTR502_GPIO 63
+#define MPU_GPIO_PIN 56
+
+static struct i2c_board_info pr2_i2c_bus5_devs[] = {
+       {
+               .type           = "accel",
+               .irq            = 0xff,
+               .addr           = 0x18,
+               .platform_data  = &lis3dh_pdata,
+       },
+       {
+               .type           = "compass",
+               .irq            = 0xff,
+               .addr           = 0x1E,
+       },
+       {
+               .type           = "gyro",
+               .irq            = MPU_GPIO_PIN,
+               .addr           = 0x68,
+       },
+       {
+               .type           = "baro",
+               .irq            = 0xff,
+               .addr           = 0x77,
+               .platform_data  = &baro_pdata,
+       },
+       {
+               .type           = "als",
+               .irq            = LTR502_GPIO,
+               .addr           = 0x1d,
+       },
+       {
+               .type           = "audience_es305",
+               .irq            = 0xff,
+               .addr           = 0x3e,
+               .platform_data  = &mfld_audience_platform_data,
+       },
+};
+
+static void register_board_i2c_devs()
+{
+       i2c_register_board_info(0, pr2_i2c_bus0_devs,
+                               ARRAY_SIZE(pr2_i2c_bus0_devs));
+       i2c_register_board_info(5, pr2_i2c_bus5_devs,
+                               ARRAY_SIZE(pr2_i2c_bus5_devs));
+}
+static int __init platform_bkbpr2_subsys_init(void)
+{
+       switch (mfld_board_id()) {
+       case MFLD_BID_PR2_PROTO:
+       case MFLD_BID_PR2_PNP:
+       case MFLD_BID_PR2_VOLUME:
+       case MFLD_BID_PR3:
+       case MFLD_BID_PR3_PNP:
+               register_board_i2c_devs();
+               return 0;
+       default:
+               return 1;
+       }
+}
+device_initcall(platform_bkbpr2_subsys_init);
+
+static int hdmi_i2c_workaround(void)
+{
+       int ret;
+       struct platform_device *pdev;
+       struct i2c_gpio_platform_data *pdata;
+
+       /*
+        * Hard code a gpio controller platform device to take over
+        * the two gpio pins used to be controlled by i2c bus 3.
+        * This is to support HDMI EDID extension block read, which
+        * is not supported by the current i2c controller, so we use
+        * GPIO pin the simulate an i2c bus.
+        */
+       pdev = platform_device_alloc("i2c-gpio", 8);
+       if (!pdev) {
+               pr_err("i2c-gpio: failed to alloc platform device\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       pdata = kzalloc(sizeof(struct i2c_gpio_platform_data), GFP_KERNEL);
+       if (!pdata) {
+               pr_err("i2c-gpio: failed to alloc platform data\n");
+               kfree(pdev);
+               ret = -ENOMEM;
+               goto out;
+       }
+       pdata->scl_pin = 35 + 96;
+       pdata->sda_pin = 36 + 96;
+       pdata->sda_is_open_drain = 0;
+       pdata->scl_is_open_drain = 0;
+       pdev->dev.platform_data = pdata;
+
+       platform_device_add(pdev);
+
+       lnw_gpio_set_alt(pdata->sda_pin, LNW_GPIO);
+       lnw_gpio_set_alt(pdata->scl_pin, LNW_GPIO);
+
+out:
+       return ret;
+}
+rootfs_initcall(hdmi_i2c_workaround);
index 388d89e..c5bfd6e 100644 (file)
@@ -68,7 +68,7 @@
 #include <asm/apb_timer.h>
 #include <asm/intel_mid_gpadc.h>
 #include <asm/reboot.h>
-
+#include <linux/i2c/tc35876x.h>
 /*
  * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
  * cmdline option x86_mrst_timer can be used to override the configuration
@@ -482,6 +482,15 @@ static int get_gpio_by_name(const char *name)
        }
        return -1;
 }
+/*tc35876x DSI_LVDS bridge chip and panel platform data*/
+static void *tc35876x_platform_data(void *data)
+{
+       static struct tc35876x_platform_data pdata;
+       pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN");
+       pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN");
+       pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3");
+       return &pdata;
+}
 
 /*
  * Here defines the array of devices platform data that IAFW would export
@@ -1753,6 +1762,7 @@ static const struct devs_id __initconst device_ids[] = {
        {"mt9m114", SFI_DEV_TYPE_I2C, 0, &mt9m114_platform_data_init},
        {"mxt224", SFI_DEV_TYPE_I2C, 0, &atmel_mxt224_platform_data_init},
        {"synaptics_3202", SFI_DEV_TYPE_I2C, 0, &s3202_platform_data_init},
+       {"i2c_disp_brig", SFI_DEV_TYPE_I2C, 0, &tc35876x_platform_data},
        {},
 };
 
@@ -2230,7 +2240,6 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
                        ;
                }
        }
-
 #ifdef CONFIG_LEDS_INTEL_KPD
        pdev = platform_device_alloc("intel_kpd_led", 0);
        if (!pdev)
@@ -2242,7 +2251,6 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
                intel_scu_device_register(pdev);
        }
 #endif
-
        return 0;
 }
 
index 1e61387..0b5b646 100644 (file)
 /*
- * Atmel maXTouch Touchscreen driver
+ *  Atmel maXTouch Touchscreen Controller Driver
  *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
  *
- * 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;  either version 2 of the  License, or (at your
- * option) any later version.
+ *  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.
  *
  */
 
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
 #include <linux/i2c.h>
-#include <linux/i2c/atmel_mxt_ts.h>
-#include <linux/input/mt.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/gpio.h>
+#include <linux/earlysuspend.h>
+#include <linux/pm_runtime.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+#include <linux/atmel_mxt_ts.h>
+
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <asm/io.h>
+/* 1-->WINTEK  0-->SINTEK */
+#define TOUCH_PANEL_IS_WINTEK 0
+#define MAGIC_PRODUCT_T38_BYTE7_WINTEK 0x02
+#define MAGIC_PRODUCT_T38_BYTE7_SINTEK 0x03
+#if TOUCH_PANEL_IS_WINTEK
+#define MAGIC_PRODUCT_T38_BYTE7 MAGIC_PRODUCT_T38_BYTE7_WINTEK
+#else /* SINTEK */
+#define MAGIC_PRODUCT_T38_BYTE7 MAGIC_PRODUCT_T38_BYTE7_SINTEK
+#endif
 
-/* Version */
-#define MXT_VER_20             20
-#define MXT_VER_21             21
-#define MXT_VER_22             22
-
-/* Slave addresses */
-#define MXT_APP_LOW            0x4a
-#define MXT_APP_HIGH           0x4b
-#define MXT_BOOT_LOW           0x24
-#define MXT_BOOT_HIGH          0x25
-
-/* Firmware */
-#define MXT_FW_NAME            "maxtouch.fw"
-
-/* Registers */
-#define MXT_FAMILY_ID          0x00
-#define MXT_VARIANT_ID         0x01
-#define MXT_VERSION            0x02
-#define MXT_BUILD              0x03
-#define MXT_MATRIX_X_SIZE      0x04
-#define MXT_MATRIX_Y_SIZE      0x05
-#define MXT_OBJECT_NUM         0x06
-#define MXT_OBJECT_START       0x07
-
-#define MXT_OBJECT_SIZE                6
-
-/* Object types */
-#define MXT_DEBUG_DIAGNOSTIC   37
-#define MXT_GEN_MESSAGE                5
-#define MXT_GEN_COMMAND                6
-#define MXT_GEN_POWER          7
-#define MXT_GEN_ACQUIRE                8
-#define MXT_TOUCH_MULTI                9
-#define MXT_TOUCH_KEYARRAY     15
-#define MXT_TOUCH_PROXIMITY    23
-#define MXT_PROCI_GRIPFACE     20
-#define MXT_PROCG_NOISE                22
-#define MXT_PROCI_ONETOUCH     24
-#define MXT_PROCI_TWOTOUCH     27
-#define MXT_PROCI_GRIP         40
-#define MXT_PROCI_PALM         41
-#define MXT_SPT_COMMSCONFIG    18
-#define MXT_SPT_GPIOPWM                19
-#define MXT_SPT_SELFTEST       25
-#define MXT_SPT_CTECONFIG      28
-#define MXT_SPT_USERDATA       38
-#define MXT_SPT_DIGITIZER      43
-#define MXT_SPT_MESSAGECOUNT   44
-
-/* MXT_GEN_COMMAND field */
-#define MXT_COMMAND_RESET      0
-#define MXT_COMMAND_BACKUPNV   1
-#define MXT_COMMAND_CALIBRATE  2
-#define MXT_COMMAND_REPORTALL  3
-#define MXT_COMMAND_DIAGNOSTIC 5
-
-/* MXT_GEN_POWER field */
-#define MXT_POWER_IDLEACQINT   0
-#define MXT_POWER_ACTVACQINT   1
-#define MXT_POWER_ACTV2IDLETO  2
-
-/* MXT_GEN_ACQUIRE field */
-#define MXT_ACQUIRE_CHRGTIME   0
-#define MXT_ACQUIRE_TCHDRIFT   2
-#define MXT_ACQUIRE_DRIFTST    3
-#define MXT_ACQUIRE_TCHAUTOCAL 4
-#define MXT_ACQUIRE_SYNC       5
-#define MXT_ACQUIRE_ATCHCALST  6
-#define MXT_ACQUIRE_ATCHCALSTHR        7
-
-/* MXT_TOUCH_MULTI field */
-#define MXT_TOUCH_CTRL         0
-#define MXT_TOUCH_XORIGIN      1
-#define MXT_TOUCH_YORIGIN      2
-#define MXT_TOUCH_XSIZE                3
-#define MXT_TOUCH_YSIZE                4
-#define MXT_TOUCH_BLEN         6
-#define MXT_TOUCH_TCHTHR       7
-#define MXT_TOUCH_TCHDI                8
-#define MXT_TOUCH_ORIENT       9
-#define MXT_TOUCH_MOVHYSTI     11
-#define MXT_TOUCH_MOVHYSTN     12
-#define MXT_TOUCH_NUMTOUCH     14
-#define MXT_TOUCH_MRGHYST      15
-#define MXT_TOUCH_MRGTHR       16
-#define MXT_TOUCH_AMPHYST      17
-#define MXT_TOUCH_XRANGE_LSB   18
-#define MXT_TOUCH_XRANGE_MSB   19
-#define MXT_TOUCH_YRANGE_LSB   20
-#define MXT_TOUCH_YRANGE_MSB   21
-#define MXT_TOUCH_XLOCLIP      22
-#define MXT_TOUCH_XHICLIP      23
-#define MXT_TOUCH_YLOCLIP      24
-#define MXT_TOUCH_YHICLIP      25
-#define MXT_TOUCH_XEDGECTRL    26
-#define MXT_TOUCH_XEDGEDIST    27
-#define MXT_TOUCH_YEDGECTRL    28
-#define MXT_TOUCH_YEDGEDIST    29
-#define MXT_TOUCH_JUMPLIMIT    30
-
-/* MXT_PROCI_GRIPFACE field */
-#define MXT_GRIPFACE_CTRL      0
-#define MXT_GRIPFACE_XLOGRIP   1
-#define MXT_GRIPFACE_XHIGRIP   2
-#define MXT_GRIPFACE_YLOGRIP   3
-#define MXT_GRIPFACE_YHIGRIP   4
-#define MXT_GRIPFACE_MAXTCHS   5
-#define MXT_GRIPFACE_SZTHR1    7
-#define MXT_GRIPFACE_SZTHR2    8
-#define MXT_GRIPFACE_SHPTHR1   9
-#define MXT_GRIPFACE_SHPTHR2   10
-#define MXT_GRIPFACE_SUPEXTTO  11
-
-/* MXT_PROCI_NOISE field */
-#define MXT_NOISE_CTRL         0
-#define MXT_NOISE_OUTFLEN      1
-#define MXT_NOISE_GCAFUL_LSB   3
-#define MXT_NOISE_GCAFUL_MSB   4
-#define MXT_NOISE_GCAFLL_LSB   5
-#define MXT_NOISE_GCAFLL_MSB   6
-#define MXT_NOISE_ACTVGCAFVALID        7
-#define MXT_NOISE_NOISETHR     8
-#define MXT_NOISE_FREQHOPSCALE 10
-#define MXT_NOISE_FREQ0                11
-#define MXT_NOISE_FREQ1                12
-#define MXT_NOISE_FREQ2                13
-#define MXT_NOISE_FREQ3                14
-#define MXT_NOISE_FREQ4                15
-#define MXT_NOISE_IDLEGCAFVALID        16
-
-/* MXT_SPT_COMMSCONFIG */
-#define MXT_COMMS_CTRL         0
-#define MXT_COMMS_CMD          1
-
-/* MXT_SPT_CTECONFIG field */
-#define MXT_CTE_CTRL           0
-#define MXT_CTE_CMD            1
-#define MXT_CTE_MODE           2
-#define MXT_CTE_IDLEGCAFDEPTH  3
-#define MXT_CTE_ACTVGCAFDEPTH  4
-#define MXT_CTE_VOLTAGE                5
-
-#define MXT_VOLTAGE_DEFAULT    2700000
-#define MXT_VOLTAGE_STEP       10000
-
-/* Define for MXT_GEN_COMMAND */
-#define MXT_BOOT_VALUE         0xa5
-#define MXT_BACKUP_VALUE       0x55
-#define MXT_BACKUP_TIME                25      /* msec */
-#define MXT_RESET_TIME         65      /* msec */
-
-#define MXT_FWRESET_TIME       175     /* msec */
-
-/* Command to unlock bootloader */
-#define MXT_UNLOCK_CMD_MSB     0xaa
-#define MXT_UNLOCK_CMD_LSB     0xdc
-
-/* Bootloader mode status */
-#define MXT_WAITING_BOOTLOAD_CMD       0xc0    /* valid 7 6 bit only */
-#define MXT_WAITING_FRAME_DATA 0x80    /* valid 7 6 bit only */
-#define MXT_FRAME_CRC_CHECK    0x02
-#define MXT_FRAME_CRC_FAIL     0x03
-#define MXT_FRAME_CRC_PASS     0x04
-#define MXT_APP_CRC_FAIL       0x40    /* valid 7 8 bit only */
-#define MXT_BOOT_STATUS_MASK   0x3f
-
-/* Touch status */
-#define MXT_SUPPRESS           (1 << 1)
-#define MXT_AMP                        (1 << 2)
-#define MXT_VECTOR             (1 << 3)
-#define MXT_MOVE               (1 << 4)
-#define MXT_RELEASE            (1 << 5)
-#define MXT_PRESS              (1 << 6)
-#define MXT_DETECT             (1 << 7)
-
-/* Touch orient bits */
-#define MXT_XY_SWITCH          (1 << 0)
-#define MXT_X_INVERT           (1 << 1)
-#define MXT_Y_INVERT           (1 << 2)
-
-/* Touchscreen absolute values */
-#define MXT_MAX_AREA           0xff
-
-#define MXT_MAX_FINGER         10
-
-struct mxt_info {
-       u8 family_id;
-       u8 variant_id;
-       u8 version;
-       u8 build;
-       u8 matrix_xsize;
-       u8 matrix_ysize;
-       u8 object_num;
+/* Routines for memory access within a 16 bit address space */
+static void mxt_calibrate(struct i2c_client *client);
+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
+
+#ifdef CONFIG_DEBUG_FS
+static int  intel_mid_add_debugfs(void);
+static unsigned char reg_add = 0;
+static unsigned char reg_add_offset = 0;
+#endif
+
+#define DRIVER_VERSION "0.9a"
+#define MULTI_TOUCH_ENABLED 1
+#define MXT_RESET_DELAY   65 /* ms */
+static int debug = DEBUG_INFO;
+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 int iForceUpdateConfigValue = 0;
+static struct mxt_data *mxt_es;
+/* For backup NVM */
+u8 mxt_debug = 1;
+u16 T6_addr;
+u16 T38_addr;
+u8 v20_T38[] = { 11, 10, 26, 1, 0, 0, 0, MAGIC_PRODUCT_T38_BYTE7 };
+u8 arg1 = 0;
+u8 arg2 = 0;
+u8 mxt_cmd = 0;
+u16 low_boundary = 0;
+u16 high_boundary = 0;
+u8 slave_addr = MXT1386_I2C_ADDR1;
+
+/* 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 {
-       u8 type;
-       u16 start_address;
-       u8 size;
-       u8 instances;
-       u8 num_report_ids;
-
-       /* to map object and message */
-       u8 max_reportid;
+       u16 chip_addr;
+       u8  type;
+       u8  size;
+       u8  instances;
+       u8  num_report_ids;
 };
 
-struct mxt_message {
-       u8 reportid;
-       u8 message[7];
-       u8 checksum;
-};
 
-struct mxt_finger {
-       int status;
-       int x;
-       int y;
-       int area;
+/* 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;
 };
 
-/* Each client has this additional data */
+
+/* Driver datastructure */
 struct mxt_data {
-       struct i2c_client *client;
-       struct input_dev *input_dev;
-       const struct mxt_platform_data *pdata;
-       struct mxt_object *object_table;
-       struct mxt_info info;
-       struct mxt_finger finger[MXT_MAX_FINGER];
-       unsigned int irq;
-       unsigned int max_x;
-       unsigned int max_y;
+       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
+       /* 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;
+
+       u8                   *message_buf;
+       int                  recal_flag;
+       u64                  timestamp;
+       u16                  finger_pressed;
+       u8                   finger_count;
+       u8                   first_pressed;
+       u8                   grip_suppression;
+       u8                   face_suppression;
+
+       struct point_info    pre_data[10];
+};
+
+/*
+ * 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",
+       [18] = "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",
 };
 
-static bool mxt_object_readable(unsigned int type)
+/*
+ * All entries spare upto 255
+ */
+#define RESERVED_T255                             255u
+void mxt_config_init(struct mxt_data *mxt)
 {
-       switch (type) {
-       case MXT_GEN_MESSAGE:
-       case MXT_GEN_COMMAND:
-       case MXT_GEN_POWER:
-       case MXT_GEN_ACQUIRE:
-       case MXT_TOUCH_MULTI:
-       case MXT_TOUCH_KEYARRAY:
-       case MXT_TOUCH_PROXIMITY:
-       case MXT_PROCI_GRIPFACE:
-       case MXT_PROCG_NOISE:
-       case MXT_PROCI_ONETOUCH:
-       case MXT_PROCI_TWOTOUCH:
-       case MXT_PROCI_GRIP:
-       case MXT_PROCI_PALM:
-       case MXT_SPT_COMMSCONFIG:
-       case MXT_SPT_GPIOPWM:
-       case MXT_SPT_SELFTEST:
-       case MXT_SPT_CTECONFIG:
-       case MXT_SPT_USERDATA:
-               return true;
-       default:
-               return false;
+       int err = 0;
+       dev_info(&mxt->client->dev, "In function %s", __func__);
+       /* Fix for current comsumption. */
+       u8 v20_T7[] = { 32, 16, 50 };
+       u8 v20_T8[]  = { 10, 0, 15, 15, 0, 0, 5, 45, 10, 192 };
+#if TOUCH_PANEL_IS_WINTEK
+       u8 v20_T9[] = { 143, 0, 0, 27, 42, 0, 16, 60, 3, 3, 0, 0, 3, 14, 10, 20,
+               20, 10, 31, 3, 255, 4, 0, 0, 0, 0, 0, 0, 64, 0, 15, 15,
+               49, 52 };
+#else /* SINTEK */
+       u8 v20_T9[] = { 143, 0, 0, 28, 42, 0, 16, 60, 3, 3, 0, 0, 3, 14, 10, 20,
+               20, 10, 31, 3, 255, 4, 0, 0, 0, 0, 0, 0, 64, 0, 15, 15,
+               49, 52 };
+#endif
+
+       u8 v20_T15[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+       u8 v20_T18[] = { 0, 0 };
+       u8 v20_T22[] = { 5, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 15, 25, 35, 255, 255,
+               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[] = { 3, 0, 248, 42, 112, 23, 0, 0, 0, 0, 0, 0, 0, 0 };
+       u8 v20_T27[] = { 0, 0, 0, 0, 0, 0, 0 };
+       u8 v20_T28[] = { 0, 0, 0, 8, 16, 60 };
+       u8 v20_T40[] = { 0, 0, 0, 0, 0 };
+       u8 v20_T41[] = { 1, 0, 0, 35, 5, 20, 170 };
+       u8 v20_T43[] = { 0, 0, 0, 0, 0, 0 };
+
+       if (slave_addr == MXT1386_I2C_ADDR2) { /* 0X4C means Wintek and 0x4D means Sintek */
+               v20_T9[3] = 28;
+               v20_T22[8] = 20;
        }
-}
 
-static bool mxt_object_writable(unsigned int type)
-{
-       switch (type) {
-       case MXT_GEN_COMMAND:
-       case MXT_GEN_POWER:
-       case MXT_GEN_ACQUIRE:
-       case MXT_TOUCH_MULTI:
-       case MXT_TOUCH_KEYARRAY:
-       case MXT_TOUCH_PROXIMITY:
-       case MXT_PROCI_GRIPFACE:
-       case MXT_PROCG_NOISE:
-       case MXT_PROCI_ONETOUCH:
-       case MXT_PROCI_TWOTOUCH:
-       case MXT_PROCI_GRIP:
-       case MXT_PROCI_PALM:
-       case MXT_SPT_GPIOPWM:
-       case MXT_SPT_SELFTEST:
-       case MXT_SPT_CTECONFIG:
-               return true;
-       default:
-               return false;
+       u8 i = 0, max_objs = 0, j = 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;
+               for (j = 1; j < I2C_RETRY_COUNT; j++) {
+                       err = 1;
+                       switch (obj_index->type) {
+                       case MXT_GEN_POWERCONFIG_T7:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T7), v20_T7);
+                               break;
+                       case MXT_GEN_ACQUIRECONFIG_T8:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T8), v20_T8);
+                               break;
+                       case MXT_TOUCH_MULTITOUCHSCREEN_T9:
+                               err = 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:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T15), v20_T15);
+                               break;
+                       case MXT_SPT_COMMSCONFIG_T18:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T18), v20_T18);
+                               break;
+                       case MXT_PROCG_NOISESUPPRESSION_T22:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T22), v20_T22);
+                               break;
+                       case MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T24), v20_T24);
+                               break;
+                       case MXT_SPT_SELFTEST_T25:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T25), v20_T25);
+                               break;
+                       case MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T27), v20_T27);
+                       break;
+                       case MXT_SPT_CTECONFIG_T28:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T28), v20_T28);
+                       break;
+                       case MXT_USER_INFO_T38:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T38), v20_T38);
+                               break;
+                       case MXT_PROCI_GRIPSUPPRESSION_T40:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T40), v20_T40);
+                               break;
+                       case MXT_PROCI_PALMSUPPRESSION_T41:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T41), v20_T41);
+                               break;
+                       case MXT_SPT_DIGITIZER_T43:
+                               err = mxt_write_block(mxt->client, addr, sizeof(v20_T43), v20_T43);
+                               break;
+                       default:
+                               break;
+                       }
+                       if (err > 0)
+                               break;
+               }
+               if (j >= I2C_RETRY_COUNT)
+                       dev_info(&mxt->client->dev,
+                               "touch: config init abnormal,obj_index's type is %d",
+                               obj_index->type);
+
+               obj_index++;
        }
+       mxt_calibrate(mxt->client);
+       dev_dbg(&mxt->client->dev, "config init Done.");
 }
 
-static void mxt_dump_message(struct device *dev,
-                                 struct mxt_message *message)
+/* 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)
 {
-       dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
-       dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
-       dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
-       dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
-       dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
-       dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
-       dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
-       dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
-       dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
+       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;
 }
 
-static int mxt_check_bootloader(struct i2c_client *client,
-                                    unsigned int state)
+int BackupNVM(struct mxt_data *mxt)
 {
-       u8 val;
+       u8 buf[1] = {0x55};
+       u8 T38_buf[8] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+
+       /* Backup the non-volatile memory (NVM). */
+       T6_addr = get_object_address(MXT_GEN_COMMANDPROCESSOR_T6, 0,
+                       mxt->object_table, mxt->device_info.num_objs);
+       T38_addr = get_object_address(MXT_USER_INFO_T38, 0,
+                       mxt->object_table, mxt->device_info.num_objs);
+
+       pr_info("BackupNVM T6_addr+1=0x%4x, T38_addr=0x%4x.\n", T6_addr+1, T38_addr);
+       mxt_read_block(mxt->client, T38_addr, sizeof(T38_buf), T38_buf);
+
+       if (iForceUpdateConfigValue == 1) {
+                       pr_info("%s force update. ver=%d.%d.%d.%d --> %d.%d.%d.%d\n", \
+                       __func__,                                         \
+                       T38_buf[0], T38_buf[1], T38_buf[2], T38_buf[3],   \
+                       v20_T38[0], v20_T38[1], v20_T38[2], v20_T38[3]);
+       } else {
+               #define PRINT_T38_V20() do {                                      \
+                       pr_info("%s not update. ver=%d.%d.%d.%d (%d)> %d.%d.%d.%d  (%d)\n", \
+                       __func__,                                         \
+                       T38_buf[0], T38_buf[1], T38_buf[2], T38_buf[3], T38_buf[7],  \
+                       v20_T38[0], v20_T38[1], v20_T38[2], v20_T38[3], v20_T38[7]);  \
+               } while (0)
+
+               /* Check T38 previous config version. */
+               if ((T38_buf[0] != 0 && T38_buf[1] != 0) &&
+                       (T38_buf[2] != 0 && T38_buf[3] != 0) &&
+                       (T38_buf[4] == 0 && T38_buf[5] == 0) &&
+                       (T38_buf[6] == 0 && T38_buf[7] == MAGIC_PRODUCT_T38_BYTE7)) {
+                       if (T38_buf[0] > v20_T38[0]) {
+                               PRINT_T38_V20();
+                               return 0;
+                       } else if (T38_buf[0] == v20_T38[0]) {
+                               if (T38_buf[1] > v20_T38[1]) {
+                                       PRINT_T38_V20();
+                                       return 0;
+                               } else if (T38_buf[1] == v20_T38[1]) {
+                                       if (T38_buf[2] > v20_T38[2]) {
+                                               PRINT_T38_V20();
+                                               return 0;
+                                       } else if (T38_buf[2] == v20_T38[2]) {
+                                               if  (T38_buf[3] >= v20_T38[3]) {
+                                                       PRINT_T38_V20();
+                                                       return 0;
+                                               }
+                                       }
+                               }
+                       }
+               } else {
+                        if (T38_buf[7] != MAGIC_PRODUCT_T38_BYTE7) {
+                               pr_info("%s  PRODUCT_T38_BYTE7 diff, force update. ver=%d.%d.%d.%d(%d) --> %d.%d.%d.%d(%d)\n", \
+                               __func__,                                         \
+                               T38_buf[0], T38_buf[1], T38_buf[2], T38_buf[3], T38_buf[7],  \
+                               v20_T38[0], v20_T38[1], v20_T38[2], v20_T38[3], v20_T38[7]);
+                        }
 
-recheck:
-       if (i2c_master_recv(client, &val, 1) != 1) {
-               dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
-               return -EIO;
+               }
+               #undef PRINT_T38_V20
        }
 
-       switch (state) {
-       case MXT_WAITING_BOOTLOAD_CMD:
-       case MXT_WAITING_FRAME_DATA:
-               val &= ~MXT_BOOT_STATUS_MASK;
-               break;
-       case MXT_FRAME_CRC_PASS:
-               if (val == MXT_FRAME_CRC_CHECK)
-                       goto recheck;
-               break;
-       default:
-               return -EINVAL;
+       mxt_config_init(mxt);
+
+       if (mxt_write_block(mxt->client, T6_addr+1, sizeof(buf), buf) == 1)
+               pr_info("Backup the configurations to non-volatile memory.\n");
+       else {
+               pr_err("Backup the configurations to non-volatile memory failed!!!\n");
+               return -1;
        }
 
-       if (val != state) {
-               dev_err(&client->dev, "Unvalid bootloader mode state\n");
-               return -EINVAL;
+       /*Reset the IC.*/
+       if (mxt_write_block(mxt->client, T6_addr, sizeof(buf), buf) == 1)
+               pr_info("Software reset the IC.\n");
+       else {
+               pr_err("Software reset the IC failed!!!\n");
+               return -1;
        }
 
+       msleep(400);
+       pr_info("BackupNVM done. ver=%d.%d.%d.%d\n", v20_T38[0], v20_T38[1], v20_T38[2], v20_T38[3]);
        return 0;
 }
 
-static int mxt_unlock_bootloader(struct i2c_client *client)
+/* Calculates the 24-bit CRC sum. */
+static u32 CRC_24(u32 crc, u8 byte1, u8 byte2)
 {
-       u8 buf[2];
+       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;
+}
 
-       buf[0] = MXT_UNLOCK_CMD_LSB;
-       buf[1] = MXT_UNLOCK_CMD_MSB;
+/* Calibrate rz*/
+static void mxt_calibrate(struct i2c_client *client)
+{
+       u16 base_addr;
+       struct mxt_data *mxt;
 
-       if (i2c_master_send(client, buf, 2) != 2) {
-               dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-               return -EIO;
-       }
+       mxt = i2c_get_clientdata(client);
+       dev_dbg(&mxt->client->dev, "In function %s", __func__);
 
-       return 0;
+       base_addr = get_object_address(MXT_GEN_COMMANDPROCESSOR_T6,
+                               0, mxt->object_table,
+                               mxt->device_info.num_objs);
+       base_addr += MXT_ADR_T6_CALIBRATE;
+       mxt_write_byte(mxt->client, base_addr, 0x55);
 }
 
-static int mxt_fw_write(struct i2c_client *client,
-                            const u8 *data, unsigned int frame_size)
+
+/*
+ * 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)
 {
-       if (i2c_master_send(client, data, frame_size) != frame_size) {
-               dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-               return -EIO;
+       struct i2c_adapter *adapter = client->adapter;
+       struct i2c_msg msg[2];
+       __le16  le_addr;
+       struct mxt_data *mxt;
+       int err;
+
+       mxt = i2c_get_clientdata(client);
+
+       if (mxt != NULL) {
+               if ((mxt->last_read_addr == addr) &&
+                       (addr == mxt->msg_proc_addr)) {
+                       pm_runtime_get_sync(&client->dev);
+                       if  (i2c_master_recv(client, value, length) == length)
+                               err = length;
+                       else
+                               err = -EIO;
+                       pm_runtime_put(&client->dev);
+                       return err;
+               } else {
+                       mxt->last_read_addr = addr;
+               }
        }
 
-       return 0;
-}
-
-static int __mxt_read_reg(struct i2c_client *client,
-                              u16 reg, u16 len, void *val)
+       dev_dbg(&client->dev, "Writing address pointer & reading %d bytes"
+               " in on i2c transaction...\n", length);
+
+/* FIH { */
+/* Avoid stop delay */
+#if 0
+       le_addr = cpu_to_le16(addr);
+       msg[0].addr  = client->addr;
+       msg[0].flags = 0x00;
+       msg[0].len   = 2;
+       msg[0].buf   = (u8 *) &le_addr;
+
+       msg[1].addr  = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len   = length;
+       msg[1].buf   = (u8 *) value;
+       pm_runtime_get_sync(&client->dev);
+       if  (i2c_transfer(adapter, msg, 2) == 2)
+               err = length;
+       else
+               err = -EIO;
+       pm_runtime_put(&client->dev);
+#else
 {
-       struct i2c_msg xfer[2];
-       u8 buf[2];
-
-       buf[0] = reg & 0xff;
-       buf[1] = (reg >> 8) & 0xff;
-
-       /* Write register */
-       xfer[0].addr = client->addr;
-       xfer[0].flags = 0;
-       xfer[0].len = 2;
-       xfer[0].buf = buf;
-
-       /* Read data */
-       xfer[1].addr = client->addr;
-       xfer[1].flags = I2C_M_RD;
-       xfer[1].len = len;
-       xfer[1].buf = val;
-
-       if (i2c_transfer(client->adapter, xfer, 2) != 2) {
-               dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
-               return -EIO;
+       u8 reg[2];
+       reg[0] = addr & 0xFF;
+       reg[1] = (addr>>8) & 0xFF;
+
+       err = i2c_master_send(client, (u8 *)reg, 2);
+       if (err == 2)
+               err = 0;
+       else {
+               msleep(100); /* For deep sleep mode */
+               err = i2c_master_send(client, (u8 *)reg, 2);
+               if (err == 2)
+                       err = 0;
+               else
+                       err = -EIO;
        }
 
-       return 0;
+       if (err < 0)
+               return err;
+
+       err = i2c_master_recv(client, (u8 *)value, length);
+       if (err == length)
+               err = length;
+       else
+               err = -EIO;
 }
+#endif
+/* FIH } */
+       return err;
+}
+
 
-static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
+/* Writes one byte to given address in mXT chip. */
+
+static int mxt_write_byte(struct i2c_client *client, u16 addr, u8 value)
 {
-       return __mxt_read_reg(client, reg, 1, val);
+
+       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;
 }
 
-static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
+/* 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)
 {
-       u8 buf[3];
+       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;
 
-       buf[0] = reg & 0xff;
-       buf[1] = (reg >> 8) & 0xff;
-       buf[2] = val;
+       mxt = i2c_get_clientdata(client);
+       if (mxt != NULL)
+               mxt->last_read_addr = -1;
 
-       if (i2c_master_send(client, buf, 3) != 3) {
-               dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+       memcpy(i2c_block_transfer.data, value, length);
+       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;
-       }
-
-       return 0;
 }
 
-static int mxt_read_object_table(struct i2c_client *client,
-                                     u16 reg, u8 *object_buf)
+/* Calculates the CRC value for mXT infoblock. */
+int calculate_infoblock_crc(u32 *crc_result, u8 *data, int crc_area_size)
 {
-       return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
-                                  object_buf);
+       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 struct mxt_object *
-mxt_get_object(struct mxt_data *data, u8 type)
+static void report_mt(struct mxt_data *mxt)
 {
-       struct mxt_object *object;
        int i;
+       int active_touches = 0;
+
+       for (i = 0; i < mxt->numtouch; i++) {
+               if (!stored_size[i])
+                       continue;
 
-       for (i = 0; i < data->info.object_num; i++) {
-               object = data->object_table + i;
-               if (object->type == type)
-                       return object;
+               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);
        }
 
-       dev_err(&data->client->dev, "Invalid object type\n");
-       return NULL;
+       if (active_touches == 0)
+               input_mt_sync(mxt->touch_input);
+       input_sync(mxt->touch_input);
 }
 
-static int mxt_read_message(struct mxt_data *data,
-                                struct mxt_message *message)
+static void process_T9_message(u8 *message, struct mxt_data *mxt)
 {
-       struct mxt_object *object;
-       u16 reg;
+       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(&mxt->client->dev, "SUPRESS");
+       } else {
+/* FIH { */
+/* Correct coordinate */
+#if 0
+               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);
+               printk(KERN_INFO "[TOUCH] X=%d, Y=%d\n", xpos, ypos);
+
+               if (mxt->max_x_val < 1024)
+                               xpos = xpos >> 2;
+
+               if (mxt->max_y_val < 1024)
+                               ypos = ypos >> 2;
+
+               printk(KERN_INFO "[TOUCH] [X=%d, Y=%d] max_x=%d , max_y=%d\n", xpos, ypos, mxt->max_x_val, mxt->max_y_val);
+#else
+               xpos = message[MXT_MSG_T9_XPOSMSB] * 16 +
+                       ((message[MXT_MSG_T9_XYPOSLSB] >> 4) & 0xF);
+               ypos = message[MXT_MSG_T9_YPOSMSB] * 4 +
+                       ((message[MXT_MSG_T9_XYPOSLSB] >> 6) & 0x3);
+               printk(KERN_INFO "[TOUCH] X=%d, Y=%d\n", xpos, ypos);
+
+#if 0
+               xpos = xpos*1024*9/12800 + 51;
+               ypos = ypos*1024*9/8000 + 51;
+               printk(KERN_INFO "[TOUCH] [X=%d, Y=%d]\n", xpos, ypos);
+#else
+               xpos = (xpos)*1024/1280;
+               if (xpos > 1024)
+                       xpos = 1024;
+               if (xpos < 0)
+                       xpos = 0;
+               ypos = (ypos)*1024/800;
+               if (ypos > 1024)
+                       ypos = 1024;
+               if (ypos < 0)
+                       ypos = 0;
+               printk(KERN_INFO "[TOUCH] [X=%d, Y=%d]\n", xpos, ypos);
+#endif
 
-       object = mxt_get_object(data, MXT_GEN_MESSAGE);
-       if (!object)
-               return -EINVAL;
+#endif
 
-       reg = object->start_address;
-       return __mxt_read_reg(data->client, reg,
-                       sizeof(struct mxt_message), message);
-}
 
-static int mxt_read_object(struct mxt_data *data,
-                               u8 type, u8 offset, u8 *val)
-{
-       struct mxt_object *object;
-       u16 reg;
 
-       object = mxt_get_object(data, type);
-       if (!object)
-               return -EINVAL;
 
-       reg = object->start_address;
-       return __mxt_read_reg(data->client, reg + offset, 1, val);
-}
+/* FIH } */
 
-static int mxt_write_object(struct mxt_data *data,
-                                u8 type, u8 offset, u8 val)
-{
-       struct mxt_object *object;
-       u16 reg;
+               touch_number = message[MXT_MSG_REPORTID] -
+                       mxt->rid_map[report_id].first_rid;
 
-       object = mxt_get_object(data, type);
-       if (!object)
-               return -EINVAL;
+               stored_x[touch_number] = xpos;
+               stored_y[touch_number] = ypos;
 
-       reg = object->start_address;
-       return mxt_write_reg(data->client, reg + offset, val);
-}
+               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];
 
-static void mxt_input_report(struct mxt_data *data, int single_id)
-{
-       struct mxt_finger *finger = data->finger;
-       struct input_dev *input_dev = data->input_dev;
-       int status = finger[single_id].status;
-       int finger_num = 0;
-       int id;
-
-       for (id = 0; id < MXT_MAX_FINGER; id++) {
-               if (!finger[id].status)
-                       continue;
+                       printk(KERN_INFO, "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) {
+                       printk(KERN_INFO, "RELEASE");
 
-               input_mt_slot(input_dev, id);
-               input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
-                               finger[id].status != MXT_RELEASE);
-
-               if (finger[id].status != MXT_RELEASE) {
-                       finger_num++;
-                       input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
-                                       finger[id].area);
-                       input_report_abs(input_dev, ABS_MT_POSITION_X,
-                                       finger[id].x);
-                       input_report_abs(input_dev, ABS_MT_POSITION_Y,
-                                       finger[id].y);
-               } else {
-                       finger[id].status = 0;
+                       /* The previously reported touch has been removed.*/
+                       stored_size[touch_number] = 0;
                }
-       }
-
-       input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
 
-       if (status != MXT_RELEASE) {
-               input_report_abs(input_dev, ABS_X, finger[single_id].x);
-               input_report_abs(input_dev, ABS_Y, finger[single_id].y);
+               printk(KERN_INFO, "X=%d, Y=%d, touch number=%d, TOUCHSIZE=%d",
+                       xpos, ypos, touch_number, stored_size[touch_number]);
        }
-
-       input_sync(input_dev);
 }
 
-static void mxt_input_touchevent(struct mxt_data *data,
-                                     struct mxt_message *message, int id)
+void process_key_message(u8 *message, struct mxt_data *mxt)
 {
-       struct mxt_finger *finger = data->finger;
-       struct device *dev = &data->client->dev;
-       u8 status = message->message[0];
-       int x;
-       int y;
-       int area;
-
-       /* Check the touch is present on the screen */
-       if (!(status & MXT_DETECT)) {
-               if (status & MXT_RELEASE) {
-                       dev_dbg(dev, "[%d] released\n", id);
-
-                       finger[id].status = MXT_RELEASE;
-                       mxt_input_report(data, id);
+       /*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;
                }
+               input_sync(mxt->key_input);
                return;
        }
 
-       /* Check only AMP detection */
-       if (!(status & (MXT_PRESS | MXT_MOVE)))
-               return;
-
-       x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
-       y = (message->message[2] << 4) | ((message->message[3] & 0xf));
-       if (data->max_x < 1024)
-               x = x >> 2;
-       if (data->max_y < 1024)
-               y = y >> 2;
-
-       area = message->message[4];
-
-       dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
-               status & MXT_MOVE ? "moved" : "pressed",
-               x, y, area);
-
-       finger[id].status = status & MXT_MOVE ?
-                               MXT_MOVE : MXT_PRESS;
-       finger[id].x = x;
-       finger[id].y = y;
-       finger[id].area = area;
-
-       mxt_input_report(data, id);
+printk(KERN_INFO "message[1]=%d, message[2]=%d, message[3]=%d, message[4]=%d", message[1], message[2], message[3], message[4]);
+
+       /*key down*/
+       if (message[1] == 128 && message[2] == 0 && message[3] == 2 && 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] == 0 && message[3] == 4 && 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] == 8 && 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] == 8 && message[3] == 0 && 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;
+       }
+       input_sync(mxt->key_input);
 }
 
-static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+static int process_message(u8 *message, u8 object, struct mxt_data *mxt)
 {
-       struct mxt_data *data = dev_id;
-       struct mxt_message message;
-       struct mxt_object *object;
-       struct device *dev = &data->client->dev;
-       int id;
-       u8 reportid;
-       u8 max_reportid;
-       u8 min_reportid;
-
-       do {
-               if (mxt_read_message(data, &message)) {
-                       dev_err(dev, "Failed to read message\n");
-                       goto end;
+       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];
+
+       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");
+               }
+               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;
 
-               reportid = message.reportid;
-
-               /* whether reportid is thing of MXT_TOUCH_MULTI */
-               object = mxt_get_object(data, MXT_TOUCH_MULTI);
-               if (!object)
-                       goto end;
-
-               max_reportid = object->max_reportid;
-               min_reportid = max_reportid - object->num_report_ids + 1;
-               id = reportid - min_reportid;
+       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;
 
-               if (reportid >= min_reportid && reportid <= max_reportid)
-                       mxt_input_touchevent(data, &message, id);
-               else
-                       mxt_dump_message(dev, &message);
-       } while (reportid != 0xff);
+       case MXT_TOUCH_MULTITOUCHSCREEN_T9:
+               process_T9_message(message, mxt);
+               report_mt(mxt);
+               break;
 
-end:
-       return IRQ_HANDLED;
-}
+       case MXT_SPT_GPIOPWM_T19:
+               if (debug >= DEBUG_TRACE)
+                       dev_info(&client->dev, "Receiving GPIO message\n");
+               break;
 
-static int mxt_check_reg_init(struct mxt_data *data)
-{
-       const struct mxt_platform_data *pdata = data->pdata;
-       struct mxt_object *object;
-       struct device *dev = &data->client->dev;
-       int index = 0;
-       int i, j, config_offset;
-
-       if (!pdata->config) {
-               dev_dbg(dev, "No cfg data defined, skipping reg init\n");
-               return 0;
-       }
+       case MXT_PROCI_GRIPFACESUPPRESSION_T20:
+               if (debug >= DEBUG_TRACE)
+                       dev_info(&client->dev, "Receiving face suppression msg\n");
+               break;
 
-       for (i = 0; i < data->info.object_num; i++) {
-               object = data->object_table + i;
+       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;
 
-               if (!mxt_object_writable(object->type))
-                       continue;
+       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;
 
-               for (j = 0; j < object->size + 1; j++) {
-                       config_offset = index + j;
-                       if (config_offset > pdata->config_length) {
-                               dev_err(dev, "Not enough config data!\n");
-                               return -EINVAL;
-                       }
-                       mxt_write_object(data, object->type, j,
-                                        pdata->config[config_offset]);
+       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]
+                               );
                }
-               index += object->size + 1;
+               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;
 }
 
-static int mxt_make_highchg(struct mxt_data *data)
+/*
+ * 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 device *dev = &data->client->dev;
-       struct mxt_message message;
-       int count = 10;
-       int error;
-
-       /* Read dummy message to make high CHG pin */
-       do {
-               error = mxt_read_message(data, &message);
-               if (error)
-                       return error;
-       } while (message.reportid != 0xff && --count);
-
-       if (!count) {
-               dev_err(dev, "CHG pin isn't cleared\n");
-               return -EBUSY;
+       struct i2c_client *client;
+       u8      *message;
+       u16     message_length;
+       u16     message_addr;
+       u8      report_id;
+       u8      object;
+       int     error;
+       int     i;
+       int     intr_value;
+
+       client         = mxt->client;
+       message        = mxt->message_buf;
+       message_addr   = mxt->msg_proc_addr;
+       message_length = mxt->message_size;
+
+       if (message_length >= 256) {
+               dev_err(&client->dev, "Message length > 256 bytes not supported\n");
+               return;
        }
 
-       return 0;
+       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 - 1, message);
+                       if (error >= 0)
+                               break;
+                       mxt->read_fail_counter++;
+                       dev_err(&client->dev, "Failure reading maxTouch device\n");
+               }
+               if (error < 0)
+                       return;
+
+               report_id = message[0];
+
+               if (reg_add > 0)
+                       dev_info(
+                       &client->dev,
+                       "Atmel Debug info message[0]=%d,message[1]=%d,message[2]=%d,message[3]=%d"
+                       "message[4]=%d,message[5]=%d,message[6]=%d,message[7]=%d,message_length=%d",
+                       message[0], message[1], message[2], message[3],
+                       message[4], message[5], message[6], message[7], message_length);
+
+               if ((report_id != MXT_END_OF_MESSAGES) && (report_id != 0)) {
+                       /* 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());*/
+               intr_value = gpio_get_value(mxt->mxt_intr_gpio);
+       } while (intr_value == 0);
 }
 
-static void mxt_handle_pdata(struct mxt_data *data)
+/*
+ * 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)
 {
-       const struct mxt_platform_data *pdata = data->pdata;
-       u8 voltage;
-
-       /* Set touchscreen lines */
-       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE,
-                       pdata->x_line);
-       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE,
-                       pdata->y_line);
-
-       /* Set touchscreen orient */
-       mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT,
-                       pdata->orient);
-
-       /* Set touchscreen burst length */
-       mxt_write_object(data, MXT_TOUCH_MULTI,
-                       MXT_TOUCH_BLEN, pdata->blen);
-
-       /* Set touchscreen threshold */
-       mxt_write_object(data, MXT_TOUCH_MULTI,
-                       MXT_TOUCH_TCHTHR, pdata->threshold);
-
-       /* Set touchscreen resolution */
-       mxt_write_object(data, MXT_TOUCH_MULTI,
-                       MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
-       mxt_write_object(data, MXT_TOUCH_MULTI,
-                       MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
-       mxt_write_object(data, MXT_TOUCH_MULTI,
-                       MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
-       mxt_write_object(data, MXT_TOUCH_MULTI,
-                       MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
-
-       /* Set touchscreen voltage */
-       if (pdata->voltage) {
-               if (pdata->voltage < MXT_VOLTAGE_DEFAULT) {
-                       voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) /
-                               MXT_VOLTAGE_STEP;
-                       voltage = 0xff - voltage + 1;
-               } else
-                       voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) /
-                               MXT_VOLTAGE_STEP;
-
-               mxt_write_object(data, MXT_SPT_CTECONFIG,
-                               MXT_CTE_VOLTAGE, voltage);
+       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;
 }
 
-static int mxt_get_info(struct mxt_data *data)
+/******************************************************************************/
+/* Initialization of driver                                                   */
+/******************************************************************************/
+
+static int __devinit mxt_identify(struct i2c_client *client,
+                                 struct mxt_data *mxt,
+                                 u8 *id_block_data)
 {
-       struct i2c_client *client = data->client;
-       struct mxt_info *info = &data->info;
+       u8 buf[7];
        int error;
-       u8 val;
+       int identified;
 
-       error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
-       if (error)
-               return error;
-       info->family_id = val;
+       identified = 0;
 
-       error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
-       if (error)
-               return error;
-       info->variant_id = val;
+       /* Read Device info to check if chip is valid */
+       error = mxt_read_block(client, MXT_ADDR_INFO_BLOCK, MXT_ID_BLOCK_SIZE,
+                              (u8 *) buf);
 
-       error = mxt_read_reg(client, MXT_VERSION, &val);
-       if (error)
-               return error;
-       info->version = val;
+       if (error < 0) {
+               client->addr = MXT1386_I2C_ADDR2;
+               slave_addr = MXT1386_I2C_ADDR2;
+               printk(KERN_INFO "[TOUCH] switch slave address to 0x%02x", client->addr);
+               error = mxt_read_block(client, MXT_ADDR_INFO_BLOCK, MXT_ID_BLOCK_SIZE, (u8 *) buf);
+       }
 
-       error = mxt_read_reg(client, MXT_BUILD, &val);
-       if (error)
-               return error;
-       info->build = val;
+       if (error < 0) {
+               mxt->read_fail_counter++;
+               dev_err(&client->dev, "Failure accessing maXTouch device\n");
+               return -EIO;
+       }
 
-       error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
-       if (error)
-               return error;
-       info->object_num = val;
+       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; */
+               }
 
-       return 0;
-}
+       /* MXT1386 */
+       } else if (mxt->device_info.family_id == MXT1386_FAMILYID) {
+/* FIH { */
+#if 0
+               strcpy(mxt->device_info.family_name, "mXT1386");
+#else
+               strcpy(mxt->device_info.family_name, "mxt1386");
+#endif
+/* FIH } */
 
-static int mxt_get_object_table(struct mxt_data *data)
-{
-       int error;
-       int i;
-       u16 reg;
-       u8 reportid = 0;
-       u8 buf[MXT_OBJECT_SIZE];
-
-       for (i = 0; i < data->info.object_num; i++) {
-               struct mxt_object *object = data->object_table + i;
-
-               reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
-               error = mxt_read_object_table(data->client, reg, buf);
-               if (error)
-                       return error;
-
-               object->type = buf[0];
-               object->start_address = (buf[2] << 8) | buf[1];
-               object->size = buf[3];
-               object->instances = buf[4];
-               object->num_report_ids = buf[5];
-
-               if (object->num_report_ids) {
-                       reportid += object->num_report_ids *
-                                       (object->instances + 1);
-                       object->max_reportid = reportid;
+               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; */
        }
 
-       return 0;
+       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;
 }
 
-static int mxt_initialize(struct mxt_data *data)
+/*
+ * 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)
 {
-       struct i2c_client *client = data->client;
-       struct mxt_info *info = &data->info;
-       int error;
-       u8 val;
-
-       error = mxt_get_info(data);
-       if (error)
-               return error;
-
-       data->object_table = kcalloc(info->object_num,
-                                    sizeof(struct mxt_object),
-                                    GFP_KERNEL);
-       if (!data->object_table) {
-               dev_err(&client->dev, "Failed to allocate memory\n");
-               return -ENOMEM;
+       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;
        }
 
-       /* Get object table information */
-       error = mxt_get_object_table(data);
-       if (error)
-               return error;
-
-       /* Check register init values */
-       error = mxt_check_reg_init(data);
-       if (error)
-               return error;
-
-       mxt_handle_pdata(data);
-
-       /* Backup to memory */
-       mxt_write_object(data, MXT_GEN_COMMAND,
-                       MXT_COMMAND_BACKUPNV,
-                       MXT_BACKUP_VALUE);
-       msleep(MXT_BACKUP_TIME);
-
-       /* Soft reset */
-       mxt_write_object(data, MXT_GEN_COMMAND,
-                       MXT_COMMAND_RESET, 1);
-       msleep(MXT_RESET_TIME);
-
-       /* Update matrix size at info struct */
-       error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
-       if (error)
-               return error;
-       info->matrix_xsize = val;
-
-       error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
-       if (error)
-               return error;
-       info->matrix_ysize = val;
-
-       dev_info(&client->dev,
-                       "Family ID: %d Variant ID: %d Version: %d Build: %d\n",
-                       info->family_id, info->variant_id, info->version,
-                       info->build);
-
-       dev_info(&client->dev,
-                       "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
-                       info->matrix_xsize, info->matrix_ysize,
-                       info->object_num);
+       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;
+       }
 
-       return 0;
-}
+       /* Copy the ID data for CRC calculation. */
+       memcpy(raw_ib_data, raw_id_data, MXT_ID_BLOCK_SIZE);
+       ib_pointer = MXT_ID_BLOCK_SIZE;
 
-static void mxt_calc_resolution(struct mxt_data *data)
-{
-       unsigned int max_x = data->pdata->x_size - 1;
-       unsigned int max_y = data->pdata->y_size - 1;
+       mxt->object_table = object_table;
 
-       if (data->pdata->orient & MXT_XY_SWITCH) {
-               data->max_x = max_y;
-               data->max_y = max_x;
-       } else {
-               data->max_x = max_x;
-               data->max_y = max_y;
-       }
-}
+       dev_dbg(&mxt->client->dev, "maXTouch driver Memory allocated\n");
 
-static ssize_t mxt_object_show(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
-{
-       struct mxt_data *data = dev_get_drvdata(dev);
-       struct mxt_object *object;
-       int count = 0;
-       int i, j;
-       int error;
-       u8 val;
+       object_info_address = MXT_ADDR_OBJECT_TABLE;
 
-       for (i = 0; i < data->info.object_num; i++) {
-               object = data->object_table + i;
+       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);
 
-               count += sprintf(buf + count,
-                               "Object Table Element %d(Type %d)\n",
-                               i + 1, object->type);
+               error = mxt_read_block(client, object_info_address,
+                                      MXT_OBJECT_TABLE_ELEMENT_SIZE, buf);
 
-               if (!mxt_object_readable(object->type)) {
-                       count += sprintf(buf + count, "\n");
-                       continue;
+               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;
                }
 
-               for (j = 0; j < object->size + 1; j++) {
-                       error = mxt_read_object(data,
-                                               object->type, j, &val);
-                       if (error)
-                               return error;
-
-                       count += sprintf(buf + count,
-                                       "  Byte %d: 0x%x (%d)\n", j, val, val);
+               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;
                }
 
-               count += sprintf(buf + count, "\n");
-       }
+               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;
 
-       return count;
-}
-
-static int mxt_load_fw(struct device *dev, const char *fn)
-{
-       struct mxt_data *data = dev_get_drvdata(dev);
-       struct i2c_client *client = data->client;
-       const struct firmware *fw = NULL;
-       unsigned int frame_size;
-       unsigned int pos = 0;
-       int ret;
-
-       ret = request_firmware(&fw, fn, dev);
-       if (ret) {
-               dev_err(dev, "Unable to open firmware %s\n", fn);
-               return ret;
+               object_info_address += MXT_OBJECT_TABLE_ELEMENT_SIZE;
        }
 
-       /* Change to the bootloader mode */
-       mxt_write_object(data, MXT_GEN_COMMAND,
-                       MXT_COMMAND_RESET, MXT_BOOT_VALUE);
-       msleep(MXT_RESET_TIME);
-
-       /* Change to slave address of bootloader */
-       if (client->addr == MXT_APP_LOW)
-               client->addr = MXT_BOOT_LOW;
-       else
-               client->addr = MXT_BOOT_HIGH;
+       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;
+       }
 
-       ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
-       if (ret)
-               goto out;
+       mxt->message_buf = kmalloc(256, GFP_KERNEL);
+       if (mxt->message_buf == NULL) {
+               printk(KERN_WARNING "Error allocating memory\n");
+               error = -ENOMEM;
+               goto err_msg_alloc3;
+       }
 
-       /* Unlock bootloader */
-       mxt_unlock_bootloader(client);
+       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;
+       }
 
-       while (pos < fw->size) {
-               ret = mxt_check_bootloader(client,
-                                               MXT_WAITING_FRAME_DATA);
-               if (ret)
-                       goto out;
+       /* 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++;
+                       }
+               }
+       }
 
-               frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
+       /* 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");
+       }
 
-               /* We should add 2 at frame size as the the firmware data is not
-                * included the CRC bytes.
-                */
-               frame_size += 2;
+       crc = (buf[2] << 16) | (buf[1] << 8) | buf[0];
 
-               /* Write one frame to device */
-               mxt_fw_write(client, fw->data + pos, frame_size);
+       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);
 
-               ret = mxt_check_bootloader(client,
-                                               MXT_FRAME_CRC_PASS);
-               if (ret)
-                       goto out;
+       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);
 
-               pos += frame_size;
+       if (crc == calculated_crc) {
+               mxt->info_block_crc = crc;
+       } else {
+               mxt->info_block_crc = 0;
+               pr_err("maXTouch: Info block CRC invalid!\n");
+       }
 
-               dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
+       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);
+               }
        }
 
-out:
-       release_firmware(fw);
+       return 0;
+err_msg_alloc3:
+       kfree(mxt->message_buf);
+err_max_rid:
+       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;
+}
 
-       /* Change to slave address of application */
-       if (client->addr == MXT_BOOT_LOW)
-               client->addr = MXT_APP_LOW;
-       else
-               client->addr = MXT_APP_HIGH;
 
-       return ret;
+static u8 mxt_valid_interrupt_dummy(void)
+{
+       return 1;
 }
 
-static ssize_t mxt_update_fw_store(struct device *dev,
-                                       struct device_attribute *attr,
-                                       const char *buf, size_t count)
+static int __devinit mxt_probe(struct i2c_client *client,
+                              const struct i2c_device_id *id)
 {
-       struct mxt_data *data = dev_get_drvdata(dev);
-       int error;
+       struct mxt_data          *mxt;
+       struct mxt_platform_data *pdata;
+       struct input_dev         *touch_input;
+       struct input_dev         *key_input;
+       u8 *id_data;
+       int error, gpio_intr, i;
+       u16 base_addr;
+
+       pr_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;
+       }
 
-       disable_irq(data->irq);
+       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;
+       }
 
-       error = mxt_load_fw(dev, MXT_FW_NAME);
-       if (error) {
-               dev_err(dev, "The firmware update failed(%d)\n", error);
-               count = error;
-       } else {
-               dev_dbg(dev, "The firmware update succeeded\n");
+       dev_dbg(&client->dev, "maXTouch driver functionality OK\n");
 
-               /* Wait for reset */
-               msleep(MXT_FWRESET_TIME);
+       /* 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;
+       }
 
-               kfree(data->object_table);
-               data->object_table = NULL;
+       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;
+       }
 
-               mxt_initialize(data);
+       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;
        }
 
-       enable_irq(data->irq);
+       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;
+       }
 
-       error = mxt_make_highchg(data);
-       if (error)
-               return error;
+       /* 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;
+
+       error = gpio_request(mxt->mxt_intr_gpio, 0);
+       if (error < 0)
+               pr_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) {
+               pr_err("Failed to set interrupt direction, error=%d\n", error);
+               gpio_free(mxt->mxt_intr_gpio);
+       }
 
-       return count;
-}
+       error = gpio_request(mxt->mxt_reset_gpio, "MaxTouch-reset");
+       if (error < 0)
+               pr_err("Failed to request GPIO%d (MaxTouch-reset) error=%d\n",
+                       mxt->mxt_reset_gpio, error);
 
-static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
-static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
+       error = gpio_direction_output(mxt->mxt_reset_gpio, 1);
+       if (error) {
+               pr_info("Failed to set reset direction, error=%d\n", error);
+               gpio_free(mxt->mxt_reset_gpio);
+       }
 
-static struct attribute *mxt_attrs[] = {
-       &dev_attr_object.attr,
-       &dev_attr_update_fw.attr,
-       NULL
-};
+       /* maXTouch wants 40mSec minimum after reset to get organized */
+       gpio_set_value(mxt->mxt_reset_gpio, 1);
+       msleep(40);
+/* FIH { */
+/* Wait for interrupt and delay for unstable reset status */
+#if 1
+{
+       int i = 0;
 
-static const struct attribute_group mxt_attr_group = {
-       .attrs = mxt_attrs,
-};
+       for (i = 0; i < 10; i++) {
+               printk(KERN_INFO "Polling GPIO%d (MaxTouch-intr). retry=%d\n", mxt->mxt_intr_gpio, i);
+               if (gpio_get_value(mxt->mxt_intr_gpio) == LOW)
+                       break;
+               msleep(50);
+       }
 
-static void mxt_start(struct mxt_data *data)
-{
-       /* Touch enable */
-       mxt_write_object(data,
-                       MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0x83);
+       /* msleep(10000); */
 }
+#endif
+/* FIH } */
 
-static void mxt_stop(struct mxt_data *data)
-{
-       /* Touch disable */
-       mxt_write_object(data,
-                       MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0);
-}
+       /* 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;
 
-static int mxt_input_open(struct input_dev *dev)
-{
-       struct mxt_data *data = input_get_drvdata(dev);
+       if (pdata->valid_interrupt != NULL)
+               mxt->valid_interrupt = pdata->valid_interrupt;
+       else
+               mxt->valid_interrupt = mxt_valid_interrupt_dummy;
 
-       mxt_start(data);
+       if (mxt->init_hw != NULL)
+               mxt->init_hw();
 
-       return 0;
-}
+       if (debug >= DEBUG_TRACE)
+               printk(KERN_INFO "maXTouch driver identifying chip\n");
 
-static void mxt_input_close(struct input_dev *dev)
-{
-       struct mxt_data *data = input_get_drvdata(dev);
+       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;
+
+       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;
+
+       /* Key input parameter */
+       key_input->name         = "mxt224_key_0";
+       key_input->phys         = mxt->key_phys_name;
+
+       /* 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);
+
+       i2c_set_clientdata(client, mxt);
+       input_set_drvdata(touch_input, mxt);
+       input_set_drvdata(key_input, mxt);
+
+       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;
+       }
 
-       mxt_stop(data);
-}
+       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;
+       }
 
-static int __devinit mxt_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
-{
-       const struct mxt_platform_data *pdata = client->dev.platform_data;
-       struct mxt_data *data;
-       struct input_dev *input_dev;
-       int error;
+       mxt->message_buf = NULL;
+       error = mxt_read_object_table(client, mxt, id_data);
+       if (error < 0)
+               goto err_read_ot;
+
+       BackupNVM(mxt);
+       msleep(40);
+
+       mxt->prev_key = 0;
+
+       if (pdata->numtouch)
+               mxt->numtouch = pdata->numtouch;
+       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;
+               }
+       }
 
-       if (!pdata)
-               return -EINVAL;
+       mutex_lock(&mxt->dev_mutex);
+       gpio_intr = gpio_get_value(mxt->mxt_intr_gpio);
+       while (gpio_intr == 0) {
+               for (i = 1; i < I2C_RETRY_COUNT; i++) {
+                       error = mxt_read_block(mxt->client, mxt->msg_proc_addr,
+                                       mxt->message_size, mxt->message_buf);
+                       if (error >= 0)
+                               break;
+                       dev_info(&client->dev, "flush the buffer failed in the probe function\n");
 
-       data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!data || !input_dev) {
-               dev_err(&client->dev, "Failed to allocate memory\n");
-               error = -ENOMEM;
-               goto err_free_mem;
-       }
+               }
+               gpio_intr = gpio_get_value(mxt->mxt_intr_gpio);
 
-       input_dev->name = "Atmel maXTouch Touchscreen";
-       input_dev->id.bustype = BUS_I2C;
-       input_dev->dev.parent = &client->dev;
-       input_dev->open = mxt_input_open;
-       input_dev->close = mxt_input_close;
-
-       data->client = client;
-       data->input_dev = input_dev;
-       data->pdata = pdata;
-       data->irq = client->irq;
-
-       mxt_calc_resolution(data);
-
-       __set_bit(EV_ABS, input_dev->evbit);
-       __set_bit(EV_KEY, input_dev->evbit);
-       __set_bit(BTN_TOUCH, input_dev->keybit);
-
-       /* For single touch */
-       input_set_abs_params(input_dev, ABS_X,
-                            0, data->max_x, 0, 0);
-       input_set_abs_params(input_dev, ABS_Y,
-                            0, data->max_y, 0, 0);
-
-       /* For multi touch */
-       input_mt_init_slots(input_dev, MXT_MAX_FINGER);
-       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
-                            0, MXT_MAX_AREA, 0, 0);
-       input_set_abs_params(input_dev, ABS_MT_POSITION_X,
-                            0, data->max_x, 0, 0);
-       input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
-                            0, data->max_y, 0, 0);
-
-       input_set_drvdata(input_dev, data);
-       i2c_set_clientdata(client, data);
-
-       error = mxt_initialize(data);
-       if (error)
-               goto err_free_object;
-
-       error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
-                       pdata->irqflags, client->dev.driver->name, data);
-       if (error) {
-               dev_err(&client->dev, "Failed to register interrupt\n");
-               goto err_free_object;
+       }
+       mutex_unlock(&mxt->dev_mutex);
+
+       /* Store the number of multi-touches allowed, default was 0. */
+       base_addr = get_object_address(MXT_TOUCH_MULTITOUCHSCREEN_T9,
+                       0, mxt->object_table, mxt->device_info.num_objs);
+       base_addr += MXT_ADR_T9_NUMTOUCH;
+
+       error = mxt_write_byte(mxt->client, base_addr, mxt->numtouch);
+       if (error < 0) {
+               dev_err(&client->dev,
+                       "Multi-touch init failure, T9 object, error = %d\n",
+                       error);
+               goto err_irq;
        }
 
-       error = mxt_make_highchg(data);
-       if (error)
-               goto err_free_irq;
+       kfree(id_data);
 
-       error = input_register_device(input_dev);
-       if (error)
-               goto err_free_irq;
+#ifdef CONFIG_DEBUG_FS
+       error = intel_mid_add_debugfs();
+       if (error < 0)
+               printk(KERN_ERR "failed to initialize  intel_mid debugfs\n");
 
-       error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
-       if (error)
-               goto err_unregister_device;
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       mxt->suspended  = false;
+       mxt->T7[0]      = 32;
+       mxt->T7[1]      = 15;
+       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_unregister_device:
-       input_unregister_device(input_dev);
-       input_dev = NULL;
-err_free_irq:
-       free_irq(client->irq, data);
-err_free_object:
-       kfree(data->object_table);
-err_free_mem:
-       input_free_device(input_dev);
-       kfree(data);
+err_irq:
+       kfree(mxt->rid_map);
+       kfree(mxt->object_table);
+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 *data = i2c_get_clientdata(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 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->message_buf);
+       }
+       kfree(mxt);
 
-       sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
-       free_irq(data->irq, data);
-       input_unregister_device(data->input_dev);
-       kfree(data->object_table);
-       kfree(data);
+       if (debug >= DEBUG_TRACE)
+               dev_info(&client->dev, "Touchscreen unregistered\n");
 
        return 0;
 }
 
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM)
 static int mxt_suspend(struct device *dev)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct mxt_data *data = i2c_get_clientdata(client);
-       struct input_dev *input_dev = data->input_dev;
-
-       mutex_lock(&input_dev->mutex);
+       struct mxt_data *mxt = dev_get_drvdata(dev);
 
-       if (input_dev->users)
-               mxt_stop(data);
+       dev_dbg(dev, "In function %s", __func__);
 
-       mutex_unlock(&input_dev->mutex);
+       if (device_may_wakeup(dev))
+               enable_irq_wake(mxt->irq);
 
        return 0;
 }
 
 static int mxt_resume(struct device *dev)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct mxt_data *data = i2c_get_clientdata(client);
-       struct input_dev *input_dev = data->input_dev;
+       struct mxt_data *mxt = dev_get_drvdata(dev);
+
+       dev_dbg(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 pwcfg_addr;
+       u8 buf[3] = {0, 0, 0};
+       u8 err;
 
-       /* Soft reset */
-       mxt_write_object(data, MXT_GEN_COMMAND,
-                       MXT_COMMAND_RESET, 1);
+       disable_irq(mxt_es->irq);
 
-       msleep(MXT_RESET_TIME);
+       mutex_lock(&mxt_es->dev_mutex);
 
-       mutex_lock(&input_dev->mutex);
 
-       if (input_dev->users)
-               mxt_start(data);
+       pwcfg_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, pwcfg_addr, 3, mxt_es->T7);
+       err = mxt_write_block(mxt_es->client, pwcfg_addr, 3, buf);
+       if (err > 0)
+               dev_info(&mxt_es->client->dev, "Driver enter deep sleep mode.");
+       else
+               dev_info(&mxt_es->client->dev,
+                        "Driver can't enter deep sleep mode [%d].", err);
+       /* clear touch state when suspending */
+       memset(stored_size, 0, mxt_es->numtouch * sizeof(stored_size[0]));
+       report_mt(mxt_es);
 
-       mutex_unlock(&input_dev->mutex);
+       mxt_es->suspended = true;
 
-       return 0;
+       mutex_unlock(&mxt_es->dev_mutex);
 }
 
+void mxt_late_resume(struct early_suspend *h)
+{
+       int gpio_intr;
+       u16 pwcfg_addr;
+       u8 err;
+       u8 i;
+
+       enable_irq(mxt_es->irq);
+       mutex_lock(&mxt_es->dev_mutex);
+
+       pwcfg_addr = get_object_address(MXT_GEN_POWERCONFIG_T7,
+                       0,
+                       mxt_es->object_table,
+                       mxt_es->device_info.num_objs);
+/* FIH { */
+#if 0
+       err = mxt_write_block(mxt_es->client, pwcfg_addr, 3, mxt_es->T7);
+#else
+       for (i = 0; i < I2C_RETRY_COUNT; i++) {
+               err = mxt_write_block(mxt_es->client, pwcfg_addr, 3, mxt_es->T7);
+               if (err == 3)
+                       break;
+               msleep(100);
+       }
+#endif
+/* FIH } */
+       if (err > 0)
+               dev_info(&mxt_es->client->dev, "resume from early suspend");
+       else
+               dev_info(&mxt_es->client->dev, "fail to late resume");
+
+       msleep(25);
+       gpio_intr = gpio_get_value(mxt_es->mxt_intr_gpio);
+       while (gpio_intr == 0) {
+               for (i = 1; i < I2C_RETRY_COUNT; i++) {
+                       err = mxt_read_block(mxt_es->client,
+                                               mxt_es->msg_proc_addr,
+                                               mxt_es->message_size,
+                                               mxt_es->message_buf);
+                       if (err >= 0)
+                               break;
+                       dev_info(&mxt_es->client->dev, "flush the buffer failed in the resume function\n");
+
+               }
+               gpio_intr = gpio_get_value(mxt_es->mxt_intr_gpio);
+
+       }
+       mxt_calibrate(mxt_es->client);
+       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,
+       .suspend = mxt_suspend,
+       .resume  = mxt_resume,
 };
-#endif
 
-static const struct i2c_device_id mxt_id[] = {
-       { "qt602240_ts", 0 },
-       { "atmel_mxt_ts", 0 },
-       { "mXT224", 0 },
+static const struct i2c_device_id mxt_idtable[] = {
+       {TOUCH_DEVICE_NAME, 1,},
        { }
 };
-MODULE_DEVICE_TABLE(i2c, mxt_id);
+
+MODULE_DEVICE_TABLE(i2c, mxt_idtable);
 
 static struct i2c_driver mxt_driver = {
        .driver = {
-               .name   = "atmel_mxt_ts",
-               .owner  = THIS_MODULE,
+               .name   = TOUCH_DEVICE_NAME,
+               .owner  = THIS_MODULE,
 #ifdef CONFIG_PM
-               .pm     = &mxt_pm_ops,
+               .pm = &mxt_pm_ops,
 #endif
        },
+
+       .id_table       = mxt_idtable,
        .probe          = mxt_probe,
        .remove         = __devexit_p(mxt_remove),
-       .id_table       = mxt_id,
 };
 
 static int __init mxt_init(void)
 {
-       return i2c_add_driver(&mxt_driver);
+       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_exit(void)
+static void __exit mxt_cleanup(void)
 {
        i2c_del_driver(&mxt_driver);
 }
 
-module_init(mxt_init);
-module_exit(mxt_exit);
 
-/* Module information */
-MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
-MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
+late_initcall(mxt_init);
+module_exit(mxt_cleanup);
+
+MODULE_AUTHOR("Iiro Valkonen");
+MODULE_DESCRIPTION("Driver for Atmel maXTouch Touchscreen Controller");
 MODULE_LICENSE("GPL");
+
+
+#ifdef CONFIG_DEBUG_FS
+/******************************************************************************
+debugfs for touch driver, contain four debug files:
+
+1.sread
+       can be read and write.
+       write: set the address of a single register to be accessed;
+       read: return the content of the register.
+2.swrite
+       can be write only.
+       write: set the value of the corresponding register, and the register's
+       address is determined by 'write' operation of 'single_read' file.
+3.sread_offset
+       can be write only
+       write:set the offset of the register
+*********************************************************************************/
+
+
+static int intel_mid_single_read_get(void *data, u64 *val)
+{
+       int ret, gpio_intr, gpio_rst;
+       u16 addr;
+       addr = get_object_address(reg_add,
+                       0,
+                       mxt_es->object_table,
+                       mxt_es->device_info.num_objs)+reg_add_offset;
+
+       ret = mxt_read_block(mxt_es->client, addr, 1, (u8 *)val);
+       if (ret < 0)
+               printk(KERN_ERR "intel_touch debugfs read_set err add=0x%x\n", reg_add);
+       gpio_intr = gpio_get_value(mxt_es->mxt_intr_gpio);
+       gpio_rst = gpio_get_value(mxt_es->mxt_reset_gpio);
+       printk("touch interrupt value = %d,gpio_rst = %d\n", gpio_intr, gpio_rst);
+       return 0;
+}
+
+static int intel_mid_single_read_set(void *data, u64 val)
+{
+       reg_add = (u8)val;
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(intel_mid_single_read_reg_fops,
+                               intel_mid_single_read_get,
+                               intel_mid_single_read_set, "0x%02llx\n");
+
+static int intel_mid_single_read_set_offset(void *data, u64 val)
+{
+       reg_add_offset = (u8)val;
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(intel_mid_single_read_reg_offset_fops,
+                               NULL, intel_mid_single_read_set_offset,
+                               "0x%02llx\n");
+
+static int intel_mid_single_write_set(void *data, u64 val)
+{
+       int ret;
+       u16 addr;
+       uint8_t data1[1] = {0};
+       data1[0] = (u8)val;
+       addr = get_object_address(reg_add,
+                       0,
+                       mxt_es->object_table,
+                       mxt_es->device_info.num_objs)+reg_add_offset;
+
+       ret = mxt_write_block(mxt_es->client, addr, 1, data1);
+
+       if (ret < 0)
+               printk(KERN_ERR "intel_touch debugfs write err add=0x%x\n", reg_add);
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(intel_mid_single_write_reg_fops,
+                               NULL, intel_mid_single_write_set, "0x%02llx\n");
+
+
+static int  intel_mid_add_debugfs(void)
+{
+       struct dentry *root;
+
+       root = debugfs_create_dir("touch_debug", NULL);
+
+       if (IS_ERR(root))
+               /* Don't complain -- debugfs just isn't enabled */
+               return -1;
+       if (!root)
+               /* Complain -- debugfs is enabled, but it failed to
+               * create the directory. */
+               goto err;
+
+       if (!debugfs_create_file("sread", S_IWUGO|S_IRUGO, root, NULL, &intel_mid_single_read_reg_fops))
+               goto err;
+
+       if (!debugfs_create_file ("sread_offset", S_IWUGO|S_IRUGO, root, NULL, &intel_mid_single_read_reg_offset_fops))
+               goto err;
+
+       if (!debugfs_create_file ("swrite", S_IWUGO, root, NULL, &intel_mid_single_write_reg_fops))
+               goto err;
+
+       return 0;
+err:
+       debugfs_remove_recursive(root);
+       printk(KERN_ERR "failed to initialize  intel_mid debugfs\n");
+       return -1;
+}
+
+#endif
index 883745c..8ac8651 100644 (file)
@@ -125,6 +125,13 @@ config SUPPORT_TMD_MIPI_600X1024_DISPLAY
        help
          xxxxxx
 
+config SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+       bool "Support Toshiba LVDS MIPI Bridge interface Panel"
+       depends on DRM_MDFLD || DRM_CTP
+       default n
+       help
+         xxxxxx
+
 config MDFD_VIDEO_DECODE
        bool "Support for Medfield Video Decode"
        depends on DRM_MDFLD || DRM_CTP
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 28e17a4..cc3dfc8
 #include "mdfld_dsi_pkg_sender.h"
 #include "psb_drv.h"
 
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+#include "mdfld_dsi_lvds_bridge.h"
+static void dsi_debug_MIPI_reg(struct drm_device *dev);
+static void mipi_set_properties(struct mdfld_dsi_config *dsi_config, int pipe);
+static void mdfld_mipi_set_video_timing(struct mdfld_dsi_config *dsi_config,
+                                                               int pipe);
+static void mdfld_mipi_config(struct mdfld_dsi_config *dsi_config, int pipe);
+static void mdfld_set_pipe_timing(struct mdfld_dsi_config *dsi_config,
+                                                               int pipe);
+static u32 mode_hdisplay;
+static u32 mode_vdisplay;
+#endif
+
+/* Local functions */
+static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe);
+bool dsi_device_ready = true;
+struct drm_encoder *gencoder;
 extern struct drm_device *gpDrmDevice;
 
 #ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
@@ -153,6 +170,47 @@ static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe)
                DRM_INFO("MIPI: HS CMD FIFO was never cleared!\n");
 }
 
+static void mdfld_wait_for_PIPEA_DISABLE(struct drm_device *dev, u32 pipe)
+{
+       u32 pipeconf_reg = PIPEACONF;
+       int timeout = 0;
+
+       if (pipe == 2)
+               pipeconf_reg = PIPECCONF;
+
+       udelay(500);
+
+       /* This will time out after approximately 2+ seconds */
+       while ((timeout < 20000) && (REG_READ(pipeconf_reg) & 0x40000000)) {
+               udelay(100);
+               timeout++;
+       }
+
+       if (timeout == 20000)
+               DRM_INFO("MIPI: PIPE was not disabled!\n");
+}
+
+static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe)
+{
+       u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
+       int timeout = 0;
+
+       if (pipe == 2)
+               gen_fifo_stat_reg += MIPIC_REG_OFFSET;
+
+       udelay(500);
+
+       /* This will time out after approximately 2+ seconds */
+       while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & DPI_FIFO_EMPTY)
+               != DPI_FIFO_EMPTY)) {
+               udelay(100);
+               timeout++;
+       }
+
+       if (timeout == 20000)
+               DRM_INFO("MIPI: DPI FIFO was never cleared!\n");
+}
+
 static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe)
 {
        u32 intr_stat_reg = MIPIA_INTR_STAT_REG;
@@ -194,7 +252,8 @@ void dsi_set_bridge_reset_state(int state)
                mdelay(40);
        }
 }
-
+#endif
+#if defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
 void dsi_set_device_ready_state(struct drm_device *dev, int state, int pipe)
 {
        u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
@@ -244,7 +303,9 @@ void dsi_set_ptarget_state(struct drm_device *dev, int state)
                } while (pp_sts_reg & PP_ON);
        }
 }
+#endif
 
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
 void dsi_set_pipe_plane_enable_state(struct drm_device *dev,
                                int state,
                                int pipe)
@@ -626,6 +687,63 @@ void mdfld_deinit_TOSHIBA_MIPI(struct drm_device *dev)
 
        disp_init = 0;
 }
+#endif /*-- CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY --// */
+/*DIV5-MM-DISPLAY-NC-LCM_INIT-00-]- */
+
+
+#if defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
+
+void dsi_set_pipe_plane_enable_state(struct drm_device *dev, int state, int pipe)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       u32 pipeconf_reg = PIPEACONF;
+       u32 dspcntr_reg = DSPACNTR;
+       u32 mipi_reg = MIPI;
+       u32 reg_offset = 0;
+
+       u32 pipeconf = dev_priv->pipeconf;
+       u32 dspcntr = dev_priv->dspcntr;
+       u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+
+       printk(KERN_ALERT "[DISPLAY TRK] %s: state = %d, pipe = %d\n", __func__, state, pipe);
+
+       if (pipe) {
+               pipeconf_reg = PIPECCONF;
+               dspcntr_reg = DSPCCNTR;
+               mipi_reg = MIPI_C;
+               reg_offset = MIPIC_REG_OFFSET;
+       } else {
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+               mipi &= (~0x03);
+#else
+               mipi |= 2;
+#endif
+       }
+
+       if (state) {
+               int retry;
+               /*Set up pipe */
+               REG_WRITE(pipeconf_reg, pipeconf);
+
+               /*Wait for pipe enabling*/
+               retry = 10000;
+               while (--retry && !(REG_READ(pipeconf_reg) & BIT30))
+                       udelay(3);
+
+               if (!retry)
+                       printk(KERN_ALERT "Fatal Error: Failed to enable pipe\n");
+
+
+               /*Set up display plane */
+               REG_WRITE(dspcntr_reg, dspcntr);
+       } else {
+               /*Disable PIPE */
+               REG_WRITE(pipeconf_reg, 0);
+               mdfld_wait_for_PIPEA_DISABLE(dev, pipe);
+               mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
+
+       }
+}
 
 static void mdfld_dsi_configure_down(struct mdfld_dsi_encoder * dsi_encoder, int pipe)
 {
@@ -640,17 +758,22 @@ static void mdfld_dsi_configure_down(struct mdfld_dsi_encoder * dsi_encoder, int
                PSB_DEBUG_ENTRY("[DISPLAY] %s: DPI Panel is Already Off\n", __func__);
                return;
        }
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+       dsi_lvds_toshiba_bridge_panel_off();
+       udelay(100);
+       dsi_lvds_deinit_lvds_bridge(dev);
+       /* dsi_lvds_suspend_lvds_bridge(dev); */
+#else
+       mdfld_deinit_TOSHIBA_MIPI(dev);  /* De-init MIPI bridge and Panel */
+       dsi_set_bridge_reset_state(1);  /* Pull Low Reset */
+#endif
+       dsi_set_pipe_plane_enable_state(dev, 0, pipe);  /* Disable pipe and plane */
 
-       mdfld_deinit_TOSHIBA_MIPI(dev);  //De-init MIPI bridge and Panel
-       dsi_set_bridge_reset_state(1);  //Pull Low Reset
-
-       dsi_set_pipe_plane_enable_state(dev, 0, pipe);  //Disable pipe and plane
-
-//     dsi_set_ptarget_state(dev, 0);  //Disable PTARGET
+       /* dsi_set_ptarget_state(dev, 0); */ /* Disable PTARGET */
 
-       mdfld_dsi_dpi_shut_down(dpi_output, pipe);  //Send shut down command
+       mdfld_dsi_dpi_shut_down(dpi_output, pipe);  /* Send shut down command */
 
-       dsi_set_device_ready_state(dev, 0, pipe);  //Clear device ready state
+       dsi_set_device_ready_state(dev, 0, pipe);  /* Clear device ready state */
 
        dev_priv->dpi_panel_on = false;
 }
@@ -671,17 +794,25 @@ static void mdfld_dsi_configure_up(struct mdfld_dsi_encoder * dsi_encoder, int p
        }
 
        /* For resume path sequence */
-//     dsi_set_pipe_plane_enable_state(dev, 0, pipe);
-//     dsi_set_ptarget_state(dev, 0);
+       /* dsi_set_pipe_plane_enable_state(dev, 0, pipe); */
+       /* dsi_set_ptarget_state(dev, 0); */
        mdfld_dsi_dpi_shut_down(dpi_output, pipe);
        dsi_set_device_ready_state(dev, 0, pipe);  //Clear Device Ready Bit
 
        dsi_set_device_ready_state(dev, 1, pipe);  //Set device ready state
-       dsi_set_bridge_reset_state(0);  //Pull High Reset
-       mdfld_init_TOSHIBA_MIPI(dev);  //Init MIPI Bridge and Panel
-       mdfld_dsi_dpi_turn_on(dpi_output, pipe);  //Send turn on command
-//     dsi_set_ptarget_state(dev, 1);  //Enable PTARGET
-       dsi_set_pipe_plane_enable_state(dev, 1, pipe);  //Enable plane and pipe
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+       dsi_lvds_toshiba_bridge_panel_on();
+       udelay(100);
+       /* dsi_lvds_set_bridge_reset_state(0); */
+       dsi_lvds_configure_lvds_bridge(dev);
+#else
+       dsi_set_bridge_reset_state(0);  /* Pull High Reset */
+       mdfld_init_TOSHIBA_MIPI(dev);  /* Init MIPI Bridge and Panel */
+#endif
+
+       mdfld_dsi_dpi_turn_on(dpi_output, pipe);  /* Send turn on command */
+       /* dsi_set_ptarget_state(dev, 1); */ /* Enable PTARGET */
+       dsi_set_pipe_plane_enable_state(dev, 1, pipe);  /* Enable plane and pipe */
 
        dev_priv->dpi_panel_on = true;
 }
@@ -955,11 +1086,16 @@ int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
        dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hbp, num_lane, bpp);
        dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hfp, num_lane, bpp);
        dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hactive, num_lane, bpp);
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+       dpi_timing->vsync_count = pclk_vsync;
+       dpi_timing->vbp_count = pclk_vbp;
+       dpi_timing->vfp_count = pclk_vfp;
+#else
        dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vsync, num_lane, bpp);
        dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vbp, num_lane, bpp);
        dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vfp, num_lane, bpp);
 #endif
-
+#endif
        PSB_DEBUG_ENTRY("DPI timings: %d, %d, %d, %d, %d, %d, %d\n", 
                        dpi_timing->hsync_count, dpi_timing->hbp_count,
                        dpi_timing->hfp_count, dpi_timing->hactive_count,
@@ -1107,10 +1243,14 @@ void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config * dsi_config, int pip
        REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
        
        /*TODO: figure out how to setup these registers*/
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+       REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x2A0c6008);
+#else
        REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
-       
+#endif
        REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14);
 #endif
+
        /*set device ready*/
        REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
 }
@@ -1228,6 +1368,47 @@ static int __dpi_exit_ulps_locked(struct mdfld_dsi_config *dsi_config)
        REG_WRITE(regs->device_ready_reg, ctx->device_ready);
        return 0;
 }
+static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe)
+{
+       struct drm_device *dev = output->dev;
+       /* struct drm_psb_private * dev_priv = dev->dev_private; */
+       u32 reg_offset = 0;
+
+       PSB_DEBUG_ENTRY("pipe %d panel state %d\n", pipe, output->panel_on);
+
+       /*if output is on, or mode setting didn't happen, ignore this*/
+       if ((!output->panel_on) || output->first_boot) {
+               output->first_boot = 0;
+               return;
+       }
+
+       if (pipe)
+               reg_offset = MIPIC_REG_OFFSET;
+
+       /* Wait for dpi fifo to empty */
+       mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
+
+       /* Clear the special packet interrupt bit if set */
+       if (REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)
+               REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
+
+       if (REG_READ(MIPIA_DPI_CONTROL_REG + reg_offset) == DSI_DPI_CTRL_HS_SHUTDOWN) {
+               PSB_DEBUG_ENTRY("try to send the same package again, abort!");
+               goto shutdown_out;
+       }
+
+       REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
+
+shutdown_out:
+       output->panel_on = 0;
+       output->first_boot = 0;
+
+       /* FIXME the following is disabled to WA the X slow start issue for TMD panel */
+       /* if(pipe == 2) */
+       /*      dev_priv->dpi_panel_on2 = false; */
+       /* else if (pipe == 0) */
+       /*      dev_priv->dpi_panel_on = false;  */
+}
 
 /**
  * Power on sequence for video mode MIPI panel.
@@ -1611,6 +1792,8 @@ set_power_err:
 void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
 {
        struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+       struct mdfld_dsi_dpi_output *dpi_output =
+               MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
        struct mdfld_dsi_config *dsi_config =
                mdfld_dsi_encoder_get_config(dsi_encoder);
        int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
@@ -1636,10 +1819,10 @@ void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
                                        OSPM_UHB_FORCE_POWER_ON))
                return;
 
-#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
-       if(on) {
+#if defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
+       if (on) {
                if (get_panel_type(dev, pipe) == TMD_VID){
-                       if(dsi_device_ready) {
+                       if (dsi_device_ready) {
                                ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
                                return;
                        }
@@ -1655,16 +1838,15 @@ void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
                        mdfld_dsi_tpo_ic_init(dsi_config, pipe);
                }
 
-               if(pipe == 2) {
+               if (pipe == 2) {
                        dev_priv->dpi_panel_on2 = true;
-               }
-               else {
+               } else {
                        dev_priv->dpi_panel_on  = true;
                }
 
        } else {
                if (get_panel_type(dev, pipe) == TMD_VID) {
-                       if(!dsi_device_ready) {
+                       if (!dsi_device_ready) {
                                ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
                                return;
                        }
@@ -1679,13 +1861,10 @@ void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
                        REG_READ(mipi_reg);
                }
 
-               if(pipe == 2) {
+               if (pipe == 2)
                        dev_priv->dpi_panel_on2 = false;
-               }
-               else {
+               else
                        dev_priv->dpi_panel_on  = false;
-               }
-
        }
 
 #else
@@ -1779,8 +1958,10 @@ void mdfld_dsi_dpi_commit(struct drm_encoder *encoder)
        dsi_encoder = MDFLD_DSI_ENCODER(encoder);
        dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
 
-#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#if  defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY)
        mdfld_dsi_dpi_set_power(encoder, false);
+#elif defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
+       mdfld_dsi_dpi_set_power(encoder, true);
 #else
        /*Everything is ready, commit DSI hw context to HW*/
        __mdfld_dsi_dpi_set_power(encoder, true);
@@ -1860,6 +2041,110 @@ void dsi_debug_MIPI_reg(struct drm_device *dev)
        PSB_DEBUG_ENTRY("[DISPLAY] DSPACNTR = %x\n", temp_val);
 */
 }
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+/* This functionality was implemented in FW in iCDK */
+/* But removed in DV0 and later. So need to add here. */
+static void mipi_set_properties(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+       struct drm_device *dev = dsi_config->dev;
+       u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+
+       printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+
+       REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);  /*0xB104 */
+       REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);  /*0xB008 */
+       REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0xffffff);  /*0xB010 */
+       REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffffff);  /*0xB014 */
+       REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14);  /*0xB018 */
+       REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xff);  /*0xB01C */
+       REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x25);  /*0xB044 */
+       REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0xf0);  /*0xB050 */
+       REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);  /*0xB05C */
+       REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);  /*0xB060 */
+       REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000820);  /*0xB084 */
+       REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14);  /*B088 */
+}
+
+static void mdfld_mipi_set_video_timing(struct mdfld_dsi_config *dsi_config,
+                                                               int pipe)
+{
+       struct drm_device *dev = dsi_config->dev;
+       u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+       struct mdfld_dsi_dpi_timing dpi_timing;
+       struct drm_display_mode *mode = dsi_config->mode;
+
+       printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+
+       mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp);
+
+       REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay);  /*0xB020 */
+       REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);  /*0xB028 */
+       REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);  /*0xB02C */
+       REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);  /*0xB030 */
+       REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);  /*0xB034 */
+       REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset),
+               dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);  /*0xB038 */
+       REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset),
+               dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);  /*0xB03C */
+       REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset),
+               dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);  /*0xB040 */
+}
+
+static void mdfld_mipi_config(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+       struct drm_device *dev = dsi_config->dev;
+       u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+       int lane_count = dsi_config->lane_count;
+
+       printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+
+       if (pipe) {
+               REG_WRITE(MIPI, 0x00000002);  /*0x61190 */
+               REG_WRITE(MIPI_C, 0x80000000);  /*0x62190 */
+       } else {
+               REG_WRITE(MIPI_C, 0x00);  /*0x62190 */
+               REG_WRITE(MIPI, 0x80010000);  /*0x61190 */
+       }
+       REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset),
+                               0x150A600F);  /*0xB080 */
+
+
+       REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset),
+                               0x0000000F);  /*0xB058 */
+
+       /*lane_count = 3 */
+       REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), (0x00000200 | lane_count)); /*0xB00C */
+
+       mdfld_mipi_set_video_timing(dsi_config, pipe);
+}
+
+static void mdfld_set_pipe_timing(struct mdfld_dsi_config *dsi_config,
+                                       int pipe)
+{
+       struct drm_device *dev = dsi_config->dev;
+       struct drm_display_mode *mode = dsi_config->mode;
+
+       printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+        /*0x60000 */
+       REG_WRITE(HTOTAL_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
+        /*0x60004 */
+       REG_WRITE(HBLANK_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
+       /*0x60008 */
+       REG_WRITE(HSYNC_A, ((mode->hsync_end - 1) << 16) |
+                                               (mode->hsync_start - 1));
+       /*0x6000C */
+       REG_WRITE(VTOTAL_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
+       /*0x60010 */
+       REG_WRITE(VBLANK_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
+       /*0x60014 */
+       REG_WRITE(VSYNC_A, ((mode->vsync_end - 1) << 16) |
+                                               (mode->vsync_start - 1));
+       /*0x6001C */
+       REG_WRITE(PIPEASRC, ((mode->hdisplay - 1) << 16) |
+                                               (mode->vdisplay - 1));
+}
+
+#endif
 
 /**
  * Setup DPI timing for video mode MIPI panel.
@@ -1911,18 +2196,20 @@ void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
                                   struct drm_display_mode *adjusted_mode)
 {
        struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+       struct mdfld_dsi_dpi_output *dpi_output =
+                       MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
        struct mdfld_dsi_config *dsi_config =
        mdfld_dsi_encoder_get_config(dsi_encoder);
-#ifdef MIPI_DEBUG_LOG
        struct drm_device *dev = dsi_config->dev;
-#endif
+       struct drm_psb_private *dev_priv = dev->dev_private;
        int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
 
        u32 pipeconf_reg = PIPEACONF;
        u32 dspcntr_reg = DSPACNTR;
        u32 mipi_reg = MIPI;
        u32 reg_offset = 0;
-
+       u32 pipeconf = dev_priv->pipeconf;
+       u32 dspcntr = dev_priv->dspcntr;
        u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
 
        PSB_DEBUG_ENTRY("set mode %dx%d on pipe %d",
@@ -1936,15 +2223,65 @@ void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
                mipi_reg = MIPI_C;
                reg_offset = MIPIC_REG_OFFSET;
        } else {
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+               mipi &= (~0x03); /* Use all four lanes */
+#else
                mipi |= 2;
+#endif
        }
 
-#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#if defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
        /*start up display island if it was shutdown*/
        if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
                                        OSPM_UHB_FORCE_POWER_ON))
                return;
 
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+       /* The following logic is required to do reset the bridge and configure. */
+       /* This also start DSI clock at 200MHz */
+       {
+           int timeout = 0;
+
+           dsi_lvds_set_bridge_reset_state(0);  /*Pull High Reset */
+           dsi_lvds_toshiba_bridge_panel_on();
+           udelay(100);
+           /* Now start the DSI clock */
+           REG_WRITE(MRST_DPLL_A, 0x00);  /*0xF014 */
+           REG_WRITE(MRST_FPA0, 0xC1);  /*0xF040 */
+           REG_WRITE(MRST_DPLL_A, 0x00800000);  /*0xF014 */
+           udelay(500);
+           REG_WRITE(MRST_DPLL_A, 0x80800000);  /*0xF014 */
+           /*Wait for DSI PLL to lock */
+           while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+               udelay(150);
+               timeout++;
+           }
+           if (timeout == 20000)
+               printk(KERN_ALERT "[DISPLAY] DSI PLL Locked timeout\n");
+           REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x2A0c6008);  /*0xB080 */
+
+           mipi_set_properties(dsi_config, pipe);
+           mdfld_mipi_config(dsi_config, pipe);
+           mdfld_set_pipe_timing(dsi_config, pipe);
+
+           REG_WRITE(DSPABASE, 0x00);  /*0x70184 */
+
+           REG_WRITE(DSPASTRIDE, (mode->hdisplay * 4));  /*0x70188 */
+
+           REG_WRITE(DSPASIZE, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));  /*0x70190 */
+
+           REG_WRITE(DSPACNTR, 0x98000000);  /*0x70180 */
+
+           REG_WRITE(DSPASURF, 0x00);  /*0x7019C */
+
+           REG_WRITE(VGACNTRL, 0x80000000);  /*0x71400 */
+
+           REG_WRITE(DEVICE_READY_REG, 0x00000001);  /*0xB000 */
+
+           REG_WRITE(mipi_reg, 0x80810000); /*0x61190 */
+       }
+#endif
+
        /*set up mipi port FIXME: do at init time */
        REG_WRITE(mipi_reg, mipi);
        REG_READ(mipi_reg);
@@ -1953,11 +2290,17 @@ void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
        mdfld_dsi_dpi_controller_init(dsi_config, pipe);
 
        if (get_panel_type(dev, pipe) == TMD_VID) {
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+               dsi_lvds_configure_lvds_bridge(dev);  /*Configure MIPI Bridge and Panel */
+               dsi_device_ready = true;
+               dev_priv->dpi_panel_on = true;
+#else
                /*Pull High Reset*/
                dsi_set_bridge_reset_state(0);
                /*Init MIPI Bridge and Panel*/
                mdfld_init_TOSHIBA_MIPI(dev);
                dsi_device_ready = true;
+#endif
        } else {
                /*turn on DPI interface*/
                mdfld_dsi_dpi_turn_on(dpi_output, pipe);
@@ -1978,7 +2321,10 @@ void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
                        dpi_output->panel_on);
 
        if (get_panel_type(dev, pipe) == TMD_VID) {
-               /*mdfld_dsi_dpi_turn_on(dpi_output, pipe);*/
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+               mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+#endif
+               /* mdfld_dsi_dpi_turn_on(dpi_output, pipe); */
        } else {
                /* init driver ic */
                mdfld_dsi_tpo_ic_init(dsi_config, pipe);
@@ -2086,6 +2432,7 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
        pipe = dsi_connector->pipe;
 
 #ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
        /*panel hard-reset*/
        if (p_funcs->reset) {
                ret = p_funcs->reset(dsi_config, RESET_FROM_BOOT_UP);
@@ -2123,6 +2470,9 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
        if (p_funcs->dsi_controller_init)
                p_funcs->dsi_controller_init(dsi_config, pipe, 0);
 #else
+       dsi_connector->status = connector_status_connected;
+#endif
+#else
        /* Enable MIPI panel  by default for PR1
         * platform where panel detection code
         * doesn't ready.
@@ -2147,7 +2497,7 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
                return NULL;
        }
 
-#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#if defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
        if (dsi_connector->pipe)
                dpi_output->panel_on = 0;
 #endif
@@ -2160,6 +2510,7 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
        fixed_mode = dsi_config->fixed_mode;
 
 #ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
        /*detect power status of the connected panel*/
        if (p_funcs->get_panel_power_state) {
                ret = p_funcs->get_panel_power_state(dsi_config, pipe);
@@ -2175,6 +2526,7 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
                        dsi_config->dsi_hw_context.panel_on = 0;
        }
 #endif
+#endif
        /*create drm encoder object*/
        connector = &dsi_connector->base.base;
        encoder = &dpi_output->base.base;
@@ -2212,6 +2564,14 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
        gpio_request(GPIO_MIPI_BRIDGE_RESET, "display");
        gpio_request(GPIO_MIPI_PANEL_RESET , "display");
 #endif
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+       {
+               struct drm_psb_private *dev_priv = dev->dev_private;
+               dev_priv->dpi_panel_on = false;
+               gencoder = encoder;
+               dsi_lvds_init_lvds_bridge(dev);
+       }
+#endif
 
        PSB_DEBUG_ENTRY("successfully\n");
 
@@ -2363,8 +2723,8 @@ static int mipi_dsi_dev_ioctl(struct inode *inode, struct file *file,
        void __user *argp = (void __user*)arg;
 #if defined(CONFIG_SUPPORT_TMD_MIPI_600X1024_DISPLAY) \
        || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) \
-       || defined(CONFIG_SUPPORT_MIPI_H8C7_DISPLAY)
-
+       || defined(CONFIG_SUPPORT_MIPI_H8C7_DISPLAY) \
+       || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
        struct drm_encoder *encoder = gencoder;
 #endif
 
@@ -2373,8 +2733,8 @@ static int mipi_dsi_dev_ioctl(struct inode *inode, struct file *file,
        switch (cmd) {
 #if defined(CONFIG_SUPPORT_TMD_MIPI_600X1024_DISPLAY) \
        || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) \
-       || defined(CONFIG_SUPPORT_MIPI_H8C7_DISPLAY)
-
+       || defined(CONFIG_SUPPORT_MIPI_H8C7_DISPLAY) \
+       || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
                case IOCTL_LCM_POWER_ON:
                        mdfld_dsi_dpi_set_power(encoder, 1);
                        break;
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_lvds_bridge.c b/drivers/staging/mrst/drv/mdfld_dsi_lvds_bridge.c
new file mode 100644 (file)
index 0000000..db2f516
--- /dev/null
@@ -0,0 +1,592 @@
+/*
+ * Copyright Â© 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+
+#define CONFIG_LVDS_HARD_RESET
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+
+/*GPIO Pins */
+#define GPIO_MIPI_BRIDGE_RESET 115
+
+#define GPIO_MIPI_LCD_BL_EN    112  /* DV1.0 GP_CORE_016 (+96 = GPIO number), 6S6P_BL_EN */
+#define GPIO_MIPI_LCD_VADD     110
+/* All these pins removed on DV1.0 */
+#define GPIO_MIPI_LCD_BIAS_EN  -1
+#define GPIO_MIPI_PANEL_RESET  -1
+#define GPIO_MIPI_LCD_STBYB    -1
+#define GPIO_MIPI_LCD_COLOR_EN -1
+
+int lvds_disp_init;
+
+struct dsi_lvds_bridge_instance {
+       struct i2c_client *client;
+       struct work_struct wqueue;
+       struct work_struct pre_init_work;
+       struct work_struct test_work;
+} *dsi_lvds_inst;
+
+
+static int DSI_I2C_ByteRead(u16 reg, int count);
+static int DSI_I2C_ByteWrite(u16 reg, u32 data, int count);
+
+static bool lvds_suspend_state;
+
+/************************************************************************** *\
+ * FUNCTION: dsi_lvds_suspend_lvds_bridge
+ *
+ * DESCRIPTION:  This function is called by psb power management
+ *                              during early suspend.
+\* ************************************************************************* */
+void dsi_lvds_suspend_lvds_bridge(struct drm_device *dev)
+{
+       u32 temp;
+
+       printk(KERN_INFO "[DISPLAY ] Enter %s\n", __func__);
+
+       if (gpio_direction_output(GPIO_MIPI_LCD_BL_EN, 0))
+               gpio_set_value_cansleep(GPIO_MIPI_LCD_BL_EN, 0);
+       mdelay(1);
+       if (gpio_direction_output(GPIO_MIPI_LCD_VADD, 0))
+               gpio_set_value_cansleep(GPIO_MIPI_LCD_VADD, 0);
+#ifdef CONFIG_LVDS_HARD_RESET
+       if (gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 0))
+               gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 0);
+#else
+       /* Put the panel in ULPS mode for S0ix. */
+       temp = REG_READ(DEVICE_READY_REG);
+       temp &= ~ULPS_MASK;
+       temp |= ENTERING_ULPS;
+       REG_WRITE(DEVICE_READY_REG, temp);
+       temp = REG_READ(DEVICE_READY_REG);
+
+       /* LP Hold */
+       temp = REG_READ(MIPI);
+       temp &= ~LP_OUTPUT_HOLD;
+       REG_WRITE(MIPI, temp);
+       temp = REG_READ(MIPI);
+
+       mdelay(1);
+#endif
+       lvds_suspend_state = true;
+}
+
+/************************************************************************** *\
+ * FUNCTION: dsi_lvds_resumed_lvds_bridge
+ *
+ * DESCRIPTION:  This function is called by psb power management
+ *                              during late resume.
+\* ************************************************************************* */
+void dsi_lvds_resume_lvds_bridge(struct drm_device *dev)
+{
+       u32 temp;
+       printk(KERN_INFO "[DISPLAY ] Enter %s\n", __func__);
+       if (gpio_direction_output(GPIO_MIPI_LCD_BL_EN, 1))
+               gpio_set_value_cansleep(GPIO_MIPI_LCD_BL_EN, 1);
+       /* VADD */
+       if (gpio_direction_output(GPIO_MIPI_LCD_VADD, 1))
+               gpio_set_value_cansleep(GPIO_MIPI_LCD_VADD, 1);
+       mdelay(10);
+
+#ifdef CONFIG_LVDS_HARD_RESET
+       /* RESET */
+       if (gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 1))
+               gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 1);
+       msleep(20);
+       if (gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 0))
+               gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 0);
+       msleep(20);
+       if (gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 1))
+               gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 1);
+       mdelay(20);
+#else
+       /* LP Hold Release */
+       temp = REG_READ(MIPI);
+       temp |= LP_OUTPUT_HOLD_RELEASE;
+       REG_WRITE(MIPI, temp);
+       mdelay(1);
+       temp = REG_READ(MIPI);
+
+
+       /* Set DSI host to exit from Utra Low Power State */
+       temp = REG_READ(DEVICE_READY_REG);
+
+       temp &= ~ULPS_MASK;
+       temp |= EXITING_ULPS;
+       REG_WRITE(DEVICE_READY_REG, temp);
+       mdelay(1);
+       temp = REG_READ(DEVICE_READY_REG);
+
+       temp &= ~ULPS_MASK;
+       REG_WRITE(DEVICE_READY_REG, temp);
+       mdelay(1);
+       temp = REG_READ(DEVICE_READY_REG);
+
+#endif
+       lvds_suspend_state = false;
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: dsi_lvds_set_bridge_reset_state
+ *
+ * DESCRIPTION:  This function uses GPIO to force in and out of reset state.
+\* ************************************************************************* */
+void dsi_lvds_set_bridge_reset_state(int state)
+{
+       printk(KERN_INFO "[DISPLAY ] %s: state = %d, gpio = %d\n", __func__, state, gpio_get_value(GPIO_MIPI_BRIDGE_RESET));
+
+       if (state) {
+               if (gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 0))
+                       gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 0);
+               mdelay(10);
+       } else {
+
+               if (gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 0))
+                       gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 0);  /*Pull MIPI Bridge reset pin to Low */
+               mdelay(20);
+               if (gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 1))
+                       gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 1);  /*Pull MIPI Bridge reset pin to High */
+               mdelay(40);
+       }
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: dsi_lvds_configure_lvds_bridge
+ *
+ * DESCRIPTION:  This function uses I2C interface to set bridge registers.
+ *                             to configure timings and MIPI lanes.
+\* ************************************************************************* */
+void dsi_lvds_configure_lvds_bridge(struct drm_device *dev)
+{
+       if (lvds_disp_init) {
+               printk(KERN_ALERT "[DISPLAY ] %s is already initialized\n", __func__);
+               return;
+       }
+
+       printk(KERN_INFO "[DISPLAY ]%s: Enter\n", __func__);
+
+       DSI_I2C_ByteWrite(0x013C, 0x00050006, 6);  /*PPI_TX_RX_TA, BTA parameters */
+       DSI_I2C_ByteRead(0x013C, 4);
+       DSI_I2C_ByteWrite(0x0114, 0x00000004, 6);  /*PPI_LPTXTIMCNT */
+       DSI_I2C_ByteWrite(0x0164, 0x00000001, 6);  /*PPI_D0S_CLRSIPOCOUNT */
+       DSI_I2C_ByteWrite(0x0168, 0x00000001, 6);  /*PPI_D1S_CLRSIPOCOUNT */
+       DSI_I2C_ByteWrite(0x016c, 0x00000001, 6);  /*PPI_D2S_CLRSIPOCOUNT */
+       DSI_I2C_ByteWrite(0x0170, 0x00000001, 6);  /*PPI_D3S_CLRSIPOCOUNT */
+       /*Enabling MIPI & PPI lanes, Enable 4 lanes */
+       DSI_I2C_ByteWrite(0x0134, 0x0000001F, 6);  /*PPI_LANEENABLE */
+       DSI_I2C_ByteWrite(0x0210, 0x0000001F, 6);  /*DSI_LANEENABLE */
+       DSI_I2C_ByteWrite(0x0104, 0x00000001, 6);  /*PPI_SARTPPI */
+       DSI_I2C_ByteWrite(0x0204, 0x00000001, 6);  /*DSI_SARTPPI */
+
+       /*Setting LVDS output frequency */
+       DSI_I2C_ByteWrite(0x04A0, 0x00048006, 6);  /*LVDS PHY Register 0 (LVPHY0) */
+
+       /*Calculating video panel control settings */
+       /*Setting video panel control register */
+       DSI_I2C_ByteWrite(0x0450, 0x00000120, 6);  /*VPCTRL, Video Path Control, VTGen=ON */
+
+       /*Setting display timing registers */
+       DSI_I2C_ByteWrite(0x0454, 0x00280028, 6);  /*HTIM1, HBPR=100, HPW=10 */
+
+       /* value = ((hsync_start - hdisplay)<<16 | hdisplay) */
+       DSI_I2C_ByteWrite(0x0458, ((1360 - 1280)<<16 | 1280), 6);  /*HTIM2, HFPR=190, HDISPR=1024 */
+       DSI_I2C_ByteWrite(0x045c, 0x00080007, 6);  /*VTIM1, VBPR=8, VPW=7 */
+
+       /* value = ((vsync_start - vdisplay)<<16 | vdisplay */
+       DSI_I2C_ByteWrite(0x0460, ((808 - 8)<<16 | 800), 6);  /*VTIM2, VFPR=8, VDISPR=800 */
+       DSI_I2C_ByteWrite(0x0464, 0x00000001, 6);  /*VFUEN */
+
+       /*Setting LVDS bit arrangement */
+       DSI_I2C_ByteWrite(0x0480, 0x05040302, 6);  /*LVMX0003 */
+       DSI_I2C_ByteWrite(0x0484, 0x0A070106, 6);  /*LVMX0407 */
+       DSI_I2C_ByteWrite(0x0488, 0x09080C0B, 6);  /*LVMX0811 */
+       DSI_I2C_ByteWrite(0x048C, 0x120F0E0D, 6);  /*LVMX1215 */
+       DSI_I2C_ByteWrite(0x0490, 0x14131110, 6);  /*LVMX1619 */
+       DSI_I2C_ByteWrite(0x0494, 0x1B171615, 6);  /*LVMX2023 */
+       DSI_I2C_ByteWrite(0x0498, 0x001A1918, 6);  /*LVMX2427 */
+       DSI_I2C_ByteWrite(0x049c, 0x00000001, 6); /*LVCFG */
+
+
+       DSI_I2C_ByteWrite(0x0288, 0xFFFFFFFF, 6); /*DSI_INTCLR */
+
+       lvds_disp_init = 1;
+
+       printk(KERN_INFO "[DISPLAY]%s: Exit\n", __func__);
+
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: dsi_lvds_toshiba_bridge_panel_off
+ *
+ * DESCRIPTION:  This function uses GPIO to turn OFF panel.
+\* ************************************************************************* */
+void dsi_lvds_toshiba_bridge_panel_off(void)
+{
+       printk(KERN_INFO "[DISPLAY ] %s\n", __func__);
+
+       if (gpio_direction_output(GPIO_MIPI_LCD_BL_EN, 0))
+               gpio_set_value_cansleep(GPIO_MIPI_LCD_BL_EN, 0);
+       mdelay(1);
+
+       /* if (gpio_direction_output(GPIO_MIPI_LCD_VADD, 0))
+        *      gpio_set_value_cansleep(GPIO_MIPI_LCD_VADD, 0);
+        */
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: dsi_lvds_toshiba_bridge_panel_on
+ *
+ * DESCRIPTION:  This function uses GPIO to turn ON panel.
+\* ************************************************************************* */
+void dsi_lvds_toshiba_bridge_panel_on(void)
+{
+       printk(KERN_INFO "[DISPLAY ] %s\n", __func__);
+
+       if (gpio_direction_output(GPIO_MIPI_LCD_VADD, 1))
+               gpio_set_value_cansleep(GPIO_MIPI_LCD_VADD, 1);
+       mdelay(50);
+
+       if (gpio_direction_output(GPIO_MIPI_LCD_BL_EN, 1))
+               gpio_set_value_cansleep(GPIO_MIPI_LCD_BL_EN, 1);
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: dsi_lvds_init_lvds_bridge
+ *
+ * DESCRIPTION:  This function does all one time init. Currently defining
+ *                               GPIOs only.
+\* ************************************************************************* */
+void dsi_lvds_init_lvds_bridge(struct drm_device *dev)
+{
+       int ret;
+       ret = gpio_request(GPIO_MIPI_LCD_VADD, "display");
+       if (ret)
+               printk(KERN_ALERT "[DISPLAY]%s: GPIO request failed [%d]\n",
+                       __func__, GPIO_MIPI_LCD_VADD);
+
+       ret = gpio_request(GPIO_MIPI_BRIDGE_RESET, "display");
+       if (ret)
+               printk(KERN_ALERT "[DISPLAY]%s: GPIO request failed [%d]\n",
+                               __func__, GPIO_MIPI_BRIDGE_RESET);
+
+       ret = gpio_request(GPIO_MIPI_LCD_BL_EN, "display");
+       if (ret)
+               printk(KERN_ALERT "[DISPLAY]%s: GPIO request failed [%d]\n",
+                               __func__, GPIO_MIPI_LCD_BL_EN);
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: dsi_lvds_deinit_lvds_bridge
+ *
+ * DESCRIPTION:  This function does is called during deinit time.
+ *
+\* ************************************************************************* */
+void dsi_lvds_deinit_lvds_bridge(struct drm_device *dev)
+{
+       if (!lvds_disp_init) {
+               printk(KERN_ALERT "[DISPLAY ] %s has not initialized\n", __func__);
+               return;
+       }
+
+       printk(KERN_INFO "[DISPLAY ] Enter %s\n", __func__);
+
+#ifdef CONFIG_LVDS_HARD_RESET
+       lvds_disp_init = 0;
+#endif
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: dsi_lvds_bridge_get_display_params
+ *
+ * DESCRIPTION:  This function is a callback to get the panel resolution and
+ *                                     timing settings.
+ *
+\* ************************************************************************* */
+void dsi_lvds_bridge_get_display_params(struct drm_display_mode *mode)
+{
+       mode->hdisplay = 1280;
+       mode->vdisplay = 800;
+       mode->hsync_start = mode->hdisplay + 80;
+       mode->hsync_end = mode->hsync_start + 40;
+       mode->htotal = mode->hsync_end + 40;
+       /* Original settings
+       mode->vsync_start = mode->vdisplay + 8;
+       mode->vsync_end = mode->vsync_start + 7;
+       mode->vtotal = mode->vsync_end + 8;
+       mode->clock = 16500;
+       */
+       mode->vsync_start = mode->vdisplay + 14;
+       mode->vsync_end = mode->vsync_start + 10;
+       mode->vtotal = mode->vsync_end + 14;
+       mode->clock = 33324;
+       printk(KERN_INFO "[DISPLAY]: hdisplay(w) is %d\n", mode->hdisplay);
+       printk(KERN_INFO "[DISPLAY]: vdisplay(h) is %d\n", mode->vdisplay);
+       printk(KERN_INFO "[DISPLAY]: HSS is %d\n", mode->hsync_start);
+       printk(KERN_INFO "[DISPLAY]: HSE is %d\n", mode->hsync_end);
+       printk(KERN_INFO "[DISPLAY]: htotal is %d\n", mode->htotal);
+       printk(KERN_INFO "[DISPLAY]: VSS is %d\n", mode->vsync_start);
+       printk(KERN_INFO "[DISPLAY]: VSE is %d\n", mode->vsync_end);
+       printk(KERN_INFO "[DISPLAY]: vtotal is %d\n", mode->vtotal);
+       printk(KERN_INFO "[DISPLAY]: clock is %d\n", mode->clock);
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: __DSI_I2C_ByteRead
+ *
+ * DESCRIPTION:  Local functions to process read req for I2C registers
+ *
+\* ************************************************************************* */
+static int __DSI_I2C_ByteRead(u16 reg, int count)
+{
+       char rxData[4] = {0};
+       char regData[2] = {0};
+       struct i2c_msg msgs[] = {
+               {
+                .addr = dsi_lvds_inst->client->addr,
+                .flags = 0,
+                .len = 2,
+                },
+               {
+                .addr = dsi_lvds_inst->client->addr,
+                .flags = I2C_M_RD,
+                .len = count - 2,
+                },
+       };
+
+       regData[0] = (reg & 0xFF00) >> 8;
+       regData[1] = reg & 0xFF;
+
+       msgs[0].buf = regData;
+       msgs[1].buf = rxData;
+
+       printk(KERN_INFO "Register: 0x%x\n", reg);
+       if (i2c_transfer(dsi_lvds_inst->client->adapter, msgs, 2) < 0) {
+               printk(KERN_ERR "[DISPLAY] %s: transfer error\n", __func__);
+               return -EIO;
+       } else if (count > 2) {
+               int i = 0;
+               for (i = count - 3; i > -1; --i)
+                       printk(KERN_INFO "%02x ", rxData[i]);
+               printk(KERN_INFO "\n");
+               return rxData[0];
+       }
+       return 0;
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: DSI_I2C_ByteRead
+ *
+ * DESCRIPTION:  Local functions to read I2C registers
+ *
+\* ************************************************************************* */
+static int DSI_I2C_ByteRead(u16 reg, int count)
+{
+       if (dsi_lvds_inst->client)
+               return __DSI_I2C_ByteRead(reg, count);
+       else
+               return -EIO;
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: __DSI_I2C_ByteWrite
+ *
+ * DESCRIPTION:  Local functions to process write req for I2C registers
+ *
+\* ************************************************************************* */
+static int __DSI_I2C_ByteWrite(u16 reg, u32 data, int count)
+{
+       char txData[6] = {0};
+       struct i2c_msg msg[] = {
+               {
+                .addr = dsi_lvds_inst->client->addr,
+                .flags = 0,
+                .len = count,
+                },
+       };
+
+       /*Set the register */
+       txData[0] = (reg & 0xFF00) >> 8;
+       txData[1] = reg & 0xFF;
+
+       if (count == 6) {
+               /*Set the data */
+               txData[2] = (data & 0xFF);
+               txData[3] = (data & 0xFF00) >> 8;
+               txData[4] = (data & 0xFF0000) >> 16;
+               txData[5] = (data & 0xFF000000) >> 24;
+       } else {
+               /* Not valid for this bridge chipset */
+       }
+
+       printk(KERN_INFO "[DISPLAY] %s: addr = %x, reg = %x, data = %x\n",
+               __func__, dsi_lvds_inst->client->addr, reg, data);
+
+       msg[0].buf = txData;
+
+       if (i2c_transfer(dsi_lvds_inst->client->adapter, msg, 1) < 0) {
+               printk(KERN_ERR "[DISPLAY] %s: transfer error\n", __func__);
+               return -EIO;
+       } else {
+               return 0;
+       }
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: DSI_I2C_ByteWrite
+ *
+ * DESCRIPTION:  Local functions to issue write req for I2C registers
+ *
+\* ************************************************************************* */
+static int DSI_I2C_ByteWrite(u16 reg, u32 data, int count)
+{
+       if (dsi_lvds_inst->client)
+               return __DSI_I2C_ByteWrite(reg, data, count);
+       else
+               return -EIO;
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: dsi_lvds_bridge_probe
+ *
+ * DESCRIPTION:  Probe function for LVDS bridge.
+ *
+\* ************************************************************************* */
+static int dsi_lvds_bridge_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+       printk(KERN_INFO "[DISPLAY] %s: Enter\n", __func__);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               printk(KERN_ERR "[DISPLAY] %s: Check I2C functionality failed.\n", __func__);
+               return -ENODEV;
+       }
+
+       dsi_lvds_inst = kzalloc(sizeof(struct dsi_lvds_bridge_instance), GFP_KERNEL);
+
+       if (dsi_lvds_inst == NULL) {
+               printk(KERN_ERR "[DISPLAY] %s: Can not allocate memory.\n", __func__);
+               return -ENOMEM;
+       }
+
+       dsi_lvds_inst->client = client;
+
+       i2c_set_clientdata(client, dsi_lvds_inst);
+
+       dsi_lvds_inst->client->addr = 0x0F;
+
+       printk(KERN_INFO "[DISPLAY] %s: Exit\n", __func__);
+
+       return 0;
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: dsi_lvds_bridge_remove
+ *
+ * DESCRIPTION:  Function to free driver instance.
+ *
+\* ************************************************************************* */
+static int dsi_lvds_bridge_remove(struct i2c_client *client)
+{
+       printk(KERN_INFO "[DISPLAY] %s\n", __func__);
+
+       dev_set_drvdata(&client->dev, 0);
+       kfree(dsi_lvds_inst);
+       return 0;
+}
+
+static const struct i2c_device_id dsi_lvds_bridge_id[] = {
+       { "i2c_disp_brig", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, dsi_lvds_bridge_id);
+
+static struct i2c_driver dsi_lvds_bridge_i2c_driver = {
+       .driver = {
+               .name = "i2c_disp_brig",
+       },
+       .id_table = dsi_lvds_bridge_id,
+       .probe    = dsi_lvds_bridge_probe,
+       .remove   = dsi_lvds_bridge_remove,
+};
+
+static int dsi_lvds_dev_ioctl(struct file *file,
+               unsigned int cmd, unsigned long arg)
+{
+
+       printk(KERN_INFO "[DISPLAY] %s: MIPI DSI driver IOCTL, cmd = %d.\n", __func__, cmd);
+
+       return 0;
+}
+
+static const struct file_operations mipi_dsi_dev_fops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = dsi_lvds_dev_ioctl,
+};
+
+static struct miscdevice dsi_lvds_bridge_dev = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "mipi_dsi",
+       .fops = &mipi_dsi_dev_fops,
+};
+
+/* ************************************************************************* *\
+ * FUNCTION: dsi_lvds_bridge_init
+ *
+ * DESCRIPTION:  Driver Init function for lvds bridge
+ *
+\* ************************************************************************* */
+static int __init dsi_lvds_bridge_init(void)
+{
+       int ret = 0;
+
+       printk(KERN_INFO "[DISPLAY] %s: Enter\n", __func__);
+
+       ret = i2c_add_driver(&dsi_lvds_bridge_i2c_driver);
+
+       printk(KERN_INFO "[DISPLAY] %s: Exit, ret = %d\n", __func__, ret);
+
+       return 0;
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: dsi_lvds_bridge_exit
+ *
+ * DESCRIPTION:  Driver exit function for lvds bridge
+ *
+\* ************************************************************************* */
+static void __exit dsi_lvds_bridge_exit(void)
+{
+       printk(KERN_INFO "[DISPLAY] %s\n", __func__);
+
+       misc_deregister(&dsi_lvds_bridge_dev);
+
+       i2c_del_driver(&dsi_lvds_bridge_i2c_driver);
+}
+
+
+module_init(dsi_lvds_bridge_init);
+module_exit(dsi_lvds_bridge_exit);
+
+#endif
diff --git a/drivers/staging/mrst/drv/mdfld_dsi_lvds_bridge.h b/drivers/staging/mrst/drv/mdfld_dsi_lvds_bridge.h
new file mode 100644 (file)
index 0000000..87e7134
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright Â© 2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __MDFLD_DSI_LVDS_BRIDGE_H__
+#define __MDFLD_DSI_LVDS_BRIDGE_H__
+
+void dsi_lvds_set_bridge_reset_state(int state);
+void dsi_lvds_configure_lvds_bridge(struct drm_device *dev);
+void dsi_lvds_toshiba_bridge_panel_off(void);
+void dsi_lvds_toshiba_bridge_panel_on(void);
+void dsi_lvds_init_lvds_bridge(struct drm_device *dev);
+void dsi_lvds_deinit_lvds_bridge(struct drm_device *dev);
+void dsi_lvds_bridge_get_display_params(struct drm_display_mode *mode);
+void dsi_lvds_resume_lvds_bridge(struct drm_device *dev);
+void dsi_lvds_suspend_lvds_bridge(struct drm_device *dev);
+
+#endif /*__MDFLD_DSI_LVDS_BRIDGE_H__*/
index a680252..3cc9be0 100755 (executable)
@@ -203,7 +203,7 @@ void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u3
  */
 void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
 {
-#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#if defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
        int ret = 0;
 
        PSB_DEBUG_ENTRY("[DISPLAY] %s\n", __func__);
@@ -277,7 +277,7 @@ void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
  */
 void mdfld_dsi_brightness_control (struct drm_device *dev, int pipe, int level)
 {
-#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#if defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
        int duty_val = 0;
        int ret = 0;
 
@@ -440,10 +440,14 @@ static enum drm_connector_status mdfld_dsi_connector_detect
        struct mdfld_dsi_connector *dsi_connector
                = MDFLD_DSI_CONNECTOR(psb_output);
 
-#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+
+       PSB_DEBUG_ENTRY("\n");
+
+
+#if defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
+
        dsi_connector->status = connector_status_connected;
 #else
-       PSB_DEBUG_ENTRY("\n");
        return dsi_connector->status;
 #endif
 }
@@ -706,9 +710,11 @@ static int mdfld_dsi_get_default_config(struct drm_device *dev,
        config->bpp = 24;
        config->type = is_panel_vid_or_cmd(dev);
 
-#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#if defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY)
        /* Gideon: changing lane count to 1 lane for toshiba panel*/
        config->lane_count = 1;
+#elif defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
+       config->lane_count = 4;
 #else
        config->lane_count = 2;
        config->lane_config = MDFLD_DSI_DATA_LANE_2_2;
@@ -717,7 +723,11 @@ static int mdfld_dsi_get_default_config(struct drm_device *dev,
        config->channel_num = 0;
        /*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/
        if (get_panel_type(dev, pipe) == TMD_VID) {
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+               config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS;
+#else
                config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
+#endif
        } else {
                config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
        }
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 0a1fe04..ff24d53 100644 (file)
@@ -1103,6 +1103,11 @@ bool mrst_get_vbt_data(struct drm_psb_private *dev_priv)
                #endif
        }
 
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+               dev_priv->panel_id = TMD_VID;
+               printk(KERN_ALERT
+               "[DISPLAY] %s:SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE Panel\n", __func__);
+#endif
        return true;
 }
 
@@ -1120,7 +1125,20 @@ void hdmi_do_hotplug_wq(struct work_struct *work)
        atomic_inc(&dev_priv->hotplug_wq_done);
        /* notify user space of hotplug event via a uevent message */
 
-#ifdef CONFIG_X86_MDFLD
+#if defined(CONFIG_X86_MDFLD) && defined(CONFIG_MDFD_HDMI)
+       /* As in the hdmi_do_audio_wq() function below
+       * it seems we should not be running this section of
+       * code if we don't also have CONFIG_MDFD_HDMI set,
+       * some devices might not want/need support for HDMI
+       * early in the platform bring up and by having this
+       * available to run might produce unexpected results
+       * if HDMI connector is plugged in.
+       * Also, the vrint_dat variable is not defined if
+       * CONFIG_MDFD_HDMI is not set so this causes build issue, see
+       * ifdef above in this file that blocks including
+       * the header file "mdfld_msic.h" where this is defined.
+       */
+
        intel_scu_ipc_iowrite8(MSIC_VCC330CNT, VCC330_ON);
 
        if (vrint_dat & HDMI_OCP_STATUS) {
@@ -1166,7 +1184,16 @@ void hdmi_do_audio_wq(struct work_struct *work)
                                           struct drm_psb_private,
                                           hdmi_audio_wq);
 
-#ifdef CONFIG_X86_MDFLD
+#if defined(CONFIG_X86_MDFLD) && defined(CONFIG_MDFD_HDMI)
+       /* As in the hdmi_do_hotplug_wq() function above
+       * it seems we should not be running this section of
+       * code if we don't also have CONFIG_MDFD_HDMI set,
+       * some devices might not want/need support for HDMI
+       * early in the platform bring up and by having this
+       * available to run might produce unexpected results
+       * if HDMI connector is plugged in.
+       */
+
        intel_scu_ipc_iowrite8(MSIC_VCC330CNT, VCC330_ON);
        intel_scu_ipc_ioread8(MSIC_HDMI_STATUS, &data);
        DRM_INFO("hdmi_do_audio_wq: Checking for HDMI connection at boot\n");
old mode 100755 (executable)
new mode 100644 (file)
index 9805c75..45c434c
@@ -656,6 +656,7 @@ void mdfld_disable_crtc (struct drm_device *dev, int pipe)
        PSB_DEBUG_ENTRY("pipe = %d\n", pipe);
 
 #ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
        /**
         * NOTE: this path only works for TMD panel now. update it to
         * support all MIPI panels later.
@@ -666,6 +667,7 @@ void mdfld_disable_crtc (struct drm_device *dev, int pipe)
 
                return;
 #endif
+#endif
 
        switch (pipe) {
        case 0:
@@ -763,6 +765,7 @@ static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
        PSB_DEBUG_ENTRY("mode = %d, pipe = %d\n", mode, pipe);
 
 #ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
        /**
         * MIPI dpms
         * NOTE: this path only works for TMD panel now. update it to
@@ -774,6 +777,7 @@ static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
                        return;
        }
 #endif
+#endif
 
        if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
                                       OSPM_UHB_FORCE_POWER_ON))
@@ -1486,6 +1490,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
        PSB_DEBUG_ENTRY("pipe = 0x%x\n", pipe);
 
 #ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
        /**
         * MIPI panel mode setting
         * NOTE: this path only works for TMD panel now. update it to
@@ -1504,6 +1509,7 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
                                adjusted_mode, x, y, old_fb);
         }
 #endif
+#endif
 
        switch (pipe) {
        case 0:
index bfc9c7d..61585e2 100644 (file)
@@ -1995,8 +1995,16 @@ mrst_dsi_get_configuration_mode(struct drm_device *dev)
        /* DPI MIPI display */
        dev_priv->dpi = true;
 
-       /* Should get the lane count from GCT or from the attached MIPI panel spec. */
+       /* FIXME hard coded 4 lanes for Himax HX8858-A, 2 lanes for NSC LM2550 */
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+       dev_priv->laneCount = 1;
+#else
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+       dev_priv->laneCount = 4;
+#else
        dev_priv->laneCount = 2;
+#endif
+#endif
        dev_priv->bpp = 24;
 
        dev_priv->videoModeFormat =  NON_BURST_MODE_SYNC_EVENTS;
index 5594334..3278bfe 100644 (file)
@@ -835,11 +835,13 @@ static int mdfld_save_display_registers (struct drm_device *dev, int pipe)
         * panels later
         */
 #ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
        if (pipe != 1 && ((get_panel_type(dev, pipe) == TMD_VID) ||
                (get_panel_type(dev, pipe) == TMD_6X10_VID) ||
                (get_panel_type(dev, pipe) == H8C7_VID)))
                return 0;
 #endif
+#endif
 
        switch (pipe) {
        case 0:
@@ -1079,11 +1081,13 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
         * panels later
         */
 #ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
        if (pipe != 1 && ((get_panel_type(dev, pipe) == TMD_VID) ||
                (get_panel_type(dev, pipe) == TMD_6X10_VID) ||
                (get_panel_type(dev, pipe) == H8C7_VID)))
                return 0;
 #endif
+#endif
 
        switch (pipe) {
        case 0:
@@ -1725,7 +1729,7 @@ static void gfx_early_suspend(struct early_suspend *h)
                if ((dev_priv->panel_id == TMD_VID) ||
                        (dev_priv->panel_id == H8C7_VID) ||
                        (dev_priv->panel_id == TMD_6X10_VID)) {
-#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#if defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
                        if (dev_priv->encoder0 &&
                                (dev_priv->panel_desc & DISPLAY_A))
                                mdfld_dsi_dpi_set_power(
@@ -1796,7 +1800,7 @@ static void gfx_late_resume(struct early_suspend *h)
                        if ((dev_priv->panel_id == TMD_VID) ||
                                (dev_priv->panel_id == H8C7_VID) ||
                                (dev_priv->panel_id == TMD_6X10_VID)) {
-#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY
+#if    defined(CONFIG_SUPPORT_TOSHIBA_MIPI_DISPLAY) || defined(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE)
                                if (dev_priv->encoder0 &&
                                        (dev_priv->panel_desc & DISPLAY_A))
                                        mdfld_dsi_dpi_set_power(
index a0580ee..cdcf5be 100644 (file)
 #include "psb_intel_reg.h"
 #include "mdfld_dsi_pkg_sender.h"
 
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+#include "mdfld_dsi_lvds_bridge.h"
+#endif
+
 struct drm_display_mode*
 tmd_vid_get_config_mode(struct drm_device* dev)
 {
@@ -67,6 +71,9 @@ tmd_vid_get_config_mode(struct drm_device* dev)
        PSB_DEBUG_ENTRY( "[DISPLAY]: vtotal is %d\n", mode->vtotal);
        PSB_DEBUG_ENTRY( "[DISPLAY]: clock is %d\n", mode->clock);
 #else
+#ifdef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
+       dsi_lvds_bridge_get_display_params(mode);
+#else
        if (use_gct) {
                PSB_DEBUG_ENTRY("gct find MIPI panel.\n");
 
@@ -112,6 +119,8 @@ tmd_vid_get_config_mode(struct drm_device* dev)
                mode->clock = mode->vrefresh * (mode->vtotal + 1) *
                                (mode->htotal + 1) / 1000;
        }
+
+#endif
 #endif
        drm_mode_set_name(mode);
        drm_mode_set_crtcinfo(mode, 0);
@@ -382,10 +391,13 @@ static int mdfld_dsi_tmd_detect(struct mdfld_dsi_config *dsi_config,
 
        /*init drvIC*/
        mdfld_dsi_tmd_drv_ic_init(dsi_config, pipe);
-
+#ifndef CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE
        ret = mdfld_dsi_get_power_mode(dsi_config,
                                 &data,
                                 MDFLD_DSI_LP_TRANSMISSION);
+#else
+       ret = 0;
+#endif
        if (ret)
                status = MDFLD_DSI_PANEL_DISCONNECTED;
        else
old mode 100755 (executable)
new mode 100644 (file)
index 39c6cd0..b594213 100644 (file)
@@ -228,3 +228,4 @@ gfx-$(CONFIG_MDFD_GL3) += $(DRMDRVDIR)/mdfld_gl3.o
 
 obj-$(CONFIG_DRM_MDFLD) += gfx.o
 obj-$(CONFIG_DRM_CTP) += gfx.o
+obj-$(CONFIG_SUPPORT_TOSHIBA_MIPI_LVDS_BRIDGE) += $(DRMDRVDIR)/mdfld_dsi_lvds_bridge.o
diff --git a/include/linux/atmel_mxt_ts.h b/include/linux/atmel_mxt_ts.h
new file mode 100644 (file)
index 0000000..c5253a8
--- /dev/null
@@ -0,0 +1,377 @@
+/*
+ *  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                                 MXT1386_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_COMMSCONFIG_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
+#define MXT_PROCI_GRIPSUPPRESSION_T40       40
+#define MXT_PROCI_PALMSUPPRESSION_T41       41
+#define MXT_SPT_DIGITIZER_T43               43
+
+
+/*
+ * 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 T8_CFG_CHRGTIME                         0
+/* Reserved */
+#define T8_CFG_TCHDRIFT                         2
+#define T8_CFG_DRIFTST                          3
+#define T8_CFG_TCHAUTOCAL                       4
+#define T8_CFG_SYNC                             5
+#define T8_CFG_ATCHCALST                        6
+#define T8_CFG_ATCHCALSTHR                      7
+#define T8_CFG_ATCHFRCCALTHR                    8 /* FW v2.x */
+#define T8_CFG_ATCHFRCCALRATIO                  9 /* FW v2.x */
+
+#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);
+
+/* Add by Richard zhu(jianxin.zhu@borqs.com) */
+#define TOUCH_DEVICE_NAME                              "mxt1386"
+#define LOW                             0
+#define HIGH                            1
+#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
+
+/* anti-touch calibration */
+#define RECALIB_NEED                            0
+#define RECALIB_NG                              1
+#define RECALIB_DONE                            2
+
+struct point_info {
+       int x;
+       int y;
+       int num;
+       int first_area;
+       int last_area;
+};
+
+enum touch_state {
+       NO_TOUCH = 0,
+       PRESS_TOUCH_AREA,
+};
diff --git a/include/linux/i2c/tc35876x.h b/include/linux/i2c/tc35876x.h
new file mode 100644 (file)
index 0000000..cd6a51c
--- /dev/null
@@ -0,0 +1,11 @@
+
+#ifndef _TC35876X_H
+#define _TC35876X_H
+
+struct tc35876x_platform_data {
+       int gpio_bridge_reset;
+       int gpio_panel_bl_en;
+       int gpio_panel_vadd;
+};
+
+#endif /* _TC35876X_H */