K97 项目相关修改
[firefly-linux-kernel-4.4.55.git] / drivers / input / touchscreen / ili2102_ts.c
index 6000f2c7dd740c6f6f71ede25ec3fe76d5ff561b..e043d1b5f34899646cfcc1fc7e9ab5be1aac30b2 100755 (executable)
 #include <linux/irq.h>
 #include <linux/cdev.h>
 #include <asm/uaccess.h>
-
+#include <linux/proc_fs.h>
+#include <linux/input/mt.h>
 #include "ili2102_ts.h"
 
+static int  ts_dbg_enable = 0;
 
-#if 0
-       #define DBG(msg...)     printk(msg);
-#else
-       #define DBG(msg...)
-#endif
-
+#define DBG(msg...) \
+       ({if(ts_dbg_enable == 1) printk(msg);})
+               
 #define TOUCH_NUMBER 2
 
-static int touch_state[TOUCH_NUMBER] = {TOUCH_UP,TOUCH_UP};
-static unsigned int g_x[TOUCH_NUMBER] =  {0},g_y[TOUCH_NUMBER] = {0};
+static volatile int touch_state[TOUCH_NUMBER] = {TOUCH_UP,TOUCH_UP};
+static volatile unsigned int g_x[TOUCH_NUMBER] =  {0},g_y[TOUCH_NUMBER] = {0};
 
 struct ili2102_ts_data {
        u16             model;                  /* 801. */      
@@ -110,6 +109,30 @@ static struct dev_data g_dev;
 #define ILITEK_IOCTL_STOP_READ_DATA             _IOWR(ILITEK_IOCTL_BASE, 12, int)
 #define ILITEK_IOCTL_START_READ_DATA            _IOWR(ILITEK_IOCTL_BASE, 13, int)
 
+
+static ssize_t ili2102_proc_write(struct file *file, const char __user *buffer,
+                          unsigned long count, void *data)
+{
+       char c;
+       int rc;
+       
+       rc = get_user(c, buffer);
+       if (rc)
+               return rc; 
+       
+       if (c == '1')
+               ts_dbg_enable = 1; 
+       else if (c == '0')
+               ts_dbg_enable = 0; 
+
+       return count; 
+}
+
+static const struct file_operations ili2102_proc_fops = {
+       .owner          = THIS_MODULE, 
+       .write          = ili2102_proc_write,
+}; 
+
 static int ilitek_file_open(struct inode *inode, struct file *filp)
 {
        return 0; 
@@ -128,7 +151,7 @@ static ssize_t ilitek_file_write(struct file *filp, const char *buf, size_t coun
        msg[0].scl_rate = 400*1000;
        msg[0].udelay = 80;
 
-       printk("%s:count=0x%x\n",__FUNCTION__,count);
+       DBG("%s:count=0x%x\n",__FUNCTION__,count);
        
        // before sending data to touch device, we need to check whether the device is working or not
        if(g_ts->valid_i2c_register == 0){
@@ -178,7 +201,9 @@ static ssize_t ilitek_file_write(struct file *filp, const char *buf, size_t coun
 }
 
 
-static int ilitek_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+//static int ilitek_file_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+long ilitek_file_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
+
 {
        static unsigned char buffer[64]={0};
        static int len=0;
@@ -243,7 +268,7 @@ static int ilitek_file_ioctl(struct inode *inode, struct file *filp, unsigned in
                return -1;
        }
        
-       printk("%s:cmd=0x%x\n",__FUNCTION__,cmd);
+       DBG("%s:cmd=0x%x\n",__FUNCTION__,cmd);
        
        return 0;
 }
@@ -263,7 +288,7 @@ static int ilitek_file_close(struct inode *inode, struct file *filp)
 
 // declare file operations
 struct file_operations ilitek_fops = {
-       .ioctl = ilitek_file_ioctl,
+       .unlocked_ioctl = ilitek_file_ioctl,    
        .read = ilitek_file_read,
        .write = ilitek_file_write,
        .open = ilitek_file_open,
@@ -275,11 +300,24 @@ static int verify_coord(struct ili2102_ts_data *ts,unsigned int *x,unsigned int
 {
 
        //DBG("%s:(%d/%d)\n",__FUNCTION__,*x, *y);
+       #ifndef CONFIG_MACH_RK29_TD8801_V2
        if((*x< ts->x_min) || (*x > ts->x_max))
                return -1;
 
        if((*y< ts->y_min) || (*y > ts->y_max))
                return -1;
+    #endif
+
+       /*android do not support min and max value*/
+       if(*x == ts->x_min)
+               *x = ts->x_min + 1;
+       if(*y == ts->y_min)
+               *y = ts->y_min + 1;
+       if(*x == ts->x_max)
+               *x = ts->x_max - 1;
+       if(*y == ts->y_max)
+               *y = ts->y_max - 1;
+       
 
        return 0;
 }
@@ -293,7 +331,7 @@ static int ili2102_init_panel(struct ili2102_ts_data *ts)
 
 static void ili2102_ts_work_func(struct work_struct *work)
 {
-       int i,ret;
+       int i,ret,num=1;
        int syn_flag = 0;
        unsigned int x, y;
        struct i2c_msg msg[2];
@@ -310,14 +348,14 @@ static void ili2102_ts_work_func(struct work_struct *work)
        msg[0].flags = ts->client->flags;
        msg[0].len = 1;
        msg[0].buf = &start_reg;
-       msg[0].scl_rate = 400*1000;
+       msg[0].scl_rate = 200*1000;
        msg[0].udelay = 200;
        
        msg[1].addr = ts->client->addr;
        msg[1].flags = ts->client->flags | I2C_M_RD;
        msg[1].len = 9; 
        msg[1].buf = buf;
-       msg[1].scl_rate = 400*1000;
+       msg[1].scl_rate = 200*1000;
        msg[1].udelay = 0;
        
        ret = i2c_transfer(ts->client->adapter, msg, 2); 
@@ -326,7 +364,7 @@ static void ili2102_ts_work_func(struct work_struct *work)
                printk("%s:i2c_transfer fail, ret=%d\n",__FUNCTION__,ret);
                goto out;
        }
-
+       
        for(i=0; i<TOUCH_NUMBER; i++)
        {
 
@@ -335,12 +373,13 @@ static void ili2102_ts_work_func(struct work_struct *work)
                        if (touch_state[i] == TOUCH_DOWN)
                        {
                                DBG("ili2102_ts_work_func:buf[%d]=%d\n",i,buf[i]);
-                               input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); //Finger Size
-                               input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); //Touch Size
-                               input_mt_sync(ts->input_dev);
+                               //input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
+                               //input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0);
+                               input_mt_slot(ts->input_dev, i);
+                               input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
                                syn_flag = 1;
                                touch_state[i] = TOUCH_UP;
-                               DBG("touch_up \n");
+                               DBG("i=%d,touch_up \n",i);
                        }
 
                }
@@ -360,15 +399,16 @@ static void ili2102_ts_work_func(struct work_struct *work)
                                        x = g_x[i];
                                        y = g_y[i];
                                }
-
                                g_x[i] = x;
-                               g_y[i] = y;                     
-                               input_event(ts->input_dev, EV_ABS, ABS_MT_TRACKING_ID, i);
-                       input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 1); //Finger Size
-                       input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
-                       input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
-                       input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 5); //Touch Size
-                       input_mt_sync(ts->input_dev);
+                               g_y[i] = y;     
+                               
+                               input_mt_slot(ts->input_dev, i);
+                               input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
+                               input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 1);
+                               //input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100);
+                               input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
+                               input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
+       
                                syn_flag = 1;
                                touch_state[i] = TOUCH_DOWN;
                                 ts->pendown = 1;
