Merge remote-tracking branch 'aosp/android-3.0' into develop-3.0
[firefly-linux-kernel-4.4.55.git] / drivers / input / touchscreen / gt818_ts.c
1 /* drivers/input/touchscreen/gt818_ts.c\r
2  *\r
3  * Copyright (C) 2011 Rockcip, Inc.\r
4  * \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
8  *\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
13  *\r
14  * Author: hhb@rock-chips.com\r
15  * Date: 2011.06.20\r
16  */\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
29 \r
30 #include <linux/gpio.h>\r
31 #include <mach/iomux.h>\r
32 \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
37 \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
44 \r
45 #include "gt818_ts.h"\r
46 \r
47 \r
48 \r
49 #if !defined(GT801_PLUS) && !defined(GT801_NUVOTON)\r
50 #error The code does not match this touchscreen.\r
51 #endif\r
52 \r
53 static struct workqueue_struct *goodix_wq;\r
54 \r
55 static const char *gt818_ts_name = "Goodix Capacitive TouchScreen";\r
56 \r
57 static struct point_queue finger_list;\r
58 \r
59 struct i2c_client * i2c_connect_client = NULL;\r
60 \r
61 //EXPORT_SYMBOL(i2c_connect_client);\r
62 \r
63 static struct proc_dir_entry *goodix_proc_entry;\r
64         \r
65 #ifdef CONFIG_HAS_EARLYSUSPEND\r
66 static void goodix_ts_early_suspend(struct early_suspend *h);\r
67 static void goodix_ts_late_resume(struct early_suspend *h);\r
68 #endif\r
69 \r
70 #ifdef HAVE_TOUCH_KEY\r
71         const uint16_t gt818_key_array[]={\r
72                                                                           KEY_MENU,\r
73                                                                           KEY_HOME,\r
74                                                                           KEY_BACK,\r
75                                                                           KEY_SEARCH\r
76                                                                          };\r
77         #define MAX_KEY_NUM      (sizeof(gt818_key_array)/sizeof(gt818_key_array[0]))\r
78 #endif\r
79 \r
80 unsigned int last_x[MAX_FINGER_NUM + 1]= {0};\r
81 unsigned int last_y[MAX_FINGER_NUM + 1]= {0};\r
82 \r
83 \r
84 /*Function as i2c_master_send */\r
85 static int i2c_read_bytes(struct i2c_client *client, u8 *buf, int len)\r
86 {\r
87         struct i2c_msg msgs[2];\r
88         int ret = -1;\r
89 \r
90         msgs[0].addr = client->addr;\r
91         msgs[0].flags = client->flags;\r
92         msgs[0].len = 2;\r
93         msgs[0].buf = &buf[0];\r
94         msgs[0].scl_rate = GT818_I2C_SCL;\r
95         msgs[0].udelay = client->udelay;\r
96 \r
97         msgs[1].addr = client->addr;\r
98         msgs[1].flags = client->flags | I2C_M_RD;\r
99         msgs[1].len = len-2;\r
100         msgs[1].buf = &buf[2];\r
101         msgs[1].scl_rate = GT818_I2C_SCL;\r
102         msgs[1].udelay = client->udelay;\r
103 \r
104         ret = i2c_transfer(client->adapter, msgs, 2);\r
105         if(ret < 0)\r
106                 printk("%s:i2c_transfer fail =%d\n",__func__, ret);\r
107 \r
108         return ret;\r
109 }\r
110 \r
111 /*Function as i2c_master_send */\r
112 static int i2c_write_bytes(struct i2c_client *client,u8 *data,int len)\r
113 {\r
114         struct i2c_msg msg;\r
115         int ret = -1;\r
116 \r
117         msg.addr = client->addr;\r
118         msg.flags = client->flags;\r
119         msg.len = len;\r
120         msg.buf = data;\r
121         msg.scl_rate = GT818_I2C_SCL;\r
122         msg.udelay = client->udelay;\r
123 \r
124         ret = i2c_transfer(client->adapter, &msg, 1);\r
125         if(ret < 0)\r
126                 printk("%s:i2c_transfer fail =%d\n",__func__, ret);\r
127 \r
128         return ret;\r
129 }\r
130 \r
131 \r
132 static int i2c_pre_cmd(struct gt818_ts_data *ts)\r
133 {\r
134         int ret;\r
135         u8 pre_cmd_data[2] = {0};\r
136         pre_cmd_data[0] = 0x0f;\r
137         pre_cmd_data[1] = 0xff;\r
138         ret = i2c_write_bytes(ts->client,pre_cmd_data,2);\r
139         udelay(20);\r
140         return ret;\r
141 }\r
142 \r
143 \r
144 static int i2c_end_cmd(struct gt818_ts_data *ts)\r
145 {\r
146         int ret;\r
147         u8 end_cmd_data[2] = {0};\r
148         end_cmd_data[0] = 0x80;\r
149         end_cmd_data[1] = 0x00;\r
150         ret = i2c_write_bytes(ts->client,end_cmd_data,2);\r
151         udelay(20);\r
152         return ret;\r
153 }\r
154 \r
155 \r
156 \r
157 static int goodix_init_panel(struct gt818_ts_data *ts)\r
158 {\r
159         int ret = -1;\r
160         int i = 0;\r
161 #if 1\r
162         u8 config_info[] = {\r
163         0x06,0xA2,\r
164         0x00,0x02,0x04,0x06,0x08,0x0A,0x0C,0x0E,\r
165         0x10,0x12,0x00,0x00,0x10,0x00,0x20,0x00,\r
166         0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,\r
167         0xE0,0x00,0xD0,0x00,0xC0,0x00,0xB0,0x00,\r
168         0xA0,0x00,0x90,0x00,0x80,0x00,0x70,0x00,\r
169         0xF0,0x00,0x13,0x13,0x90,0x90,0x90,0x27,\r
170         0x27,0x27,0x0F,0x0E,0x0A,0x40,0x30,0x01,\r
171         0x03,0x00,MAX_FINGER_NUM,0x00,0x14,0xFA,0x1B,0x00,\r
172         0x00,0x66,0x5A,0x6A,0x5E,0x00,0x00,0x05,\r
173         0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
174         0x14,0x10,0xEF,0x03,0x00,0x00,0x00,0x00,\r
175         0x00,0x00,0x20,0x40,0x70,0x90,0x0F,0x40,\r
176         0x30,0x3C,0x28,0x00,0x00,0x00,0x00,0x00,\r
177         0x00,0x01\r
178         };\r
179 #endif\r
180         u8 read_config_info[sizeof(config_info)] = {0};\r
181         read_config_info[0] = 0x06;\r
182         read_config_info[1] = 0xa2;\r
183 \r
184         ret = i2c_write_bytes(ts->client, config_info, (sizeof(config_info)/sizeof(config_info[0])));\r
185         if (ret < 0) {\r
186                 printk("config gt818 fail\n");\r
187                 return ret;\r
188         }\r
189 \r
190         ret = i2c_read_bytes(ts->client, read_config_info, (sizeof(config_info)/sizeof(config_info[0])));\r
191         if (ret < 0){\r
192                 printk("read gt818 config fail\n");\r
193                 return ret;\r
194         }\r
195 \r
196         for(i = 2; i < 106; i++){\r
197                 if(read_config_info[i] != config_info[i]){\r
198                         printk("write gt818 config error\n");\r
199                         ret = -1;\r
200                         return ret;\r
201                 }\r
202         }\r
203         msleep(10);\r
204         return 0;\r
205 \r
206 }\r
207 \r
208 static int  goodix_read_version(struct gt818_ts_data *ts)\r
209 {\r
210         int ret;\r
211         u8 version_data[5] = {0};       //store touchscreen version infomation\r
212         memset(version_data, 0, 5);\r
213         version_data[0] = 0x07;\r
214         version_data[1] = 0x17;\r
215         msleep(2);\r
216         ret = i2c_read_bytes(ts->client, version_data, 4);\r
217         if (ret < 0) \r
218                 return ret;\r
219         dev_info(&ts->client->dev," Guitar Version: %d.%d\n",version_data[3],version_data[2]);\r
220         return 0;\r
221         \r
222 }\r
223 \r
224 \r
225 \r
226 static void goodix_ts_work_func(struct work_struct *work)\r
227 {       \r
228         u8  touch_status[8*MAX_FINGER_NUM + 18] = {READ_TOUCH_ADDR_H, READ_TOUCH_ADDR_L, 0};\r
229         u8  *key_value = NULL;\r
230         u8  *point_data = NULL;\r
231         static u8 finger_last[MAX_FINGER_NUM + 1]={0};\r
232         u8  finger_current[MAX_FINGER_NUM + 1] = {0};\r
233         u8  coor_data[6*MAX_FINGER_NUM] = {0};\r
234         static u8  last_key = 0;\r
235 \r
236         u8  finger = 0;\r
237         u8  key = 0;\r
238         u8 retry = 0;\r
239         unsigned int  count = 0;\r
240         unsigned int position = 0;      \r
241         int temp = 0;\r
242         int x = 0, y = 0 , pressure;\r
243 \r
244         u16 *coor_point;\r
245 \r
246         int syn_flag = 0;\r
247 \r
248         struct gt818_ts_data *ts = container_of(work, struct gt818_ts_data, work);\r
249 \r
250         i2c_pre_cmd(ts);\r
251         i2c_read_bytes(ts->client, touch_status, sizeof(touch_status)/sizeof(touch_status[0]));\r
252         i2c_end_cmd(ts);\r
253 \r
254         //judge whether the data is ready\r
255         if((touch_status[2] & 0x30) != 0x20)\r
256         {\r
257                 printk("%s:DATA_NO_READY\n", __func__);\r
258                 goto DATA_NO_READY;\r
259         }\r
260         //judge whether it is large area touch\r
261         if(touch_status[13] & 0x0f)\r
262         {\r
263                 goto DATA_NO_READY;\r
264         }\r
265 \r
266         ts->bad_data = 0;\r
267         finger = touch_status[2] & 0x07;\r
268         key_value = touch_status + 15;\r
269         key = key_value[2] & 0x0f;\r
270 \r
271         if(finger > 0)\r
272         {\r
273                 point_data = key_value + 3;\r
274 \r
275                 for(position = 0; position < (finger*8); position += 8)\r
276                 {\r
277                         temp = point_data[position];\r
278                         //printk("track:%d\n", temp);\r
279                         if(temp < (MAX_FINGER_NUM + 1))\r
280                         {\r
281                                 finger_current[temp] = 1;\r
282                                 for(count = 0; count < 6; count++)\r
283                                 {\r
284                                         coor_data[(temp - 1) * 6 + count] = point_data[position+1+count];\r
285                                 }\r
286                         }\r
287                         else\r
288                         {\r
289                                 //dev_err(&(ts->client->dev),"Track Id error:%d\n ",);\r
290                                 ts->bad_data = 1;\r
291                                 ts->retry++;\r
292                                 goto XFER_ERROR;\r
293                         }               \r
294                 }\r
295         \r
296         }\r
297         \r
298         else\r
299         {\r
300                 for(position = 1; position < MAX_FINGER_NUM+1; position++)\r
301                 {\r
302                         finger_current[position] = 0;\r
303                 }\r
304         }\r
305 \r
306         coor_point = (u16 *)coor_data;\r
307 \r
308         for(position = 1; position < MAX_FINGER_NUM + 1; position++)\r
309         {\r
310                 if((finger_current[position] == 0) && (finger_last[position] != 0))\r
311                 {\r
312                         //printk("<<<<<<<<<<<<<<<<<<<%s:positon:%d (%d,%d)\n", __func__, position,last_x,last_y);\r
313                         //printk("<<<%d , %d ",finger_current[position],finger_last[position]);\r
314                         //input_mt_slot(ts->input_dev, position);\r
315                         //input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);\r
316                         //input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);\r
317                         //input_report_abs(ts->input_dev, ABS_MT_POSITION_X, last_x[position]);\r
318                         //input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, last_y[position]);\r
319                         //input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100);\r
320                         //input_mt_sync(ts->input_dev);\r
321                         input_mt_slot(ts->input_dev, position);\r
322                         input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);\r
323                         syn_flag = 1;\r
324                 }\r
325                 else if(finger_current[position])\r
326                 {\r
327                         x = (*(coor_point+3*(position-1)))*SCREEN_MAX_WIDTH/(TOUCH_MAX_WIDTH);\r
328                         y = (*(coor_point+3*(position-1)+1))*SCREEN_MAX_HEIGHT/(TOUCH_MAX_HEIGHT);\r
329                         pressure = (*(coor_point+3*(position-1)+2));\r
330                         if(x < SCREEN_MAX_WIDTH){\r
331                                 x = SCREEN_MAX_WIDTH - x;\r
332                         }\r
333 \r
334                         if(y < SCREEN_MAX_HEIGHT){\r
335                         //      y = SCREEN_MAX_HEIGHT-y;\r
336                         }\r
337 \r
338                         //printk(">>>>>>>>>>>>>>>>>%s:positon:%d (%d,%d)\n", __func__, position,x,y);\r
339                         input_mt_slot(ts->input_dev, position);\r
340                         input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);\r
341                         input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 1);\r
342                         input_report_abs(ts->input_dev, ABS_MT_PRESSURE, pressure);\r
343                         input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);\r
344                         input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);\r
345 \r
346                         last_x[position] = x;\r
347                         last_y[position] = y;\r
348                         //input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, pressure);\r
349                         //input_mt_sync(ts->input_dev);\r
350                         syn_flag = 1;\r
351                 }\r
352 \r
353 }\r
354 input_sync(ts->input_dev);\r
355 \r
356 \r
357 \r
358 #ifdef HAVE_TOUCH_KEY\r
359         if((last_key == 0) && (key == 0)){\r
360                 goto NO_KEY_PRESS;\r
361         }\r
362         else{\r
363                 syn_flag = 1;\r
364                 switch(key){\r
365                         case 1:\r
366                                 key = 4;\r
367                                 break;\r
368                         case 2:\r
369                                 key = 3;\r
370                                 break;\r
371                         case 4:\r
372                                 key = 2;\r
373                                 break;\r
374                         case 8:\r
375                                 key = 1;\r
376                                 break;\r
377                         default:\r
378                                 key = 0;\r
379                                 break;\r
380                 }\r
381                 if(key != 0){\r
382                         input_report_key(ts->input_dev, gt818_key_array[key - 1], 1);\r
383                 }\r
384                 else{\r
385                         input_report_key(ts->input_dev, gt818_key_array[last_key - 1], 0);\r
386                 }\r
387                 last_key = key;\r
388         }               \r
389 \r
390 #endif\r
391 \r
392 \r
393 NO_KEY_PRESS:\r
394         if(syn_flag){\r
395                 input_sync(ts->input_dev);\r
396         }\r
397 \r
398         for(position = 1; position < MAX_FINGER_NUM + 1; position++)\r
399         {\r
400                 finger_last[position] = finger_current[position];\r
401         }\r
402 \r
403 DATA_NO_READY:\r
404 XFER_ERROR:\r
405 //      i2c_end_cmd(ts);\r
406         if(ts->use_irq)\r
407                 enable_irq(ts->client->irq);\r
408 \r
409 }\r
410 \r
411 static int test_suspend_resume(struct gt818_ts_data *ts){\r
412         while(1){\r
413                 ts->power(ts, 0);\r
414                 msleep(5000);\r
415                 ts->power(ts, 1);\r
416                 msleep(5000);\r
417         }\r
418         return 0;\r
419 }\r
420 \r
421 \r
422 static enum hrtimer_restart goodix_ts_timer_func(struct hrtimer *timer)\r
423 {\r
424         struct gt818_ts_data *ts = container_of(timer, struct gt818_ts_data, timer);\r
425         queue_work(goodix_wq, &ts->work);\r
426         hrtimer_start(&ts->timer, ktime_set(0, (POLL_TIME+6)*1000000), HRTIMER_MODE_REL);\r
427         return HRTIMER_NORESTART;\r
428 }\r
429 \r
430 \r
431 static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)\r
432 {\r
433         struct gt818_ts_data *ts = dev_id;\r
434         disable_irq_nosync(ts->client->irq);\r
435         queue_work(goodix_wq, &ts->work);\r
436         return IRQ_HANDLED;\r
437 }\r
438 \r
439 static int goodix_ts_power(struct gt818_ts_data * ts, int on)\r
440 {\r
441         int ret = -1;\r
442         struct gt818_platform_data      *pdata = ts->client->dev.platform_data;\r
443         unsigned char i2c_control_buf[3] = {0x06,0x92,0x01};            //suspend cmd\r
444         if(ts != NULL && !ts->use_irq)\r
445                 return -2;\r
446         switch(on)\r
447         {\r
448                 case 0:\r
449                         i2c_pre_cmd(ts);\r
450                         // set the io port high level to avoid level change which might stop gt818 from sleeping\r
451                         gpio_direction_output(pdata->gpio_reset, 1);\r
452                         gpio_direction_output(pdata->gpio_pendown, 1);\r
453                         msleep(5);\r
454                         ret = i2c_write_bytes(ts->client, i2c_control_buf, 3);\r
455                         if(ret < 0)\r
456                         {\r
457                                 printk(KERN_INFO"**gt818 suspend fail**\n");\r
458                         }\r
459                         else\r
460                         {\r
461                                 //printk(KERN_INFO"**gt818 suspend**\n");\r
462                                 ret = 0;\r
463                         }\r
464 //                      i2c_end_cmd(ts);\r
465                         return ret;\r
466                         \r
467                 case 1:\r
468 \r
469                         gpio_pull_updown(pdata->gpio_pendown, 1);\r
470                         gpio_direction_output(pdata->gpio_pendown, 0);\r
471                         msleep(1);\r
472                         gpio_direction_output(pdata->gpio_pendown, 1);\r
473                         msleep(1);\r
474                         gpio_direction_input(pdata->gpio_pendown);\r
475                         gpio_pull_updown(pdata->gpio_pendown, 0);\r
476 \r
477 /*\r
478                         msleep(2);\r
479                         gpio_pull_updown(pdata->gpio_reset, 1);\r
480                         gpio_direction_output(pdata->gpio_reset, 0);\r
481                         msleep(2);\r
482                         gpio_direction_input(pdata->gpio_reset);\r
483                         gpio_pull_updown(pdata->gpio_reset, 0);\r
484                         msleep(30);\r
485 */\r
486                         msleep(1);\r
487                         ret = i2c_pre_cmd(ts);\r
488                         //printk(KERN_INFO"**gt818 reusme**\n");\r
489                         ret = i2c_end_cmd(ts);\r
490 \r
491                         return ret;\r
492                                 \r
493                 default:\r
494                         printk(KERN_DEBUG "%s: Cant't support this command.", gt818_ts_name);\r
495                         return -EINVAL;\r
496         }\r
497 \r
498 }\r
499 \r
500 \r
501 static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)\r
502 {\r
503         int ret = 0;\r
504         int retry=0;\r
505         u8 goodix_id[3] = {0,0xff,0};\r
506         struct gt818_ts_data *ts;\r
507 \r
508         struct gt818_platform_data *pdata;\r
509         dev_info(&client->dev,"Install touch driver.\n");\r
510         printk("gt818: Install touch driver.\n");\r
511         //Check I2C function\r
512         if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) \r
513         {\r
514                 dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n");\r
515                 ret = -ENODEV;\r
516                 goto err_check_functionality_failed;\r
517         }\r
518 \r
519         ts = kzalloc(sizeof(*ts), GFP_KERNEL);\r
520         if (ts == NULL) {\r
521                 ret = -ENOMEM;\r
522                 goto err_alloc_data_failed;\r
523         }\r
524 \r
525         i2c_connect_client = client;    //used by Guitar_Update\r
526         pdata = client->dev.platform_data;\r
527         ts->client = client;\r
528         i2c_set_clientdata(client, ts);\r
529 \r
530         //init int and reset ports\r
531         ret = gpio_request(pdata->gpio_pendown, "TS_INT");      //Request IO\r
532         if (ret){\r
533                 dev_err(&client->dev, "Failed to request GPIO:%d, ERRNO:%d\n",(int)pdata->gpio_pendown, ret);\r
534                 goto err_gpio_request_failed;\r
535         }\r
536         rk29_mux_api_set(pdata->pendown_iomux_name, pdata->pendown_iomux_mode);\r
537         gpio_direction_input(pdata->gpio_pendown);\r
538         gpio_pull_updown(pdata->gpio_pendown, 0);\r
539 \r
540         ret = gpio_request(pdata->gpio_reset, "gt818_resetPin");\r
541         if(ret){\r
542                 dev_err(&client->dev, "failed to request resetPin GPIO%d\n", pdata->gpio_reset);\r
543                 goto err_gpio_request_failed;\r
544         }\r
545         rk29_mux_api_set(pdata->resetpin_iomux_name, pdata->resetpin_iomux_mode);\r
546 \r
547 #if 1\r
548         for(retry = 0; retry < 4; retry++)\r
549         {\r
550                 gpio_pull_updown(pdata->gpio_reset, 1);\r
551                 gpio_direction_output(pdata->gpio_reset, 0);\r
552                 msleep(1);     //delay at least 1ms\r
553                 gpio_direction_input(pdata->gpio_reset);\r
554                 gpio_pull_updown(pdata->gpio_reset, 0);\r
555                 msleep(25);   //delay at least 20ms\r
556                 ret = i2c_pre_cmd(ts);\r
557                 if (ret > 0)\r
558                         break;\r
559                 msleep(50);\r
560         }\r
561 \r
562         if(ret <= 0)\r
563         {\r
564                 dev_err(&client->dev, "Warnning: I2C communication might be ERROR!\n");\r
565                 goto err_i2c_failed;\r
566         }       \r
567 #endif\r
568 \r
569         for(retry = 0; retry < 3; retry++)\r
570         {\r
571                 ret = goodix_init_panel(ts);\r
572 \r
573                 dev_info(&client->dev,"the config ret is :%d\n", ret);\r
574                 msleep(20);\r
575                 if(ret < 0)     //Initiall failed\r
576                         continue;\r
577                 else\r
578                         break;\r
579         }\r
580 \r
581         if(ret < 0) {\r
582                 ts->bad_data = 1;\r
583                 goto err_init_godix_ts;\r
584         }\r
585 \r
586         goodix_read_version(ts);\r
587 \r
588 \r
589         INIT_WORK(&ts->work, goodix_ts_work_func);              //init work_struct\r
590         ts->input_dev = input_allocate_device();\r
591         if (ts->input_dev == NULL) {\r
592                 ret = -ENOMEM;\r
593                 dev_dbg(&client->dev,"goodix_ts_probe: Failed to allocate input device\n");\r
594                 goto err_input_dev_alloc_failed;\r
595         }\r
596 \r
597         //ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;\r
598         //ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);\r
599         //ts->input_dev->absbit[0] = BIT_MASK(ABS_MT_POSITION_X) | BIT_MASK(ABS_MT_POSITION_Y) |\r
600         //              BIT_MASK(ABS_MT_TOUCH_MAJOR) | BIT_MASK(ABS_MT_WIDTH_MAJOR);  // for android\r
601 \r
602 \r
603 #ifdef HAVE_TOUCH_KEY\r
604         for(retry = 0; retry < MAX_KEY_NUM; retry++)\r
605         {\r
606                 input_set_capability(ts->input_dev, EV_KEY, gt818_key_array[retry]);\r
607         }\r
608 #endif\r
609 \r
610         snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev));\r
611         snprintf(ts->name, sizeof(ts->name), "gt818-touchscreen");\r
612 \r
613         ts->input_dev->name = "gt818_ts";//ts->name;\r
614         ts->input_dev->phys = ts->phys;\r
615         ts->input_dev->dev.parent = &client->dev;\r
616         ts->input_dev->id.bustype = BUS_I2C;\r
617         ts->input_dev->id.vendor = 0xDEAD;\r
618         ts->input_dev->id.product = 0xBEEF;\r
619         ts->input_dev->id.version = 10427;      //screen firmware version\r
620 \r
621         __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);\r
622         __set_bit(EV_ABS, ts->input_dev->evbit);\r
623 #ifdef GOODIX_MULTI_TOUCH\r
624         input_mt_init_slots(ts->input_dev, MAX_FINGER_NUM);\r
625         //input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);\r
626         input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);\r
627         input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, SCREEN_MAX_WIDTH, 0, 0);\r
628         input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, SCREEN_MAX_HEIGHT, 0, 0);\r
629         //input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, MAX_FINGER_NUM, 0, 0);\r
630         input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);\r
631 #else\r
632         input_set_abs_params(ts->input_dev, ABS_X, 0, SCREEN_MAX_HEIGHT, 0, 0);\r
633         input_set_abs_params(ts->input_dev, ABS_Y, 0, SCREEN_MAX_WIDTH, 0, 0);\r
634         input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, 0, 0);\r
635 #endif  \r
636         \r
637         ret = input_register_device(ts->input_dev);\r
638         if (ret) {\r
639                 dev_err(&client->dev,"Probe: Unable to register %s input device\n", ts->input_dev->name);\r
640                 goto err_input_register_device_failed;\r
641         }\r
642         ts->bad_data = 0;\r
643 //      16finger_list.length = 0;\r
644 \r
645         client->irq = gpio_to_irq(pdata->gpio_pendown);         //If not defined in client\r
646         if (client->irq)\r
647         {\r
648 \r
649         #if INT_TRIGGER==0\r
650                 #define GT801_PLUS_IRQ_TYPE IRQ_TYPE_EDGE_RISING\r
651         #elif INT_TRIGGER==1\r
652                 #define GT801_PLUS_IRQ_TYPE IRQ_TYPE_EDGE_FALLING\r
653         #elif INT_TRIGGER==2\r
654                 #define GT801_PLUS_IRQ_TYPE IRQ_TYPE_LEVEL_LOW\r
655         #elif INT_TRIGGER==3\r
656                 #define GT801_PLUS_IRQ_TYPE IRQ_TYPE_LEVEL_HIGH\r
657         #endif\r
658 \r
659                 ret = request_irq(client->irq, goodix_ts_irq_handler, GT801_PLUS_IRQ_TYPE,\r
660                         client->name, ts);\r
661                 if (ret != 0) {\r
662                         dev_err(&client->dev,"Cannot allocate ts INT!ERRNO:%d\n", ret);\r
663                         gpio_direction_input(pdata->gpio_pendown);\r
664                         gpio_free(pdata->gpio_pendown);\r
665                         goto err_gpio_request_failed;\r
666                 }\r
667                 else \r
668                 {       \r
669                         disable_irq(client->irq);\r
670                         ts->use_irq = 1;\r
671                         dev_dbg(&client->dev,"Reques EIRQ %d succesd on GPIO:%d\n", client->irq, pdata->gpio_pendown);\r
672                 }       \r
673         }\r
674 \r
675 err_gpio_request_failed:\r
676         ts->power = goodix_ts_power;\r
677 #ifdef CONFIG_HAS_EARLYSUSPEND\r
678         ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;\r
679         ts->early_suspend.suspend = goodix_ts_early_suspend;\r
680         ts->early_suspend.resume = goodix_ts_late_resume;\r
681         register_early_suspend(&ts->early_suspend);\r
682 #endif\r
683         dev_info(&client->dev,"Start %s in %s mode\n",\r
684                 ts->input_dev->name, ts->use_irq ? "interrupt" : "polling");\r
685 \r
686         if (ts->use_irq)\r
687         {\r
688                 enable_irq(client->irq);\r
689         }\r
690         else\r
691         {\r
692                 hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);\r
693                 ts->timer.function = goodix_ts_timer_func;\r
694                 hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);\r
695         }\r
696 \r
697         i2c_end_cmd(ts);\r
698         return 0;\r
699 \r
700 err_init_godix_ts:\r
701         i2c_end_cmd(ts);\r
702         if(ts->use_irq)\r
703         {\r
704                 ts->use_irq = 0;\r
705                 free_irq(client->irq,ts);\r
706                 gpio_direction_input(pdata->gpio_pendown);\r
707                 gpio_free(pdata->gpio_pendown);\r
708         }\r
709         else \r
710                 hrtimer_cancel(&ts->timer);\r
711 \r
712 err_input_register_device_failed:\r
713         input_free_device(ts->input_dev);\r
714 \r
715 err_input_dev_alloc_failed:\r
716         i2c_set_clientdata(client, NULL);\r
717 err_i2c_failed: \r
718         kfree(ts);\r
719 err_alloc_data_failed:\r
720 err_check_functionality_failed:\r
721 err_create_proc_entry:\r
722         return ret;\r
723 }\r
724 \r
725 \r
726 static int goodix_ts_remove(struct i2c_client *client)\r
727 {\r
728         struct gt818_ts_data *ts = i2c_get_clientdata(client);\r
729         struct gt818_platform_data      *pdata = client->dev.platform_data;\r
730 \r
731 #ifdef CONFIG_HAS_EARLYSUSPEND\r
732         unregister_early_suspend(&ts->early_suspend);\r
733 #endif\r
734 #ifdef CONFIG_TOUCHSCREEN_GOODIX_IAP\r
735         remove_proc_entry("goodix-update", NULL);\r
736 #endif\r
737         if (ts && ts->use_irq) \r
738         {\r
739                 gpio_direction_input(pdata->gpio_pendown);\r
740                 gpio_free(pdata->gpio_pendown);\r
741                 free_irq(client->irq, ts);\r
742         }       \r
743         else if(ts)\r
744                 hrtimer_cancel(&ts->timer);\r
745         \r
746         dev_notice(&client->dev,"The driver is removing...\n");\r
747         i2c_set_clientdata(client, NULL);\r
748         input_unregister_device(ts->input_dev);\r
749         kfree(ts);\r
750         return 0;\r
751 }\r
752 \r
753 \r
754 static int goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg)\r
755 {\r
756         int ret;\r
757         struct gt818_ts_data *ts = i2c_get_clientdata(client);\r
758 \r
759         if (ts->use_irq)\r
760                 disable_irq(client->irq);\r
761         else\r
762                 hrtimer_cancel(&ts->timer);\r
763         //ret = cancel_work_sync(&ts->work);\r
764         //if(ret && ts->use_irq)        \r
765                 //enable_irq(client->irq);\r
766         if (ts->power) {\r
767                 ret = ts->power(ts, 0);\r
768                 if (ret < 0)\r
769                         printk(KERN_ERR "goodix_ts_resume power off failed\n");\r
770         }\r
771         return 0;\r
772 }\r
773 \r
774 \r
775 static int goodix_ts_resume(struct i2c_client *client)\r
776 {\r
777         int ret;\r
778         struct gt818_ts_data *ts = i2c_get_clientdata(client);\r
779 \r
780         if (ts->power) {\r
781                 ret = ts->power(ts, 1);\r
782                 if (ret < 0)\r
783                         printk(KERN_ERR "goodix_ts_resume power on failed\n");\r
784         }\r
785 \r
786         if (ts->use_irq)\r
787                 enable_irq(client->irq);\r
788         else\r
789                 hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);\r
790 \r
791         return 0;\r
792 }\r
793 \r
794 #ifdef CONFIG_HAS_EARLYSUSPEND\r
795 static void goodix_ts_early_suspend(struct early_suspend *h)\r
796 {\r
797         struct gt818_ts_data *ts;\r
798         ts = container_of(h, struct gt818_ts_data, early_suspend);\r
799         goodix_ts_suspend(ts->client, PMSG_SUSPEND);\r
800 }\r
801 \r
802 static void goodix_ts_late_resume(struct early_suspend *h)\r
803 {\r
804         struct gt818_ts_data *ts;\r
805         ts = container_of(h, struct gt818_ts_data, early_suspend);\r
806         goodix_ts_resume(ts->client);\r
807 }\r
808 #endif\r
809 \r
810 \r
811 //only one client\r
812 static const struct i2c_device_id goodix_ts_id[] = {\r
813         { GOODIX_I2C_NAME, 0 },\r
814         { }\r
815 };\r
816 \r
817 \r
818 static struct i2c_driver goodix_ts_driver = {\r
819         .probe          = goodix_ts_probe,\r
820         .remove         = goodix_ts_remove,\r
821 #ifndef CONFIG_HAS_EARLYSUSPEND\r
822         .suspend        = goodix_ts_suspend,\r
823         .resume         = goodix_ts_resume,\r
824 #endif\r
825         .id_table       = goodix_ts_id,\r
826         .driver = {\r
827                 .name   = GOODIX_I2C_NAME,\r
828                 .owner = THIS_MODULE,\r
829         },\r
830 };\r
831 \r
832 \r
833 static int __devinit goodix_ts_init(void)\r
834 {\r
835         int ret;\r
836         goodix_wq = create_singlethread_workqueue("goodix_wq");         //create a work queue and worker thread\r
837         if (!goodix_wq) {\r
838                 printk(KERN_ALERT "creat workqueue faiked\n");\r
839                 return -ENOMEM;\r
840         }\r
841         ret = i2c_add_driver(&goodix_ts_driver);\r
842         return ret; \r
843 }\r
844 \r
845 \r
846 static void __exit goodix_ts_exit(void)\r
847 {\r
848         printk(KERN_ALERT "Touchscreen driver of guitar exited.\n");\r
849         i2c_del_driver(&goodix_ts_driver);\r
850         if (goodix_wq)\r
851                 destroy_workqueue(goodix_wq);           //release our work queue\r
852 }\r
853 \r
854 late_initcall(goodix_ts_init);\r
855 module_exit(goodix_ts_exit);\r
856 \r
857 MODULE_DESCRIPTION("Goodix Touchscreen Driver");\r
858 MODULE_AUTHOR("hhb@rock-chips.com");\r
859 MODULE_LICENSE("GPL");\r
860 \r