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