import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / kr076_nand / touchpanel / mtk_tpd.c
1 /******************************************************************************
2 * mtk_tpd.c - MTK Android Linux Touch Panel Device Driver *
3 * *
4 * Copyright 2008-2009 MediaTek Co.,Ltd. *
5 * *
6 * DESCRIPTION: *
7 * this file provide basic touch panel event to input sub system *
8 * *
9 * AUTHOR: *
10 * Kirby.Wu (mtk02247) *
11 * *
12 * NOTE: *
13 * 1. Sensitivity for touch screen should be set to edge-sensitive. *
14 * But in this driver it is assumed to be done by interrupt core, *
15 * though not done yet. Interrupt core may provide interface to *
16 * let drivers set the sensitivity in the future. In this case, *
17 * this driver should set the sensitivity of the corresponding IRQ *
18 * line itself. *
19 ******************************************************************************/
20
21 #include "tpd.h"
22
23 //#ifdef VELOCITY_CUSTOM
24 #include <linux/slab.h>
25 #include <linux/device.h>
26 #include <linux/miscdevice.h>
27 #include <linux/device.h>
28 #include <linux/slab.h>
29 #include <asm/uaccess.h>
30
31 // for magnify velocity********************************************
32 #define TOUCH_IOC_MAGIC 'A'
33
34 #define TPD_GET_VELOCITY_CUSTOM_X _IO(TOUCH_IOC_MAGIC,0)
35 #define TPD_GET_VELOCITY_CUSTOM_Y _IO(TOUCH_IOC_MAGIC,1)
36 int gesture_value;
37 char tpd_firmware_version_val[5];
38 int tpd_config_version;
39 int tpd_x_line;
40 int tpd_y_line;
41 /*[PLATFORM]-Add-BEGIN by falin.luo@tcl.com 2015/5/6*/
42 /*MMI test app read sensor id to distinguish the tp manufacturer*/
43 u8 tpd_sensor_id;
44 /*[PLATFORM]-Add-END by falin.luo@tcl.com 2015/5/6*/
45 EXPORT_SYMBOL(gesture_value);
46 EXPORT_SYMBOL(tpd_firmware_version_val);
47 EXPORT_SYMBOL(tpd_config_version);
48 EXPORT_SYMBOL(tpd_x_line);
49 EXPORT_SYMBOL(tpd_y_line);
50 /*[PLATFORM]-Add-BEGIN by falin.luo@tcl.com 2015/5/6*/
51 /*MMI test app read sensor id to distinguish the tp manufacturer*/
52 EXPORT_SYMBOL(tpd_sensor_id);
53 /*[PLATFORM]-Add-END by falin.luo@tcl.com 2015/5/6*/
54
55
56
57
58
59 extern int tpd_v_magnify_x;
60 extern int tpd_v_magnify_y;
61 extern UINT32 DISP_GetScreenHeight(void);
62 extern UINT32 DISP_GetScreenWidth(void);
63
64 static int tpd_misc_open(struct inode *inode, struct file *file)
65 {
66 return nonseekable_open(inode, file);
67 }
68
69 static int tpd_misc_release(struct inode *inode, struct file *file)
70 {
71 return 0;
72 }
73
74 static long tpd_unlocked_ioctl(struct file *file, unsigned int cmd,
75 unsigned long arg)
76 {
77 //char strbuf[256];
78 void __user *data;
79
80 long err = 0;
81
82 if (_IOC_DIR(cmd) & _IOC_READ)
83 {
84 err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
85 }
86 else if (_IOC_DIR(cmd) & _IOC_WRITE)
87 {
88 err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
89 }
90
91 if (err)
92 {
93 printk("tpd: access error: %08X, (%2d, %2d)\n", cmd, _IOC_DIR(cmd), _IOC_SIZE(cmd));
94 return -EFAULT;
95 }
96
97 switch (cmd)
98 {
99 case TPD_GET_VELOCITY_CUSTOM_X:
100 data = (void __user *) arg;
101
102 if (data == NULL)
103 {
104 err = -EINVAL;
105 break;
106 }
107
108 if (copy_to_user(data, &tpd_v_magnify_x, sizeof(tpd_v_magnify_x)))
109 {
110 err = -EFAULT;
111 break;
112 }
113
114 break;
115
116 case TPD_GET_VELOCITY_CUSTOM_Y:
117 data = (void __user *) arg;
118
119 if (data == NULL)
120 {
121 err = -EINVAL;
122 break;
123 }
124
125 if (copy_to_user(data, &tpd_v_magnify_y, sizeof(tpd_v_magnify_y)))
126 {
127 err = -EFAULT;
128 break;
129 }
130
131 break;
132
133 default:
134 printk("tpd: unknown IOCTL: 0x%08x\n", cmd);
135 err = -ENOIOCTLCMD;
136 break;
137
138 }
139
140 return err;
141 }
142
143
144 static struct file_operations tpd_fops =
145 {
146 // .owner = THIS_MODULE,
147 .open = tpd_misc_open,
148 .release = tpd_misc_release,
149 .unlocked_ioctl = tpd_unlocked_ioctl,
150 };
151 /*----------------------------------------------------------------------------*/
152 static struct miscdevice tpd_misc_device =
153 {
154 .minor = MISC_DYNAMIC_MINOR,
155 .name = "touch",
156 .fops = &tpd_fops,
157 };
158
159 //**********************************************
160 //#endif
161
162
163 /* function definitions */
164 static int __init tpd_device_init(void);
165 static void __exit tpd_device_exit(void);
166 static int tpd_probe(struct platform_device *pdev);
167 static int tpd_remove(struct platform_device *pdev);
168
169 extern void tpd_suspend(struct early_suspend *h);
170 extern void tpd_resume(struct early_suspend *h);
171 extern void tpd_button_init(void);
172
173 //int tpd_load_status = 0; //0: failed, 1: sucess
174 int tpd_register_flag=0;
175 /* global variable definitions */
176 struct tpd_device *tpd = 0;
177 static struct tpd_driver_t tpd_driver_list[TP_DRV_MAX_COUNT] ;//= {0};
178
179 static struct platform_driver tpd_driver = {
180 .remove = tpd_remove,
181 .shutdown = NULL,
182 .probe = tpd_probe,
183 #ifndef CONFIG_HAS_EARLYSUSPEND
184 .suspend = NULL,
185 .resume = NULL,
186 #endif
187 .driver = {
188 .name = TPD_DEVICE,
189 },
190 };
191
192 /*20091105, Kelvin, re-locate touch screen driver to earlysuspend*/
193 #ifdef CONFIG_HAS_EARLYSUSPEND
194 static struct early_suspend MTK_TS_early_suspend_handler =
195 {
196 .level = EARLY_SUSPEND_LEVEL_STOP_DRAWING-1,
197 .suspend = NULL,
198 .resume = NULL,
199 };
200 #endif
201
202 static struct tpd_driver_t *g_tpd_drv = NULL;
203 /* Add driver: if find TPD_TYPE_CAPACITIVE driver sucessfully, loading it */
204 int tpd_driver_add(struct tpd_driver_t *tpd_drv)
205 {
206 int i;
207
208 if(g_tpd_drv != NULL)
209 {
210 TPD_DMESG("touch driver exist \n");
211 return -1;
212 }
213 /* check parameter */
214 if(tpd_drv == NULL)
215 {
216 return -1;
217 }
218 /* R-touch */
219 if(strcmp(tpd_drv->tpd_device_name, "generic") == 0)
220 {
221 tpd_driver_list[0].tpd_device_name = tpd_drv->tpd_device_name;
222 tpd_driver_list[0].tpd_local_init = tpd_drv->tpd_local_init;
223 tpd_driver_list[0].suspend = tpd_drv->suspend;
224 tpd_driver_list[0].resume = tpd_drv->resume;
225 tpd_driver_list[0].tpd_have_button = tpd_drv->tpd_have_button;
226 return 0;
227 }
228 for(i = 1; i < TP_DRV_MAX_COUNT; i++)
229 {
230 /* add tpd driver into list */
231 if(tpd_driver_list[i].tpd_device_name == NULL)
232 {
233 tpd_driver_list[i].tpd_device_name = tpd_drv->tpd_device_name;
234 tpd_driver_list[i].tpd_local_init = tpd_drv->tpd_local_init;
235 tpd_driver_list[i].suspend = tpd_drv->suspend;
236 tpd_driver_list[i].resume = tpd_drv->resume;
237 tpd_driver_list[i].tpd_have_button = tpd_drv->tpd_have_button;
238 tpd_driver_list[i].attrs = tpd_drv->attrs;
239 #if 0
240 if(tpd_drv->tpd_local_init()==0)
241 {
242 TPD_DMESG("load %s sucessfully\n", tpd_driver_list[i].tpd_device_name);
243 g_tpd_drv = &tpd_driver_list[i];
244 }
245 #endif
246 break;
247 }
248 if(strcmp(tpd_driver_list[i].tpd_device_name, tpd_drv->tpd_device_name) == 0)
249 {
250 return 1; // driver exist
251 }
252 }
253
254 return 0;
255 }
256
257 int tpd_driver_remove(struct tpd_driver_t *tpd_drv)
258 {
259 int i = 0;
260 /* check parameter */
261 if(tpd_drv == NULL)
262 {
263 return -1;
264 }
265 for(i = 0; i < TP_DRV_MAX_COUNT; i++)
266 {
267 /* find it */
268 if (strcmp(tpd_driver_list[i].tpd_device_name, tpd_drv->tpd_device_name) == 0)
269 {
270 memset(&tpd_driver_list[i], 0, sizeof(struct tpd_driver_t));
271 break;
272 }
273 }
274 return 0;
275 }
276
277 static void tpd_create_attributes(struct device *dev, struct tpd_attrs *attrs)
278 {
279 int num = attrs->num;
280
281 for (; num>0;)
282 device_create_file(dev, attrs->attr[--num]);
283 }
284
285
286 static ssize_t hello_val_show(struct device* dev, struct device_attribute* attr, char* buf) {
287 return snprintf(buf, PAGE_SIZE, "%d\n", gesture_value);
288 }
289
290
291 static ssize_t hello_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) {
292 int val = 0;
293 val = simple_strtol(buf, NULL, 10);
294 gesture_value = val;
295 return count;
296 }
297
298 static ssize_t firmware_version_val_show(struct device* dev, struct device_attribute* attr, char* buf) {
299 printk(KERN_ERR"caoyang test read!\n");
300 return snprintf(buf, PAGE_SIZE, "%s\n", tpd_firmware_version_val);
301
302 }
303 static ssize_t firmware_version_val_store(struct device* dev, struct device_attribute* attr, char* buf, size_t count) {
304
305 return count;
306
307 }
308 static ssize_t config_version_val_show(struct device* dev, struct device_attribute* attr, char* buf) {
309 printk(KERN_ERR"caoyang test read!\n");
310 return snprintf(buf, PAGE_SIZE, "%x\n", tpd_config_version);
311
312 }
313 static ssize_t config_version_val_store(struct device* dev, struct device_attribute* attr, char* buf,size_t count) {
314
315 return count;
316
317 }
318 static ssize_t tpd_x_line_val_show(struct device* dev, struct device_attribute* attr, char* buf) {
319 printk(KERN_ERR"caoyang test read!\n");
320 return snprintf(buf, PAGE_SIZE, "%d\n", tpd_x_line);
321
322 }
323 static ssize_t tpd_x_line_val_store(struct device* dev, struct device_attribute* attr, char* buf,size_t count) {
324
325 return count;
326
327 }
328 static ssize_t tpd_y_line_val_show(struct device* dev, struct device_attribute* attr, char* buf) {
329 printk(KERN_ERR"caoyang test read!\n");
330 return snprintf(buf, PAGE_SIZE, "%d\n", tpd_y_line);
331
332 }
333 static ssize_t tpd_y_line_val_store(struct device* dev, struct device_attribute* attr, char* buf,size_t count) {
334
335 return count;
336
337 }
338
339 /*[PLATFORM]-Add-BEGIN by falin.luo@tcl.com 2015/5/6*/
340 /*MMI test app read sensor id to distinguish the tp manufacturer*/
341 static ssize_t sensor_id_val_show(struct device* dev, struct device_attribute* attr, char* buf) {
342 return snprintf(buf, PAGE_SIZE, "%x\n", tpd_sensor_id);
343
344 }
345 static ssize_t sensor_id_val_store(struct device* dev, struct device_attribute* attr, char* buf,size_t count) {
346 return count;
347 }
348 /*[PLATFORM]-Add-END by falin.luo@tcl.com 2015/5/6*/
349
350
351 static DEVICE_ATTR(gesture_val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store);
352 static DEVICE_ATTR(firmware_version, S_IRUGO | S_IWUSR, firmware_version_val_show, firmware_version_val_store);
353 static DEVICE_ATTR(cfg_version, S_IRUGO | S_IWUSR, config_version_val_show, config_version_val_store);
354 static DEVICE_ATTR(tpd_xline, S_IRUGO | S_IWUSR, tpd_x_line_val_show, tpd_x_line_val_store);
355 static DEVICE_ATTR(tpd_yline, S_IRUGO | S_IWUSR, tpd_y_line_val_show, tpd_y_line_val_store);
356 /*[PLATFORM]-Add-BEGIN by falin.luo@tcl.com 2015/5/6*/
357 /*MMI test app read sensor id to distinguish the tp manufacturer*/
358 static DEVICE_ATTR(sensor_id, S_IRUGO | S_IWUSR, sensor_id_val_show, sensor_id_val_store);
359 /*[PLATFORM]-Add-END by falin.luo@tcl.com 2015/5/6*/
360
361
362
363
364
365
366
367 /* touch panel probe */
368 static int tpd_probe(struct platform_device *pdev) {
369 int touch_type = 1; // 0:R-touch, 1: Cap-touch
370 int i=0;
371 TPD_DMESG("enter %s, %d\n", __FUNCTION__, __LINE__);
372 /* Select R-Touch */
373 // if(g_tpd_drv == NULL||tpd_load_status == 0)
374 #if 0
375 if(g_tpd_drv == NULL)
376 {
377 g_tpd_drv = &tpd_driver_list[0];
378 /* touch_type:0: r-touch, 1: C-touch */
379 touch_type = 0;
380 TPD_DMESG("Generic touch panel driver\n");
381 }
382
383 #ifdef CONFIG_HAS_EARLYSUSPEND
384 MTK_TS_early_suspend_handler.suspend = g_tpd_drv->suspend;
385 MTK_TS_early_suspend_handler.resume = g_tpd_drv->resume;
386 register_early_suspend(&MTK_TS_early_suspend_handler);
387 #endif
388 #endif
389
390 if (misc_register(&tpd_misc_device))
391 {
392 printk("mtk_tpd: tpd_misc_device register failed\n");
393 }
394
395 if((tpd=(struct tpd_device*)kmalloc(sizeof(struct tpd_device), GFP_KERNEL))==NULL) return -ENOMEM;
396 memset(tpd, 0, sizeof(struct tpd_device));
397
398 /* allocate input device */
399 if((tpd->dev=input_allocate_device())==NULL) { kfree(tpd); return -ENOMEM; }
400
401 //TPD_RES_X = simple_strtoul(LCM_WIDTH, NULL, 0);
402 //TPD_RES_Y = simple_strtoul(LCM_HEIGHT, NULL, 0);
403 TPD_RES_X = DISP_GetScreenWidth();
404 TPD_RES_Y = DISP_GetScreenHeight();
405
406
407 printk("mtk_tpd: TPD_RES_X = %d, TPD_RES_Y = %d\n", TPD_RES_X, TPD_RES_Y);
408
409 tpd_mode = TPD_MODE_NORMAL;
410 tpd_mode_axis = 0;
411 tpd_mode_min = TPD_RES_Y/2;
412 tpd_mode_max = TPD_RES_Y;
413 tpd_mode_keypad_tolerance = TPD_RES_X*TPD_RES_X/1600;
414 /* struct input_dev dev initialization and registration */
415 tpd->dev->name = TPD_DEVICE;
416 set_bit(EV_ABS, tpd->dev->evbit);
417 set_bit(EV_KEY, tpd->dev->evbit);
418 set_bit(ABS_X, tpd->dev->absbit);
419 set_bit(ABS_Y, tpd->dev->absbit);
420 set_bit(ABS_PRESSURE, tpd->dev->absbit);
421 set_bit(BTN_TOUCH, tpd->dev->keybit);
422 set_bit(INPUT_PROP_DIRECT, tpd->dev->propbit);
423 #if 1
424 for(i = 1; i < TP_DRV_MAX_COUNT; i++)
425 {
426 /* add tpd driver into list */
427 if(tpd_driver_list[i].tpd_device_name != NULL)
428 {
429 tpd_driver_list[i].tpd_local_init();
430 //msleep(1);
431 if(tpd_load_status ==1) {
432 TPD_DMESG("[mtk-tpd]tpd_probe, tpd_driver_name=%s\n", tpd_driver_list[i].tpd_device_name);
433 g_tpd_drv = &tpd_driver_list[i];
434 break;
435 }
436 }
437 }
438 if(g_tpd_drv == NULL) {
439 if(tpd_driver_list[0].tpd_device_name != NULL) {
440 g_tpd_drv = &tpd_driver_list[0];
441 /* touch_type:0: r-touch, 1: C-touch */
442 touch_type = 0;
443 g_tpd_drv->tpd_local_init();
444 TPD_DMESG("[mtk-tpd]Generic touch panel driver\n");
445 } else {
446 TPD_DMESG("[mtk-tpd]cap touch and Generic touch both are not loaded!!\n");
447 return 0;
448 }
449 }
450 #ifdef CONFIG_HAS_EARLYSUSPEND
451 MTK_TS_early_suspend_handler.suspend = g_tpd_drv->suspend;
452 MTK_TS_early_suspend_handler.resume = g_tpd_drv->resume;
453 register_early_suspend(&MTK_TS_early_suspend_handler);
454 #endif
455 #endif
456 //#ifdef TPD_TYPE_CAPACITIVE
457 /* TPD_TYPE_CAPACITIVE handle */
458 if(touch_type == 1){
459
460 set_bit(ABS_MT_TRACKING_ID, tpd->dev->absbit);
461 set_bit(ABS_MT_TOUCH_MAJOR, tpd->dev->absbit);
462 set_bit(ABS_MT_TOUCH_MINOR, tpd->dev->absbit);
463 set_bit(ABS_MT_POSITION_X, tpd->dev->absbit);
464 set_bit(ABS_MT_POSITION_Y, tpd->dev->absbit);
465 #if 0 // linux kernel update from 2.6.35 --> 3.0
466 tpd->dev->absmax[ABS_MT_POSITION_X] = TPD_RES_X;
467 tpd->dev->absmin[ABS_MT_POSITION_X] = 0;
468 tpd->dev->absmax[ABS_MT_POSITION_Y] = TPD_RES_Y;
469 tpd->dev->absmin[ABS_MT_POSITION_Y] = 0;
470 tpd->dev->absmax[ABS_MT_TOUCH_MAJOR] = 100;
471 tpd->dev->absmin[ABS_MT_TOUCH_MINOR] = 0;
472 #else
473 input_set_abs_params(tpd->dev, ABS_MT_POSITION_X, 0, TPD_RES_X, 0, 0);
474 input_set_abs_params(tpd->dev, ABS_MT_POSITION_Y, 0, TPD_RES_Y, 0, 0);
475 input_set_abs_params(tpd->dev, ABS_MT_TOUCH_MAJOR, 0, 100, 0, 0);
476 input_set_abs_params(tpd->dev, ABS_MT_TOUCH_MINOR, 0, 100, 0, 0);
477 #endif
478 TPD_DMESG("Cap touch panel driver\n");
479 }
480 //#endif
481 #if 0 //linux kernel update from 2.6.35 --> 3.0
482 tpd->dev->absmax[ABS_X] = TPD_RES_X;
483 tpd->dev->absmin[ABS_X] = 0;
484 tpd->dev->absmax[ABS_Y] = TPD_RES_Y;
485 tpd->dev->absmin[ABS_Y] = 0;
486
487 tpd->dev->absmax[ABS_PRESSURE] = 255;
488 tpd->dev->absmin[ABS_PRESSURE] = 0;
489 #else
490 input_set_abs_params(tpd->dev, ABS_X, 0, TPD_RES_X, 0, 0);
491 input_set_abs_params(tpd->dev, ABS_Y, 0, TPD_RES_Y, 0, 0);
492 input_abs_set_res(tpd->dev, ABS_X, TPD_RES_X);
493 input_abs_set_res(tpd->dev, ABS_Y, TPD_RES_Y);
494 input_set_abs_params(tpd->dev, ABS_PRESSURE, 0, 255, 0, 0);
495
496 #endif
497 if(input_register_device(tpd->dev))
498 TPD_DMESG("input_register_device failed.(tpd)\n");
499 else
500 tpd_register_flag = 1;
501
502 //add by caoyang
503 if(device_create_file(&pdev->dev, &dev_attr_gesture_val) < 0) {
504 printk(KERN_ALERT"caoyang creat attribute val.");
505 }
506 if(device_create_file(&pdev->dev, &dev_attr_firmware_version) < 0) {
507 printk(KERN_ALERT"caoyang creat attribute val.");
508 }
509 if(device_create_file(&pdev->dev, &dev_attr_cfg_version) < 0) {
510 printk(KERN_ALERT"caoyang creat attribute val.");
511 }
512 if(device_create_file(&pdev->dev, &dev_attr_tpd_xline) < 0) {
513 printk(KERN_ALERT"caoyang creat attribute val.");
514 }
515 if(device_create_file(&pdev->dev, &dev_attr_tpd_yline) < 0) {
516 printk(KERN_ALERT"caoyang creat attribute val.");
517 }
518 /*[PLATFORM]-Add-BEGIN by falin.luo@tcl.com 2015/5/6*/
519 /*MMI test app read sensor id to distinguish the tp manufacturer*/
520 if(device_create_file(&pdev->dev, &dev_attr_sensor_id) < 0) {
521 printk(KERN_ERR"create sensor_id sys file failed!\n");
522 }
523 /*[PLATFORM]-Add-END by falin.luo@tcl.com 2015/5/6*/
524
525 /* init R-Touch */
526 #if 0
527 if(touch_type == 0)
528 {
529 g_tpd_drv->tpd_local_init();
530 }
531 #endif
532 if(g_tpd_drv->tpd_have_button)
533 {
534 tpd_button_init();
535 }
536
537 if (g_tpd_drv->attrs.num)
538 tpd_create_attributes(&pdev->dev, &g_tpd_drv->attrs);
539
540 return 0;
541 }
542
543 static int tpd_remove(struct platform_device *pdev)
544 {
545 input_unregister_device(tpd->dev);
546 #ifdef CONFIG_HAS_EARLYSUSPEND
547 unregister_early_suspend(&MTK_TS_early_suspend_handler);
548 #endif
549 return 0;
550 }
551
552 /* called when loaded into kernel */
553 static int __init tpd_device_init(void) {
554 printk("MediaTek touch panel driver init\n");
555 if(platform_driver_register(&tpd_driver)!=0) {
556 TPD_DMESG("unable to register touch panel driver.\n");
557 return -1;
558 }
559 return 0;
560 }
561
562 /* should never be called */
563 static void __exit tpd_device_exit(void) {
564 TPD_DMESG("MediaTek touch panel driver exit\n");
565 //input_unregister_device(tpd->dev);
566 platform_driver_unregister(&tpd_driver);
567 #ifdef CONFIG_HAS_EARLYSUSPEND
568 unregister_early_suspend(&MTK_TS_early_suspend_handler);
569 #endif
570 }
571
572 module_init(tpd_device_init);
573 module_exit(tpd_device_exit);
574
575 MODULE_LICENSE("GPL");
576 MODULE_DESCRIPTION("MediaTek touch panel driver");
577 MODULE_AUTHOR("Kirby Wu<kirby.wu@mediatek.com>");
578