Merge branch 'develop-3.0' of ssh://192.168.1.29/rk/kernel into develop-3.0
[firefly-linux-kernel-4.4.55.git] / drivers / input / touchscreen / eeti_egalax_i2c.c
old mode 100644 (file)
new mode 100755 (executable)
index a59fcaa..ee5624b
 #include <linux/kfifo.h>
 #include <linux/version.h>
 #include <linux/input.h>
+#include <linux/input/mt.h>
 #include <linux/irq.h>
 #include <linux/async.h>
 #include <mach/board.h>
 
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
 //#define DEBUG
-#ifdef DEBUG
+#ifdef CONFIG_EETI_EGALAX_DEBUG
        #define TS_DEBUG(fmt,args...)  printk( KERN_DEBUG "[egalax_i2c]: " fmt, ## args)
        #define DBG() printk("[%s]:%d => \n",__FUNCTION__,__LINE__)
 #else
 
 static int global_major = 0; // dynamic major by default 
 static int global_minor = 0;
-
+#define EETI_I2C_RATE   (200*1000)
 #define MAX_I2C_LEN            10
 #define FIFO_SIZE              PAGE_SIZE
-#define MAX_SUPPORT_POINT      5
+#define MAX_SUPPORT_POINT      2
 #define REPORTID_MOUSE         0x01
 #define REPORTID_VENDOR                0x03
 #define REPORTID_MTOUCH                0x04
@@ -67,6 +72,8 @@ static int global_minor = 0;
 #define        EGALAX_IOCWAKEUP        _IO(EGALAX_IOC_MAGIC, 1)
 #define EGALAX_IOC_MAXNR       1
 
+#define EETI_EARLYSUSPEND_LEVEL        151
+
 struct point_data {
        short Status;
        short X;
@@ -83,6 +90,13 @@ struct _egalax_i2c {
        int irq;
 };
 
+#ifdef CONFIG_HAS_EARLYSUSPEND 
+struct suspend_info {
+       struct early_suspend early_suspend;
+       struct _egalax_i2c *egalax_i2c;
+};
+#endif
+
 struct egalax_char_dev
 {
        int OpenCnts;
@@ -244,7 +258,7 @@ static ssize_t egalax_cdev_write(struct file *file, const char __user *buf, size
                return -EFAULT;
        }
        
-       ret = i2c_master_send(p_egalax_i2c_dev->client, tmp, count);
+       ret = i2c_master_normal_send(p_egalax_i2c_dev->client, tmp, count,EETI_I2C_RATE);
        TS_DEBUG("I2C writing %zu bytes.\n", count);
 
        kfree(tmp);
@@ -276,7 +290,7 @@ static int wakeup_controller(int gpio)
        return ret;
 }
 
-static int egalax_cdev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long args)
+static long egalax_cdev_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
 {      
        //struct egalax_char_dev *cdev = file->private_data;
        int ret=0;
@@ -338,7 +352,6 @@ static void ProcessReport(unsigned char *buf, int buflen)
 {
        int i;
        short X=0, Y=0, ContactID=0, Status=0;
-
        if(buflen!=MAX_I2C_LEN || buf[0]!=0x04) // check buffer len & header
                return;
 
@@ -360,17 +373,21 @@ static void ProcessReport(unsigned char *buf, int buflen)
                {
                        if(PointBuf[i].Status >= 0)
                        {
-                               input_report_abs(input_dev, ABS_MT_TRACKING_ID, i);                     
+                               input_mt_slot(input_dev, i);
+                               input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, true);
                                input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, PointBuf[i].Status);
-                               input_report_abs(input_dev, ABS_MT_WIDTH_MAJOR, 0);
+                               input_report_abs(input_dev, ABS_MT_PRESSURE, 100);
                                input_report_abs(input_dev, ABS_MT_POSITION_X, PointBuf[i].X);
                                input_report_abs(input_dev, ABS_MT_POSITION_Y, PointBuf[i].Y);
 
-                               input_mt_sync(input_dev);
-
                                if(PointBuf[i].Status == 0)
                                        PointBuf[i].Status--;
                        }
+                       else
+                       {
+                               input_mt_slot(input_dev, i);
+                               input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false);
+                       }
                }
                input_sync(input_dev);
                TS_DEBUG("Input sync point data done!\n");
