phone-pad:add code for nas touchscreen
authorzwp <zwp@rock-chips.com>
Mon, 8 Aug 2011 03:53:09 +0000 (20:53 -0700)
committerzwp <zwp@rock-chips.com>
Mon, 8 Aug 2011 03:53:09 +0000 (20:53 -0700)
arch/arm/configs/rk29_phonepadsdk_defconfig
arch/arm/mach-rk29/board-rk29phonepadsdk.c [changed mode: 0644->0755]
arch/arm/mach-rk29/include/mach/board.h
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile [changed mode: 0755->0644]
drivers/input/touchscreen/nas_ts.c [new file with mode: 0755]

index 1bb061035c65f93eb920da299ed117064caae06f..b0bb4a157f9eae38d61040fcea2bd04fdad35cef 100755 (executable)
@@ -1053,7 +1053,8 @@ CONFIG_INPUT_TOUCHSCREEN=y
 # CONFIG_EETI_EGALAX is not set
 # CONFIG_TOUCHSCREEN_IT7260 is not set
 # CONFIG_TOUCHSCREEN_GT801_IIC is not set
-CONFIG_D70_L3188A=y
+CONFIG_TOUCHSCREEN_NAS=y
+#CONFIG_D70_L3188A is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 # CONFIG_INPUT_GPIO is not set
old mode 100644 (file)
new mode 100755 (executable)
index 63eb59c..5e10e9a
@@ -446,6 +446,7 @@ struct p1003_platform_data p1003_info = {
 };
 #endif
 #if defined (CONFIG_EETI_EGALAX)
+
 #define TOUCH_RESET_PIN RK29_PIN6_PC3
 #define TOUCH_INT_PIN   RK29_PIN0_PA2
 
@@ -481,7 +482,62 @@ static struct eeti_egalax_platform_data eeti_egalax_info = {
   .disp_on_pin = TOUCH_SCREEN_DISPLAY_PIN,
   .disp_on_value = TOUCH_SCREEN_DISPLAY_VALUE,
 };
+
 #endif
