1 /* drivers/input/touchscreen/gt818_ts.c
\r
3 * Copyright (C) 2011 Rockcip, Inc.
\r
5 * This software is licensed under the terms of the GNU General Public
\r
6 * License version 2, as published by the Free Software Foundation, and
\r
7 * may be copied, distributed, and modified under those terms.
\r
9 * This program is distributed in the hope that it will be useful,
\r
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
12 * GNU General Public License for more details.
\r
14 * Author: hhb@rock-chips.com
\r
17 #include <linux/kernel.h>
\r
18 #include <linux/module.h>
\r
19 #include <linux/time.h>
\r
20 #include <linux/delay.h>
\r
21 #include <linux/device.h>
\r
22 #include <linux/earlysuspend.h>
\r
23 #include <linux/hrtimer.h>
\r
24 #include <linux/i2c.h>
\r
25 #include <linux/input.h>
\r
26 #include <linux/interrupt.h>
\r
27 #include <linux/io.h>
\r
28 #include <linux/platform_device.h>
\r
30 #include <linux/gpio.h>
\r
31 #include <mach/iomux.h>
\r
33 #include <linux/irq.h>
\r
34 #include <linux/syscalls.h>
\r
35 #include <linux/reboot.h>
\r
36 #include <linux/proc_fs.h>
\r
38 #include <linux/vmalloc.h>
\r
39 #include <linux/fs.h>
\r
40 #include <linux/string.h>
\r
41 #include <linux/completion.h>
\r
42 #include <asm/uaccess.h>
\r
43 #include <linux/input/mt.h>
\r
45 #include "gt818_ts.h"
\r
49 #if !defined(GT801_PLUS) && !defined(GT801_NUVOTON)
\r
50 #error The code does not match this touchscreen.
\r
53 static struct workqueue_struct *goodix_wq;
\r
55 static const char *gt818_ts_name = "Goodix Capacitive TouchScreen";
\r
57 //static struct point_queue finger_list;
\r
59 struct i2c_client * i2c_connect_client = NULL;
\r
61 //EXPORT_SYMBOL(i2c_connect_client);
\r
63 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
64 static void goodix_ts_early_suspend(struct early_suspend *h);
\r
65 static void goodix_ts_late_resume(struct early_suspend *h);
\r
68 #ifdef HAVE_TOUCH_KEY
\r
69 const uint16_t gt818_key_array[]={
\r
75 #define MAX_KEY_NUM (sizeof(gt818_key_array)/sizeof(gt818_key_array[0]))
\r
78 unsigned int last_x[MAX_FINGER_NUM + 1]= {0};
\r
79 unsigned int last_y[MAX_FINGER_NUM + 1]= {0};
\r
82 /*Function as i2c_master_send */
\r
83 static int i2c_read_bytes(struct i2c_client *client, u8 *buf, int len)
\r
85 struct i2c_msg msgs[2];
\r
88 msgs[0].addr = client->addr;
\r
89 msgs[0].flags = client->flags;
\r
91 msgs[0].buf = &buf[0];
\r
92 msgs[0].scl_rate = GT818_I2C_SCL;
\r
93 msgs[0].udelay = client->udelay;
\r
95 msgs[1].addr = client->addr;
\r
96 msgs[1].flags = client->flags | I2C_M_RD;
\r
97 msgs[1].len = len-2;
\r
98 msgs[1].buf = &buf[2];
\r
99 msgs[1].scl_rate = GT818_I2C_SCL;
\r
100 msgs[1].udelay = client->udelay;
\r
102 ret = i2c_transfer(client->adapter, msgs, 2);
\r
104 printk("%s:i2c_transfer fail =%d\n",__func__, ret);
\r
109 /*Function as i2c_master_send */
\r
110 static int i2c_write_bytes(struct i2c_client *client,u8 *data,int len)
\r
112 struct i2c_msg msg;
\r
115 msg.addr = client->addr;
\r
116 msg.flags = client->flags;
\r
119 msg.scl_rate = GT818_I2C_SCL;
\r
120 msg.udelay = client->udelay;
\r
122 ret = i2c_transfer(client->adapter, &msg, 1);
\r
124 printk("%s:i2c_transfer fail =%d\n",__func__, ret);
\r
130 static int i2c_pre_cmd(struct gt818_ts_data *ts)
\r
133 u8 pre_cmd_data[2] = {0};
\r
134 pre_cmd_data[0] = 0x0f;
\r
135 pre_cmd_data[1] = 0xff;
\r
136 ret = i2c_write_bytes(ts->client,pre_cmd_data,2);
\r
142 static int i2c_end_cmd(struct gt818_ts_data *ts)
\r
145 u8 end_cmd_data[2] = {0};
\r
146 end_cmd_data[0] = 0x80;
\r
147 end_cmd_data[1] = 0x00;
\r
148 ret = i2c_write_bytes(ts->client,end_cmd_data,2);
\r
155 static int goodix_init_panel(struct gt818_ts_data *ts)
\r
160 u8 config_info[] = {
\r
162 0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,
\r
163 0x10,0x12,0x00,0x00,0x10,0x00,0x20,0x00,
\r
164 0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,
\r
165 0xE0,0x00,0xD0,0x00,0xC0,0x00,0xB0,0x00,
\r
166 0xA0,0x00,0x90,0x00,0x80,0x00,0x70,0x00,
\r
167 0xF0,0x00,0x13,0x13,0x90,0x90,0x90,0x27,
\r
168 0x27,0x27,0x0F,0x0E,0x0A,0x40,0x30,0x01,
\r
169 0x03,0x00,MAX_FINGER_NUM,0x00,0x14,0xFA,0x1B,0x00,
\r
170 0x00,0x66,0x5A,0x6A,0x5E,0x00,0x00,0x05,
\r
171 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
\r
172 0x14,0x10,0xEF,0x03,0x00,0x00,0x00,0x00,
\r
173 0x00,0x00,0x20,0x40,0x70,0x90,0x0F,0x40,
\r
174 0x30,0x3C,0x28,0x00,0x00,0x00,0x00,0x00,
\r
178 u8 read_config_info[sizeof(config_info)] = {0};
\r
179 read_config_info[0] = 0x06;
\r
180 read_config_info[1] = 0xa2;
\r
182 ret = i2c_write_bytes(ts->client, config_info, (sizeof(config_info)/sizeof(config_info[0])));
\r
184 printk("config gt818 fail\n");
\r
188 ret = i2c_read_bytes(ts->client, read_config_info, (sizeof(config_info)/sizeof(config_info[0])));
\r
190 printk("read gt818 config fail\n");
\r
194 for(i = 2; i < 106; i++){
\r
195 if(read_config_info[i] != config_info[i]){
\r
196 printk("write gt818 config error\n");
\r
206 static int goodix_read_version(struct gt818_ts_data *ts)
\r
209 u8 version_data[5] = {0}; //store touchscreen version infomation
\r
210 memset(version_data, 0, 5);
\r
211 version_data[0] = 0x07;
\r
212 version_data[1] = 0x17;
\r
214 ret = i2c_read_bytes(ts->client, version_data, 4);
\r
217 dev_info(&ts->client->dev," Guitar Version: %d.%d\n",version_data[3],version_data[2]);
\r
224 static void goodix_ts_work_func(struct work_struct *work)
\r
226 u8 touch_status[8*MAX_FINGER_NUM + 18] = {READ_TOUCH_ADDR_H, READ_TOUCH_ADDR_L, 0};
\r
227 u8 *key_value = NULL;
\r
228 u8 *point_data = NULL;
\r
229 static u8 finger_last[MAX_FINGER_NUM + 1]={0};
\r
230 u8 finger_current[MAX_FINGER_NUM + 1] = {0};
\r
231 u8 coor_data[6*MAX_FINGER_NUM] = {0};
\r
232 static u8 last_key = 0;
\r
236 unsigned int count = 0;
\r
237 unsigned int position = 0;
\r
239 int x = 0, y = 0 , pressure;
\r
245 struct gt818_ts_data *ts = container_of(work, struct gt818_ts_data, work);
\r
248 i2c_read_bytes(ts->client, touch_status, sizeof(touch_status)/sizeof(touch_status[0]));
\r
251 //judge whether the data is ready
\r
252 if((touch_status[2] & 0x30) != 0x20)
\r
254 printk("%s:DATA_NO_READY\n", __func__);
\r
255 goto DATA_NO_READY;
\r
257 //judge whether it is large area touch
\r
258 if(touch_status[13] & 0x0f)
\r
260 goto DATA_NO_READY;
\r
264 finger = touch_status[2] & 0x07;
\r
265 key_value = touch_status + 15;
\r
266 key = key_value[2] & 0x0f;
\r
270 point_data = key_value + 3;
\r
272 for(position = 0; position < (finger*8); position += 8)
\r
274 temp = point_data[position];
\r
275 //printk("track:%d\n", temp);
\r
276 if(temp < (MAX_FINGER_NUM + 1))
\r
278 finger_current[temp] = 1;
\r
279 for(count = 0; count < 6; count++)
\r
281 coor_data[(temp - 1) * 6 + count] = point_data[position+1+count];
\r
286 //dev_err(&(ts->client->dev),"Track Id error:%d\n ",);
\r
297 for(position = 1; position < MAX_FINGER_NUM+1; position++)
\r
299 finger_current[position] = 0;
\r
303 coor_point = (u16 *)coor_data;
\r
305 for(position = 1; position < MAX_FINGER_NUM + 1; position++)
\r
307 if((finger_current[position] == 0) && (finger_last[position] != 0))
\r
309 //printk("<<<<<<<<<<<<<<<<<<<%s:positon:%d (%d,%d)\n", __func__, position,last_x,last_y);
\r
310 //printk("<<<%d , %d ",finger_current[position],finger_last[position]);
\r
311 //input_mt_slot(ts->input_dev, position);
\r
312 //input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
\r
313 //input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
\r
314 //input_report_abs(ts->input_dev, ABS_MT_POSITION_X, last_x[position]);
\r
315 //input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, last_y[position]);
\r
316 //input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100);
\r
317 //input_mt_sync(ts->input_dev);
\r
318 input_mt_slot(ts->input_dev, position);
\r
319 input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
\r
322 else if(finger_current[position])
\r
324 x = (*(coor_point+3*(position-1)))*SCREEN_MAX_WIDTH/(TOUCH_MAX_WIDTH);
\r
325 y = (*(coor_point+3*(position-1)+1))*SCREEN_MAX_HEIGHT/(TOUCH_MAX_HEIGHT);
\r
326 pressure = (*(coor_point+3*(position-1)+2));
\r
327 if(x < SCREEN_MAX_WIDTH){
\r
328 x = SCREEN_MAX_WIDTH - x;
\r
331 if(y < SCREEN_MAX_HEIGHT){
\r
332 // y = SCREEN_MAX_HEIGHT-y;
\r
335 //printk(">>>>>>>>>>>>>>>>>%s:positon:%d (%d,%d)\n", __func__, position,x,y);
\r
336 input_mt_slot(ts->input_dev, position);
\r
337 input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
\r
338 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 1);
\r
339 input_report_abs(ts->input_dev, ABS_MT_PRESSURE, pressure);
\r
340 input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
\r
341 input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
\r
343 last_x[position] = x;
\r
344 last_y[position] = y;
\r
345 //input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, pressure);
\r
346 //input_mt_sync(ts->input_dev);
\r
351 input_sync(ts->input_dev);
\r
355 #ifdef HAVE_TOUCH_KEY
\r
356 if((last_key == 0) && (key == 0)){
\r
379 input_report_key(ts->input_dev, gt818_key_array[key - 1], 1);
\r
382 input_report_key(ts->input_dev, gt818_key_array[last_key - 1], 0);
\r
392 input_sync(ts->input_dev);
\r
395 for(position = 1; position < MAX_FINGER_NUM + 1; position++)
\r
397 finger_last[position] = finger_current[position];
\r
402 // i2c_end_cmd(ts);
\r
404 enable_irq(ts->client->irq);
\r
408 static int test_suspend_resume(struct gt818_ts_data *ts){
\r
419 static enum hrtimer_restart goodix_ts_timer_func(struct hrtimer *timer)
\r
421 struct gt818_ts_data *ts = container_of(timer, struct gt818_ts_data, timer);
\r
422 queue_work(goodix_wq, &ts->work);
\r
423 hrtimer_start(&ts->timer, ktime_set(0, (POLL_TIME+6)*1000000), HRTIMER_MODE_REL);
\r
424 return HRTIMER_NORESTART;
\r
428 static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
\r
430 struct gt818_ts_data *ts = dev_id;
\r
431 disable_irq_nosync(ts->client->irq);
\r
432 queue_work(goodix_wq, &ts->work);
\r
433 return IRQ_HANDLED;
\r
436 static int goodix_ts_power(struct gt818_ts_data * ts, int on)
\r
439 struct gt818_platform_data *pdata = ts->client->dev.platform_data;
\r
440 unsigned char i2c_control_buf[3] = {0x06,0x92,0x01}; //suspend cmd
\r
441 if(ts != NULL && !ts->use_irq)
\r
447 // set the io port high level to avoid level change which might stop gt818 from sleeping
\r
448 gpio_direction_output(pdata->gpio_reset, 1);
\r
449 gpio_direction_output(pdata->gpio_pendown, 1);
\r
451 ret = i2c_write_bytes(ts->client, i2c_control_buf, 3);
\r
454 printk(KERN_INFO"**gt818 suspend fail**\n");
\r
458 //printk(KERN_INFO"**gt818 suspend**\n");
\r
461 // i2c_end_cmd(ts);
\r
466 gpio_pull_updown(pdata->gpio_pendown, 1);
\r
467 gpio_direction_output(pdata->gpio_pendown, 0);
\r
469 gpio_direction_output(pdata->gpio_pendown, 1);
\r
471 gpio_direction_input(pdata->gpio_pendown);
\r
472 gpio_pull_updown(pdata->gpio_pendown, 0);
\r
476 gpio_pull_updown(pdata->gpio_reset, 1);
\r
477 gpio_direction_output(pdata->gpio_reset, 0);
\r
479 gpio_direction_input(pdata->gpio_reset);
\r
480 gpio_pull_updown(pdata->gpio_reset, 0);
\r
484 ret = i2c_pre_cmd(ts);
\r
485 //printk(KERN_INFO"**gt818 reusme**\n");
\r
486 ret = i2c_end_cmd(ts);
\r
491 printk(KERN_DEBUG "%s: Cant't support this command.", gt818_ts_name);
\r
498 static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
\r
502 struct gt818_ts_data *ts;
\r
504 struct gt818_platform_data *pdata;
\r
505 dev_info(&client->dev,"Install touch driver.\n");
\r
506 printk("gt818: Install touch driver.\n");
\r
507 //Check I2C function
\r
508 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
\r
510 dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n");
\r
512 goto err_check_functionality_failed;
\r
515 ts = kzalloc(sizeof(*ts), GFP_KERNEL);
\r
518 goto err_alloc_data_failed;
\r
521 i2c_connect_client = client; //used by Guitar_Update
\r
522 pdata = client->dev.platform_data;
\r
523 ts->client = client;
\r
524 i2c_set_clientdata(client, ts);
\r
526 //init int and reset ports
\r
527 ret = gpio_request(pdata->gpio_pendown, "TS_INT"); //Request IO
\r
529 dev_err(&client->dev, "Failed to request GPIO:%d, ERRNO:%d\n",(int)pdata->gpio_pendown, ret);
\r
530 goto err_gpio_request_failed;
\r
532 rk29_mux_api_set(pdata->pendown_iomux_name, pdata->pendown_iomux_mode);
\r
533 gpio_direction_input(pdata->gpio_pendown);
\r
534 gpio_pull_updown(pdata->gpio_pendown, 0);
\r
536 ret = gpio_request(pdata->gpio_reset, "gt818_resetPin");
\r
538 dev_err(&client->dev, "failed to request resetPin GPIO%d\n", pdata->gpio_reset);
\r
539 goto err_gpio_request_failed;
\r
541 rk29_mux_api_set(pdata->resetpin_iomux_name, pdata->resetpin_iomux_mode);
\r
544 for(retry = 0; retry < 4; retry++)
\r
546 gpio_pull_updown(pdata->gpio_reset, 1);
\r
547 gpio_direction_output(pdata->gpio_reset, 0);
\r
548 msleep(1); //delay at least 1ms
\r
549 gpio_direction_input(pdata->gpio_reset);
\r
550 gpio_pull_updown(pdata->gpio_reset, 0);
\r
551 msleep(25); //delay at least 20ms
\r
552 ret = i2c_pre_cmd(ts);
\r
560 dev_err(&client->dev, "Warnning: I2C communication might be ERROR!\n");
\r
561 goto err_i2c_failed;
\r
566 for(retry = 0; retry < 3; retry++)
\r
568 ret = goodix_init_panel(ts);
\r
570 dev_info(&client->dev,"the config ret is :%d\n", ret);
\r
572 if(ret < 0) //Initiall failed
\r
580 goto err_init_godix_ts;
\r
583 goodix_read_version(ts);
\r
586 INIT_WORK(&ts->work, goodix_ts_work_func); //init work_struct
\r
587 ts->input_dev = input_allocate_device();
\r
588 if (ts->input_dev == NULL) {
\r
590 dev_dbg(&client->dev,"goodix_ts_probe: Failed to allocate input device\n");
\r
591 goto err_input_dev_alloc_failed;
\r
594 //ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
\r
595 //ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
\r
596 //ts->input_dev->absbit[0] = BIT_MASK(ABS_MT_POSITION_X) | BIT_MASK(ABS_MT_POSITION_Y) |
\r
597 // BIT_MASK(ABS_MT_TOUCH_MAJOR) | BIT_MASK(ABS_MT_WIDTH_MAJOR); // for android
\r
600 #ifdef HAVE_TOUCH_KEY
\r
601 for(retry = 0; retry < MAX_KEY_NUM; retry++)
\r
603 input_set_capability(ts->input_dev, EV_KEY, gt818_key_array[retry]);
\r
607 snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev));
\r
608 snprintf(ts->name, sizeof(ts->name), "gt818-touchscreen");
\r
610 ts->input_dev->name = "gt818_ts";//ts->name;
\r
611 ts->input_dev->phys = ts->phys;
\r
612 ts->input_dev->dev.parent = &client->dev;
\r
613 ts->input_dev->id.bustype = BUS_I2C;
\r
614 ts->input_dev->id.vendor = 0xDEAD;
\r
615 ts->input_dev->id.product = 0xBEEF;
\r
616 ts->input_dev->id.version = 10427; //screen firmware version
\r
618 __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
\r
619 __set_bit(EV_ABS, ts->input_dev->evbit);
\r
620 #ifdef GOODIX_MULTI_TOUCH
\r
621 input_mt_init_slots(ts->input_dev, MAX_FINGER_NUM);
\r
622 //input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
\r
623 input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
\r
624 input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, SCREEN_MAX_WIDTH, 0, 0);
\r
625 input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, SCREEN_MAX_HEIGHT, 0, 0);
\r
626 //input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, MAX_FINGER_NUM, 0, 0);
\r
627 input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
\r
629 input_set_abs_params(ts->input_dev, ABS_X, 0, SCREEN_MAX_HEIGHT, 0, 0);
\r
630 input_set_abs_params(ts->input_dev, ABS_Y, 0, SCREEN_MAX_WIDTH, 0, 0);
\r
631 input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, 0, 0);
\r
634 ret = input_register_device(ts->input_dev);
\r
636 dev_err(&client->dev,"Probe: Unable to register %s input device\n", ts->input_dev->name);
\r
637 goto err_input_register_device_failed;
\r
640 // 16finger_list.length = 0;
\r
642 client->irq = gpio_to_irq(pdata->gpio_pendown); //If not defined in client
\r
647 #define GT801_PLUS_IRQ_TYPE IRQ_TYPE_EDGE_RISING
\r
648 #elif INT_TRIGGER==1
\r
649 #define GT801_PLUS_IRQ_TYPE IRQ_TYPE_EDGE_FALLING
\r
650 #elif INT_TRIGGER==2
\r
651 #define GT801_PLUS_IRQ_TYPE IRQ_TYPE_LEVEL_LOW
\r
652 #elif INT_TRIGGER==3
\r
653 #define GT801_PLUS_IRQ_TYPE IRQ_TYPE_LEVEL_HIGH
\r
656 ret = request_irq(client->irq, goodix_ts_irq_handler, GT801_PLUS_IRQ_TYPE,
\r
659 dev_err(&client->dev,"Cannot allocate ts INT!ERRNO:%d\n", ret);
\r
660 gpio_direction_input(pdata->gpio_pendown);
\r
661 gpio_free(pdata->gpio_pendown);
\r
662 goto err_gpio_request_failed;
\r
666 disable_irq(client->irq);
\r
668 dev_dbg(&client->dev,"Reques EIRQ %d succesd on GPIO:%d\n", client->irq, pdata->gpio_pendown);
\r
672 err_gpio_request_failed:
\r
673 ts->power = goodix_ts_power;
\r
674 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
675 ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
\r
676 ts->early_suspend.suspend = goodix_ts_early_suspend;
\r
677 ts->early_suspend.resume = goodix_ts_late_resume;
\r
678 register_early_suspend(&ts->early_suspend);
\r
680 dev_info(&client->dev,"Start %s in %s mode\n",
\r
681 ts->input_dev->name, ts->use_irq ? "interrupt" : "polling");
\r
685 enable_irq(client->irq);
\r
689 hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
\r
690 ts->timer.function = goodix_ts_timer_func;
\r
691 hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
\r
702 free_irq(client->irq,ts);
\r
703 gpio_direction_input(pdata->gpio_pendown);
\r
704 gpio_free(pdata->gpio_pendown);
\r
707 hrtimer_cancel(&ts->timer);
\r
709 err_input_register_device_failed:
\r
710 input_free_device(ts->input_dev);
\r
712 err_input_dev_alloc_failed:
\r
713 i2c_set_clientdata(client, NULL);
\r
716 err_alloc_data_failed:
\r
717 err_check_functionality_failed:
\r
722 static int goodix_ts_remove(struct i2c_client *client)
\r
724 struct gt818_ts_data *ts = i2c_get_clientdata(client);
\r
725 struct gt818_platform_data *pdata = client->dev.platform_data;
\r
727 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
728 unregister_early_suspend(&ts->early_suspend);
\r
730 #ifdef CONFIG_TOUCHSCREEN_GOODIX_IAP
\r
731 remove_proc_entry("goodix-update", NULL);
\r
733 if (ts && ts->use_irq)
\r
735 gpio_direction_input(pdata->gpio_pendown);
\r
736 gpio_free(pdata->gpio_pendown);
\r
737 free_irq(client->irq, ts);
\r
740 hrtimer_cancel(&ts->timer);
\r
742 dev_notice(&client->dev,"The driver is removing...\n");
\r
743 i2c_set_clientdata(client, NULL);
\r
744 input_unregister_device(ts->input_dev);
\r
750 static int goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg)
\r
753 struct gt818_ts_data *ts = i2c_get_clientdata(client);
\r
756 disable_irq(client->irq);
\r
758 hrtimer_cancel(&ts->timer);
\r
759 //ret = cancel_work_sync(&ts->work);
\r
760 //if(ret && ts->use_irq)
\r
761 //enable_irq(client->irq);
\r
763 ret = ts->power(ts, 0);
\r
765 printk(KERN_ERR "goodix_ts_resume power off failed\n");
\r
771 static int goodix_ts_resume(struct i2c_client *client)
\r
774 struct gt818_ts_data *ts = i2c_get_clientdata(client);
\r
777 ret = ts->power(ts, 1);
\r
779 printk(KERN_ERR "goodix_ts_resume power on failed\n");
\r
783 enable_irq(client->irq);
\r
785 hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
\r
790 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
791 static void goodix_ts_early_suspend(struct early_suspend *h)
\r
793 struct gt818_ts_data *ts;
\r
794 ts = container_of(h, struct gt818_ts_data, early_suspend);
\r
795 goodix_ts_suspend(ts->client, PMSG_SUSPEND);
\r
798 static void goodix_ts_late_resume(struct early_suspend *h)
\r
800 struct gt818_ts_data *ts;
\r
801 ts = container_of(h, struct gt818_ts_data, early_suspend);
\r
802 goodix_ts_resume(ts->client);
\r
808 static const struct i2c_device_id goodix_ts_id[] = {
\r
809 { GOODIX_I2C_NAME, 0 },
\r
814 static struct i2c_driver goodix_ts_driver = {
\r
815 .probe = goodix_ts_probe,
\r
816 .remove = goodix_ts_remove,
\r
817 #ifndef CONFIG_HAS_EARLYSUSPEND
\r
818 .suspend = goodix_ts_suspend,
\r
819 .resume = goodix_ts_resume,
\r
821 .id_table = goodix_ts_id,
\r
823 .name = GOODIX_I2C_NAME,
\r
824 .owner = THIS_MODULE,
\r
829 static int __devinit goodix_ts_init(void)
\r
832 goodix_wq = create_singlethread_workqueue("goodix_wq"); //create a work queue and worker thread
\r
834 printk(KERN_ALERT "creat workqueue faiked\n");
\r
837 ret = i2c_add_driver(&goodix_ts_driver);
\r
842 static void __exit goodix_ts_exit(void)
\r
844 printk(KERN_ALERT "Touchscreen driver of guitar exited.\n");
\r
845 i2c_del_driver(&goodix_ts_driver);
\r
847 destroy_workqueue(goodix_wq); //release our work queue
\r
850 late_initcall(goodix_ts_init);
\r
851 module_exit(goodix_ts_exit);
\r
853 MODULE_DESCRIPTION("Goodix Touchscreen Driver");
\r
854 MODULE_AUTHOR("hhb@rock-chips.com");
\r
855 MODULE_LICENSE("GPL");
\r