@@ -396,14 +413,15 @@ static struct input_dev * allocate_Input_Dev(void)
        pInputDev->id.bustype = BUS_I2C;
        pInputDev->id.vendor = 0x0EEF;
        pInputDev->id.product = 0x0020;
-       
-       set_bit(EV_ABS, pInputDev->evbit);
 
-       input_set_abs_params(pInputDev, ABS_MT_POSITION_X, 0, 1080, 0, 0);
-       input_set_abs_params(pInputDev, ABS_MT_POSITION_Y, 0, 800, 0, 0);
+       __set_bit(INPUT_PROP_DIRECT, pInputDev->propbit);
+       __set_bit(EV_ABS, pInputDev->evbit);
+
+       input_mt_init_slots(pInputDev, MAX_SUPPORT_POINT);
+       input_set_abs_params(pInputDev, ABS_MT_POSITION_X, 0, CONFIG_EETI_EGALAX_MAX_X, 0, 0);
+       input_set_abs_params(pInputDev, ABS_MT_POSITION_Y, 0, CONFIG_EETI_EGALAX_MAX_Y, 0, 0);
        input_set_abs_params(pInputDev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
-       input_set_abs_params(pInputDev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
-       input_set_abs_params(pInputDev, ABS_MT_TRACKING_ID, 0, 10, 0, 0);
+       input_set_abs_params(pInputDev, ABS_MT_PRESSURE, 0, 255, 0, 0);
 
        ret = input_register_device(pInputDev);
        if(ret) 
@@ -421,10 +439,9 @@ static int egalax_i2c_measure(struct i2c_client *client, char skip_packet)
 {
        u8 x_buf[MAX_I2C_LEN];
        int count, loop=3;
-       
        DBG();
        do{
-               count = i2c_master_recv(client, x_buf, MAX_I2C_LEN);
+               count = i2c_master_normal_recv(client, x_buf, MAX_I2C_LEN,EETI_I2C_RATE);
        }while(count==EAGAIN && --loop);
 
        if( count<0 || (x_buf[0]!=REPORTID_VENDOR && x_buf[0]!=REPORTID_MTOUCH) )
@@ -467,7 +484,6 @@ static void egalax_i2c_wq(struct work_struct *work)
        struct _egalax_i2c *egalax_i2c = container_of(work, struct _egalax_i2c, work);
        struct i2c_client *client = egalax_i2c->client;
        int gpio = client->irq;
-
        TS_DEBUG("egalax_i2c_wq run\n");
        mutex_lock(&egalax_i2c->mutex_wq);
 
@@ -475,16 +491,39 @@ static void egalax_i2c_wq(struct work_struct *work)
        while( !gpio_get_value(gpio) && egalax_i2c->work_state>0 )
        {
                egalax_i2c_measure(client, egalax_i2c->skip_packet);
-               schedule();
+               schedule_timeout_interruptible(HZ/100);
        }
-       
+
+#ifndef _NON_INPUT_DEV
+       if (gpio_get_value(gpio) && egalax_i2c->work_state > 0 && !egalax_i2c->skip_packet) {
+               int i;
+               for(i = 0; i < MAX_SUPPORT_POINT; i++) {
+                       if (PointBuf[i].Status > 0) {
+                               TS_DEBUG("point %d still down\n", i);
+                               input_mt_slot(input_dev, i);
+                               input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, true);
+                               input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 0);
+                               input_report_abs(input_dev, ABS_MT_PRESSURE, 100);
+                               input_report_abs(input_dev, ABS_MT_POSITION_X, PointBuf[i].X);
+                               input_report_abs(input_dev, ABS_MT_POSITION_Y, PointBuf[i].Y);
+                               PointBuf[i].Status = 0;
+                       }
+                       else
+                       {
+                               input_mt_slot(input_dev, i);
+                               input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false);
+                       }
+               }
+               input_sync(input_dev);
+       }
+#endif
+
        if( egalax_i2c->skip_packet > 0 )
                egalax_i2c->skip_packet = 0;
 
        mutex_unlock(&egalax_i2c->mutex_wq);
