#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
#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;
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;
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);
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;
{
int i;
short X=0, Y=0, ContactID=0, Status=0;
-
if(buflen!=MAX_I2C_LEN || buf[0]!=0x04) // check buffer len & header
return;
{
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");
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)
{
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) )
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);
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");
}
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);
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");
{
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);
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);
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 )
{
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");
.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,
{
int result;
dev_t devno = 0;
-printk("--------> %s <-------------\n",__func__);
+
DBG();
// Asking for a dynamic major unless directed otherwise at load time.
if (result < 0)
{
TS_DEBUG(" egalax_i2c cdev can't get major number\n");
- return 0;
+ return;
}
// allocate the character device
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)