@@ -384,7 +424,7 @@ out:
 #if 0
        if(ts->pendown)
        {
-               schedule_delayed_work(&ts->work, msecs_to_jiffies(10));
+               schedule_delayed_work(&ts->work, msecs_to_jiffies(12));
                ts->pendown = 0;
        }
        else
@@ -636,10 +676,14 @@ static int ili2102_ts_probe(struct i2c_client *client, const struct i2c_device_i
        ts->pendown = 0;
        ts->valid_i2c_register = 1;
 
-       ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_ABS);
+       //ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_ABS);
        //ts->input_dev->absbit[0] = 
                //BIT(ABS_MT_POSITION_X) | BIT(ABS_MT_POSITION_Y) | 
                //BIT(ABS_MT_TOUCH_MAJOR) | BIT(ABS_MT_WIDTH_MAJOR);  // for android
+
+       __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
+       __set_bit(EV_ABS, ts->input_dev->evbit);
+       
        input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 
                    ts->x_min ? : 0,
                        ts->x_max ? : 480,
@@ -648,8 +692,9 @@ static int ili2102_ts_probe(struct i2c_client *client, const struct i2c_device_i
                        ts->y_min ? : 0,
                        ts->y_max ? : 800,
                        0, 0);
-       input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 1, 0, 0); //Finger Size
-       input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 10, 0, 0); //Touch Size
+       input_mt_init_slots(ts->input_dev, TOUCH_NUMBER);
+       input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+       //input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
 
        /* ts->input_dev->name = ts->keypad_info->name; */
        ret = input_register_device(ts->input_dev);