-       
-       if( egalax_i2c->work_state > 0 )
-               enable_irq(p_egalax_i2c_dev->irq);
+
+       enable_irq(p_egalax_i2c_dev->irq);
 
        TS_DEBUG("egalax_i2c_wq leave\n");
 }
@@ -492,7 +531,6 @@ static void egalax_i2c_wq(struct work_struct *work)
 static irqreturn_t egalax_i2c_interrupt(int irq, void *dev_id)
 {
        struct _egalax_i2c *egalax_i2c = (struct _egalax_i2c *)dev_id;
-
        TS_DEBUG("egalax_i2c_interrupt with irq:%d\n", irq);
        disable_irq_nosync(irq);
        queue_work(egalax_i2c->ktouch_wq, &egalax_i2c->work);
@@ -500,17 +538,44 @@ static irqreturn_t egalax_i2c_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+
+void egalax_i2c_set_standby(struct i2c_client *client, int enable)
+{
+        struct eeti_egalax_platform_data *mach_info = client->dev.platform_data;
+       unsigned display_on = mach_info->disp_on_pin;
+       unsigned lcd_standby = mach_info->standby_pin;
+
+       int display_on_pol = mach_info->disp_on_value;
+       int lcd_standby_pol = mach_info->standby_value;
+
+        printk("%s : %s, enable = %d", __FILE__, __FUNCTION__,enable);
+    if(display_on != INVALID_GPIO)
+    {
+        gpio_direction_output(display_on, 0);
+        gpio_set_value(display_on, enable ? display_on_pol : !display_on_pol);                         
+    }
+    if(lcd_standby != INVALID_GPIO)
+    {
+        gpio_direction_output(lcd_standby, 0);
+       gpio_set_value(lcd_standby, enable ? lcd_standby_pol : !lcd_standby_pol);                         
+    }
+}
+
 #ifdef CONFIG_PM
 static int egalax_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
 {
        struct _egalax_i2c *egalax_i2c = i2c_get_clientdata(client);
        u8 cmdbuf[MAX_I2C_LEN]={0x03, 0x05, 0x0A, 0x03, 0x36, 0x3F, 0x02, 0, 0, 0};
        
-       i2c_master_send(client, cmdbuf, MAX_I2C_LEN);
+       i2c_master_normal_send(client, cmdbuf, MAX_I2C_LEN, EETI_I2C_RATE);
 
-       egalax_i2c->work_state = 0;
        disable_irq(p_egalax_i2c_dev->irq);
-       cancel_work_sync(&egalax_i2c->work);
+       egalax_i2c->work_state = 0;
+       if (cancel_work_sync(&egalax_i2c->work)) {
+               /* if work was pending disable-count is now 2 */
+               pr_info("%s: work was pending\n", __func__);
+               enable_irq(p_egalax_i2c_dev->irq);
+       }
 
        printk(KERN_DEBUG "[egalax_i2c]: device suspend done\n");       
 
@@ -522,14 +587,14 @@ static int egalax_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
        {
                printk(KERN_DEBUG "[egalax_i2c]: device_may_wakeup false\n");
        }
-
+       egalax_i2c_set_standby(client, 0);
        return 0;
 }
 
 static int egalax_i2c_resume(struct i2c_client *client)
 {
        struct _egalax_i2c *egalax_i2c = i2c_get_clientdata(client);
-       
+       egalax_i2c_set_standby(client, 1);      
        if(device_may_wakeup(&client->dev)) 
        {
                disable_irq_wake(p_egalax_i2c_dev->irq);
@@ -547,17 +612,51 @@ static int egalax_i2c_resume(struct i2c_client *client)
 
        return 0;
 }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND 
+
+static void egalax_i2c_early_suspend(struct early_suspend *h)
+{
+       pm_message_t mesg = {.event = 0};
+       struct suspend_info *info = container_of(h,struct suspend_info,early_suspend);
+       struct i2c_client *client = info->egalax_i2c->client;
+       egalax_i2c_suspend(client,mesg);
+
+}
+static void egalax_i2c_early_resume(struct early_suspend *h)
+{
+   
+    struct suspend_info *info = container_of(h,struct suspend_info,early_suspend);
+    struct i2c_client *client = info->egalax_i2c->client;
+
+    egalax_i2c_resume(client);
+
+}
+
+#endif
+
+
+
 #else
 #define egalax_i2c_suspend       NULL
 #define egalax_i2c_resume        NULL
 #endif
 
-static int __devinit egalax_i2c_probe(struct i2c_client *client)
+#ifdef CONFIG_HAS_EARLYSUSPEND 
+static struct suspend_info suspend_info = {
+       .early_suspend.suspend = egalax_i2c_early_suspend,
+       .early_suspend.resume = egalax_i2c_early_resume,
+       .early_suspend.level = EETI_EARLYSUSPEND_LEVEL,
+};
+#endif
+
+
+static int __devinit egalax_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        int ret;
        int gpio = client->irq;
        struct eeti_egalax_platform_data *pdata = pdata = client->dev.platform_data;
-       DBG();
+
        printk(KERN_DEBUG "[egalax_i2c]: start probe\n");
 
        p_egalax_i2c_dev = (struct _egalax_i2c *)kzalloc(sizeof(struct _egalax_i2c), GFP_KERNEL);
@@ -600,7 +699,7 @@ if (pdata->init_platform_hw)
        
        p_egalax_i2c_dev->irq = gpio_to_irq(client->irq);
        
-       ret = request_irq(p_egalax_i2c_dev->irq, egalax_i2c_interrupt, 0,
+       ret = request_irq(p_egalax_i2c_dev->irq, egalax_i2c_interrupt, IRQF_TRIGGER_LOW,
                 client->name, p_egalax_i2c_dev);
        if( ret ) 
        {
@@ -610,7 +709,14 @@ if (pdata->init_platform_hw)
        TS_DEBUG("egalax_i2c request irq(%d) gpio(%d) with result:%d\n", p_egalax_i2c_dev->irq, gpio, ret);
 
 #ifdef CONFIG_PM
-       device_init_wakeup(&client->dev, 1);
+       device_init_wakeup(&client->dev, 0);
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+
+
+       suspend_info.egalax_i2c = p_egalax_i2c_dev;
+       register_early_suspend(&suspend_info.early_suspend);
 #endif
 
        printk(KERN_DEBUG "[egalax_i2c]: probe done\n");
@@ -681,15 +787,15 @@ static struct i2c_driver egalax_i2c_driver = {
        .id_table       = egalax_i2c_idtable,
        .probe          = egalax_i2c_probe,
        .remove         = __devexit_p(egalax_i2c_remove),
-       .suspend        = egalax_i2c_suspend,
-       .resume         = egalax_i2c_resume,
+       //.suspend      = egalax_i2c_suspend,
+       //.resume               = egalax_i2c_resume,
 };
 
 static const struct file_operations egalax_cdev_fops = {
        .owner  = THIS_MODULE,
        .read   = egalax_cdev_read,
        .write  = egalax_cdev_write,
-       .ioctl  = egalax_cdev_ioctl,
+       .unlocked_ioctl = egalax_cdev_ioctl,
        .poll   = egalax_cdev_poll,
        .open   = egalax_cdev_open,
        .release= egalax_cdev_release,
@@ -781,7 +887,7 @@ static void __init egalax_i2c_ts_init_async(void *unused, async_cookie_t cookie)
 {
        int result;
        dev_t devno = 0;
-printk("--------> %s <-------------\n",__func__);
+
        DBG();
 
        // Asking for a dynamic major unless directed otherwise at load time.
@@ -799,7 +905,7 @@ printk("--------> %s <-------------\n",__func__);
        if (result < 0)
        {
                TS_DEBUG(" egalax_i2c cdev can't get major number\n");
-               return 0;
+               return;
        }
 
        // allocate the character device
@@ -824,13 +930,13 @@ printk("--------> %s <-------------\n",__func__);
        device_create(egalax_class, NULL, devno, NULL, "egalax_i2c");
 #endif
        TS_DEBUG("register egalax_i2c cdev, major: %d \n",global_major);
-printk("--------> %s <-------------\n",__func__);
+
        printk(KERN_DEBUG "[egalax_i2c]: init done\n");
-       return i2c_add_driver(&egalax_i2c_driver);
+       i2c_add_driver(&egalax_i2c_driver);
+       return;
 
 fail:  
        egalax_i2c_ts_exit();
-       return result;
 }
 
 static int __init egalax_i2c_ts_init(void)