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 EXPORT_SYMBOL(gesture_value
);
42 EXPORT_SYMBOL(tpd_firmware_version_val
);
43 EXPORT_SYMBOL(tpd_config_version
);
44 EXPORT_SYMBOL(tpd_x_line
);
45 EXPORT_SYMBOL(tpd_y_line
);
50 extern int tpd_v_magnify_x
;
51 extern int tpd_v_magnify_y
;
52 extern UINT32
DISP_GetScreenHeight(void);
53 extern UINT32
DISP_GetScreenWidth(void);
55 static int tpd_misc_open(struct inode
*inode
, struct file
*file
)
57 return nonseekable_open(inode
, file
);
60 static int tpd_misc_release(struct inode
*inode
, struct file
*file
)
65 static long tpd_unlocked_ioctl(struct file
*file
, unsigned int cmd
,
73 if (_IOC_DIR(cmd
) & _IOC_READ
)
75 err
= !access_ok(VERIFY_WRITE
, (void __user
*)arg
, _IOC_SIZE(cmd
));
77 else if (_IOC_DIR(cmd
) & _IOC_WRITE
)
79 err
= !access_ok(VERIFY_READ
, (void __user
*)arg
, _IOC_SIZE(cmd
));
84 printk("tpd: access error: %08X, (%2d, %2d)\n", cmd
, _IOC_DIR(cmd
), _IOC_SIZE(cmd
));
90 case TPD_GET_VELOCITY_CUSTOM_X
:
91 data
= (void __user
*) arg
;
99 if (copy_to_user(data
, &tpd_v_magnify_x
, sizeof(tpd_v_magnify_x
)))
107 case TPD_GET_VELOCITY_CUSTOM_Y
:
108 data
= (void __user
*) arg
;
116 if (copy_to_user(data
, &tpd_v_magnify_y
, sizeof(tpd_v_magnify_y
)))
125 printk("tpd: unknown IOCTL: 0x%08x\n", cmd
);
135 static struct file_operations tpd_fops
=
137 // .owner = THIS_MODULE,
138 .open
= tpd_misc_open
,
139 .release
= tpd_misc_release
,
140 .unlocked_ioctl
= tpd_unlocked_ioctl
,
142 /*----------------------------------------------------------------------------*/
143 static struct miscdevice tpd_misc_device
=
145 .minor
= MISC_DYNAMIC_MINOR
,
150 //**********************************************
154 /* function definitions */
155 static int __init
tpd_device_init(void);
156 static void __exit
tpd_device_exit(void);
157 static int tpd_probe(struct platform_device
*pdev
);
158 static int tpd_remove(struct platform_device
*pdev
);
160 extern void tpd_suspend(struct early_suspend
*h
);
161 extern void tpd_resume(struct early_suspend
*h
);
162 extern void tpd_button_init(void);
164 //int tpd_load_status = 0; //0: failed, 1: sucess
165 int tpd_register_flag
=0;
166 /* global variable definitions */
167 struct tpd_device
*tpd
= 0;
168 static struct tpd_driver_t tpd_driver_list
[TP_DRV_MAX_COUNT
] ;//= {0};
170 static struct platform_driver tpd_driver
= {
171 .remove
= tpd_remove
,
174 #ifndef CONFIG_HAS_EARLYSUSPEND
183 /*20091105, Kelvin, re-locate touch screen driver to earlysuspend*/
184 #ifdef CONFIG_HAS_EARLYSUSPEND
185 static struct early_suspend MTK_TS_early_suspend_handler
=
187 .level
= EARLY_SUSPEND_LEVEL_STOP_DRAWING
-1,
193 static struct tpd_driver_t
*g_tpd_drv
= NULL
;
194 /* Add driver: if find TPD_TYPE_CAPACITIVE driver sucessfully, loading it */
195 int tpd_driver_add(struct tpd_driver_t
*tpd_drv
)
199 if(g_tpd_drv
!= NULL
)
201 TPD_DMESG("touch driver exist \n");
204 /* check parameter */
210 if(strcmp(tpd_drv
->tpd_device_name
, "generic") == 0)
212 tpd_driver_list
[0].tpd_device_name
= tpd_drv
->tpd_device_name
;
213 tpd_driver_list
[0].tpd_local_init
= tpd_drv
->tpd_local_init
;
214 tpd_driver_list
[0].suspend
= tpd_drv
->suspend
;
215 tpd_driver_list
[0].resume
= tpd_drv
->resume
;
216 tpd_driver_list
[0].tpd_have_button
= tpd_drv
->tpd_have_button
;
219 for(i
= 1; i
< TP_DRV_MAX_COUNT
; i
++)
221 /* add tpd driver into list */
222 if(tpd_driver_list
[i
].tpd_device_name
== NULL
)
224 tpd_driver_list
[i
].tpd_device_name
= tpd_drv
->tpd_device_name
;
225 tpd_driver_list
[i
].tpd_local_init
= tpd_drv
->tpd_local_init
;
226 tpd_driver_list
[i
].suspend
= tpd_drv
->suspend
;
227 tpd_driver_list
[i
].resume
= tpd_drv
->resume
;
228 tpd_driver_list
[i
].tpd_have_button
= tpd_drv
->tpd_have_button
;
229 tpd_driver_list
[i
].attrs
= tpd_drv
->attrs
;
231 if(tpd_drv
->tpd_local_init()==0)
233 TPD_DMESG("load %s sucessfully\n", tpd_driver_list
[i
].tpd_device_name
);
234 g_tpd_drv
= &tpd_driver_list
[i
];
239 if(strcmp(tpd_driver_list
[i
].tpd_device_name
, tpd_drv
->tpd_device_name
) == 0)
241 return 1; // driver exist
248 int tpd_driver_remove(struct tpd_driver_t
*tpd_drv
)
251 /* check parameter */
256 for(i
= 0; i
< TP_DRV_MAX_COUNT
; i
++)
259 if (strcmp(tpd_driver_list
[i
].tpd_device_name
, tpd_drv
->tpd_device_name
) == 0)
261 memset(&tpd_driver_list
[i
], 0, sizeof(struct tpd_driver_t
));
268 static void tpd_create_attributes(struct device
*dev
, struct tpd_attrs
*attrs
)
270 int num
= attrs
->num
;
273 device_create_file(dev
, attrs
->attr
[--num
]);
277 static ssize_t
hello_val_show(struct device
* dev
, struct device_attribute
* attr
, char* buf
) {
278 return snprintf(buf
, PAGE_SIZE
, "%d\n", gesture_value
);
282 static ssize_t
hello_val_store(struct device
* dev
, struct device_attribute
* attr
, const char* buf
, size_t count
) {
284 val
= simple_strtol(buf
, NULL
, 10);
289 static ssize_t
firmware_version_val_show(struct device
* dev
, struct device_attribute
* attr
, char* buf
) {
290 printk(KERN_ERR
"caoyang test read!\n");
291 return snprintf(buf
, PAGE_SIZE
, "%s\n", tpd_firmware_version_val
);
294 static ssize_t
firmware_version_val_store(struct device
* dev
, struct device_attribute
* attr
, char* buf
, size_t count
) {
299 static ssize_t
config_version_val_show(struct device
* dev
, struct device_attribute
* attr
, char* buf
) {
300 printk(KERN_ERR
"caoyang test read!\n");
301 return snprintf(buf
, PAGE_SIZE
, "%x\n", tpd_config_version
);
304 static ssize_t
config_version_val_store(struct device
* dev
, struct device_attribute
* attr
, char* buf
,size_t count
) {
309 static ssize_t
tpd_x_line_val_show(struct device
* dev
, struct device_attribute
* attr
, char* buf
) {
310 printk(KERN_ERR
"caoyang test read!\n");
311 return snprintf(buf
, PAGE_SIZE
, "%d\n", tpd_x_line
);
314 static ssize_t
tpd_x_line_val_store(struct device
* dev
, struct device_attribute
* attr
, char* buf
,size_t count
) {
319 static ssize_t
tpd_y_line_val_show(struct device
* dev
, struct device_attribute
* attr
, char* buf
) {
320 printk(KERN_ERR
"caoyang test read!\n");
321 return snprintf(buf
, PAGE_SIZE
, "%d\n", tpd_y_line
);
324 static ssize_t
tpd_y_line_val_store(struct device
* dev
, struct device_attribute
* attr
, char* buf
,size_t count
) {
331 static DEVICE_ATTR(gesture_val
, S_IRUGO
| S_IWUSR
, hello_val_show
, hello_val_store
);
332 static DEVICE_ATTR(firmware_version
, S_IRUGO
| S_IWUSR
, firmware_version_val_show
, firmware_version_val_store
);
333 static DEVICE_ATTR(cfg_version
, S_IRUGO
| S_IWUSR
, config_version_val_show
, config_version_val_store
);
334 static DEVICE_ATTR(tpd_xline
, S_IRUGO
| S_IWUSR
, tpd_x_line_val_show
, tpd_x_line_val_store
);
335 static DEVICE_ATTR(tpd_yline
, S_IRUGO
| S_IWUSR
, tpd_y_line_val_show
, tpd_y_line_val_store
);
342 /* touch panel probe */
343 static int tpd_probe(struct platform_device
*pdev
) {
344 int touch_type
= 1; // 0:R-touch, 1: Cap-touch
346 TPD_DMESG("enter %s, %d\n", __FUNCTION__
, __LINE__
);
348 // if(g_tpd_drv == NULL||tpd_load_status == 0)
350 if(g_tpd_drv
== NULL
)
352 g_tpd_drv
= &tpd_driver_list
[0];
353 /* touch_type:0: r-touch, 1: C-touch */
355 TPD_DMESG("Generic touch panel driver\n");
358 #ifdef CONFIG_HAS_EARLYSUSPEND
359 MTK_TS_early_suspend_handler
.suspend
= g_tpd_drv
->suspend
;
360 MTK_TS_early_suspend_handler
.resume
= g_tpd_drv
->resume
;
361 register_early_suspend(&MTK_TS_early_suspend_handler
);
365 if (misc_register(&tpd_misc_device
))
367 printk("mtk_tpd: tpd_misc_device register failed\n");
370 if((tpd
=(struct tpd_device
*)kmalloc(sizeof(struct tpd_device
), GFP_KERNEL
))==NULL
) return -ENOMEM
;
371 memset(tpd
, 0, sizeof(struct tpd_device
));
373 /* allocate input device */
374 if((tpd
->dev
=input_allocate_device())==NULL
) { kfree(tpd
); return -ENOMEM
; }
376 //TPD_RES_X = simple_strtoul(LCM_WIDTH, NULL, 0);
377 //TPD_RES_Y = simple_strtoul(LCM_HEIGHT, NULL, 0);
378 TPD_RES_X
= DISP_GetScreenWidth();
379 TPD_RES_Y
= DISP_GetScreenHeight();
382 printk("mtk_tpd: TPD_RES_X = %d, TPD_RES_Y = %d\n", TPD_RES_X
, TPD_RES_Y
);
384 tpd_mode
= TPD_MODE_NORMAL
;
386 tpd_mode_min
= TPD_RES_Y
/2;
387 tpd_mode_max
= TPD_RES_Y
;
388 tpd_mode_keypad_tolerance
= TPD_RES_X
*TPD_RES_X
/1600;
389 /* struct input_dev dev initialization and registration */
390 tpd
->dev
->name
= TPD_DEVICE
;
391 set_bit(EV_ABS
, tpd
->dev
->evbit
);
392 set_bit(EV_KEY
, tpd
->dev
->evbit
);
393 set_bit(ABS_X
, tpd
->dev
->absbit
);
394 set_bit(ABS_Y
, tpd
->dev
->absbit
);
395 set_bit(ABS_PRESSURE
, tpd
->dev
->absbit
);
396 set_bit(BTN_TOUCH
, tpd
->dev
->keybit
);
397 set_bit(INPUT_PROP_DIRECT
, tpd
->dev
->propbit
);
399 for(i
= 1; i
< TP_DRV_MAX_COUNT
; i
++)
401 /* add tpd driver into list */
402 if(tpd_driver_list
[i
].tpd_device_name
!= NULL
)
404 tpd_driver_list
[i
].tpd_local_init();
406 if(tpd_load_status
==1) {
407 TPD_DMESG("[mtk-tpd]tpd_probe, tpd_driver_name=%s\n", tpd_driver_list
[i
].tpd_device_name
);
408 g_tpd_drv
= &tpd_driver_list
[i
];
413 if(g_tpd_drv
== NULL
) {
414 if(tpd_driver_list
[0].tpd_device_name
!= NULL
) {
415 g_tpd_drv
= &tpd_driver_list
[0];
416 /* touch_type:0: r-touch, 1: C-touch */
418 g_tpd_drv
->tpd_local_init();
419 TPD_DMESG("[mtk-tpd]Generic touch panel driver\n");
421 TPD_DMESG("[mtk-tpd]cap touch and Generic touch both are not loaded!!\n");
425 #ifdef CONFIG_HAS_EARLYSUSPEND
426 MTK_TS_early_suspend_handler
.suspend
= g_tpd_drv
->suspend
;
427 MTK_TS_early_suspend_handler
.resume
= g_tpd_drv
->resume
;
428 register_early_suspend(&MTK_TS_early_suspend_handler
);
431 //#ifdef TPD_TYPE_CAPACITIVE
432 /* TPD_TYPE_CAPACITIVE handle */
435 set_bit(ABS_MT_TRACKING_ID
, tpd
->dev
->absbit
);
436 set_bit(ABS_MT_TOUCH_MAJOR
, tpd
->dev
->absbit
);
437 set_bit(ABS_MT_TOUCH_MINOR
, tpd
->dev
->absbit
);
438 set_bit(ABS_MT_POSITION_X
, tpd
->dev
->absbit
);
439 set_bit(ABS_MT_POSITION_Y
, tpd
->dev
->absbit
);
440 #if 0 // linux kernel update from 2.6.35 --> 3.0
441 tpd
->dev
->absmax
[ABS_MT_POSITION_X
] = TPD_RES_X
;
442 tpd
->dev
->absmin
[ABS_MT_POSITION_X
] = 0;
443 tpd
->dev
->absmax
[ABS_MT_POSITION_Y
] = TPD_RES_Y
;
444 tpd
->dev
->absmin
[ABS_MT_POSITION_Y
] = 0;
445 tpd
->dev
->absmax
[ABS_MT_TOUCH_MAJOR
] = 100;
446 tpd
->dev
->absmin
[ABS_MT_TOUCH_MINOR
] = 0;
448 input_set_abs_params(tpd
->dev
, ABS_MT_POSITION_X
, 0, TPD_RES_X
, 0, 0);
449 input_set_abs_params(tpd
->dev
, ABS_MT_POSITION_Y
, 0, TPD_RES_Y
, 0, 0);
450 input_set_abs_params(tpd
->dev
, ABS_MT_TOUCH_MAJOR
, 0, 100, 0, 0);
451 input_set_abs_params(tpd
->dev
, ABS_MT_TOUCH_MINOR
, 0, 100, 0, 0);
453 TPD_DMESG("Cap touch panel driver\n");
456 #if 0 //linux kernel update from 2.6.35 --> 3.0
457 tpd
->dev
->absmax
[ABS_X
] = TPD_RES_X
;
458 tpd
->dev
->absmin
[ABS_X
] = 0;
459 tpd
->dev
->absmax
[ABS_Y
] = TPD_RES_Y
;
460 tpd
->dev
->absmin
[ABS_Y
] = 0;
462 tpd
->dev
->absmax
[ABS_PRESSURE
] = 255;
463 tpd
->dev
->absmin
[ABS_PRESSURE
] = 0;
465 input_set_abs_params(tpd
->dev
, ABS_X
, 0, TPD_RES_X
, 0, 0);
466 input_set_abs_params(tpd
->dev
, ABS_Y
, 0, TPD_RES_Y
, 0, 0);
467 input_abs_set_res(tpd
->dev
, ABS_X
, TPD_RES_X
);
468 input_abs_set_res(tpd
->dev
, ABS_Y
, TPD_RES_Y
);
469 input_set_abs_params(tpd
->dev
, ABS_PRESSURE
, 0, 255, 0, 0);
472 if(input_register_device(tpd
->dev
))
473 TPD_DMESG("input_register_device failed.(tpd)\n");
475 tpd_register_flag
= 1;
478 if(device_create_file(&pdev
->dev
, &dev_attr_gesture_val
) < 0) {
479 printk(KERN_ALERT
"caoyang creat attribute val.");
481 if(device_create_file(&pdev
->dev
, &dev_attr_firmware_version
) < 0) {
482 printk(KERN_ALERT
"caoyang creat attribute val.");
484 if(device_create_file(&pdev
->dev
, &dev_attr_cfg_version
) < 0) {
485 printk(KERN_ALERT
"caoyang creat attribute val.");
487 if(device_create_file(&pdev
->dev
, &dev_attr_tpd_xline
) < 0) {
488 printk(KERN_ALERT
"caoyang creat attribute val.");
490 if(device_create_file(&pdev
->dev
, &dev_attr_tpd_yline
) < 0) {
491 printk(KERN_ALERT
"caoyang creat attribute val.");
499 g_tpd_drv
->tpd_local_init();
502 if(g_tpd_drv
->tpd_have_button
)
507 if (g_tpd_drv
->attrs
.num
)
508 tpd_create_attributes(&pdev
->dev
, &g_tpd_drv
->attrs
);
513 static int tpd_remove(struct platform_device
*pdev
)
515 input_unregister_device(tpd
->dev
);
516 #ifdef CONFIG_HAS_EARLYSUSPEND
517 unregister_early_suspend(&MTK_TS_early_suspend_handler
);
522 /* called when loaded into kernel */
523 static int __init
tpd_device_init(void) {
524 printk("MediaTek touch panel driver init\n");
525 if(platform_driver_register(&tpd_driver
)!=0) {
526 TPD_DMESG("unable to register touch panel driver.\n");
532 /* should never be called */
533 static void __exit
tpd_device_exit(void) {
534 TPD_DMESG("MediaTek touch panel driver exit\n");
535 //input_unregister_device(tpd->dev);
536 platform_driver_unregister(&tpd_driver
);
537 #ifdef CONFIG_HAS_EARLYSUSPEND
538 unregister_early_suspend(&MTK_TS_early_suspend_handler
);
542 module_init(tpd_device_init
);
543 module_exit(tpd_device_exit
);
545 MODULE_LICENSE("GPL");
546 MODULE_DESCRIPTION("MediaTek touch panel driver");
547 MODULE_AUTHOR("Kirby Wu<kirby.wu@mediatek.com>");