1 /******************************************************************************
2 * mtk_tpd.c - MTK Android Linux Touch Panel Device Driver *
4 * Copyright 2008-2009 MediaTek Co.,Ltd. *
7 * this file provide basic touch panel event to input sub system *
10 * Kirby.Wu (mtk02247) *
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 *
19 ******************************************************************************/
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>
31 // for magnify velocity********************************************
32 #define TOUCH_IOC_MAGIC 'A'
34 #define TPD_GET_VELOCITY_CUSTOM_X _IO(TOUCH_IOC_MAGIC,0)
35 #define TPD_GET_VELOCITY_CUSTOM_Y _IO(TOUCH_IOC_MAGIC,1)
37 char tpd_firmware_version_val
[5];
38 int tpd_config_version
;
41 /*[PLATFORM]-Add-BEGIN by falin.luo@tcl.com 2015/5/6*/
42 /*MMI test app read sensor id to distinguish the tp manufacturer*/
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*/
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);
64 static int tpd_misc_open(struct inode
*inode
, struct file
*file
)
66 return nonseekable_open(inode
, file
);
69 static int tpd_misc_release(struct inode
*inode
, struct file
*file
)
74 static long tpd_unlocked_ioctl(struct file
*file
, unsigned int cmd
,
82 if (_IOC_DIR(cmd
) & _IOC_READ
)
84 err
= !access_ok(VERIFY_WRITE
, (void __user
*)arg
, _IOC_SIZE(cmd
));
86 else if (_IOC_DIR(cmd
) & _IOC_WRITE
)
88 err
= !access_ok(VERIFY_READ
, (void __user
*)arg
, _IOC_SIZE(cmd
));
93 printk("tpd: access error: %08X, (%2d, %2d)\n", cmd
, _IOC_DIR(cmd
), _IOC_SIZE(cmd
));
99 case TPD_GET_VELOCITY_CUSTOM_X
:
100 data
= (void __user
*) arg
;
108 if (copy_to_user(data
, &tpd_v_magnify_x
, sizeof(tpd_v_magnify_x
)))
116 case TPD_GET_VELOCITY_CUSTOM_Y
:
117 data
= (void __user
*) arg
;
125 if (copy_to_user(data
, &tpd_v_magnify_y
, sizeof(tpd_v_magnify_y
)))
134 printk("tpd: unknown IOCTL: 0x%08x\n", cmd
);
144 static struct file_operations tpd_fops
=
146 // .owner = THIS_MODULE,
147 .open
= tpd_misc_open
,
148 .release
= tpd_misc_release
,
149 .unlocked_ioctl
= tpd_unlocked_ioctl
,
151 /*----------------------------------------------------------------------------*/
152 static struct miscdevice tpd_misc_device
=
154 .minor
= MISC_DYNAMIC_MINOR
,
159 //**********************************************
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
);
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);
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};
179 static struct platform_driver tpd_driver
= {
180 .remove
= tpd_remove
,
183 #ifndef CONFIG_HAS_EARLYSUSPEND
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
=
196 .level
= EARLY_SUSPEND_LEVEL_STOP_DRAWING
-1,
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
)
208 if(g_tpd_drv
!= NULL
)
210 TPD_DMESG("touch driver exist \n");
213 /* check parameter */
219 if(strcmp(tpd_drv
->tpd_device_name
, "generic") == 0)
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
;
228 for(i
= 1; i
< TP_DRV_MAX_COUNT
; i
++)
230 /* add tpd driver into list */
231 if(tpd_driver_list
[i
].tpd_device_name
== NULL
)
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
;
240 if(tpd_drv
->tpd_local_init()==0)
242 TPD_DMESG("load %s sucessfully\n", tpd_driver_list
[i
].tpd_device_name
);
243 g_tpd_drv
= &tpd_driver_list
[i
];
248 if(strcmp(tpd_driver_list
[i
].tpd_device_name
, tpd_drv
->tpd_device_name
) == 0)
250 return 1; // driver exist
257 int tpd_driver_remove(struct tpd_driver_t
*tpd_drv
)
260 /* check parameter */
265 for(i
= 0; i
< TP_DRV_MAX_COUNT
; i
++)
268 if (strcmp(tpd_driver_list
[i
].tpd_device_name
, tpd_drv
->tpd_device_name
) == 0)
270 memset(&tpd_driver_list
[i
], 0, sizeof(struct tpd_driver_t
));
277 static void tpd_create_attributes(struct device
*dev
, struct tpd_attrs
*attrs
)
279 int num
= attrs
->num
;
282 device_create_file(dev
, attrs
->attr
[--num
]);
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
);
291 static ssize_t
hello_val_store(struct device
* dev
, struct device_attribute
* attr
, const char* buf
, size_t count
) {
293 val
= simple_strtol(buf
, NULL
, 10);
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
);
303 static ssize_t
firmware_version_val_store(struct device
* dev
, struct device_attribute
* attr
, char* buf
, size_t count
) {
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
);
313 static ssize_t
config_version_val_store(struct device
* dev
, struct device_attribute
* attr
, char* buf
,size_t count
) {
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
);
323 static ssize_t
tpd_x_line_val_store(struct device
* dev
, struct device_attribute
* attr
, char* buf
,size_t count
) {
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
);
333 static ssize_t
tpd_y_line_val_store(struct device
* dev
, struct device_attribute
* attr
, char* buf
,size_t count
) {
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
);
345 static ssize_t
sensor_id_val_store(struct device
* dev
, struct device_attribute
* attr
, char* buf
,size_t count
) {
348 /*[PLATFORM]-Add-END by falin.luo@tcl.com 2015/5/6*/
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*/
367 /* touch panel probe */
368 static int tpd_probe(struct platform_device
*pdev
) {
369 int touch_type
= 1; // 0:R-touch, 1: Cap-touch
371 TPD_DMESG("enter %s, %d\n", __FUNCTION__
, __LINE__
);
373 // if(g_tpd_drv == NULL||tpd_load_status == 0)
375 if(g_tpd_drv
== NULL
)
377 g_tpd_drv
= &tpd_driver_list
[0];
378 /* touch_type:0: r-touch, 1: C-touch */
380 TPD_DMESG("Generic touch panel driver\n");
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
);
390 if (misc_register(&tpd_misc_device
))
392 printk("mtk_tpd: tpd_misc_device register failed\n");
395 if((tpd
=(struct tpd_device
*)kmalloc(sizeof(struct tpd_device
), GFP_KERNEL
))==NULL
) return -ENOMEM
;
396 memset(tpd
, 0, sizeof(struct tpd_device
));
398 /* allocate input device */
399 if((tpd
->dev
=input_allocate_device())==NULL
) { kfree(tpd
); return -ENOMEM
; }
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();
407 printk("mtk_tpd: TPD_RES_X = %d, TPD_RES_Y = %d\n", TPD_RES_X
, TPD_RES_Y
);
409 tpd_mode
= TPD_MODE_NORMAL
;
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
);
424 for(i
= 1; i
< TP_DRV_MAX_COUNT
; i
++)
426 /* add tpd driver into list */
427 if(tpd_driver_list
[i
].tpd_device_name
!= NULL
)
429 tpd_driver_list
[i
].tpd_local_init();
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
];
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 */
443 g_tpd_drv
->tpd_local_init();
444 TPD_DMESG("[mtk-tpd]Generic touch panel driver\n");
446 TPD_DMESG("[mtk-tpd]cap touch and Generic touch both are not loaded!!\n");
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
);
456 //#ifdef TPD_TYPE_CAPACITIVE
457 /* TPD_TYPE_CAPACITIVE handle */
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;
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);
478 TPD_DMESG("Cap touch panel driver\n");
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;
487 tpd
->dev
->absmax
[ABS_PRESSURE
] = 255;
488 tpd
->dev
->absmin
[ABS_PRESSURE
] = 0;
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);
497 if(input_register_device(tpd
->dev
))
498 TPD_DMESG("input_register_device failed.(tpd)\n");
500 tpd_register_flag
= 1;
503 if(device_create_file(&pdev
->dev
, &dev_attr_gesture_val
) < 0) {
504 printk(KERN_ALERT
"caoyang creat attribute val.");
506 if(device_create_file(&pdev
->dev
, &dev_attr_firmware_version
) < 0) {
507 printk(KERN_ALERT
"caoyang creat attribute val.");
509 if(device_create_file(&pdev
->dev
, &dev_attr_cfg_version
) < 0) {
510 printk(KERN_ALERT
"caoyang creat attribute val.");
512 if(device_create_file(&pdev
->dev
, &dev_attr_tpd_xline
) < 0) {
513 printk(KERN_ALERT
"caoyang creat attribute val.");
515 if(device_create_file(&pdev
->dev
, &dev_attr_tpd_yline
) < 0) {
516 printk(KERN_ALERT
"caoyang creat attribute val.");
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");
523 /*[PLATFORM]-Add-END by falin.luo@tcl.com 2015/5/6*/
529 g_tpd_drv
->tpd_local_init();
532 if(g_tpd_drv
->tpd_have_button
)
537 if (g_tpd_drv
->attrs
.num
)
538 tpd_create_attributes(&pdev
->dev
, &g_tpd_drv
->attrs
);
543 static int tpd_remove(struct platform_device
*pdev
)
545 input_unregister_device(tpd
->dev
);
546 #ifdef CONFIG_HAS_EARLYSUSPEND
547 unregister_early_suspend(&MTK_TS_early_suspend_handler
);
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");
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
);
572 module_init(tpd_device_init
);
573 module_exit(tpd_device_exit
);
575 MODULE_LICENSE("GPL");
576 MODULE_DESCRIPTION("MediaTek touch panel driver");
577 MODULE_AUTHOR("Kirby Wu<kirby.wu@mediatek.com>");