f08670e1cb779836586b3929dff09e5943376aa1
[firefly-linux-kernel-4.4.55.git] / drivers / input / touchscreen / ct36x_ts / tscore.c
1 /* 
2  * drivers/input/touchscreen/ct36x_ts.c
3  *
4  * VTL ct36x TouchScreen driver. 
5  *
6  * Copyright (c) 2010  VTL tech Ltd.
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  *
18  * George Chen, 2012-06-15
19  */
20
21 // ****************************************************************************
22 // Includes
23 // ****************************************************************************
24
25 #include <linux/kernel.h>
26 #include <linux/version.h>
27 #include <linux/proc_fs.h>
28 #include <linux/i2c.h>
29 #include <linux/delay.h>
30 #include <linux/interrupt.h>
31 #include <linux/input.h>
32 #include <linux/gpio.h>
33
34
35 #include "tscore.h"
36 #include "platform.h"
37
38 enum enum_ct36x_ts_cmds {
39         CT36X_TS_CHIP_ID,
40         CT36X_TS_CHIP_RESET,
41         CT36X_TS_FW_VER,
42         CT36X_TS_FW_CHKSUM,
43         CT36X_TS_FW_UPDATE,
44         CT36X_TS_BIN_VER,
45         CT36X_TS_BIN_CHKSUM,
46 };
47
48
49 // ****************************************************************************
50 // Globel or static variables
51 // ****************************************************************************
52 static struct ct36x_ts_info     ct36x_ts;
53
54
55 // ****************************************************************************
56 // Function declaration
57 // ****************************************************************************
58 int ct36x_cmd_list_ind[] = { 
59         CT36X_TS_CHIP_ID, 
60         CT36X_TS_CHIP_RESET, 
61         CT36X_TS_FW_VER, 
62         CT36X_TS_FW_CHKSUM,
63         CT36X_TS_FW_UPDATE, 
64         CT36X_TS_BIN_VER,
65         CT36X_TS_BIN_CHKSUM,
66 };
67
68 char ct36x_cmd_list_cmd[] = { 'i','r','v','c','u','b','k',0, };
69
70 static int ct36x_ts_cmd(char *cmdlist, const char cmd)
71 {
72         int i = 0;
73
74         // search cmd
75         while ( cmdlist[i] ) {
76                 if ( cmd == cmdlist[i] ) 
77                         return ct36x_cmd_list_ind[i];
78                 i++;
79         }
80
81         return -1;
82 }
83
84 static int ct36x_ts_open(struct inode *inode, struct file *file)
85 {
86         if ( CT36X_TS_CORE_DEBUG )
87         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
88         
89         return 0;
90 }
91
92 static int ct36x_ts_close(struct inode *inode, struct file *file)
93 {
94         if ( CT36X_TS_CORE_DEBUG )
95         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
96         
97         return 0;
98 }
99
100 static ssize_t ct36x_ts_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset)
101 {
102         int cmd = 0;
103         int rslt = 0;
104         
105         if ( CT36X_TS_CORE_DEBUG ) {
106         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
107         printk("%s(): count=0x%x \n", __FUNCTION__, count);
108         }
109
110         // search cmd
111         cmd = ct36x_ts_cmd(ct36x_cmd_list_cmd, buffer[0]);
112
113         switch ( cmd ) {
114                 case CT36X_TS_CHIP_ID:
115                 break;
116
117                 case CT36X_TS_CHIP_RESET:
118                 printk("%s(): CT36X_TS_CHIP_RESET\n", __FUNCTION__);
119                 ct36x_platform_hw_reset(&ct36x_ts);
120                 break;
121
122                 case CT36X_TS_FW_VER:
123                 break;
124
125                 case CT36X_TS_FW_CHKSUM:
126                 printk("%s(): CT36X_TS_FW_CHKSUM\n", __FUNCTION__);
127                 rslt = ct36x_chip_get_fwchksum(ct36x_ts.client, ct36x_ts.data.buf);
128                 printk("%s(): Fw checksum: 0x%x\n", __FUNCTION__, rslt);
129                 break;
130
131                 case CT36X_TS_FW_UPDATE:
132                 printk("%s(): CT36X_TS_FW_UPDATE\n", __FUNCTION__);
133                 ct36x_chip_go_bootloader(ct36x_ts.client, ct36x_ts.data.buf);
134                 break;
135
136                 case CT36X_TS_BIN_VER:
137                 break;
138
139                 case CT36X_TS_BIN_CHKSUM:
140                 printk("%s(): CT36X_TS_BIN_CHKSUM\n", __FUNCTION__);
141                 rslt = ct36x_chip_get_binchksum(ct36x_ts.data.buf);
142                 printk("%s(): bin checksum: 0x%x\n", __FUNCTION__, rslt);
143                 break;
144
145                 default:
146                 printk("%s(): No such command (0x%x). \n", __FUNCTION__, buffer[0]);
147                 break;
148         }
149
150
151         return count;
152 }
153
154 static ssize_t ct36x_ts_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
155 {
156         int err = -1;
157         
158         if ( CT36X_TS_CORE_DEBUG ) {
159         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
160         printk("%s(): count=0x%x \n", __FUNCTION__, count);
161         }
162
163         if ( !ct36x_ts.ready )
164                 return 0;
165
166         //ct36x_ts_reg_read(ct36x_ts->client, buf[0], buf+1, buf[]);
167
168         return count;
169 }
170
171 static struct file_operations ct36x_ts_fops = {
172         .owner = THIS_MODULE,
173         .open = ct36x_ts_open,
174         .release = ct36x_ts_close,
175         .write = ct36x_ts_write,
176         .read = ct36x_ts_read,
177 };
178
179 static irqreturn_t ct36x_ts_irq(int irq, void *dev)
180 {
181         struct ct36x_ts_info *ts;
182
183         if ( CT36X_TS_CORE_DEBUG )
184         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
185
186         ts = (struct ct36x_ts_info *)dev;
187
188         // touch device is ready??
189         if ( ts->ready ) {
190                 // Disable ts interrupt
191                 disable_irq_nosync(ts->irq);
192
193                 queue_work(ts->workqueue, &ts->event_work);
194         }
195
196         return IRQ_HANDLED;
197 }
198
199 static void ct36x_ts_workfunc(struct work_struct *work)
200 {
201         int iter;
202         int sync;
203         int x, y;
204         struct ct36x_ts_info *ts;
205
206         if ( CT36X_TS_CORE_DEBUG )
207         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
208
209         ts = container_of(work, struct ct36x_ts_info, event_work);
210
211         /* read touch points */
212         ct36x_ts_reg_read(ts->client, ts->i2c_address, (char *) ts->data.pts, sizeof(struct ct36x_finger_info) * CT36X_TS_POINT_NUM);
213
214         /* report points */
215         sync = 0; ts->press = 0;
216         for ( iter = 0; iter < CT36X_TS_POINT_NUM; iter++ ) {
217                 if ( ts->data.pts[iter].xhi != 0xFF && ts->data.pts[iter].yhi != 0xFF &&
218                      (ts->data.pts[iter].status == 1 || ts->data.pts[iter].status == 2) ) {
219                 #ifdef CONFIG_TOUCHSCREEN_CT36X_MISC_XY_SWAP
220                         x = (ts->data.pts[iter].yhi<<4)|(ts->data.pts[iter].ylo&0xF);
221                         y = (ts->data.pts[iter].xhi<<4)|(ts->data.pts[iter].xlo&0xF);
222                 #else
223                         x = (ts->data.pts[iter].xhi<<4)|(ts->data.pts[iter].xlo&0xF);
224                         y = (ts->data.pts[iter].yhi<<4)|(ts->data.pts[iter].ylo&0xF);
225                 #endif
226                 #ifdef CONFIG_TOUCHSCREEN_CT36X_MISC_X_REVERSE
227                         x = CT36X_TS_ABS_X_MAX - x;
228                 #endif
229                 #ifdef CONFIG_TOUCHSCREEN_CT36X_MISC_Y_REVERSE
230                         y = CT36X_TS_ABS_Y_MAX - y;
231                 #endif
232                 
233                         if ( CT36X_TS_EVENT_DEBUG ) {
234                                 printk("ID:       %d\n", ts->data.pts[iter].id);
235                                 printk("status:   %d\n", ts->data.pts[iter].status);
236                                 printk("X Lo:     %d\n", ts->data.pts[iter].xlo);
237                                 printk("Y Lo:     %d\n", ts->data.pts[iter].ylo);
238                                 printk("X Hi:     %d\n", ts->data.pts[iter].xhi);
239                                 printk("Y Hi:     %d\n", ts->data.pts[iter].yhi);
240                                 printk("X:        %d\n", x);
241                                 printk("Y:        %d\n", y);
242                         }
243
244                         input_report_abs(ts->input, ABS_MT_POSITION_X, x);
245                         input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
246
247                         input_mt_sync(ts->input);
248                 
249                         sync = 1;
250                         ts->press |= 0x01 << (ts->data.pts[iter].id - 1);
251                 }
252         }
253
254         ts->release &= ts->release ^ ts->press;
255         for ( iter = 0; iter < CT36X_TS_POINT_NUM; iter++ ) {
256                 if ( ts->release & (0x01<<iter) ) {
257                         input_mt_sync(ts->input);
258                         sync = 1;
259                 }
260         }
261         ts->release = ts->press;
262
263         if ( sync ) input_sync(ts->input);
264
265         // Enable ts interrupt
266         enable_irq(ts->irq);
267
268 }
269
270 static void ct36x_ts_adapter(int state)
271 {
272         if ( CT36X_TS_CORE_DEBUG )
273         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
274
275         if ( !ct36x_ts.ready ) return;
276 }
277
278 #ifdef CONFIG_HAS_EARLYSUSPEND
279 static void ct36x_early_suspend(struct early_suspend *handler)
280 {
281         struct ct36x_ts_info *ts;
282
283         if (CT36X_TS_CORE_DEBUG)
284         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
285         
286         ts = container_of(handler, struct ct36x_ts_info, early_suspend);
287
288         ct36x_ts_suspend(ts->client, PMSG_SUSPEND);
289 }
290
291 static void ct36x_early_resume(struct early_suspend *handler)
292 {
293         struct ct36x_ts_info *ts;
294
295         if (CT36X_TS_CORE_DEBUG)
296         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
297         
298         ts = container_of(handler, struct ct36x_ts_info, early_suspend);
299         
300         ct36x_ts_resume(ts->client);
301 }
302 #endif
303
304 int ct36x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
305 {
306         int err = -1;
307         int binchksum, fwchksum;
308         int updcnt;
309         struct ct36x_ts_info *ts;
310         struct ct36x_platform_data *pdata;
311         struct device *dev;
312
313         if ( CT36X_TS_CORE_DEBUG )
314         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
315
316         dev = &client->dev;
317
318         pdata = dev->platform_data;
319
320         if ( pdata ) {
321                 ct36x_ts.i2c_address = client->addr;
322                 ct36x_ts.rst = pdata->rst;
323                 ct36x_ts.ss = pdata->ss;
324                 ct36x_platform_get_cfg(&ct36x_ts);
325
326                 ct36x_ts.client = client;
327                 i2c_set_clientdata(client, &ct36x_ts);
328         } else {
329                 printk("No platform data for device %s.\n", DRIVER_NAME);
330         }
331         ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);
332
333         /* Create Proc Entry File */
334         ts->proc_entry = create_proc_entry(DRIVER_NAME, 0666/*S_IFREG | S_IRUGO | S_IWUSR*/, NULL);
335         if ( ts->proc_entry == NULL ) {
336                 dev_err(dev, "Failed creating proc dir entry file.\n");
337         } else {
338                 ts->proc_entry->proc_fops = &ct36x_ts_fops;
339         }
340
341         /* register early suspend */
342 #ifdef CONFIG_HAS_EARLYSUSPEND
343         ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
344         ts->early_suspend.suspend = ct36x_early_suspend;
345         ts->early_suspend.resume = ct36x_early_resume;
346         register_early_suspend(&ts->early_suspend);
347 #endif
348
349         /* Check I2C Functionality */
350         err = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
351         if ( !err ) {
352                 dev_err(dev, "Check I2C Functionality Failed.\n");
353                 goto ERR_I2C_CHK;
354         }
355
356         /* Request platform resources (gpio/interrupt pins) */
357         err = ct36x_platform_get_resource(ts);
358         if ( err ) {
359                 dev_err(dev, "Unable to request platform resource for device %s.\n", DRIVER_NAME);
360                 goto ERR_PLAT_RSC;
361         }
362
363         /* Hardware reset */
364         ct36x_platform_hw_reset(ts);
365
366         // Get binary Checksum
367         binchksum = ct36x_chip_get_binchksum(ts->data.buf);
368         if ( CT36X_TS_CORE_DEBUG )
369         printk("Bin checksum: 0x%x\n", binchksum);
370
371         // Get firmware Checksum
372         fwchksum = ct36x_chip_get_fwchksum(client, ts->data.buf);
373         if ( CT36X_TS_CORE_DEBUG )
374         printk("Fw checksum: 0x%x\n", fwchksum);
375
376         updcnt = 5;
377         while ( binchksum != fwchksum && updcnt--) {
378                 /* Update Firmware */
379                 ct36x_chip_go_bootloader(client, ts->data.buf);
380
381                 /* Hardware reset */
382                 ct36x_platform_hw_reset(ts);
383
384                 // Get firmware Checksum
385                 fwchksum = ct36x_chip_get_fwchksum(client, ts->data.buf);
386                 if ( CT36X_TS_CORE_DEBUG )
387                 printk("Fw checksum: 0x%x\n", fwchksum);
388         }
389
390         printk("Fw update %s. 0x%x, 0x%x\n", binchksum != fwchksum ? "Failed" : "Success", binchksum, fwchksum);
391
392         /* Hardware reset */
393         ct36x_platform_hw_reset(ts);
394
395         /* allocate input device */
396         ts->input = input_allocate_device();
397         if ( !ts->input ) {
398                 dev_err(dev, "Unable to allocate input device for device %s.\n", DRIVER_NAME);
399                 err = -ENOMEM;
400                 goto ERR_INPUT_ALLOC;
401         }
402
403         /* config input device */
404         __set_bit(EV_SYN, ts->input->evbit);
405         __set_bit(EV_KEY, ts->input->evbit);
406         __set_bit(EV_ABS, ts->input->evbit);
407
408         __set_bit(INPUT_PROP_DIRECT, ts->input->propbit);
409
410         input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, CT36X_TS_ABS_X_MAX, 0, 0);
411         input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, CT36X_TS_ABS_Y_MAX, 0, 0);
412
413         ts->input->name = DRIVER_NAME;
414         ts->input->id.bustype = BUS_I2C;
415
416         /* register input device */
417         err = input_register_device(ts->input);
418         if ( err ) {
419                 dev_err(dev, "Unable to register input device for device %s.\n", DRIVER_NAME);
420                 goto ERR_INPUT_REGIS;
421         }
422
423         /* Create work queue */
424         INIT_WORK(&ts->event_work, ct36x_ts_workfunc);
425         ts->workqueue = create_singlethread_workqueue(dev_name(&client->dev));
426
427         /* Init irq */
428         err = request_irq(ts->irq, ct36x_ts_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, DRIVER_NAME, ts);
429         if ( err ) {
430                 dev_err(dev, "Unable to request irq for device %s.\n", DRIVER_NAME);
431                 goto ERR_IRQ_REQ;
432         }
433
434         /* Set device is ready */
435         ts->ready = 1;
436         ts->state = CT36X_STATE_NORMAL;
437
438         /* power denoisy*/
439         //ct36x_chip_set_adapter_on(client, ts->data.buf);
440         //ct36x_chip_set_adapter_off(client, ts->data.buf);
441         ct36x_ts_adapter(0);
442         
443         return 0;
444
445         ERR_IRQ_REQ:
446         destroy_workqueue(ts->workqueue);
447         ERR_INPUT_REGIS:
448         input_free_device(ts->input);
449         ERR_INPUT_ALLOC:
450         ERR_PLAT_RSC:
451         ct36x_platform_put_resource(ts);
452         ERR_I2C_CHK:
453 #ifdef CONFIG_HAS_EARLYSUSPEND
454         unregister_early_suspend(&ts->early_suspend);
455 #endif
456         remove_proc_entry(DRIVER_NAME, NULL);
457         return err;
458 }
459
460 void ct36x_ts_shutdown(struct i2c_client *client)
461 {
462         struct ct36x_ts_info *ts;
463
464         if (CT36X_TS_CORE_DEBUG)
465         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
466
467         ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);
468
469         ct36x_chip_go_sleep(client, ts->data.buf);
470 }
471
472 int ct36x_ts_suspend(struct i2c_client *client, pm_message_t mesg)
473 {
474         struct ct36x_ts_info *ts;
475
476         if (CT36X_TS_CORE_DEBUG)
477         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
478
479         ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);
480
481         if ( ts->state == CT36X_STATE_SLEEP ) return 0;
482
483         disable_irq(ts->irq);
484
485         cancel_work_sync(&ts->event_work);
486
487         ct36x_chip_go_sleep(client, ts->data.buf);
488
489         ts->state = CT36X_STATE_SLEEP;
490
491         return 0;
492 }
493
494 int ct36x_ts_resume(struct i2c_client *client)
495 {
496         struct ct36x_ts_info *ts;
497
498         if (CT36X_TS_CORE_DEBUG)
499         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
500
501         ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);
502
503         if ( ts->state == CT36X_STATE_NORMAL ) return 0;
504
505         /* Hardware reset */
506         ct36x_platform_hw_reset(ts);
507
508         enable_irq(ts->irq);
509
510         ts->state = CT36X_STATE_NORMAL;
511
512         return 0;
513 }
514
515 int __devexit ct36x_ts_remove(struct i2c_client *client)
516 {
517         struct ct36x_ts_info *ts;
518
519         if (CT36X_TS_CORE_DEBUG)
520         printk(">>>>> %s() called <<<<< \n", __FUNCTION__);
521
522         ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);
523
524         /* Driver clean up */
525         disable_irq(ts->irq);
526         cancel_work_sync(&ts->event_work);
527         destroy_workqueue(ts->workqueue);
528         input_free_device(ts->input);
529         free_irq(ts->irq, ts);
530         ct36x_platform_put_resource(ts);
531         i2c_unregister_device(client);
532 #ifdef CONFIG_HAS_EARLYSUSPEND
533         unregister_early_suspend(&ts->early_suspend);
534 #endif
535         remove_proc_entry(DRIVER_NAME, NULL);
536
537         return 0;
538 }
539
540 int __init ct36x_ts_init(void)
541 {
542         int err = -1;
543
544         printk("VTL ct36x TouchScreen driver, <george.chen@vtl.com.cn>.\n");
545
546         ct36x_platform_get_cfg(&ct36x_ts);
547
548         err = ct36x_platform_set_dev(&ct36x_ts);
549         if ( err ) goto ERR_INIT;
550
551         err = i2c_add_driver(&ct36x_ts_driver);
552         if ( err ) goto ERR_INIT;
553
554         return 0;
555
556         ERR_INIT:
557         return err;
558 }
559
560 void __exit ct36x_ts_exit(void)
561 {
562         i2c_del_driver(&ct36x_ts_driver);
563 }
564
565 module_init(ct36x_ts_init);
566 module_exit(ct36x_ts_exit);
567
568 MODULE_AUTHOR("<george.chen@vtl.com>");
569 MODULE_DESCRIPTION("VTL ct36x TouchScreen driver");
570 MODULE_LICENSE("GPL");
571
572