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