add touchscreen ctp_it7250
author邓训金 <dxj@rock-chips.com>
Mon, 23 Aug 2010 12:08:31 +0000 (20:08 +0800)
committer邓训金 <dxj@rock-chips.com>
Mon, 23 Aug 2010 12:08:31 +0000 (20:08 +0800)
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ctp_it7250.c [new file with mode: 0644]

index 4c712f5542ffb063375256be6c824cfa2e62fbe5..7e3975d838459a7f861596e1ca4dd5b6fd612254 100644 (file)
@@ -92,7 +92,16 @@ config TOUCHSCREEN_XPT2046_320X480_CBN_SPI
          If unsure, say N (but it's safe to say "Y").
 
          To compile this driver as a module, choose M here: the
-         module will be called xpt2046_cbn_ts.   
+         module will be called xpt2046_cbn_ts. 
+      
+config TOUCHSCREEN_IT7250
+       tristate "IT7250 based touchscreens: IT7250 Interface"
+       help
+         Say Y here if you have a touchscreen interface using the
+         xpt2046 controller, and your board-specific initialization
+         code includes that in its table of SPI devices.
+
+         If unsure, say N (but it's safe to say "Y").
 
 config TOUCHSCREEN_AD7879_I2C
        tristate "AD7879 based touchscreens: AD7879-1 I2C Interface"
index a34f0b533ab0cee33591b1e1c6ec6e30725dd9c6..e865ae66fc465ea6ca3a2d2b521d16d6ce160a4a 100644 (file)
@@ -46,4 +46,5 @@ obj-$(CONFIG_TOUCHSCREEN_PCAP)                += pcap_ts.o
 obj-$(CONFIG_TOUCHSCREEN_XPT2046_SPI)          += xpt2046_ts.o
 obj-$(CONFIG_TOUCHSCREEN_XPT2046_CBN_SPI)              += xpt2046_cbn_ts.o calibration_ts.o largenum_ts.o
 obj-$(CONFIG_TOUCHSCREEN_XPT2046_320X480_SPI)          += xpt2046_ts_320X480.o
-#obj-$(CONFIG_TOUCHSCREEN_XPT2046_320X480_CBN_SPI)             += xpt2046_cbn_ts.o calibration_ts.o largenum_ts.o
\ No newline at end of file
+#obj-$(CONFIG_TOUCHSCREEN_XPT2046_320X480_CBN_SPI)             += xpt2046_cbn_ts.o calibration_ts.o largenum_ts.o
+obj-$(CONFIG_TOUCHSCREEN_IT7250) += ctp_it7250.o
diff --git a/drivers/input/touchscreen/ctp_it7250.c b/drivers/input/touchscreen/ctp_it7250.c
new file mode 100644 (file)
index 0000000..cc979aa
--- /dev/null
@@ -0,0 +1,1083 @@
+#include <linux/init.h>\r
+#include <linux/module.h>\r
+#include <linux/kernel.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/irq.h>\r
+#include <linux/i2c.h>\r
+//#include <asm/semaphore.h>\r
+#include <linux/gpio.h>\r
+#include <mach/gpio.h>\r
+#include <linux/suspend.h>\r
+#include <linux/input.h>\r
+#include <mach/hardware.h>\r
+\r
+#include <linux/semaphore.h>\r
+#include <linux/sched.h>\r
+#include <linux/delay.h>\r
+\r
+#include <mach/iomux.h>\r
+\r
+#include <mach/spi_fpga.h>\r
+\r
+extern void rk2818_mux_api_set(char *name, unsigned int mode);\r
+extern int lp8725_ldo_en(uint8_t ldo,uint8_t enble);\r
+extern int lp8725_set_ldo_vol(uint8_t ldon,uint16_t vol);\r
+extern int lp8725_set_lilo_vol(uint8_t lilon,uint16_t vol);\r
+extern int lp8725_lilo_en(uint8_t lilon,uint8_t enble);\r
+\r
+\r
+struct Ctp_it7250_data {\r
+    char  status;
+    char  curr_tate;
+       struct input_dev *input_dev;
+       struct i2c_client *client;
+       struct delayed_work delaywork;\r
+       int irq;  /* Our chip IRQ */\r
+};\r
+static struct i2c_client *Ctp_it7250_client;\r
+\r
+#define Ctp_it7250_GPIO_INT     RK2818_PIN_PE1\r
+\r
+#if 0\r
+#define rk28printk(x...) printk(x)\r
+#else\r
+#define rk28printk(x...) \r
+#endif\r
+\r
+ struct KeyInfo
+{
+       int value;\r
+       int key;\r
+};
+
+static struct KeyInfo panel_key_info[]={
+{0x01, KEY_HOME},\r
+{0x02, KEY_MENU},\r
+{0x03, KEY_BACK},\r
+{0x04, KEY_SEARCH},\r
+};\r
+\r
+#define MAX_FINGER_NUM                         3\r
+//#define DEVICE_ADDRESS                                       0x8C\r
+#define COMMAND_BUFFER_INDEX                   0x20\r
+#define QUERY_BUFFER_INDEX                             0x80\r
+#define COMMAND_RESPONSE_BUFFER_INDEX  0xA0\r
+#define POINT_BUFFER_INDEX                             0xE0\r
+#define QUERY_SUCCESS                                  0x00\r
+#define QUERY_BUSY                                     0x01\r
+#define QUERY_ERROR                                    0x02\r
+#define QUERY_POINT                                    0x80\r
+\r
+\r
+static u8 gpucPointBuffer[14];\r
+static u32 gpdwSampleX[3],gpdwSampleY[3],gpdwPressure[1];\r
+\r
+static int Ctp_it7250_rx_data( u8 reg,u8* rxData, int length)\r
+{\r
+#if 0\r
+   \r
+  int ret;\r
+    struct i2c_adapter *adap;int i;\r
+    struct i2c_msg msgs[2];
+    if(!Ctp_it7250_client)\r
+               return ret;    
+    adap = Ctp_it7250_client->adapter;\r
+       \r
+    //·¢ËͼĴæÆ÷µØÖ·
+    msgs[0].addr = Ctp_it7250_client->addr;\r
+    msgs[0].buf = &reg;\r
+    msgs[0].flags = Ctp_it7250_client->flags;\r
+    msgs[0].len =1;\r
+    msgs[0].scl_rate = 400*1000;\r
+    //½ÓÊÕÊý¾Ý
+    \r
+//    rk28printk("i2c addr=0x%x \r\n",msgs[0].addr);\r
+ //   rk28printk("msgs[0].buf = 0x%x rxData=0x%x\n",*(msgs[0].buf),*rxData);\r
+       \r
+       msgs[1].buf = rxData;\r
+    msgs[1].addr = Ctp_it7250_client->addr;\r
+    msgs[1].flags = Ctp_it7250_client->flags | I2C_M_RD;\r
+    msgs[1].len = length;\r
+    msgs[1].scl_rate = 400*1000;\r
+
+    ret = i2c_transfer(adap, msgs, 2);
+    //DBG("**has run at %s %d ret=%d**\n",__FUNCTION__,__LINE__,ret);
+//     rk28printk("\r\n msgs[1].buf = 0x%x ret=%d\n",*(msgs[1].buf),ret);\r
+\r
+\r
+       //for (i=0;i<length;i++)\r
+       //      rk28printk("rxData[%d]=%d \r\n",i,rxData[i]);\r
+\r
+#else\r
+//int i;\r
+return  i2c_master_reg8_recv(Ctp_it7250_client, reg, rxData, length, 400 * 1000);\r
+//for (i=0;i<length;i++)\r
+//     rk28printk("rxData[%d]=%d \r\n",i,rxData[i]);\r
+#endif\r
+       \r
+}
+\r
+static int Ctp_it7250_tx_data(u8 reg,char *txData, int length)\r
+{
+#if 0\r
+    int ret,i;\r
+       struct i2c_adapter *adap = Ctp_it7250_client->adapter;\r
+       struct i2c_msg msg;\r
+       \r
+       u8 buf[128];//128\r
+//     rk28printk("reg=0x%x txData=0x%x  \r\n",reg,*txData);\r
+       buf[0]=reg;\r
+       for (i=0;i<length;i++)\r
+               {\r
+               buf[i+1]=*txData++;\r
+               rk28printk("buf[%d]=0x%x   ",i+1,buf[i+1]);\r
+               }\r
+       rk28printk("\r\n");\r
+//     rk28printk("buf[0]=0x%x buf[1]=0x%x",buf[0],buf[1]);\r
+       msg.addr = Ctp_it7250_client->addr;\r
+//rk28printk("i2c addr=0x%x",msg.addr);\r
+       msg.buf =&buf[0];\r
+       msg.len = length+1;//+1 means add the reg length;by roberts\r
+       msg.flags = Ctp_it7250_client->flags;\r
+       msg.scl_rate = 400*1000;\r
+    
+       ret = i2c_transfer(adap, &msg, 1);
+return ret;\r
+#else\r
+ return i2c_master_reg8_send(Ctp_it7250_client, reg, txData, length, 400 * 1000);\r
+#endif\r
+\r
+\r
+\r
+\r
+}\r
+\r
+\r
+\r
+bool  ReadQueryBuffer(u8* pucData)\r
+{\r
+       return Ctp_it7250_rx_data( QUERY_BUFFER_INDEX, pucData, 1);\r
+}\r
+\r
+bool ReadCommandResponseBuffer(u8* pucData, unsigned int unDataLength)\r
+{\r
+       return Ctp_it7250_rx_data( COMMAND_RESPONSE_BUFFER_INDEX, pucData, unDataLength);\r
+}\r
+\r
+bool ReadPointBuffer(u8* pucData)\r
+{\r
+       return Ctp_it7250_rx_data( POINT_BUFFER_INDEX, pucData, 14);\r
+}\r
+\r
+bool WriteCommandBuffer(u8* pucData, unsigned int unDataLength)\r
+{\r
+       return Ctp_it7250_tx_data(COMMAND_BUFFER_INDEX, pucData, unDataLength);\r
+}\r
+\r
+static int Ctp_it7250_touch_open(struct input_dev *idev)\r
+{\r
+       \r
+struct Ctp_it7250_data *Ctp_it7250 = (struct Ctp_it7250_data *)i2c_get_clientdata(Ctp_it7250_client);\r
+\r
+\r
+//BTN_TOUCH =0 means no touch ;by robert\r
+       input_report_key(Ctp_it7250->input_dev,BTN_TOUCH, 0);\r
+       input_sync(Ctp_it7250->input_dev);\r
+\r
+       return 0;\r
+}\r
+\r
+static void Ctp_it7250_touch_close(struct input_dev *idev)\r
+{\r
+return 0;\r
+}\r
+\r
+static irqreturn_t Ctp_it7250_touch_irq(int irq, void *dev_id)\r
+{      \r
+       struct Ctp_it7250_data *Ctp_it7250 = dev_id;\r
+\r
+       //rk28printk("%s++++ %d \r\n",__FUNCTION__,__LINE__);\r
+       disable_irq_nosync(irq);\r
+       //rk28printk("%s++++ %d irq=%d\r\n",__FUNCTION__,__LINE__,irq);\r
+       schedule_delayed_work(&Ctp_it7250->delaywork,usecs_to_jiffies(5));      \r
+       \r
+       return IRQ_HANDLED; \r
+               \r
+}\r
+\r
+\r
+\r
+static int ts_input_init(struct i2c_client *client)\r
+{\r
+       int ret = -1,i;\r
+       struct Ctp_it7250_data *Ctp_it7250;\r
+       Ctp_it7250 = i2c_get_clientdata(client);\r
+       /* register input device */\r
+       Ctp_it7250->input_dev = input_allocate_device();\r
+       if (Ctp_it7250->input_dev == NULL) {\r
+               pr_emerg( "%s: failed to allocate input dev\n",\r
+                       __FUNCTION__);\r
+               return -ENOMEM;\r
+       }\r
+rk28printk("+++++++     %s+++++++\n", __FUNCTION__);\r
+       Ctp_it7250->input_dev->name = "CTS_Ctp_it7250";\r
+       Ctp_it7250->input_dev->phys = "CTS_Ctp_it7250/input1";\r
+       \r
+     //no need to open & close it,it will do it automaticlly;noted by robert\r
+       Ctp_it7250->input_dev->open = Ctp_it7250_touch_open;\r
+       Ctp_it7250->input_dev->close = Ctp_it7250_touch_close;\r
+\r
+       __set_bit(EV_ABS, Ctp_it7250->input_dev->evbit);\r
+       __set_bit(ABS_X, Ctp_it7250->input_dev->absbit);\r
+       __set_bit(ABS_Y, Ctp_it7250->input_dev->absbit);\r
+\r
+       __set_bit(EV_SYN, Ctp_it7250->input_dev->evbit);\r
+       __set_bit(EV_KEY, Ctp_it7250->input_dev->evbit);\r
+       __set_bit(BTN_TOUCH, Ctp_it7250->input_dev->keybit);\r
+\r
+for (i = 0; i < ARRAY_SIZE(panel_key_info); i++)\r
+{rk28printk("ts_input_init  i=%d\r\n",i);\r
+       __set_bit(panel_key_info[i].key,Ctp_it7250->input_dev->keybit);\r
+}\r
+       //__clear_bit(0, input_dev->keybit);\r
+\r
+       input_set_abs_params(Ctp_it7250->input_dev, ABS_X, 0, 1000, 0, 0);\r
+       input_set_abs_params(Ctp_it7250->input_dev, ABS_Y, 0, 1000, 0, 0);\r
+//pr_emerg("+++++++ %s\n", __FUNCTION__); \r
+       ret = input_register_device(Ctp_it7250->input_dev);\r
+       if (ret) {\r
+               pr_emerg(\r
+                       "%s: unabled to register input device, ret = %d\n",\r
+                       __FUNCTION__, ret);\r
+               return ret;\r
+       }\r
+       rk28printk("+++++++     %s+++++++END\n", __FUNCTION__);\r
+       return 0;\r
+\r
+}\r
+\r
+static void CTS_configure_pin(struct i2c_client *client)\r
+{\r
+       //add  reset pin;but we not used it ;robert\r
+       //had already do it it spi_gpio.c\r
+       //end add       \r
+       //RESET THE CTP;note by robert\r
+       spi_gpio_set_pinlevel(SPI_GPIO_P2_15, SPI_GPIO_HIGH);\r
+       mdelay(5);\r
+       spi_gpio_set_pinlevel(SPI_GPIO_P2_15, SPI_GPIO_LOW);\r
+       mdelay(5);\r
+       spi_gpio_set_pinlevel(SPI_GPIO_P2_15, SPI_GPIO_HIGH);\r
+       mdelay(5);\r
+}\r
+\r
+static int Ctp_it7250_init_irq(struct i2c_client *client)\r
+{\r
+       struct Ctp_it7250_data *Ctp_it7250;\r
+       int ret;\r
+       \r
+       Ctp_it7250 = i2c_get_clientdata(client);\r
+       #if 1\r
+       if ( !gpio_is_valid(client->irq)) {\r
+               rk28printk("+++++++++++gpio_is_invalid\n");
+               return -EINVAL;
+       }
+       ret = gpio_request(client->irq, "Ctp_it7250_int");\r
+       if (ret) {
+               rk28printk( "failed to request Ctp_it7250_init_irq GPIO%d\n",gpio_to_irq(client->irq));\r
+               return ret;
+       }\r
+#if 1\r
+ret = gpio_direction_input(client->irq);\r
+       if (ret) {\r
+               rk28printk("failed to set CTS_configure_pin gpio input\n");\r
+               //goto err_free_gpio;\r
+       }\r
+       gpio_pull_updown(client->irq,GPIOPullUp);\r
+#endif\r
+\r
+       rk28printk("%s gpio_to_irq(%d) is %d\n",__FUNCTION__,client->irq,gpio_to_irq(client->irq));\r
+               \r
+       client->irq = gpio_to_irq(client->irq);\r
+       #endif\r
+       ret = request_irq(client->irq, Ctp_it7250_touch_irq, IRQF_TRIGGER_LOW, client->dev.driver->name, Ctp_it7250);\r
+       Ctp_it7250->irq=client->irq;\r
+       rk28printk("%s request irq is %d,irq1 is %d,ret is  0x%x\n",__FUNCTION__,client->irq,Ctp_it7250->irq,ret);\r
+       if (ret ) {
+               rk28printk(KERN_ERR "Ctp_it7250_init_irq: request irq failed,ret is %d\n",ret);\r
+        return ret;
+       }\r
+       \r
+}\r
+\r
+\r
+// ================================================================================\r
+// Function Name --- GetFirmwareInformation\r
+// Description --- Get firmware information\r
+// Input --- NULL\r
+//Output --- return true if the command execute successfully, otherwuse return false.\r
+// ================================================================================\r
+bool GetFirmwareInformation()\r
+{\r
+       u8 ucWriteLength, ucReadLength;\r
+       u8 pucData[128];\r
+       u8 ucQuery;\r
+int i;\r
+       ucWriteLength = 2;\r
+       ucReadLength = 0x09;\r
+       pucData[0] = 0x01;\r
+       pucData[1] = 0x00;\r
+\r
+       // Query\r
+       do\r
+       {\r
+               if(!ReadQueryBuffer(&ucQuery))\r
+               {\r
+                       ucQuery = QUERY_BUSY;\r
+               }\r
+       }while(ucQuery & QUERY_BUSY);\r
+\r
+       // Write Command\r
+       if(!WriteCommandBuffer(pucData, ucWriteLength))\r
+       {\r
+               return false;\r
+       }\r
+\r
+       // Query\r
+       do\r
+       {\r
+               if(!ReadQueryBuffer(&ucQuery))\r
+               {\r
+                       ucQuery = QUERY_BUSY;\r
+               }\r
+       }while(ucQuery & QUERY_BUSY);\r
+       pucData[5]== 0 ;\r
+        pucData[6] == 0 ;\r
+        pucData[7] == 0 ;\r
+        pucData[8] == 0;\r
+       // Read Command Response\r
+       if(!ReadCommandResponseBuffer(pucData, ucReadLength))\r
+       {\r
+               return false;\r
+       }\r
+\r
+\r
+       \r
+for (i =0;i<ucReadLength;i++)\r
+       rk28printk("GetFirmwareInformation pucData[%d]=%d \r\n",i,pucData[i]);\r
+       if(pucData[5]== 0 \r
+       && pucData[6] == 0 \r
+       && pucData[7] == 0 \r
+       && pucData[8] == 0) \r
+       {\r
+               // There is no flash code\r
+               rk28printk("There is no flash code \r\n");\r
+               return false;\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+// ================================================================================\r
+// Function Name --- SetInterruptNotification\r
+// Description --- Set It7260 interrupt mode\r
+// Input --- \r
+//     ucStatus- the interrupt status\r
+//     ucType- the interrupt type\r
+//Output --- return true if the command execute successfully, otherwuse return false.\r
+// ================================================================================\r
+bool SetInterruptNotification(u8 ucStatus, u8 ucType)\r
+{\r
+       u8 ucWriteLength, ucReadLength;\r
+       u8 pucData[128];\r
+       u8 ucQuery;\r
+int i;\r
+       ucWriteLength = 4;// 2\r
+       ucReadLength = 2;\r
+       pucData[0] = 0x02;\r
+       pucData[1] = 0x04;\r
+       pucData[2] = ucStatus;\r
+       pucData[3] = ucType;\r
+\r
+       // Query\r
+       do\r
+       {\r
+               if(!ReadQueryBuffer(&ucQuery))\r
+               {\r
+                       ucQuery = QUERY_BUSY;\r
+               }\r
+       }while(ucQuery & QUERY_BUSY);\r
+\r
+       // Write Command\r
+       if(!WriteCommandBuffer(pucData, ucWriteLength))\r
+       {\r
+               return false;\r
+       }\r
+\r
+       // Query\r
+       do\r
+       {\r
+               if(!ReadQueryBuffer(&ucQuery))\r
+               {\r
+                       ucQuery = QUERY_BUSY;\r
+               }\r
+       }while(ucQuery & QUERY_BUSY);\r
+\r
+       // Read Command Response\r
+       if(!ReadCommandResponseBuffer(pucData, ucReadLength))\r
+       {\r
+               return false;\r
+       }\r
+\r
+for (i =0;i<ucReadLength;i++)\r
+       rk28printk("SetInterruptNotification pucData[%d]=0x%x \r\n",i,pucData[i]);\r
+       if(*(u16*) pucData != 0) \r
+       {\r
+               return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+\r
+// ================================================================================\r
+// Function Name --- IdentifyCapSensor\r
+// Description --- Identify Capacitive Sensor information\r
+// Input --- NULL\r
+//Output --- return true if the command execute successfully, otherwuse return false.\r
+// ================================================================================\r
+bool IdentifyCapSensor()\r
+{\r
+       u8 ucWriteLength, ucReadLength;\r
+       u8 pucData[128];\r
+       u8 ucQuery=0;int i;\r
+\r
+       ucWriteLength = 1;\r
+       ucReadLength = 0x0A;\r
+       pucData[0] = 0x00;\r
+rk28printk("%s\r\n",__FUNCTION__);\r
+       // Query\r
+       do\r
+       {//printk("first wait 111\r\n");\r
+               if(!ReadQueryBuffer(&ucQuery))\r
+               {\r
+                       rk28printk("first wait \r\n");\r
+                       ucQuery = QUERY_BUSY;\r
+               }\r
+               rk28printk("%s ucQuery=0x%x \r\n",__FUNCTION__,ucQuery);\r
+               mdelay(500);\r
+       }while(ucQuery & QUERY_BUSY);\r
+\r
+       // Write Command\r
+       //rk28printk("%s11\r\n",__FUNCTION__);\r
+       pucData[0] = 0x00;ucWriteLength = 1;\r
+       if(!WriteCommandBuffer(pucData, ucWriteLength))\r
+       {\r
+               rk28printk("WriteCommandBuffer false \r\n");\r
+       //      return false;\r
+       }\r
+//rk28printk("show1 %s\r\n",__FUNCTION__);\r
+       // Query\r
+       do\r
+       {\r
+               if(!ReadQueryBuffer(&ucQuery))\r
+               {\r
+                       rk28printk("second wait \r\n");\r
+                       ucQuery = QUERY_BUSY;\r
+               }rk28printk("%s ucQuery1=0x%x \r\n",__FUNCTION__,ucQuery);\r
+       }while(ucQuery & QUERY_BUSY);\r
+//rk28printk("show2 %s\r\n",__FUNCTION__);\r
+       // Read Command Response\r
+       for (i=0;i<ucReadLength;i++)\r
+               {pucData[i]=0x0;\r
+               rk28printk("pucData[%d]=%d \r\n",i,pucData[i]);\r
+               }\r
+       if(!ReadCommandResponseBuffer(pucData, ucReadLength))\r
+       {\r
+               rk28printk("ReadCommandResponseBuffer false \r\n");\r
+       //      return false;\r
+       }\r
+//rk28printk("show %s\r\n",__FUNCTION__);\r
+for (i=0;i<ucReadLength;i++)\r
+               rk28printk("pucData[%d]=%d \r\n",i,pucData[i]);\r
+       rk28printk("pucData=%c %c %c %c %c %c %c \r\n",pucData[1],pucData[2],pucData[3],pucData[4],pucData[5],pucData[6],pucData[7]);\r
+\r
+       return true;\r
+}\r
+\r
+// ================================================================================\r
+// Function Name --- Get2DResolutions\r
+// Description --- Get the resolution of X and Y axes\r
+// Input --- \r
+//     pwXResolution - the X resolution\r
+//     pwYResolution - the Y resolution\r
+//     pucStep - the step\r
+//Output --- return true if the command execute successfully, otherwuse return false.\r
+// ================================================================================\r
+bool Get2DResolutions(u32 *pwXResolution, u32*pwYResolution, u8 *pucStep)\r
+{\r
+       u8 ucWriteLength, ucReadLength;\r
+       u8 pucData[128];\r
+       u8 ucQuery;\r
+int i;\r
+\r
+       ucWriteLength = 3;\r
+       ucReadLength = 0x07;\r
+       pucData[0] = 0x01;\r
+       pucData[1] = 0x02;\r
+       pucData[2] = 0x00;\r
+\r
+       // Query\r
+       do\r
+       {\r
+               if(!ReadQueryBuffer(&ucQuery))\r
+               {\r
+                       ucQuery = QUERY_BUSY;\r
+               }\r
+       }while(ucQuery & QUERY_BUSY);\r
+\r
+       // Write Command\r
+       rk28printk("%s WriteCommandBuffer\r\n",__FUNCTION__);\r
+       if(!WriteCommandBuffer(pucData, ucWriteLength))\r
+       {\r
+               return false;\r
+       }\r
+\r
+       // Query\r
+       do\r
+       {\r
+               if(!ReadQueryBuffer(&ucQuery))\r
+               {\r
+                       ucQuery = QUERY_BUSY;\r
+               }\r
+       }while(ucQuery & QUERY_BUSY);\r
+rk28printk("%s ReadCommandResponseBuffer\r\n",__FUNCTION__);\r
+       // Read Command Response\r
+       if(!ReadCommandResponseBuffer(pucData, ucReadLength))\r
+       {\r
+               return false;\r
+       }\r
+rk28printk("%s ReadCommandResponseBuffer EDN\r\n",__FUNCTION__);\r
+\r
+ for (i=0;i<ucReadLength;i++)\r
+       rk28printk("pucData[%d] = 0x%x \r\n",i,pucData[i]);\r
\r
+       if(pwXResolution != NULL) \r
+       {\r
+               *pwXResolution = (pucData[2] | (pucData[3] << 8));\r
+       }\r
+       if(pwYResolution!= NULL) \r
+       {\r
+               * pwYResolution = (pucData[4] | (pucData[5] << 8));\r
+       }\r
+       if(pucStep!= NULL) \r
+       {\r
+               * pucStep = pucData[6];\r
+       }\r
+       rk28printk("%s x res=%d y res=%d \r\n",__FUNCTION__,*pwXResolution,* pwYResolution);\r
+       return true;\r
+}\r
+\r
+// *******************************************************************************************\r
+// Function Name: CaptouchMode\r
+// Description: \r
+//   This function is mainly used to initialize cap-touch controller to active state.\r
+// Parameters: \r
+//   dwMode -- the power state to be entered\r
+// Return value: \r
+//   return zero if success, otherwise return non zero value\r
+// *******************************************************************************************\r
+int CaptouchMode(u8 dwMode)\r
+{\r
+       u8 ucQueryResponse;\r
+       u8 pucCommandBuffer[128];\r
+\r
+       do\r
+       {\r
+               ReadQueryBuffer(&ucQueryResponse);\r
+       }\r
+       while(ucQueryResponse & QUERY_BUSY);\r
+\r
+       pucCommandBuffer[0] = 0x04;\r
+       pucCommandBuffer[1] = 0x00;\r
+       switch(dwMode)\r
+       {\r
+               case 0x00:\r
+                       pucCommandBuffer[2] = 0x00;\r
+                       break;\r
+               case 0x01:\r
+                       pucCommandBuffer[2] = 0x01;\r
+                       break;\r
+               case 0x02:\r
+                       pucCommandBuffer[2] = 0x02;\r
+                       break;\r
+               default:\r
+                       return -1;\r
+       }\r
+\r
+       if(!WriteCommandBuffer( pucCommandBuffer,3))\r
+       {\r
+               return -1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+// *******************************************************************************************\r
+// Function Name: CaptouchReset\r
+// Description: \r
+//   This function is mainly used to reset cap-touch controller by sending reset command.\r
+// Parameters: NULL\r
+// Return value: \r
+//   return TRUE if success, otherwise return FALSE\r
+// *******************************************************************************************\r
+int CaptouchReset()\r
+{\r
+       u8 ucQueryResponse;\r
+       u8 pucCommandBuffer[128];\r
+\r
+       do\r
+       {\r
+               ReadQueryBuffer(&ucQueryResponse);\r
+       }\r
+       while(ucQueryResponse & QUERY_BUSY);\r
+\r
+       pucCommandBuffer[0] = 0x6F;\r
+       if(!WriteCommandBuffer(pucCommandBuffer,1))\r
+       {\r
+               return -1;\r
+       }\r
+       mdelay(200);\r
+       \r
+\r
+       do\r
+       {\r
+               ReadQueryBuffer(&ucQueryResponse);\r
+       }\r
+       while(ucQueryResponse & QUERY_BUSY);\r
+\r
+\r
+       if(!ReadCommandResponseBuffer(pucCommandBuffer,2))\r
+       {\r
+               return -1;\r
+       }\r
+\r
+       if(pucCommandBuffer[0] == 0 && pucCommandBuffer[1] == 0)\r
+       {\r
+               return 0;\r
+       }\r
+\r
+       return -1;\r
+}\r
+\r
+\r
+\r
+// *******************************************************************************************\r
+// Function Name: CaptouchHWInitial\r
+// Description: \r
+//   This function is mainly used to initialize cap-touch controller to active state.\r
+// Parameters: NULL\r
+// Return value: \r
+//   return zero if success, otherwise return non zero value\r
+// *******************************************************************************************\r
+int CaptouchHWInitial()\r
+{\r
+       u32 wXResolution=0,wYResolution=0;\r
+       u8 ucStep=0;\r
+       if (!IdentifyCapSensor())\r
+       {\r
+               rk28printk("%s IdentifyCapSensor error \r\n",__FUNCTION__);\r
+       //      goto resetagin;\r
+}\r
+       #if 1\r
+if (!GetFirmwareInformation ())\r
+       {\r
+       rk28printk("%s GetFirmwareInformation error \r\n",__FUNCTION__);\r
+       //      goto resetagin;\r
+}\r
+\r
+       if (!Get2DResolutions(&wXResolution, &wYResolution, &ucStep))\r
+       {\r
+       rk28printk("%s Get2DResolutions error \r\n",__FUNCTION__);\r
+       //      goto resetagin;\r
+}\r
+\r
+//no need to set interrupt mode because firmware has done that;note by robert\r
+       #if 0\r
+       if (!SetInterruptNotification(0x01, 0x00))\r
+       {\r
+       rk28printk("%s SetInterruptNotification error \r\n",__FUNCTION__);\r
+       goto resetagin;\r
+}\r
+       #endif\r
+       //note end\r
+#endif\r
+       return 0;\r
+\r
+resetagin:\r
+       if (!CaptouchReset())\r
+               rk28printk("CaptouchReset success \r\n");\r
+       mdelay(100);\r
+//     if (!CaptouchMode(0x00))\r
+       //      rk28printk("CaptouchMode success \r\n");\r
+}\r
+\r
+\r
+// *******************************************************************************************\r
+// Function Name: CaptouchGetSampleValue\r
+// Description: \r
+//   This function is mainly used to get sample values which shall contain x, y position and pressure. \r
+// Parameters:\r
+//   pdwSampleX -- the pointer of returned X coordinates\r
+//   pdwSampleY -- the pointer of returned Y coordinates\r
+//   pdwPressure -- the pointer of returned pressures\r
+// Return value: \r
+//   The return value is the number of sample points. Return 0 if failing to get sample. The maximum //   return value is 10 in normal case. If the CTP controller does not support pressure measurement, //   the return value is the sample values OR with PRESSURE_INVALID.\r
+// *******************************************************************************************\r
+int CaptouchGetSampleValue(u32* pdwSampleX, u32* pdwSampleY, u32* pdwPressure)\r
+{\r
+       int nRet;\r
+       int i;\r
+\r
+       if(gpucPointBuffer[1] & 0x01)\r
+       {\r
+               return MAX_FINGER_NUM + 1;\r
+       }\r
+\r
+       nRet = 0;\r
+       for(i = 0; i < MAX_FINGER_NUM; i++)\r
+       {\r
+               if(gpucPointBuffer[0] & (1 << i))\r
+               {\r
+                       nRet++;\r
+                       #if 0\r
+                       pdwSampleX[i] = ((u32)(gpucPointBuffer[i * 4 + 3] & 0x0F) << 8) + \r
+(u32)gpucPointBuffer[i * 4 + 2];;\r
+                       pdwSampleY[i] = ((u32)(gpucPointBuffer[i * 4 + 3] & 0xF0) << 4) + \r
+(u32)gpucPointBuffer[i * 4 + 4];\r
+                       pdwPressure[i] = (u32)(gpucPointBuffer[i * 4 + 5] & 0x0F);\r
+                       #else \r
+                       pdwSampleX[i] = ((u32)(gpucPointBuffer[i * 4 + 3] & 0x0F) << 8) | \r
+gpucPointBuffer[i * 4 + 2];\r
+                       pdwSampleY[i] = ((u32)(gpucPointBuffer[i * 4 + 3] & 0xF0) << 4) | \r
+gpucPointBuffer[i * 4 + 4];\r
+                       pdwPressure[i] = (u32)(gpucPointBuffer[i * 4 + 5] & 0x0F);\r
+\r
+               //      rk28printk("%s x[%d]=%d  y[%d]=%d \r\n",__FUNCTION__,i,pdwSampleX[i],i,pdwSampleY[i]);\r
+                       #endif\r
+               }\r
+               else\r
+               {\r
+                       pdwSampleX[i] = 0;\r
+                       pdwSampleY[i] = 0;\r
+                       pdwPressure[i] = 0;\r
+               }\r
+       }\r
+       //add by robert for test\r
+       #if 0\r
+       for(i = 0; i < MAX_FINGER_NUM; i++)\r
+       {\r
+               rk28printk("%s x[%d]=%d  y[%d]=%d \r\n",__FUNCTION__,0,pdwSampleX[0],0,pdwSampleY[0]);\r
+       }\r
+       #endif\r
+       return nRet;\r
+}\r
+\r
+// *******************************************************************************************\r
+// Function Name: CaptouchGetGesture\r
+// Description: \r
+//   This function is mainly used to initialize cap-touch controller to active state.\r
+// Parameters: NULL\r
+// Return value: \r
+//   return gesture ID\r
+// *******************************************************************************************\r
+int CaptouchGetGesture()\r
+{\r
+       return (int)gpucPointBuffer[1];\r
+}\r
+\r
+static void  Ctp_it7250_delaywork_func(struct work_struct  *work)\r
+{
+       
+       u8 ucQueryResponse;\r
+       u32 dwTouchEvent;\r
+       struct Ctp_it7250_data *Ctp_it7250 = (struct Ctp_it7250_data *)i2c_get_clientdata(Ctp_it7250_client);\r
+       int PE1status = 0;\r
+\r
+//     rk28printk("%s++++ %d \r\n",__FUNCTION__,__LINE__);\r
+\r
+\r
+       PE1status =  gpio_get_value(Ctp_it7250_GPIO_INT);\r
+       //  PE1status ÎªµÍ£¬±íʾµÍµçƽÖжÏÓÐЧ \r
+       if (!PE1status)\r
+               {\r
+       //      rk28printk("%s PE1status low!!  \r\n",__FUNCTION__);\r
+       if(!ReadQueryBuffer(&ucQueryResponse))\r
+       {rk28printk("%s++++ %d  ucQueryResponse=0x%x \r\n",__FUNCTION__,__LINE__,ucQueryResponse);\r
+               return false;\r
+       }\r
+//rk28printk("%s++++ %d  ucQueryResponse=0x%x \r\n",__FUNCTION__,__LINE__,ucQueryResponse);\r
+       // Touch Event\r
+       if(ucQueryResponse & QUERY_POINT)\r
+       {//rk28printk("%s++++ %d  \r\n",__FUNCTION__,__LINE__);\r
+               if(!ReadPointBuffer(gpucPointBuffer))\r
+               {rk28printk("%s++++ %d  \r\n",__FUNCTION__,__LINE__);\r
+                       return false;\r
+               }\r
+//rk28printk("%s++++ %d  ucQueryResponse=0x%x gpucPointBuffer=0x%x\r\n",__FUNCTION__,__LINE__,ucQueryResponse,gpucPointBuffer[0] & 0xF0);\r
+               switch(gpucPointBuffer[0] & 0xF0)\r
+               {\r
+                       case 0x00:\r
+                               dwTouchEvent = CaptouchGetSampleValue(gpdwSampleX, gpdwSampleY, \r
+gpdwPressure);\r
+                               if(dwTouchEvent == 0)\r
+                               {\r
+                                       //SynchroSystemEvent(SYSTEM_TOUCH_EVENT_FINGER_RELEASE);\r
+                                       rk28printk("TOUCH Release  !!\r\n");\r
+                                       input_report_key(Ctp_it7250->input_dev,BTN_TOUCH, 0);\r
+                                       input_sync(Ctp_it7250->input_dev);\r
+                               }\r
+                               else if(dwTouchEvent <=MAX_FINGER_NUM) //CTP_MAX_FINGER_NUMBER)\r
+                               {\r
+                                       //SynchroSystemEvent(SYSTEM_TOUCH_EVENT_FINGER_ASSERT);\r
+                                       \r
+                                       input_report_abs(Ctp_it7250->input_dev, ABS_X, gpdwSampleX[0]);// & 0xfff\r
+                                       input_report_abs(Ctp_it7250->input_dev, ABS_Y, gpdwSampleY[0]); //& 0xfff\r
+                                       input_report_key(Ctp_it7250->input_dev,BTN_TOUCH, 1);\r
+                                       input_sync(Ctp_it7250->input_dev);rk28printk("x=%d  y=%d \r\n",gpdwSampleX[0],gpdwSampleY[0]);\r
+                               }\r
+                               else\r
+                               {\r
+                                       rk28printk("%s SYSTEM_TOUCH_EVENT_PALM_DETECT \r\n",__FUNCTION__);\r
+                                       //SynchroSystemEvent(SYSTEM_TOUCH_EVENT_PALM_DETECT);\r
+                               }\r
+                               break;\r
+                       case 0x80:\r
+                               dwTouchEvent = CaptouchGetGesture();\r
+                               //SynchroSystemEvent(SYSTEM_GESTURE_EVENT);\r
+                               rk28printk("gesture:0x%x \r\n",dwTouchEvent);\r
+                               break;\r
+                       //for keypad below\r
+                       case 0x40:\r
+                               rk28printk("ID of button is 0x%x status is 0x%x\r\n",gpucPointBuffer[1],gpucPointBuffer[2]);\r
+                               switch (gpucPointBuffer[1]) \r
+                                       {case 0x01:\r
+                                               rk28printk("home \r\n");\r
+                                               if (gpucPointBuffer[2])\r
+                                                       input_report_key(Ctp_it7250->input_dev, panel_key_info[(gpucPointBuffer[1]-1)].key,1);\r
+                                               else\r
+                                                       input_report_key(Ctp_it7250->input_dev, panel_key_info[(gpucPointBuffer[1]-1)].key,0);\r
+                                               break;\r
+                                       case 0x02:\r
+                                               rk28printk("menu \r\n");\r
+                                               if (gpucPointBuffer[2])\r
+                                                       input_report_key(Ctp_it7250->input_dev, panel_key_info[(gpucPointBuffer[1]-1)].key,1);\r
+                                               else\r
+                                                       input_report_key(Ctp_it7250->input_dev, panel_key_info[(gpucPointBuffer[1]-1)].key,0);\r
+                                               break;\r
+                                       case 0x03:\r
+                                               rk28printk("back \r\n");\r
+                                               if (gpucPointBuffer[2])\r
+                                                       {\r
+                                                       rk28printk("back down key=%d\r\n",panel_key_info[(gpucPointBuffer[1]-1)].key);\r
+                                                       input_report_key(Ctp_it7250->input_dev, panel_key_info[(gpucPointBuffer[1]-1)].key,1);\r
+                                                       }\r
+                                               else\r
+                                                       {\r
+                                                       rk28printk("back up key=%d\r\n",panel_key_info[(gpucPointBuffer[1]-1)].key);\r
+                                                       input_report_key(Ctp_it7250->input_dev, panel_key_info[(gpucPointBuffer[1]-1)].key,0);\r
+                                                       }\r
+                                               break;\r
+                                       case 0x04:\r
+                                               rk28printk("find \r\n");\r
+                                               if (gpucPointBuffer[2])\r
+                                                       {\r
+                                                       rk28printk("find down key=%d\r\n",panel_key_info[(gpucPointBuffer[1]-1)].key);\r
+                                                       input_report_key(Ctp_it7250->input_dev, panel_key_info[(gpucPointBuffer[1]-1)].key,1);\r
+                                                       }\r
+                                               else\r
+                                                       {\r
+                                                       rk28printk("find up key=%d\r\n",panel_key_info[(gpucPointBuffer[1]-1)].key);\r
+                                                       input_report_key(Ctp_it7250->input_dev, panel_key_info[(gpucPointBuffer[1]-1)].key,0);\r
+                                                       }\r
+                                               break;          \r
+                                       default:\r
+                                                       rk28printk("shit default \r\n");\r
+                                               break;\r
+                                       }\r
+                               break;\r
+                       default:\r
+                               rk28printk("default \r\n");\r
+                               break;\r
+               }\r
+       }\r
+       else if (ucQueryResponse & QUERY_ERROR)\r
+               {\r
+               if (!CaptouchReset())\r
+               rk28printk("!! CaptouchReset success \r\n");\r
+               mdelay(100);\r
+       //if (!CaptouchMode(0x00))\r
+               //rk28printk("!! CaptouchMode success \r\n");\r
+               }\r
+       }\r
+//     rk28printk("enable ctp_irq=%d \r\n",Ctp_it7250->irq);\r
+       \r
+       enable_irq(Ctp_it7250->irq);\r
+       //²»ÊDzéѯģʽ£¬²»ÐèÒªÂÖѯ\r
+//schedule_delayed_work(&Ctp_it7250->delaywork,msecs_to_jiffies(1000));\r
+\r
+}\r
+\r
+ static int  Ctp_it7250_probe(struct i2c_client *client, const struct i2c_device_id *id)\r
+{\r
+       struct Ctp_it7250_data *Ctp_it7250;\r
+       u16 TempReg=0x0;\r
+       u16 val=0x0;\r
+       \r
+       Ctp_it7250_client = client;\r
+       rk28printk("+++++++     %s+++++++\n", __FUNCTION__);\r
+       Ctp_it7250 = kzalloc(sizeof(struct Ctp_it7250_data), GFP_KERNEL);\r
+       if (!Ctp_it7250) \r
+               {\r
+               rk28printk("[Ctp_it7250_probe]:alloc data failed.\n");\r
+               return  -ENOMEM;\r
+               }\r
+\r
+//     INIT_WORK(&Ctp_it7250->irq_work, Ctp_it7250_irq_worker);\r
+       INIT_DELAYED_WORK(&Ctp_it7250->delaywork, Ctp_it7250_delaywork_func);\r
+\r
+\r
+       Ctp_it7250->client = client;\r
+       i2c_set_clientdata(client, Ctp_it7250);\r
+\r
+       \r
+       \r
+       ts_input_init(client);\r
+//     CTS_configure_pin(client);\r
+\r
+{\r
+#if 0\r
+lp8725_lilo_en(2,0);\r
+mdelay(100);\r
+\r
+lp8725_lilo_en(2,1);\r
+mdelay(100);\r
+lp8725_set_lilo_vol(2,300);\r
+mdelay(5);\r
+#endif\r
+\r
+}\r
+CaptouchHWInitial();\r
+Ctp_it7250_init_irq(client);\r
+       \r
+       \r
+//²»ÊDzéѯģʽ£¬²»ÐèÒªÂÖѯ\r
+//schedule_delayed_work(&Ctp_it7250->delaywork,msecs_to_jiffies(50));\r
+\r
+\r
+       rk28printk("+++++++     %s+++++++\n", __FUNCTION__);\r
+       return 0;\r
+\r
+}\r
+\r
+\r
+\r
+static int Ctp_it7250_remove(struct i2c_client *client)\r
+{
+       
+       return 0;
+}
+\r
+\r
+\r
+#ifdef CONFIG_PM\r
+static int Ctp_it7250_suspend(struct i2c_client *client, pm_message_t state)\r
+{//pr_emerg("\n irq1=%d \n",irq1);\r
+struct Ctp_it7250_data *Ctp_it7250 = (struct Ctp_it7250_data *)i2c_get_clientdata(client);\r
+\r
+//send command to make ctp into sleep mode\r
+#if 1\r
+       u8 ucWriteLength;\r
+       u8 pucData[128];\r
+       u8 ucQuery;\r
+\r
+       ucWriteLength = 3;\r
+       pucData[0] = 0x04;\r
+       pucData[1] = 0x00;\r
+       pucData[2] = 0x02;\r
+\r
+       // Query\r
+       do\r
+       {\r
+               if(!ReadQueryBuffer(&ucQuery))\r
+               {\r
+                       ucQuery = QUERY_BUSY;\r
+               }\r
+       }while(ucQuery & QUERY_BUSY);\r
+\r
+       // Write Command\r
+       rk28printk("%s WriteCommandBuffer\r\n",__FUNCTION__);\r
+       if(!WriteCommandBuffer(pucData, ucWriteLength))\r
+       {\r
+               return false;\r
+       }\r
+       #endif\r
+//send sleep command end\r
+\r
+       disable_irq(Ctp_it7250->irq);\r
+\r
+       return 0;\r
+}\r
+\r
+static int Ctp_it7250_resume(struct i2c_client *client)\r
+{\r
+struct Ctp_it7250_data *Ctp_it7250 = (struct Ctp_it7250_data *)i2c_get_clientdata(client);\r
+//read command to wakeup ctp\r
+#if 1\r
+u8 ucQuery;\r
+ReadQueryBuffer(&ucQuery);\r
+#endif\r
+//wakeup end\r
+       enable_irq(Ctp_it7250->irq);\r
+       return 0;\r
+}\r
+#else\r
+#define        Ctp_it7250_suspend              NULL\r
+#define        Ctp_it7250_resume               NULL\r
+#endif\r
+\r
+static const struct i2c_device_id Ctp_it7250_id[] = {\r
+               {"Ctp_it7250", 0},\r
+               { }
+};\r
+\r
+static struct i2c_driver Ctp_it7250_driver = {\r
+       .driver = {\r
+               .name   = "Ctp_it7250",\r
+       },\r
+       .id_table       = Ctp_it7250_id,\r
+       .probe  = Ctp_it7250_probe,\r
+        .remove     =  Ctp_it7250_remove,\r
+};\r
+\r
+static int __init Ctp_it7250_init(void)\r
+{\r
+       int ret;        \r
+       rk28printk("+++++++     %s++\n", __FUNCTION__);\r
+       ret=i2c_add_driver(&Ctp_it7250_driver);\r
+       rk28printk("**Ctp_it7250_init_init return %d**\n",ret);\r
+       return ret;\r
+}\r
+\r
+static void __exit Ctp_it7250_exit(void)\r
+{\r
+       /* We move these codes here because we want to detect the\r
+        * pen down event even when touch driver is not opened.\r
+        */\r
+       i2c_del_driver(&Ctp_it7250_driver);\r
+}\r
+\r
+ late_initcall(Ctp_it7250_init);\r
+module_exit(Ctp_it7250_exit);\r
+\r
+MODULE_AUTHOR("Robert_mu<robert.mu@rahotech.com>");\r
+\r