K97 项目相关修改
[firefly-linux-kernel-4.4.55.git] / drivers / input / touchscreen / hannstar_p1003.c
index e41328029f7083684ceda767ac6ad08a223cc163..a4ba8cac958c5543ae11fd83a75519e6ce66129f 100755 (executable)
 #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>
 
 #define MAX_SUPPORT_POINT      2// //  4
-#define Singltouch_Mode     1
+#define PACKGE_BUFLEN          10
+
+//#define Singltouch_Mode
+#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__); \
 #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
 struct point_data {    
        short status;   
        short x;        
@@ -46,6 +54,7 @@ struct ts_p1003 {
        struct input_dev        *input;
        char                    phys[32];
        struct delayed_work     work;
+       struct workqueue_struct *wq;
 
        struct i2c_client       *client;
     struct multitouch_event mt_event;
@@ -67,11 +76,12 @@ int p1003_get_pendown_state(void)
 static void p1003_report_event(struct ts_p1003 *ts,struct multitouch_event *tc)
 {
        struct input_dev *input = ts->input;
-    int i;
+    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){                             
+        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);    
@@ -79,13 +89,22 @@ static void p1003_report_event(struct ts_p1003 *ts,struct multitouch_event *tc)
             input_report_abs(input, ABS_MT_POSITION_Y, tc->point_data[i].y);                           
             input_mt_sync(input);      
 
-            printk("\n");
+            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 p1003 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);
 }
+
+#if defined (Singltouch_Mode)
 static void p1003_report_single_event(struct ts_p1003 *ts,struct multitouch_event *tc)
 {
        struct input_dev *input = ts->input;
@@ -104,64 +123,109 @@ static void p1003_report_single_event(struct ts_p1003 *ts,struct multitouch_even
         sakura_dbg_report_key_msg("%s x =0x%x,y = 0x%x \n",ts->status?"down":"up",tc->point_data[cid].x,tc->point_data[cid].y);
     }
 }