@@ -712,6 +757,9 @@ static int ili2102_ts_probe(struct i2c_client *client, const struct i2c_device_i
        ts->early_suspend.resume = ili2102_ts_late_resume;
        register_early_suspend(&ts->early_suspend);
 #endif
+               
+       struct proc_dir_entry *ili2102_proc_entry;      
+       ili2102_proc_entry = proc_create("driver/ili2102", 0777, NULL, &ili2102_proc_fops); 
 
        printk(KERN_INFO "ili2102_ts_probe: Start touchscreen %s in %s mode\n", ts->input_dev->name, ts->use_irq ? "interrupt" : "polling");
 
@@ -758,6 +806,21 @@ static int ili2102_ts_suspend(struct i2c_client *client, pm_message_t mesg)
        struct ili2102_ts_data *ts = i2c_get_clientdata(client);
        uint8_t buf[1] = {0x30};
        struct i2c_msg msg[1];
+
+       //to do suspend
+       msg[0].addr =client->addr;
+       msg[0].flags = 0;
+       msg[0].len = 1;
+       msg[0].buf = buf;
+
+       ret = i2c_transfer(client->adapter, msg, 1);
+       if (ret < 0) {
+       printk("%s:err\n",__FUNCTION__);
+       }
+
+       ret = cancel_delayed_work_sync(&ts->work);
+       if (ret && ts->use_irq) /* if work was pending disable-count is now 2 */
+       enable_irq(client->irq);
        
        if (ts->use_irq)
        {
@@ -774,21 +837,6 @@ static int ili2102_ts_suspend(struct i2c_client *client, pm_message_t mesg)
        else
        hrtimer_cancel(&ts->timer);
 
-       ret = cancel_delayed_work_sync(&ts->work);
-       //if (ret && ts->use_irq) /* if work was pending disable-count is now 2 */
-       //enable_irq(client->irq);
-
-       //to do suspend
-       msg[0].addr =client->addr;
-       msg[0].flags = 0;
-       msg[0].len = 1;
-       msg[0].buf = buf;
-
-       ret = i2c_transfer(client->adapter, msg, 1);
-       if (ret < 0) {
-       printk("%s:err\n",__FUNCTION__);
-       }
-       
        DBG("%s\n",__FUNCTION__);
        
        return 0;
@@ -798,8 +846,11 @@ static int ili2102_ts_suspend(struct i2c_client *client, pm_message_t mesg)
 static void ili2102_ts_resume_work_func(struct work_struct *work)
 {
        struct ili2102_ts_data *ts = container_of(work, struct ili2102_ts_data, work);
-       int ret;
+       int ret,i;
+
+       PREPARE_DELAYED_WORK(&ts->work, ili2102_ts_work_func);
        mdelay(100); //wait for 100ms before i2c operation
+       
        free_irq(ts->client->irq, ts);
        ret = request_irq(ts->client->irq, ili2102_ts_irq_handler, IRQF_DISABLED | IRQF_TRIGGER_LOW, ts->client->name, ts);
        if (ret == 0) {
@@ -809,8 +860,7 @@ static void ili2102_ts_resume_work_func(struct work_struct *work)
        else 
        printk("%s:request irq=%d failed,ret=%d\n",__FUNCTION__,ts->client->irq,ret);
 
-       PREPARE_DELAYED_WORK(&ts->work, ili2102_ts_work_func);
-       printk("%s,irq=%d\n",__FUNCTION__,ts->client->irq);
+       DBG("%s,irq=%d\n",__FUNCTION__,ts->client->irq);
 }