+//tcl miaozh add
+/*Nas touch*/
+#if defined (CONFIG_TOUCHSCREEN_NAS)
+#define TOUCH_RESET_PIN RK29_PIN6_PC3
+#define TOUCH_INT_PIN   RK29_PIN0_PA2
+void nas_reset(void)
+{
+    msleep(5);
+    gpio_pull_updown(TOUCH_INT_PIN, 1);
+    gpio_direction_output(TOUCH_RESET_PIN, 0);
+    msleep(5);
+    gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW);
+    msleep(200);
+    gpio_set_value(TOUCH_RESET_PIN,GPIO_HIGH);
+}
+void nas_hold(void)
+{
+    printk("nas_hold()\n");
+    gpio_direction_output(TOUCH_RESET_PIN, 0);
+    msleep(5);
+    gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW);
+    msleep(30);
+ }
+void nas_request_io(void)
+{
+    if(gpio_request(TOUCH_RESET_PIN,NULL) != 0){
+      gpio_free(TOUCH_RESET_PIN);
+      printk("nas_init_platform_hw gpio_request error\n");
+      return -EIO;
+    }
+
+    if(gpio_request(TOUCH_INT_PIN,NULL) != 0){
+      gpio_free(TOUCH_INT_PIN);
+      printk("nas_init_platform_hw gpio_request error\n");
+      return -EIO;
+    }
+}
+       
+int nas_init_platform_hw(void)
+{
+               printk("enter %s()\n", __FUNCTION__);
+               //nas_request_io();
+               //nas_reset();
+    return 0;
+}
+
+
+struct nas_platform_data nas_info = {
+  .model= 1003,
+  .init_platform_hw= nas_init_platform_hw,
+
+};
+#endif
+
 
 #if defined (CONFIG_D70_L3188A)
 struct goodix_i2c_rmi_platform_data d70_l3188a_info = {
@@ -801,6 +857,18 @@ static struct i2c_board_info __initdata board_i2c2_devices[] = {
       .platform_data  = &eeti_egalax_info,
     },
 #endif
+//tcl miaozh add
+#if defined (CONFIG_TOUCHSCREEN_NAS)
+    {
+      .type           = "nas_touch",
+      .addr           = (0x70>>1),
+      .flags          = 0, //I2C_M_NEED_DELAY
+      .irq            = RK29_PIN0_PA2,
+      .platform_data  = &nas_info,
+      //.udelay                  = 100
+    },
+#endif
+
 #if defined (CONFIG_D70_L3188A)
     {
       .type           = "goodix-ts",
index d9392b92400a95480c4567d9b100c8cbcbd81e6b..4697387cbc182e64da07157cf8772fe68cdbc827 100755 (executable)
@@ -267,6 +267,18 @@ struct cs42l52_platform_data {
     void    (*exit_platform_hw)(void);
 };
 
+//tcl miaozh add
+/*nas touch */
+struct nas_platform_data {
+    u16     model;
+
+    int     (*get_pendown_state)(void);
+    int     (*init_platform_hw)(void);
+    int     (*nas_platform_sleep)(void);
+    int     (*nas_platform_wakeup)(void);
+    void    (*exit_platform_hw)(void);
+};
+
 
 struct akm8975_platform_data {
        char layouts[3][3];
index 741273af370178519badfd58d538bf60317b8d27..2fc678712b09e9f50f3d1a0aaa52f00622c3f6c2 100755 (executable)
@@ -724,6 +724,16 @@ config TOUCHSCREEN_IT7260
 
          If unsure, say N (but it's safe to say "Y").
 
+config TOUCHSCREEN_NAS
+        tristate "NAS based touchscreens: NAS Interface"
+        depends on I2C2_RK29
+        help
+          Say Y here if you have a touchscreen interface using the
+          nas controller, and your board-specific initialization
+          code includes that in its table of I2C devices.
+
+          If unsure, say N (but it's safe to say "Y").
+
 config TOUCHSCREEN_GT801_IIC
        tristate "GT801_IIC based touchscreens"
        depends on I2C2_RK29
old mode 100755 (executable)
new mode 100644 (file)
index 8fb0c7f..1bacb58
@@ -59,3 +59,4 @@ obj-$(CONFIG_TOUCHSCREEN_ILI2102_IIC)      += ili2102_ts.o
 obj-$(CONFIG_D70_L3188A)      += goodix_touch.o
 obj-$(CONFIG_TOUCHSCREEN_FT5406) += ft5406_ts.o  
 obj-$(CONFIG_TOUCHSCREEN_GT819) += gt819.o
+obj-$(CONFIG_TOUCHSCREEN_NAS)      += nas_ts.o
diff --git a/drivers/input/touchscreen/nas_ts.c b/drivers/input/touchscreen/nas_ts.c
new file mode 100755 (executable)
index 0000000..a118c4e
--- /dev/null
@@ -0,0 +1,993 @@
+/****************************************************************************************
+ * driver/input/touchscreen/hannstar_nas.c
+ *Copyright    :ROCKCHIP  Inc
+ *Author       :       sfm
+ *Date         :  2010.2.5
+ *This driver use for rk28 chip extern touchscreen. Use i2c IF ,the chip is Hannstar
+ *description??
+ ********************************************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/earlysuspend.h>
+#include <linux/hrtimer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/async.h>
+#include <mach/gpio.h>
+#include <linux/irq.h>
+#include <mach/board.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+
+#include <linux/earlysuspend.h>
+#define MAX_SUPPORT_POINT      2// //  4
+#define PACKGE_BUFLEN          10
+
+#define        CHECK_STATUS    1
+//#define      TP_ERROR_RESTART_POWER  1
+
+//#define Singltouch_Mode
+//#define      NAS_TP_DEBUG    0
+#define SAKURA_DBG                  0
+#if SAKURA_DBG 
+#define sakura_dbg_msg(fmt,...)       do {                                      \
+                                   printk("sakura dbg msg------>"                       \
+                                          " (func-->%s ; line-->%d) " fmt, __func__, __LINE__ , ##__VA_ARGS__); \
+                                  } while(0)
+#define sakura_dbg_report_key_msg(fmt,...)      do{                                                     \
+                                                    printk("sakura report " fmt,##__VA_ARGS__);          \
+                                                }while(0)
+#else
+#define sakura_dbg_msg(fmt,...)       do {} while(0)
+#define sakura_dbg_report_key_msg(fmt,...)      do{}while(0)
+#endif
+
+#define SWAP_Y_POS
+#define TOUCH_REPORT_X_MAX        1280//(1255) //(1280 - 1)//(0xfff)
+#define TOUCH_REPORT_Y_MAX        768//(700)   //(768 - 1)//(0xfff)
+
+#define RECORD_PREVIOUS_VALUES
+#define FILTER_SAME_POINTS
+
+#define NASTECH_ZERO_TOUCH        0    
+#define NASTECH_ONE_TOUCH         1
+#define NASTECH_TWO_TOUCH         2
+#define NASTECH_PENUP_RECHECK     3
+#define NASTECH_DeltaX            100
+#define NASTECH_DeltaY            80
+#define NASTECH_R_Threshold       4000
+
+/*delay used to check the touch panel current status.*/
+#define TS_RELEASE_CHECK_DELAY         (100)
+#define TS_CUR_STATUS_PUSH                     1
+#define TS_CUR_STATUS_RELEASE          0
+#define TS_POLL_DELAY_DOWN        (2)  /* ms delay before the first sample */
+#define TS_POLL_DELAY_UP          (10)  /* ms delay after pen up, to double check the pen up event */
+#define TS_POLL_PERIOD            (30)  /* ms delay between samples */
+#define PENUP_DETECT_MAX          (4)   /* How many times we should detect for a penup event. */
+#define INT_TEST_TIMES            40
+
+struct touch_point {
+       int count;
+       int curX;
+       int curY;
+       int unCalX;
+       int unCalY;
+       int prevX;
+       int prevY;
+#ifdef RECORD_PREVIOUS_VALUES
+       int sample_time;
+       int last_finger;
+       int x[2];
+       int y[2];
+#endif
+};
+
+struct point_data {    
+       short status;   
+       short x;        
+       short y;
+    short z;
+};
+
+struct multitouch_event{
+       struct point_data point_data[MAX_SUPPORT_POINT];
+       int contactid;
+    int validtouch;
+};
+
+struct ts_nas {
+       struct input_dev        *input;
+       char                    phys[32];
+       struct delayed_work     work;
+       struct workqueue_struct *wq;
+
+       struct i2c_client       *client;
+    struct multitouch_event mt_event;
+       u16                     model;
+
+       bool            pendown;
+       bool            status;
+       int                     irq;
+       int             has_relative_report;
+//add from nas
+
+       bool                sleepstatus;
+       bool                pendown_sent;          /* Whether we've sent out a pendown event */
+       bool                pendown_ignore;        /* Sample two points and send out only one point */
+       int                 penup_recheck;         /* Pen up re-check times, when it reaches PENUP_DETECTE_MAX, pen up is reported. */
+       int                 release_check_time; /* Debounse time for pen down, ms */
+       int                 pendown_debounce_time; /* Debounse time for pen down, ms */
+       int                 penup_debounce_time;   /* Debounce time for pen up, ms */
+       int                 repeat_time;           /* Time between samples, ms */
+       struct touch_point  point;
+       struct timer_list       status_check_timer;
+       int                 reported_finger_count;
+       int                             touch_cur_status;
+
+       int                     (*get_pendown_state)(void);
+       void            (*clear_penirq)(void);
+#ifdef CHECK_STATUS    
+       struct delayed_work     work1;
+       struct workqueue_struct *wq1;
+#endif 
+       
+};
+
+//mg gamma
+unsigned short y_gamma[]={
+ 0 ,   0 ,   1 ,   1 ,       
+ 2 ,   3 ,   3 ,   4 ,   5 ,   6 ,   6 ,   7 ,       
+ 8 ,   9 ,   10 ,   10 ,   11 ,   12 ,   13 ,   14 ,       
+ 15 ,   15 ,   16 ,   17 ,   18 ,   19 ,   20 ,   21 ,       
+ 21 ,   22 ,   23 ,   24 ,   25 ,   26 ,   27 ,   28 ,       
+ 28 ,   29 ,   30 ,   31 ,   32 ,   33 ,   34 ,   35 ,       
+ 36 ,   37 ,   38 ,   38 ,   39 ,   40 ,   41 ,   42 ,       
+ 43 ,   44 ,   45 ,   46 ,   47 ,   48 ,   49 ,   50 ,       
+ 51 ,   52 ,   52 ,   53 ,   54 ,   55 ,   56 ,   57 ,       
+ 58 ,   59 ,   60 ,   61 ,   62 ,   63 ,   64 ,   65 ,       
+ 66 ,   67 ,   68 ,   69 ,   70 ,   71 ,   72 ,   73 ,       
+ 74 ,   75 ,   76 ,   77 ,   78 ,   79 ,   80 ,   81 ,       
+ 82 ,   83 ,   84 ,   85 ,   86 ,   87 ,   88 ,   89 ,       
+ 90 ,   91 ,   92 ,   93 ,   94 ,   95 ,   96 ,   97 ,       
+ 98 ,   99 ,   100 ,   101 ,   102 ,   103 ,   104 ,   105 ,       
+ 106 ,   107 ,   108 ,   109 ,   110 ,   111 ,   112 ,   113 ,       
+ 114 ,   115 ,   116 ,   117 ,   118 ,   119 ,   120 ,   121 ,       
+ 122 ,   123 ,   124 ,   125 ,   126 ,   127 ,   128 ,   129 ,       
+ 130 ,   132 ,   133 ,   134 ,   135 ,   136 ,   137 ,   138 ,       
+ 139 ,   140 ,   141 ,   142 ,   143 ,   144 ,   145 ,   146 ,       
+ 147 ,   148 ,   149 ,   150 ,   151 ,   152 ,   154 ,   155 ,       
+ 156 ,   157 ,   158 ,   159 ,   160 ,   161 ,   162 ,   163 ,       
+ 164 ,   165 ,   166 ,   167 ,   168 ,   169 ,   171 ,   172 ,       
+ 173 ,   174 ,   175 ,   176 ,   177 ,   178 ,   179 ,   180 ,       
+ 181 ,   182 ,   183 ,   184 ,   186 ,   187 ,   188 ,   189 ,       
+ 190 ,   191 ,   192 ,   193 ,   194 ,   195 ,   196 ,   197 ,       
+ 199 ,   200 ,   201 ,   202 ,   203 ,   204 ,   205 ,   206 ,       
+ 207 ,   208 ,   209 ,   210 ,   212 ,   213 ,   214 ,   215 ,       
+ 216 ,   217 ,   218 ,   219 ,   220 ,   221 ,   222 ,   224 ,       
+ 225 ,   226 ,   227 ,   228 ,   229 ,   230 ,   231 ,   232 ,       
+ 233 ,   235 ,   236 ,   237 };
+
+unsigned short y_gamma900[]={
+0 ,   0 ,   1 ,   2 ,       
+ 3 ,   4 ,   4 ,   5 ,   6 ,   7 ,   8 ,   9 ,       
+ 10 ,   11 ,   12 ,   12 ,   13 ,   14 ,   15 ,   16 ,       
+ 17 ,   18 ,   19 ,   20 ,   21 ,   22 ,   23 ,   23 ,       
+ 24 ,   25 ,   26 ,   27 ,   28 ,   29 ,   30 ,   31 ,       
+ 32 ,   33 ,   34 ,   35 ,   36 ,   37 ,   38 ,   39 ,       
+ 40 ,   41 ,   42 ,   42 ,   43 ,   44 ,   45 ,   46 ,       
+ 47 ,   48 ,   49 ,   50 ,   51 ,   52 ,   53 ,   54 ,       
+ 55 ,   56 ,   57 ,   58 ,   59 ,   60 ,   61 ,   62 ,       
+ 63 ,   64 ,   65 ,   66 ,   67 ,   68 ,   69 ,   70 ,       
+ 71 ,   72 ,   73 ,   74 ,   75 ,   76 ,   77 ,   78 ,       
+ 79 ,   80 ,   81 ,   82 ,   83 ,   84 ,   85 ,   86 ,       
+ 87 ,   88 ,   89 ,   90 ,   91 ,   92 ,   93 ,   94 ,       
+ 95 ,   96 ,   97 ,   98 ,   99 ,   100 ,   101 ,   102 ,       
+ 103 ,   104 ,   105 ,   106 ,   107 ,   108 ,   109 ,   110 ,       
+ 111 ,   112 ,   113 ,   114 ,   115 ,   116 ,   117 ,   118 ,       
+ 119 ,   120 ,   121 ,   122 ,   123 ,   124 ,   125 ,   126 ,       
+ 127 ,   128 ,   129 ,   130 ,   131 ,   132 ,   133 ,   134 ,       
+ 135 ,   136 ,   137 ,   138 ,   139 ,   140 ,   141 ,   142 ,       
+ 143 ,   144 ,   145 ,   146 ,   147 ,   148 ,   149 ,   150 ,       
+ 152 ,   153 ,   154 ,   155 ,   156 ,   157 ,   158 ,   159 ,       
+ 160 ,   161 ,   162 ,   163 ,   164 ,   165 ,   166 ,   167 ,       
+ 168 ,   169 ,   170 ,   171 ,   172 ,   173 ,   174 ,   175 ,       
+ 176 ,   177 ,   178 ,   179 ,   180 ,   181 ,   182 ,   183 ,       
+ 185 ,   186 ,   187 ,   188 ,   189 ,   190 ,   191 ,   192 ,       
+ 193 ,   194 ,   195 ,   196 ,   197 ,   198 ,   199 ,   200 ,       
+ 201 ,   202 ,   203 ,   204 ,   205 ,   206 ,   207 ,   208 ,       
+ 209 ,   210 ,   212 ,   213 ,   214 ,   215 ,   216 ,   217 ,       
+ 218 ,   219 ,   220 ,   221 ,   222 ,   223 ,   224 ,   225 ,       
+ 226 ,   227 ,   228 ,   229 ,   230 ,   231 ,   232 ,   233 ,       
+ 235 ,   236 ,   237 ,   238  };  
+
+
+unsigned short y_gamma800[]={
+  0 ,   0 ,   0 ,   0 ,   1 ,   1 ,       
+ 2 ,   2 ,   3 ,   3 ,   4 ,   5 ,   5 ,   6 ,       
+ 6 ,   7 ,   8 ,   8 ,   9 ,   9 ,   10 ,   11 ,       
+ 11 ,   12 ,   13 ,   13 ,   14 ,   15 ,   16 ,   16 ,       
+ 17 ,   18 ,   19 ,   19 ,   20 ,   21 ,   22 ,   22 ,       
+ 23 ,   24 ,   25 ,   25 ,   26 ,   27 ,   28 ,   29 ,       
+ 29 ,   30 ,   31 ,   32 ,   33 ,   34 ,   34 ,   35 ,       
+ 36 ,   37 ,   38 ,   39 ,   40 ,   40 ,   41 ,   42 ,       
+ 43 ,   44 ,   45 ,   46 ,   47 ,   47 ,   48 ,   49 ,       
+ 50 ,   51 ,   52 ,   53 ,   54 ,   55 ,   56 ,   57 ,       
+ 58 ,   58 ,   59 ,   60 ,   61 ,   62 ,   63 ,   64 ,       
+ 65 ,   66 ,   67 ,   68 ,   69 ,   70 ,   71 ,   72 ,       
+ 73 ,   74 ,   75 ,   76 ,   77 ,   78 ,   79 ,   80 ,       
+ 81 ,   82 ,   83 ,   84 ,   85 ,   86 ,   87 ,   88 ,       
+ 89 ,   90 ,   91 ,   92 ,   93 ,   94 ,   95 ,   96 ,       
+ 97 ,   98 ,   99 ,   100 ,   101 ,   102 ,   103 ,   104 ,       
+ 105 ,   106 ,   107 ,   108 ,   109 ,   110 ,   111 ,   113 ,       
+ 114 ,   115 ,   116 ,   117 ,   118 ,   119 ,   120 ,   121 ,       
+ 122 ,   123 ,   124 ,   125 ,   127 ,   128 ,   129 ,   130 ,       
+ 131 ,   132 ,   133 ,   134 ,   135 ,   136 ,   137 ,   139 ,       
+ 140 ,   141 ,   142 ,   143 ,   144 ,   145 ,   146 ,   147 ,       
+ 149 ,   150 ,   151 ,   152 ,   153 ,   154 ,   155 ,   157 ,       
+ 158 ,   159 ,   160 ,   161 ,   162 ,   163 ,   164 ,   166 ,       
+ 167 ,   168 ,   169 ,   170 ,   171 ,   173 ,   174 ,   175 ,       
+ 176 ,   177 ,   178 ,   180 ,   181 ,   182 ,   183 ,   184 ,       
+ 185 ,   187 ,   188 ,   189 ,   190 ,   191 ,   192 ,   194 ,       
+ 195 ,   196 ,   197 ,   198 ,   200 ,   201 ,   202 ,   203 ,       
+ 204 ,   206 ,   207 ,   208 ,   209 ,   210 ,   212 ,   213 ,       
+ 214 ,   215 ,   216 ,   218 ,   219 ,   220 ,   221 ,   222 ,       
+ 224 ,   225 ,   226 ,   227 ,   229 ,   230 ,   231 ,   232 ,       
+ 233 ,   235 ,   236 ,   237 ,   238 ,   240 ,   241 ,   242 ,       
+ 243 ,   245 ,   246 ,   247 ,   248 ,   250 ,   251 ,   252 ,       
+ 253 ,   255 ,   256 ,   257 ,   258 ,   260 ,   261 ,   262  
+};
+
+static struct proc_dir_entry *nas_tp_debug_ctl_entry;
+static char nas_tp_debug_flag = 0;
+
+extern void nas_reset(void);
+static void nas_early_resume(struct early_suspend *h)
+{
+       //nas_reset();
+}
+static struct early_suspend nastech_early_suspend =
+{
+       .resume = nas_early_resume
+};
+#ifdef CHECK_STATUS
+static void nas_status_check_timer(unsigned long data)
+{
+       unsigned char buf[4]={0};
+       struct ts_nas *ts_dev = (struct ts_nas *)data;
+       int ret=0;
+       //printk("nas_status_check_timer ...\n");
+               queue_delayed_work(ts_dev->wq1, &ts_dev->work1, 0);
+       ts_dev->status_check_timer.expires  = jiffies + msecs_to_jiffies(1000);
+       add_timer(&ts_dev->status_check_timer);
+}
+
+#define FB_DISPLAY_ON_PIN RK29_PIN6_PD0
+extern void rk29_lcd_reset(void);
+static void nas_status_check_work(struct work_struct *work1)
+{
+       unsigned char buf[4]={0};
+       struct ts_nas *ts_dev =
+               container_of(to_delayed_work(work1), struct ts_nas, work1);
+       int ret=0;
+
+       if (GPIO_LOW == gpio_get_value(FB_DISPLAY_ON_PIN))
+               return;
+
+       //printk("nas_status_check_work ...");
+       ret = i2c_master_reg8_recv( ts_dev->client, 0xFC, buf, 1, 200*1000);
+       //printk(" ret = %d\n", ret);
+       if( ret <0)
+       {
+               printk("nas status error, ret=%d \nnas_reset()\n", ret);
+#ifdef TP_ERROR_RESTART_POWER          
+               rk29_lcd_reset();
+               msleep(100);
+#endif         
+               nas_reset();
+       }
+}      
+#endif
+/** Get point from touch pannel */
+static int nastech_ts_get_point(struct ts_nas *ts_dev, unsigned short *pX, unsigned short *pY)
+{
+       unsigned short xpos, ypos;
+       unsigned short xpos0, ypos0;
+       unsigned char event;
+       unsigned char Finger, hwFinger;
+       unsigned char buf[26];
+       //unsigned char buf[13]; // for 2 finger touch, only used the first 13 bytes
+       int ret;
+       int nTouch = 0;
+       struct i2c_client *client = ts_dev->client;
+       struct input_dev *input = ts_dev->input;
+
+       memset(buf, 0xff, sizeof(buf));
+       //ret = nastech_read_regs(client, NASTECH_READ_POS, buf, sizeof(buf));
+       ret = i2c_master_reg8_recv( ts_dev->client, 0xF9, buf, 26, 200*1000);
+
+       hwFinger=buf[3];
+
+       //-------------------------------------------------------------------------------------------
+       //xpos=(unsigned short)(buf[7]*0x100);
+       xpos=(unsigned short)((buf[7]&0x0f)<<8 );
+       xpos=xpos|buf[8];
+       //ypos=(unsigned short)(buf[5]*0x100);
+       ypos=(unsigned short)((buf[5]&0x0f)<<8 );
+       ypos=ypos|buf[6];
+
+       //xpos0=(unsigned short)(buf[11]*0x100);
+       xpos0=(unsigned short)((buf[11]&0x0f)<<8 );
+       xpos0=xpos0|buf[12];
+       //ypos0=(unsigned short)(buf[9]*0x100);
+       ypos0=(unsigned short)((buf[9]&0x0f)<<8 );
+       ypos0=ypos0|buf[10];
+       //-------------------------------------------------------------------------------------------
+       
+//#ifdef NAS_TP_DEBUG
+       if (nas_tp_debug_flag == 1)
+               printk(KERN_INFO "read from TP: (%d,%d), (%d,%d)\n", xpos, ypos, xpos0, ypos0);
+//#endif
+unsigned short   ypos_pre,ratio;
+
+
+
+       *pX = xpos;
+       *pY = ypos;
+
+#ifdef TOUCH_REPORT_ONLY_ONE_POINT
+       if(xpos==0x0FFF || ypos==0x0FFF)
+       {
+               Finger = NASTECH_ZERO_TOUCH;
+       }
+       else
+       {
+               Finger = NASTECH_ONE_TOUCH;
+       }
+#else
+
+       if(xpos==0x0FFF || ypos==0x0FFF)
+       {
+               Finger = NASTECH_ZERO_TOUCH;
+       }
+       else
+       {
+               Finger = NASTECH_ONE_TOUCH;
+       }
+       
+       if(xpos0!=0x0FFF && ypos0!=0x0FFF)
+       {
+               Finger = NASTECH_TWO_TOUCH;
+       }
+
+#ifdef SWAP_Y_POS
+ypos = TOUCH_REPORT_Y_MAX - ypos;
+       if(ypos < 0)
+               ypos = 0;
+               
+        if (ypos<262)
+{
+   ratio=ypos;
+                ypos= y_gamma800[ratio];
+            
+}
+ if (ypos>506)
+{
+    
+   ratio= 767-ypos ;
+         ypos=767-y_gamma800[ratio];
+               
+            
+}
+
+
+       if (xpos<262)
+{
+   ratio=xpos;
+                xpos= y_gamma800[ratio];
+            
+}
+if (xpos>1017)
+{
+   ratio=1279-xpos;
+                xpos= 1279-y_gamma800[ratio];
+            
+}
+
+
+       //ypos=report_y_correction(y_pre); //mg for coorection  
+       
+       ypos0 = TOUCH_REPORT_Y_MAX - ypos0;
+       if(ypos0 < 0)
+               ypos0 = 0;
+               
+        if (ypos0<262)
+{
+   ratio=ypos0;
+                ypos0= y_gamma800[ratio];
+            
+}
+ if (ypos0>506)
+{
+    
+   ratio= 767-ypos0 ;
+         ypos0=767-y_gamma800[ratio];
+               
+            
+}
+
+
+       if (xpos0<262)
+{
+   ratio=xpos0;
+                xpos0= y_gamma800[ratio];
+            
+}
+if (xpos>1017)
+{
+   ratio=1279-xpos0;
+                xpos0= 1279-y_gamma800[ratio];
+            
+}       
+#endif
+//#ifdef NAS_TP_DEBUG
+       if (nas_tp_debug_flag == 1) {
+               if (NASTECH_TWO_TOUCH == Finger) {
+                       printk(KERN_INFO "original: (%d,%d), (%d,%d)\n", xpos, ypos, xpos0, ypos0);
+               } else if (NASTECH_ONE_TOUCH == Finger) {
+                       printk(KERN_INFO "original: (%d,%d)\n", xpos, ypos);
+               }
+       }
+//#endif
+       //printk("nastech_ts_get_point: Finger = %d!\n",Finger);
+#ifdef RECORD_PREVIOUS_VALUES
+       if (ts_dev->point.last_finger == Finger)
+       {
+               switch(Finger)
+               {
+               case NASTECH_ZERO_TOUCH:
+                       break;
+               case NASTECH_ONE_TOUCH:
+                       if (ts_dev->point.x[0] == xpos && ts_dev->point.y[0] == ypos)
+                               return Finger;
+                       break;
+               case NASTECH_TWO_TOUCH:
+                       if ((ts_dev->point.x[0] == xpos && ts_dev->point.y[0] == ypos)
+                               && (ts_dev->point.x[1] == xpos0 && ts_dev->point.y[1] == ypos0))
+                               return Finger;
+                       break;
+               }
+               ts_dev->point.x[0] = xpos;
+               ts_dev->point.y[0] = ypos;
+               ts_dev->point.x[1] = xpos0;
+               ts_dev->point.y[1] = ypos0;
+       }
+       else
+       {
+               ts_dev->point.last_finger = Finger;
+               ts_dev->point.x[0] = xpos;
+               ts_dev->point.y[0] = ypos;
+               ts_dev->point.x[1] = xpos0;
+               ts_dev->point.y[1] = ypos0;
+       }
+#endif
+       {
+               int z,w;
+               if(!Finger)
+               {
+                       z=0;
+                       w=0;
+               }
+               else
+               {
+                       z=255;
+                       w=15;
+               }
+
+               ts_dev->touch_cur_status = TS_CUR_STATUS_PUSH;
+               
+               if(Finger>1)
+               {
+                       input_report_abs(input, ABS_MT_TOUCH_MAJOR, z);
+                       input_report_abs(input, ABS_MT_WIDTH_MAJOR, w);
+                       input_report_abs(input, ABS_MT_POSITION_X, xpos);
+                       input_report_abs(input, ABS_MT_POSITION_Y, ypos);
+                       input_report_key(ts_dev->input, BTN_TOUCH, 1);
+                       input_mt_sync(input);
+                       
+                       input_report_abs(input, ABS_MT_TOUCH_MAJOR, z);
+                       input_report_abs(input, ABS_MT_WIDTH_MAJOR, w);
+                       input_report_abs(input, ABS_MT_POSITION_X, xpos0);
+                       input_report_abs(input, ABS_MT_POSITION_Y, ypos0);
+                       input_report_key(ts_dev->input, BTN_2, 1);
+                       input_mt_sync(input);
+               }
+               else
+               {
+                       if (1 == Finger)
+                       {
+                               input_report_abs(input, ABS_MT_POSITION_X, xpos);
+                               input_report_abs(input, ABS_MT_POSITION_Y, ypos);
+                               input_report_abs(input, ABS_MT_TOUCH_MAJOR, z);
+                               input_report_abs(input, ABS_MT_WIDTH_MAJOR, w);
+                               input_report_key(ts_dev->input, BTN_TOUCH, 1);
+                               input_mt_sync(input);
+                               //printk("pen press (x,y):(%d,%d)\n",xpos,ypos);
+                       }
+                       else
+                       {
+                       //      printk("nastech_ts_get_point: released......!\n");
+                               input_report_abs(input, ABS_MT_POSITION_X, xpos);
+                               input_report_abs(input, ABS_MT_POSITION_Y, ypos);
+                               input_report_abs(input, ABS_MT_TOUCH_MAJOR, z);
+                               input_report_abs(input, ABS_MT_WIDTH_MAJOR, w);
+                               input_report_key(ts_dev->input, BTN_TOUCH, 0);
+                               input_mt_sync(input);
+                               ts_dev->touch_cur_status = TS_CUR_STATUS_RELEASE;
+                       }
+                       
+                       if(ts_dev->reported_finger_count > 1)
+                       {
+                               input_report_abs(input, ABS_MT_POSITION_X, xpos);
+                               input_report_abs(input, ABS_MT_POSITION_Y, ypos);
+                               input_report_abs(input, ABS_MT_TOUCH_MAJOR, 0);
+                               input_report_abs(input, ABS_MT_WIDTH_MAJOR, 0);
+                               input_report_key(ts_dev->input, BTN_2, 0);
+                               input_mt_sync(input);
+                       }
+               }
+               ts_dev->reported_finger_count = Finger;
+       }
+       input_sync(input);
+#endif
+       return (int)Finger;
+}
+
+static int nastech_sample_new_point(struct ts_nas *ts_dev)
+{
+       unsigned short  x, y;
+       unsigned int nTouch = 0;
+       
+       struct i2c_client *client = ts_dev->client;
+       struct touch_point *point = &ts_dev->point;
+       
+       nTouch = nastech_ts_get_point(ts_dev, &x, &y);
+       point->unCalX = x;
+       point->unCalY = y;
+
+       if (unlikely(NASTECH_ZERO_TOUCH == nTouch)) {
+               //printk(KERN_INFO "<======Pen released at (%d, %d)\n", point->prevX, point->prevY);
+               point->curX = point->curY = 0;
+               point->count = 0;
+       } else {
+               point->curX = x;
+               point->curY = y;
+#ifdef TOUCHPANEL_SWAP_XY
+               {
+                       int temp = point->curX;
+                       point->curX = point->curY;
+                       point->curY = temp;
+               }
+#endif
+               if(nTouch == NASTECH_ONE_TOUCH) {
+                       if( !ts_dev->pendown_sent || (abs(point->curX-point->prevX) < NASTECH_DeltaX)
+                               && (abs(point->curY - point->prevY) < NASTECH_DeltaY) ){ // is it a movement ? 
+                               // update pX, pY and send new point
+                               point->prevX = point->curX;
+                               point->prevY = point->curY;
+                       } else {
+                               printk(KERN_INFO "use the old touch: prev=(%d,%d), cur=(%d,%d)\n",
+                                               point->prevX, point->prevY, point->curX, point->curY);
+                               // use old one
+                               point->curX = point->prevX;
+                               point->curY = point->prevY;
+                       }
+               }
+       }
+       return nTouch;
+}
+int nas_get_pendown_state(void)
+{
+       return 0;
+}
+
+static void nas_report_event(struct ts_nas *ts,struct multitouch_event *tc)
+{
+       struct input_dev *input = ts->input;
+    int i,pandown = 0;
+       dev_dbg(&ts->client->dev, "UP\n");
+               
+    for(i=0; i<MAX_SUPPORT_POINT;i++){                 
+        if(tc->point_data[i].status >= 0){
+            pandown |= tc->point_data[i].status;
+            input_report_abs(input, ABS_MT_TRACKING_ID, i);                                                    
+            input_report_abs(input, ABS_MT_TOUCH_MAJOR, tc->point_data[i].status);                             
+            input_report_abs(input, ABS_MT_WIDTH_MAJOR, 0);    
+            input_report_abs(input, ABS_MT_POSITION_X, tc->point_data[i].x);                           
+            input_report_abs(input, ABS_MT_POSITION_Y, tc->point_data[i].y);                           
+            input_mt_sync(input);      
+
+            sakura_dbg_report_key_msg("ABS_MT_TRACKING_ID = %x, ABS_MT_TOUCH_MAJOR = %x\n ABS_MT_POSITION_X = %x, ABS_MT_POSITION_Y = %x\n",i,tc->point_data[i].status,tc->point_data[i].x,tc->point_data[i].y);
+#if defined(CONFIG_HANNSTAR_DEBUG)
+                       printk("hannstar nas Px = [%d],Py = [%d] \n",tc->point_data[i].x,tc->point_data[i].y);
+#endif
+
+            if(tc->point_data[i].status == 0)                                  
+               tc->point_data[i].status--;                     
+        }
+        
+    }  
+
+    ts->pendown = pandown;
+    input_sync(input);
+}
+
+
+static inline int nas_check_firmwork(struct ts_nas *ts)
+{
+    int data;
+    int len = 10;
+    char buf[10] = {0x03 , 0x03 , 0x0a , 0x01 , 'D' , 0x00 , 0x00 , 0x00 , 0x00 , 0x00};
+       int i;
+    short contactid=0;
+
+    data = i2c_master_normal_send(ts->client, buf,len, 200*1000);
+
+       if(data < 0){
+               dev_err(&ts->client->dev, "i2c io error %d \n", data);
+               return data;
+       }
+
+       data = i2c_master_normal_recv(ts->client, buf,len, 200*1000);
+
+       if(data < 0){
+               dev_err(&ts->client->dev, "i2c io error %d \n", data);
+               return data;
+       }
+
+       printk("nas reg[5] = %c ,reg[6] = %c, reg[7] = %c, reg[8] = %c\n" , buf[5],buf[6],buf[7],buf[8]);
+       printk("nas reg[5] = %x ,reg[6] = %x, reg[7] = %x, reg[8] = %x\n" , buf[5],buf[6],buf[7],buf[8]);
+    return data;
+}
+
+
+static inline int nas_read_values(struct ts_nas *ts, struct multitouch_event *tc)
+{
+    int data, j;
+    int len = 10;
+       char buff[26];
+       int ret;
+       int i;
+       unsigned short xpos, ypos, xpos0, ypos0;
+       memset(buff, 0xff, sizeof(buff));
+       ret = i2c_master_reg8_recv( ts->client, 0xF9, buff, 26, 200*1000);
+/*
+       printk("ret = %d, buff[]=\n", ret);
+       for(i=0; i<26; i++)
+       {
+               if(i %8 == 0)
+                       printk("\n");
+               printk("0x%02x ", buff[i]);
+       }
+*/
+       //-------------------------------------------------------------------------------------------
+       //xpos=(unsigned short)(buf[7]*0x100);
+       xpos=(unsigned short)((buff[7]&0x0f)<<8 );
+       xpos=xpos|buff[8];
+       //ypos=(unsigned short)(buf[5]*0x100);
+       ypos=(unsigned short)((buff[5]&0x0f)<<8 );
+       ypos=ypos|buff[6];
+
+       //xpos0=(unsigned short)(buf[11]*0x100);
+       xpos0=(unsigned short)((buff[11]&0x0f)<<8 );
+       xpos0=xpos0|buff[12];
+       //ypos0=(unsigned short)(buf[9]*0x100);
+       ypos0=(unsigned short)((buff[9]&0x0f)<<8 );
+       ypos0=ypos0|buff[10];
+       //-------------------------------------------------------------------------------------------
+       
+//     printk("read from TP: (%d,%d), (%d,%d)\n", xpos, ypos, xpos0, ypos0);
+    return 10;
+}
+
+
+static void nas_work(struct work_struct *work)
+{
+       struct ts_nas *ts =
+               container_of(to_delayed_work(work), struct ts_nas, work);
+       struct multitouch_event *tc = &ts->mt_event;
+       int rt;
+#if    0    
+       rt = nas_read_values(ts,tc);
+    
+    if(rt < 0)
+        goto out;
+       
+#if defined (Singltouch_Mode)
+    nas_report_single_event(ts,tc);
+#else
+    nas_report_event(ts,tc);
+#endif
+#endif
+
+//     if (ts->sleepstatus == 1)
+//             return;
+       
+       switch(nastech_sample_new_point(ts)) {
+       case NASTECH_ZERO_TOUCH:
+               break;
+       case NASTECH_ONE_TOUCH:
+       case NASTECH_TWO_TOUCH:
+#if    0
+               {
+                       /* periodly sample the next points */
+                       del_timer(&ts->repeat_timer);
+                       ts->repeat_timer.expires = jiffies + msecs_to_jiffies(ts->repeat_time);
+                       add_timer(&ts->repeat_timer);
+               }
+#endif
+               break;  
+       default:
+               break;
+       }
+out:               
+#if    1
+               enable_irq(ts->irq);
+#else
+       if (ts->pendown){
+               queue_delayed_work(ts->wq, &ts->work, msecs_to_jiffies(10));
+               ts->pendown = 0;
+       }
+       else{
+               enable_irq(ts->irq);
+       }
+#endif
+}
+
+static irqreturn_t nas_irq(int irq, void *handle)
+{
+       struct ts_nas *ts = handle;
+       //printk("enter nas_irq()\n");
+#if 1
+       if (!ts->get_pendown_state || likely(ts->get_pendown_state())) {
+               //printk("disable_irq_nosync()\n");
+               disable_irq_nosync(ts->irq);
+               queue_delayed_work(ts->wq, &ts->work, 0);
+       }
+
+#endif
+       return IRQ_HANDLED;
+}
+
+static void nas_free_irq(struct ts_nas *ts)
+{
+       free_irq(ts->irq, ts);
+       if (cancel_delayed_work_sync(&ts->work)) {
+               /*
+                * Work was pending, therefore we need to enable
+                * IRQ here to balance the disable_irq() done in the
+                * interrupt handler.
+                */
+               enable_irq(ts->irq);
+       }
+}
+
+
+static ssize_t nas_tp_debug_ctl(struct file *file, const char __user *buffer, size_t count, loff_t *data)
+{
+       char val;
+
+       if (copy_from_user(&val, buffer, 1))
+               return -EFAULT;
+
+       if (val != '0' && val != '1')
+               return -EINVAL;
+
+       nas_tp_debug_flag = val - '0';
+
+       return count;
+}
+
+static int __devinit nas_probe(struct i2c_client *client,
+                                  const struct i2c_device_id *id)
+{
+       struct ts_nas *ts;
+       struct nas_platform_data *pdata = pdata = client->dev.platform_data;
+       struct input_dev *input_dev;
+       int err;
+       
+       if (!pdata) {
+               dev_err(&client->dev, "platform data is required!\n");
+               return -EINVAL;
+       }
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+               return -EIO;
+
+       ts = kzalloc(sizeof(struct ts_nas), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!ts || !input_dev) {
+               err = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       ts->client = client;
+       ts->irq = client->irq;
+       ts->input = input_dev;
+       ts->status =0 ;// fjp add by 2010-9-30
+       ts->pendown = 0; // fjp add by 2010-10-06
+
+       ts->wq = create_rt_workqueue("nas_wq");
+       INIT_DELAYED_WORK(&ts->work, nas_work);
+       
+#ifdef CHECK_STATUS
+       ts->wq1 = create_rt_workqueue("nas_wq1");
+       INIT_DELAYED_WORK(&ts->work1, nas_status_check_work);
+#endif 
+       ts->model             = pdata->model;
+
+       snprintf(ts->phys, sizeof(ts->phys),
+                "%s/input0", dev_name(&client->dev));
+
+       input_dev->name = "nas Touchscreen";
+       input_dev->phys = ts->phys;
+       input_dev->id.bustype = BUS_I2C;
+
+       ts->has_relative_report = 0;
+       input_dev->evbit[0] = BIT_MASK(EV_ABS)|BIT_MASK(EV_KEY)|BIT_MASK(EV_SYN);
+       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       input_dev->keybit[BIT_WORD(BTN_2)] = BIT_MASK(BTN_2); //jaocbchen for dual
+#if    0
+       input_set_abs_params(input_dev, ABS_X, 0, CONFIG_HANNSTAR_MAX_X, 0, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, CONFIG_HANNSTAR_MAX_Y, 0, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
+       input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
+       input_set_abs_params(input_dev, ABS_HAT0X, 0, CONFIG_HANNSTAR_MAX_X, 0, 0);
+       input_set_abs_params(input_dev, ABS_HAT0Y, 0, CONFIG_HANNSTAR_MAX_Y, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_X,0, CONFIG_HANNSTAR_MAX_X, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, CONFIG_HANNSTAR_MAX_Y, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 10, 0, 0);   
+#else
+       input_set_abs_params(input_dev, ABS_X, 0, TOUCH_REPORT_X_MAX, 0, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, TOUCH_REPORT_Y_MAX, 0, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0);
+       input_set_abs_params(input_dev, ABS_HAT0X, 0, TOUCH_REPORT_X_MAX, 0, 0);
+       input_set_abs_params(input_dev, ABS_HAT0Y, 0, TOUCH_REPORT_Y_MAX, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, TOUCH_REPORT_X_MAX, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, TOUCH_REPORT_Y_MAX, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+       input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 15, 0, 0);
+#endif
+       if (pdata->init_platform_hw)
+               pdata->init_platform_hw();
+
+       if (!ts->irq) {
+               dev_dbg(&ts->client->dev, "no IRQ?\n");
+               return -ENODEV;
+       }else{
+               ts->irq = gpio_to_irq(ts->irq);
+       }
+//miaozh modify
+       err = request_irq(ts->irq, nas_irq, GPIOEdgelFalling,
+                       client->dev.driver->name, ts);
+//     err = request_irq(ts->irq, nas_irq, 0,
+//                     client->dev.driver->name, ts);
+       
+       if (err < 0) {
+               dev_err(&client->dev, "irq %d busy?\n", ts->irq);
+               goto err_free_mem;
+       }
+       
+       if (err < 0)
+               goto err_free_irq;
+#if 0
+       err = set_irq_type(ts->irq,IRQ_TYPE_LEVEL_LOW);
+       if (err < 0) {
+               dev_err(&client->dev, "irq %d busy?\n", ts->irq);
+               goto err_free_mem;
+       }
+       if (err < 0)
+               goto err_free_irq;
+#endif
+       err = input_register_device(input_dev);
+       if (err)
+               goto err_free_irq;
+
+       i2c_set_clientdata(client, ts);
+
+       nas_check_firmwork(ts);
+       
+       nas_tp_debug_ctl_entry = create_proc_entry("nas_tp_debug_ctl", 0644, NULL);
+       if (nas_tp_debug_ctl_entry) {
+               nas_tp_debug_ctl_entry->read_proc = NULL;
+               nas_tp_debug_ctl_entry->write_proc = nas_tp_debug_ctl;
+       }
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       register_early_suspend(&nastech_early_suspend);
+#endif
+
+#ifdef CHECK_STATUS
+       setup_timer(&ts->status_check_timer, nas_status_check_timer, (unsigned long)ts);
+       ts->status_check_timer.expires  = jiffies + msecs_to_jiffies(1000);
+       add_timer(&ts->status_check_timer);
+#endif 
+       return 0;
+
+ err_free_irq:
+       nas_free_irq(ts);
+       if (pdata->exit_platform_hw)
+               pdata->exit_platform_hw();
+ err_free_mem:
+       input_free_device(input_dev);
+       kfree(ts);
+       return err;
+}
+
+static int __devexit nas_remove(struct i2c_client *client)
+{
+       struct ts_nas *ts = i2c_get_clientdata(client);
+       struct nas_platform_data *pdata = client->dev.platform_data;
+
+       nas_free_irq(ts);
+
+       if (pdata->exit_platform_hw)
+               pdata->exit_platform_hw();
+
+       input_unregister_device(ts->input);
+       kfree(ts);
+       
+       if (nas_tp_debug_ctl_entry)
+               remove_proc_entry("nas_tp_debug_ctl", NULL);
+
+       return 0;
+}
+
+static struct i2c_device_id nas_idtable[] = {
+       { "nas_touch", 0 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, nas_idtable);
+
+static struct i2c_driver nas_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "nas_touch"
+       },
+       .id_table       = nas_idtable,
+       .probe          = nas_probe,
+       .remove         = __devexit_p(nas_remove),
+};
+
+static void __init nas_init_async(void *unused, async_cookie_t cookie)
+{
+       printk("--------> %s <-------------\n",__func__);
+       i2c_add_driver(&nas_driver);
+}
+
+static int __init nas_init(void)
+{
+       async_schedule(nas_init_async, NULL);
+       return 0;
+}
+
+static void __exit nas_exit(void)
+{
+       return i2c_del_driver(&nas_driver);
+}
+module_init(nas_init);
+module_exit(nas_exit);
+MODULE_LICENSE("GPL");
+