-static inline int p1003_read_values(struct ts_p1003 *ts, struct multitouch_event *tc)
+#endif
+
+static inline int p1003_check_firmwork(struct ts_p1003 *ts)
 {
-    s32 data;
+    int data;
     int len = 10;
-    char buf[10];
+    char buf[10] = {0x03 , 0x03 , 0x0a , 0x01 , 'D' , 0x00 , 0x00 , 0x00 , 0x00 , 0x00};
+       int i;
     short contactid=0;
 
-    data = i2c_master_normal_recv(ts->client, buf,len, 200*1000);
+    data = i2c_master_normal_send(ts->client, buf,len, 200*1000);
 
-    if (data < 0 || (buf[0]!=0x04)) {
-       dev_err(&ts->client->dev, "i2c io error: %d or Hannstar read reg failed\n", data);
-       enable_irq(ts->irq);
-       return data;
-    }
+       if(data < 0){
+               dev_err(&ts->client->dev, "i2c io error %d \n", data);
+               return data;
+       }
 
-    contactid = (buf[1]&0x7C)>>2;
-    tc->contactid = contactid;
-    tc->point_data[contactid].status = buf[1]&0x01; 
-    tc->point_data[contactid].x = ((buf[3]<<8) + buf[2])>>4;
-    tc->point_data[contactid].y = ((buf[5]<<8) + buf[4])>>4;
-    tc->validtouch = buf[1]&0x80;
-    ts->status = tc->point_data[contactid].status;
-//    printk("validtouch =%d,status= %d,contactid =%d\n",tc->validtouch,tc->point_data[contactid].status,contactid);
+       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("p1003 reg[5] = %c ,reg[6] = %c, reg[7] = %c, reg[8] = %c\n" , buf[5],buf[6],buf[7],buf[8]);
+       printk("p1003 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 p1003_read_values(struct ts_p1003 *ts, struct multitouch_event *tc)
+{
+    int data, j;
+    int len = 10;
+    char *buf;
+       char tempbuf[(MAX_SUPPORT_POINT * 10) << 1];
+    short contactid=0;
+
+       for(j = 0; j < MAX_SUPPORT_POINT ; j++){
+               buf = &tempbuf[j*10];
+       data = i2c_master_normal_recv(ts->client, buf, len, 200*1000);
+               if(data < 0)
+                       return data;
+               if(tempbuf[j*10] != 0x04){
+                       if(j == 0){
+                               data = -1;
+                               ts->pendown = 0;
+                       return data;
+                       }else{
+                               
+                               break;
+                       }
+               }
+               
+               contactid = (buf[1]&0x7C)>>2;
+               tc->contactid = contactid;
+               tc->point_data[contactid].status = buf[1]&0x01; 
+               tc->point_data[contactid].x = ((buf[3]<<8) + buf[2])>>4;
+               tc->point_data[contactid].y = ((buf[5]<<8) + buf[4])>>4;
+               tc->validtouch = buf[1]&0x80;
+               ts->status = tc->point_data[contactid].status;
+       }
+       
+//    printk("validtouch =%d,status= %d,contactid =%d\n",tc->validtouch,tc->point_data[contactid].status,contactid);
+    return 10;
+}
+
+
 static void p1003_work(struct work_struct *work)
 {
        struct ts_p1003 *ts =
                container_of(to_delayed_work(work), struct ts_p1003, work);
        struct multitouch_event *tc = &ts->mt_event;
-       u32 rt;
+       int rt;
     
        rt = p1003_read_values(ts,tc);
     
     if(rt < 0)
         goto out;
-
+       
+#if defined (Singltouch_Mode)
     p1003_report_single_event(ts,tc);
-    
- out:
-       if (ts->pendown)
-               schedule_delayed_work(&ts->work,
-                                     msecs_to_jiffies(10));
-       else
+#else
+    p1003_report_event(ts,tc);
+#endif
+
+out:               
+       if (ts->pendown){
+               queue_delayed_work(ts->wq, &ts->work, msecs_to_jiffies(10));
+               ts->pendown = 0;
+       }
+       else{
                enable_irq(ts->irq);
+       }
 }
 
 static irqreturn_t p1003_irq(int irq, void *handle)
 {
        struct ts_p1003 *ts = handle;
-       
 #if 1
        if (!ts->get_pendown_state || likely(ts->get_pendown_state())) {
                disable_irq_nosync(ts->irq);
-               schedule_delayed_work(&ts->work,
-                                     msecs_to_jiffies(10));
+               queue_delayed_work(ts->wq, &ts->work, 0);
        }
 
 #endif
@@ -188,7 +252,7 @@ static int __devinit p1003_probe(struct i2c_client *client,
        struct p1003_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;
@@ -209,7 +273,8 @@ static int __devinit p1003_probe(struct i2c_client *client,
        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("p1003_wq");
        INIT_DELAYED_WORK(&ts->work, p1003_work);
 
        ts->model             = pdata->model;
@@ -221,27 +286,27 @@ static int __devinit p1003_probe(struct i2c_client *client,
        input_dev->phys = ts->phys;
        input_dev->id.bustype = BUS_I2C;
 
-#if Singltouch_Mode
+#if defined (Singltouch_Mode)
        set_bit(EV_SYN, input_dev->evbit);
        set_bit(EV_KEY, input_dev->evbit);
        set_bit(BTN_TOUCH, input_dev->keybit);
        set_bit(BTN_2, input_dev->keybit);
        set_bit(EV_ABS, input_dev->evbit);
-       input_set_abs_params(input_dev,ABS_X,0,1087,0,0);
-       input_set_abs_params(input_dev,ABS_Y,0,800,0,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);
 #else
        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
-       input_set_abs_params(input_dev, ABS_X, 0, 1087, 0, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, 800, 0, 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, 1087, 0, 0);
-       input_set_abs_params(input_dev, ABS_HAT0Y, 0, 800, 0, 0);
-       input_set_abs_params(input_dev, ABS_MT_POSITION_X,0, 1087, 0, 0);
-       input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, 800, 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);   
@@ -282,6 +347,8 @@ static int __devinit p1003_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, ts);
 
+       p1003_check_firmwork(ts);
+       
        return 0;
 
  err_free_irq:
@@ -327,10 +394,16 @@ static struct i2c_driver p1003_driver = {
        .remove         = __devexit_p(p1003_remove),
 };
 
-static int __init p1003_init(void)
+static void __init p1003_init_async(void *unused, async_cookie_t cookie)
 {
        printk("--------> %s <-------------\n",__func__);
-       return i2c_add_driver(&p1003_driver);
+       i2c_add_driver(&p1003_driver);
+}
+
+static int __init p1003_init(void)
+{
+       async_schedule(p1003_init_async, NULL);
+       return 0;
 }
 
 static void __exit p1003_exit(void)