input: touchscreen: add touch screen of gslx680 for rk3399-firefly-edp
[firefly-linux-kernel-4.4.55.git] / drivers / input / touchscreen / vtl_ts / vtl_ts.c
1 /*\r
2  * VTL CTP driver\r
3  *\r
4  * Copyright (C) 2013 VTL Corporation.\r
5  *\r
6  * This program is free software; you can redistribute it and/or\r
7  * modify it under the terms of the GNU General Public License\r
8  * version 2 as published by the Free Software Foundation.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
13  * General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA\r
18  * 02110-1301 USA\r
19  *\r
20  */\r
21 \r
22 #include <linux/kernel.h>\r
23 #include <linux/timer.h>\r
24 #include <linux/types.h>\r
25 #include <linux/module.h>\r
26 #include <linux/version.h>\r
27 #include <linux/fs.h>\r
28 #include <linux/proc_fs.h>\r
29 #include <asm/uaccess.h>\r
30 #include <linux/i2c.h>\r
31 #include <linux/delay.h>\r
32 #include <linux/interrupt.h>\r
33 #include <linux/input.h>\r
34 #include <linux/input/mt.h>\r
35 #include <linux/gpio.h>\r
36 #include <linux/sched.h>\r
37 #include <linux/kthread.h>\r
38 #include <linux/of_gpio.h>\r
39 #include <linux/vmalloc.h>\r
40 \r
41 \r
42 #include "vtl_ts.h"\r
43 #include "chip.h"\r
44 #include "apk.h"\r
45 \r
46 \r
47 #define         TS_THREAD_PRIO          90\r
48 static DECLARE_WAIT_QUEUE_HEAD(waiter);\r
49 //static struct task_struct *ts_thread = NULL;\r
50 static unsigned char thread_syn_flag =0;\r
51 static volatile unsigned char thread_running_flag =0;\r
52 \r
53 \r
54 // ****************************************************************************\r
55 // Globel or static variables\r
56 // ****************************************************************************\r
57 static struct ts_driver g_driver;\r
58 static int vtl_first_init_flag = 1;\r
59 struct ts_info  g_ts = {\r
60         .driver = &g_driver,\r
61         .debug  = DEBUG_ENABLE,\r
62 };\r
63 struct ts_info  *pg_ts = &g_ts;\r
64 \r
65 static struct i2c_device_id vtl_ts_id[] = {\r
66         { DRIVER_NAME, 0 },\r
67         { }\r
68 };\r
69 MODULE_DEVICE_TABLE(i2c,vtl_ts_id);\r
70 \r
71 \r
72 /*\r
73 static struct i2c_board_info i2c_info[] = {\r
74         {\r
75                 I2C_BOARD_INFO(DRIVER_NAME, 0x01),\r
76                 .platform_data = NULL,\r
77         },\r
78 };\r
79 */\r
80 \r
81 \r
82 // ****************************************************************************\r
83 // Function declaration\r
84 // ****************************************************************************\r
85 unsigned char *gtpfw;\r
86 static int vtl_ts_config(struct ts_info *ts)\r
87 {\r
88         struct device *dev = &ts->driver->client->dev;\r
89         //struct ts_config_info *ts_config_info;        \r
90         int err;\r
91         struct device_node *np = dev->of_node;\r
92         enum of_gpio_flags rst_flags;\r
93         unsigned long irq_flags;\r
94         int val;\r
95         struct device_node *tnp;\r
96         struct property *prop;\r
97         int length,ret;\r
98         unsigned int max_num;\r
99         unsigned char *levels;\r
100 \r
101                 \r
102         tnp = of_find_node_by_path("/tp-fw");\r
103         if (!tnp){\r
104                 printk(" error tp_fw not node!!!\n");\r
105                 return -EINVAL;\r
106         }       \r
107         /* determine the number of brightness levels */
108         prop = of_find_property(tnp, "tp_fw", &length);\r
109         if (!prop){\r
110                 printk(" error tp_fw not property!!!\n");\r
111                 return -EINVAL;\r
112         }\r
113 \r
114         max_num = length / sizeof(u32);\r
115 \r
116         printk(" max-num:%d,length:%d.\n",max_num,length);\r
117         \r
118         /* read max_num from DT property */\r
119         if (max_num > 0) {\r
120         \r
121                 levels = (unsigned char*)vmalloc(max_num);\r
122                 if (!levels){\r
123                         printk("<xiaoyao> error vmalloc failed!!!\n");\r
124                         return -ENOMEM;
125                 }\r
126 \r
127                 ret = of_property_read_u8_array_tp(tnp,"tp_fw",levels,max_num);\r
128                 if (ret != 0){\r
129                         printk(" of_property_read_u8_array failed!!!\n");\r
130                         return -ENOMEM;
131                 }\r
132 \r
133         }else\r
134                 printk("tp fw error!!!\n");\r
135         \r
136         gtpfw = levels;\r
137 \r
138 \r
139         DEBUG();\r
140         /* ts config */\r
141         ts->config_info.touch_point_number = TOUCH_POINT_NUM;\r
142         if(dev->platform_data !=NULL)\r
143         {       \r
144                 return -1;\r
145         }\r
146         else\r
147         {\r
148                 \r
149                 if (of_property_read_u32(np, "screen_max_x", &val)) {\r
150                         dev_err(&ts->driver->client->dev, "no screen_max_x defined\n");\r
151                         return -EINVAL;\r
152                 }\r
153                 ts->config_info.screen_max_x = val;\r
154 \r
155                 if (of_property_read_u32(np, "screen_max_y", &val)) {\r
156                         dev_err(&ts->driver->client->dev, "no screen_max_y defined\n");\r
157                         return -EINVAL;\r
158                 }\r
159                 ts->config_info.screen_max_y = val;\r
160 \r
161         if (of_property_read_u32(np, "xy_swap", &val)) {\r
162                         val = 0;\r
163         }\r
164         ts->config_info.xy_swap = val;\r
165 \r
166         if (of_property_read_u32(np, "x_reverse", &val)) {\r
167                         val = 0;\r
168         }\r
169         ts->config_info.x_reverse = val;\r
170 \r
171         if (of_property_read_u32(np, "y_reverse", &val)) {\r
172                         val = 0;\r
173         }\r
174         ts->config_info.y_reverse = val;\r
175 \r
176         if (of_property_read_u32(np, "x_mul", &val)) {\r
177                         val = 1;\r
178         }\r
179         ts->config_info.x_mul = val;\r
180 \r
181         if (of_property_read_u32(np, "y_mul", &val)) {\r
182                         val = 1;\r
183         }\r
184         ts->config_info.y_mul = val;\r
185 \r
186 \r
187                 if (of_property_read_u32(np, "bin_ver", &val)) {\r
188             val = 0;\r
189         }\r
190                 ts->config_info.bin_ver = val;\r
191                 printk("--->>> vtl_ts : xy_swap %d, x_reverse %d, y_reverse %d, x_mul %d, y_mul %d, bin_ver %d\n",\r
192                                 ts->config_info.xy_swap, \r
193                                 ts->config_info.x_reverse, ts->config_info.y_reverse, \r
194                                 ts->config_info.x_mul, ts->config_info.y_mul, \r
195                                 ts->config_info.bin_ver);\r
196                 printk("the screen_x is %d , screen_y is %d \n",ts->config_info.screen_max_x,ts->config_info.screen_max_y);\r
197                 \r
198                 ts->config_info.irq_gpio_number = of_get_named_gpio_flags(np, "irq_gpio_number", 0, (enum of_gpio_flags *)&irq_flags);\r
199                 ts->config_info.rst_gpio_number = of_get_named_gpio_flags(np, "rst_gpio_number", 0, &rst_flags);\r
200 \r
201         }\r
202         \r
203         ts->config_info.irq_number = gpio_to_irq(ts->config_info.irq_gpio_number);/* IRQ config*/\r
204         \r
205         err = gpio_request(ts->config_info.rst_gpio_number, "vtl_ts_rst");\r
206         if ( err ) {\r
207                 return -EIO;\r
208         }\r
209         gpio_direction_output(ts->config_info.rst_gpio_number, 1);\r
210         //gpio_set_value(ts->config_info.rst_gpio_number, 1);\r
211 \r
212         return 0;\r
213 }\r
214 \r
215 \r
216 struct ts_info  * vtl_ts_get_object(void)\r
217 {\r
218         DEBUG();\r
219         \r
220         return pg_ts;\r
221 }\r
222 #if 0\r
223 static void vtl_ts_free_gpio(void)\r
224 {\r
225         struct ts_info *ts;\r
226         ts =pg_ts;\r
227         DEBUG();\r
228         \r
229         gpio_free(ts->config_info.rst_gpio_number);     \r
230 }\r
231 #endif\r
232 \r
233 void vtl_ts_hw_reset(void)\r
234 {\r
235         struct ts_info *ts;     \r
236         ts =pg_ts;\r
237         DEBUG();\r
238 \r
239         //gpio_set_value(ts->config_info.rst_gpio_number, 1);\r
240         //msleep(10);\r
241         gpio_set_value(ts->config_info.rst_gpio_number, 0);\r
242         msleep(50);\r
243         gpio_set_value(ts->config_info.rst_gpio_number, 1);\r
244         //msleep(250);\r
245         msleep(5);\r
246         chip_solfware_reset(ts->driver->client);//20140306\r
247 }\r
248 \r
249 static void vtl_ts_wakeup(void)\r
250 {\r
251         struct ts_info *ts;     \r
252         ts =pg_ts;\r
253         DEBUG();\r
254 \r
255         gpio_set_value(ts->config_info.rst_gpio_number, 0);\r
256         //msleep(50);\r
257         msleep(20);\r
258         gpio_set_value(ts->config_info.rst_gpio_number, 1);\r
259         msleep(5);\r
260         chip_solfware_reset(ts->driver->client);//20140306\r
261 }\r
262 \r
263 static irqreturn_t vtl_ts_irq(int irq, void *dev)\r
264 {\r
265         struct ts_info *ts;     \r
266         ts =pg_ts;\r
267                 \r
268         DEBUG();\r
269         \r
270         disable_irq_nosync(ts->config_info.irq_number);// Disable ts interrupt\r
271         thread_syn_flag=1; \r
272         wake_up_interruptible(&waiter);\r
273         \r
274         return IRQ_HANDLED;\r
275 }\r
276 \r
277 \r
278 static int vtl_ts_read_xy_data(struct ts_info *ts)\r
279 {\r
280         struct i2c_msg msgs;\r
281         int ret;\r
282                 \r
283         DEBUG();\r
284 \r
285         msgs.addr = ts->driver->client->addr;\r
286         msgs.flags = 0x01;  // 0x00: write 0x01:read \r
287         msgs.len = sizeof(ts->xy_data.buf);\r
288         msgs.buf = ts->xy_data.buf;\r
289         msgs.scl_rate = TS_I2C_SPEED; ///only for rockchip platform\r
290         ret = i2c_transfer( ts->driver->client->adapter, &msgs, 1);\r
291         if(ret != 1){\r
292                 printk("___%s:i2c read xy_data err___\n",__func__);\r
293                 return -1;\r
294         }\r
295         return 0;\r
296 #if 0\r
297         ret = vtl_ts_i2c_read(client,client->addr,ts->xy_data.buf,sizeof(ts->xy_data.buf));\r
298         if(ret){\r
299                 printk("___%s:i2c read err___\n",__func__);\r
300                 return -1;\r
301         }\r
302         return 0;\r
303 #endif\r
304 }\r
305 \r
306 static void vtl_ts_report_xy_coord(struct ts_info *ts)\r
307 {\r
308         int id;\r
309         int sync;\r
310         int x, y;\r
311         unsigned int press;\r
312         unsigned char touch_point_number;\r
313         static unsigned int release = 0;\r
314         struct input_dev *input_dev;\r
315         union ts_xy_data *xy_data;\r
316         \r
317         DEBUG();\r
318 \r
319         xy_data = &ts->xy_data;\r
320         input_dev = ts->driver->input_dev;\r
321         touch_point_number = ts->config_info.touch_point_number;\r
322         \r
323         \r
324         \r
325         /* report points */\r
326         sync = 0;  press = 0;\r
327         for ( id = 0; id <touch_point_number; id++ ) //down\r
328         {\r
329                 if ((xy_data->point[id].xhi != 0xFF) && (xy_data->point[id].yhi != 0xFF) &&\r
330                      ( (xy_data->point[id].status == 1) || (xy_data->point[id].status == 2))) \r
331                 {\r
332 \r
333 /*\r
334                         printk("--->>> vtl_ts report: xy_swap %d, x_reverse %d, y_reverse %d, x_mul %d, y_mul %d, bin_ver %d\n",\r
335                                         ts->config_info.xy_swap, \r
336                                         ts->config_info.x_reverse, ts->config_info.y_reverse, \r
337                                         ts->config_info.x_mul, ts->config_info.y_mul, \r
338                                         ts->config_info.bin_ver);\r
339 */\r
340                 \r
341                         if (ts->config_info.xy_swap == 1) {\r
342                                 x = (xy_data->point[id].yhi<<4)|(xy_data->point[id].ylo&0xF);\r
343                                 y = (xy_data->point[id].xhi<<4)|(xy_data->point[id].xlo&0xF);\r
344                         } else {\r
345                                 x = (xy_data->point[id].xhi<<4)|(xy_data->point[id].xlo&0xF);\r
346                                 y = (xy_data->point[id].yhi<<4)|(xy_data->point[id].ylo&0xF);\r
347                         }\r
348                         if (ts->config_info.x_reverse)\r
349                                 x = ts->config_info.screen_max_x - x;\r
350                         if (ts->config_info.y_reverse)\r
351                                 y = ts->config_info.screen_max_y - y;\r
352 \r
353                         x = ts->config_info.x_mul*x;\r
354                         y = ts->config_info.x_mul*y;\r
355 \r
356                 //#if(DEBUG_ENABLE)\r
357                 //if((ts->debug)||(DEBUG_ENABLE)){\r
358                 if(ts->debug){\r
359                         printk("id = %d,status = %d,X = %d,Y = %d\n",xy_data->point[id].id,xy_data->point[id].status,x,y);\r
360                         //XY_DEBUG(xy_data->point[id].id,xy_data->point[id].status,x,y);\r
361                 }\r
362                 //#endif        \r
363                         input_mt_slot(input_dev, xy_data->point[id].id - 1);\r
364                         input_report_abs(input_dev, ABS_MT_TRACKING_ID, xy_data->point[id].id-1);\r
365                         //input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, true);\r
366                         input_report_abs(input_dev, ABS_MT_POSITION_X, x);\r
367                         input_report_abs(input_dev, ABS_MT_POSITION_Y, y);\r
368                         input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 1);\r
369                         input_report_abs(input_dev, ABS_MT_WIDTH_MAJOR, 1);\r
370         \r
371                         press |= 0x01 << (xy_data->point[id].id - 1);\r
372                         sync = 1;\r
373                 \r
374                 }\r
375                 \r
376         }\r
377         release &= (release ^ press);//release point flag\r
378 \r
379         for ( id = 0; id < touch_point_number; id++ ) //up\r
380         {\r
381                 if ( release & (0x01<<id) ) \r
382                 {\r
383                         input_mt_slot(input_dev, id);\r
384                         input_report_abs(input_dev, ABS_MT_TRACKING_ID, -1);\r
385                         sync = 1;\r
386                 }\r
387         }\r
388 \r
389         release = press;\r
390         if(sync)\r
391         {\r
392                 input_sync(input_dev);\r
393         }\r
394 }\r
395 \r
396 \r
397 \r
398 int vtl_ts_suspend(struct i2c_client *client, pm_message_t mesg)\r
399 {\r
400         struct ts_info *ts;     \r
401         unsigned char i;\r
402         ts =pg_ts;\r
403         DEBUG();\r
404         if(ts->config_info.ctp_used)\r
405         {\r
406                 vtl_first_init_flag = 0;\r
407                 disable_irq(ts->config_info.irq_number);\r
408                 chip_enter_sleep_mode();\r
409         \r
410                 for(i=0;i<ts->config_info.touch_point_number;i++)\r
411                 {\r
412                         input_mt_slot(ts->driver->input_dev,i);\r
413                         input_report_abs(ts->driver->input_dev, ABS_MT_TRACKING_ID, -1);\r
414                         //input_mt_report_slot_state(ts->driver->input_dev, MT_TOOL_FINGER, false);\r
415                 }\r
416                 input_sync(ts->driver->input_dev);\r
417         }\r
418         return 0;\r
419 }\r
420 \r
421 int vtl_ts_resume(struct i2c_client *client)\r
422 {\r
423         struct ts_info *ts;\r
424         unsigned char i;        \r
425         ts =pg_ts;\r
426 \r
427         DEBUG();\r
428         if(ts->config_info.ctp_used)\r
429         {\r
430                 /* Hardware reset */\r
431                 //vtl_ts_hw_reset();\r
432                 vtl_ts_wakeup();\r
433                 for(i=0;i<ts->config_info.touch_point_number;i++)\r
434                 {\r
435                         input_mt_slot(ts->driver->input_dev,i);\r
436                         input_report_abs(ts->driver->input_dev, ABS_MT_TRACKING_ID, -1);\r
437                         //input_mt_report_slot_state(ts->driver->input_dev, MT_TOOL_FINGER, false);\r
438                 }\r
439                 input_sync(ts->driver->input_dev);\r
440                 if(vtl_first_init_flag==0)\r
441                         enable_irq(ts->config_info.irq_number);\r
442         }\r
443         return 0;\r
444 }\r
445 \r
446 static int vtl_ts_early_suspend(struct tp_device *tp)\r
447 {\r
448         struct ts_info *ts;     \r
449         ts =pg_ts;\r
450 \r
451         DEBUG();\r
452 \r
453         vtl_ts_suspend(ts->driver->client, PMSG_SUSPEND);\r
454 \r
455         return 0;\r
456 }\r
457 \r
458 static int vtl_ts_early_resume(struct tp_device *tp)\r
459 {\r
460         struct ts_info *ts;     \r
461         ts =pg_ts;\r
462         DEBUG();\r
463 \r
464         vtl_ts_resume(ts->driver->client);\r
465 \r
466         return 0;\r
467 }\r
468 \r
469 int  vtl_ts_remove(struct i2c_client *client)\r
470 {\r
471         struct ts_info *ts;     \r
472         ts =pg_ts;\r
473 \r
474         DEBUG();\r
475 \r
476         free_irq(ts->config_info.irq_number, ts);   \r
477         gpio_free(ts->config_info.rst_gpio_number);\r
478         //vtl_ts_free_gpio();\r
479 \r
480         //#ifdef CONFIG_HAS_EARLYSUSPEND\r
481         //unregister_early_suspend(&ts->driver->early_suspend);\r
482         tp_unregister_fb(&ts->tp);\r
483         //#endif\r
484         if(ts->driver->input_dev != NULL)\r
485         {\r
486                 input_unregister_device(ts->driver->input_dev);\r
487                 input_free_device(ts->driver->input_dev);\r
488         }\r
489 \r
490         if ( ts->driver->proc_entry != NULL ){\r
491                 remove_proc_entry(DRIVER_NAME, NULL);\r
492         }\r
493         \r
494         if(ts->driver->ts_thread != NULL)\r
495         {\r
496                 printk("___kthread stop start___\n");\r
497                 thread_syn_flag=1; \r
498                 wake_up_interruptible(&waiter);\r
499                 kthread_stop(ts->driver->ts_thread);\r
500                 ts->driver->ts_thread = NULL;\r
501                 printk("___kthread stop end___\n");\r
502         }\r
503         return 0;\r
504 }\r
505 \r
506 static int vtl_ts_init_input_dev(struct ts_info *ts)\r
507 {\r
508         struct input_dev *input_dev;\r
509         struct device *dev;     \r
510         int err;\r
511 \r
512         DEBUG();\r
513 \r
514         \r
515         dev = &ts->driver->client->dev;\r
516         \r
517         /* allocate input device */\r
518         ts->driver->input_dev = input_allocate_device();\r
519         if ( ts->driver->input_dev == NULL ) {\r
520                 dev_err(dev, "Unable to allocate input device for device %s.\n", DRIVER_NAME);\r
521                 return -1;\r
522         }\r
523                 \r
524         input_dev = ts->driver->input_dev;\r
525 \r
526         input_dev->name = DRIVER_NAME;\r
527         input_dev->id.bustype = BUS_I2C;\r
528         input_dev->id.vendor  = 0xaaaa;\r
529         input_dev->id.product = 0x5555;\r
530         input_dev->id.version = 0x0001; \r
531         \r
532         /* config input device */\r
533         __set_bit(EV_SYN, input_dev->evbit);\r
534         __set_bit(EV_KEY, input_dev->evbit);\r
535         __set_bit(EV_ABS, input_dev->evbit);\r
536 \r
537         \r
538         //set_bit(BTN_TOUCH, input_dev->keybit);//20130923\r
539         //set_bit(ABS_MT_POSITION_X, input_dev->absbit);//20130923\r
540         //set_bit(ABS_MT_POSITION_Y, input_dev->absbit);//20130923\r
541 \r
542         __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);\r
543         \r
544         input_mt_init_slots(input_dev, TOUCH_POINT_NUM,0);\r
545         input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ts->config_info.screen_max_x, 0, 0);\r
546         input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ts->config_info.screen_max_y, 0, 0);\r
547         input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,ts->config_info.touch_point_number, 0, 0);\r
548         input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);\r
549         input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);\r
550 \r
551 \r
552         /* register input device */\r
553         err = input_register_device(input_dev);\r
554         if ( err ) {\r
555                 input_free_device(ts->driver->input_dev);\r
556                 ts->driver->input_dev = NULL;\r
557                 dev_err(dev, "Unable to register input device for device %s.\n", DRIVER_NAME);\r
558                 return -1;\r
559         }\r
560         \r
561         return 0;\r
562 }\r
563 \r
564 \r
565 static int vtl_ts_handler(void *data)\r
566 {\r
567         int ret;\r
568         struct device *dev;\r
569         struct ts_info *ts;\r
570         //struct sched_param param = { .sched_priority = TS_THREAD_PRIO};\r
571         DEBUG();\r
572         //sched_setscheduler(current, SCHED_RR, &param);\r
573 \r
574         ts = (struct ts_info *)data;\r
575         dev = &ts->driver->client->dev;\r
576 \r
577 \r
578         /* Request platform resources (gpio/interrupt pins) */\r
579         ret = vtl_ts_config(ts);\r
580         if(ret){\r
581 \r
582                 dev_err(dev, "VTL touch screen config Failed.\n");\r
583                 goto ERR_TS_CONFIG;\r
584         }\r
585         \r
586         vtl_ts_hw_reset();\r
587 \r
588 \r
589         ret = chip_init();\r
590         if(ret){\r
591 \r
592                 dev_err(dev, "vtl ts chip init failed.\n");\r
593                 goto ERR_CHIP_INIT;\r
594         }\r
595 \r
596         /*init input dev*/\r
597         ret = vtl_ts_init_input_dev(ts);\r
598         if(ret){\r
599 \r
600                 dev_err(dev, "init input dev failed.\n");\r
601                 goto ERR_INIT_INPUT;\r
602         }\r
603 \r
604         /* Create Proc Entry File */\r
605         #if 0\r
606         ts->driver->proc_entry = create_proc_entry(DRIVER_NAME, 0666/*S_IFREG | S_IRUGO | S_IWUSR*/, NULL);\r
607         if ( ts->driver->proc_entry == NULL ) {\r
608                 dev_err(dev, "Failed creating proc dir entry file.\n");\r
609                 goto ERR_PROC_ENTRY;\r
610         }  else{\r
611                 ts->driver->proc_entry->proc_fops = &apk_fops;\r
612         }\r
613         #endif\r
614         /* register early suspend */\r
615 //#ifdef CONFIG_HAS_EARLYSUSPEND\r
616         //ts->driver->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;\r
617         //ts->driver->early_suspend.suspend = vtl_ts_early_suspend;\r
618         //ts->driver->early_suspend.resume = vtl_ts_early_resume;\r
619         //register_early_suspend(&ts->driver->early_suspend);\r
620         \r
621         \r
622 //#endif\r
623 \r
624         /* Init irq */\r
625         ret = request_irq(ts->config_info.irq_number, vtl_ts_irq, IRQF_TRIGGER_FALLING, DRIVER_NAME, ts);\r
626         if ( ret ) {\r
627                 dev_err(dev, "Unable to request irq for device %s.\n", DRIVER_NAME);\r
628                 goto ERR_IRQ_REQ;\r
629         }\r
630         //disable_irq(pg_ts->config_info.irq_number);\r
631         ts->config_info.ctp_used =1;\r
632         \r
633         ts->tp.tp_resume = vtl_ts_early_resume;\r
634     ts->tp.tp_suspend = vtl_ts_early_suspend;\r
635     tp_register_fb(&ts->tp);\r
636         \r
637         while (!kthread_should_stop())//while(1)\r
638         {\r
639                 //set_current_state(TASK_INTERRUPTIBLE);        \r
640                 wait_event_interruptible(waiter, thread_syn_flag);\r
641                 thread_syn_flag = 0;\r
642                 //set_current_state(TASK_RUNNING);\r
643                 //printk("__state = %x_%x_\n",current->state,ts->driver->ts_thread->state);\r
644                 ret = vtl_ts_read_xy_data(ts);\r
645 \r
646                 if(!ret){\r
647                         vtl_ts_report_xy_coord(ts);\r
648                 }\r
649                 else\r
650                 {\r
651                         printk("____read xy_data error___\n");\r
652                 }\r
653                 // Enable ts interrupt\r
654                 enable_irq(pg_ts->config_info.irq_number);\r
655         }\r
656         \r
657         printk("vtl_ts_Kthread exit,%s(%d)\n",__func__,__LINE__);\r
658         return 0;\r
659 \r
660 \r
661 \r
662 \r
663 ERR_IRQ_REQ:\r
664         //#ifdef CONFIG_HAS_EARLYSUSPEND\r
665         //unregister_early_suspend(&ts->driver->early_suspend);\r
666         //#endif\r
667         tp_unregister_fb(&ts->tp);\r
668         if ( ts->driver->proc_entry ){\r
669                 remove_proc_entry(DRIVER_NAME, NULL); \r
670                 ts->driver->proc_entry = NULL;\r
671         }\r
672 \r
673 /* ERR_PROC_ENTRY: */\r
674         if(ts->driver->input_dev){\r
675                 input_unregister_device(ts->driver->input_dev);\r
676                 input_free_device(ts->driver->input_dev);\r
677                 ts->driver->input_dev = NULL;\r
678         }\r
679 ERR_INIT_INPUT:\r
680 ERR_CHIP_INIT:  \r
681         gpio_free(ts->config_info.rst_gpio_number);\r
682 ERR_TS_CONFIG:\r
683         ts->config_info.ctp_used =0;\r
684         printk("vtl_ts_Kthread exit,%s(%d)\n",__func__,__LINE__);\r
685         //do_exit(0);\r
686         return 0;\r
687 }\r
688 \r
689 \r
690 \r
691 int vtl_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)\r
692 {\r
693         int err = -1;\r
694         struct ts_info *ts;\r
695         struct device *dev;\r
696 \r
697         DEBUG();\r
698 \r
699         ts = pg_ts;\r
700         ts->driver->client = client;\r
701         dev = &ts->driver->client->dev;\r
702         \r
703         /* Check I2C Functionality */\r
704         err = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);\r
705         if ( !err ) {\r
706                 dev_err(dev, "Check I2C Functionality Failed.\n");\r
707                 return ENODEV;\r
708         }\r
709         \r
710 \r
711         //ts->driver->ts_thread = kthread_run(vtl_ts_handler, NULL, DRIVER_NAME);\r
712         ts->driver->ts_thread = kthread_run(vtl_ts_handler, ts, DRIVER_NAME);\r
713         if (IS_ERR(ts->driver->ts_thread)) {\r
714                 err = PTR_ERR(ts->driver->ts_thread);\r
715                 ts->driver->ts_thread = NULL;\r
716                 dev_err(dev, "failed to create kernel thread: %d\n", err);\r
717                 return -1;\r
718                 //goto ERR_CREATE_TS_THREAD;\r
719         }\r
720 \r
721         printk("___%s() end____ \n", __func__);\r
722         \r
723         return 0;\r
724         \r
725 \r
726 \r
727 }\r
728 \r
729 static struct of_device_id vtl_ts_dt_ids[] = {\r
730         { .compatible = "ct,vtl_ts" },\r
731         { }\r
732 };\r
733 \r
734 struct i2c_driver vtl_ts_driver  = {\r
735         \r
736         .driver = {\r
737                 .owner  = THIS_MODULE,\r
738                 .name   = DRIVER_NAME,\r
739                 .of_match_table = of_match_ptr(vtl_ts_dt_ids),\r
740         },\r
741         .id_table       = vtl_ts_id,\r
742         .probe          = vtl_ts_probe,\r
743 //#ifndef CONFIG_HAS_EARLYSUSPEND\r
744         //.suspend      = vtl_ts_suspend,\r
745         //.resume               = vtl_ts_resume,\r
746 //#endif\r
747         .remove         = vtl_ts_remove,\r
748 };\r
749 \r
750 \r
751 \r
752 int __init vtl_ts_init(void)\r
753 {\r
754         DEBUG();\r
755         return i2c_add_driver(&vtl_ts_driver);\r
756 }\r
757 \r
758 void __exit vtl_ts_exit(void)\r
759 {\r
760         DEBUG();\r
761         i2c_del_driver(&vtl_ts_driver);\r
762 }\r
763 \r
764 module_init(vtl_ts_init);\r
765 module_exit(vtl_ts_exit);\r
766 \r
767 MODULE_AUTHOR("yangdechu@vtl.com.cn");\r
768 MODULE_DESCRIPTION("VTL touchscreen driver for rockchip,V1.0");\r
769 MODULE_LICENSE("GPL");\r
770 \r
771 \r