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 extern int tpd_v_magnify_x
;
38 extern int tpd_v_magnify_y
;
39 extern UINT32
DISP_GetScreenHeight(void);
40 extern UINT32
DISP_GetScreenWidth(void);
42 static int tpd_misc_open(struct inode
*inode
, struct file
*file
)
44 return nonseekable_open(inode
, file
);
47 static int tpd_misc_release(struct inode
*inode
, struct file
*file
)
52 static long tpd_unlocked_ioctl(struct file
*file
, unsigned int cmd
,
60 if (_IOC_DIR(cmd
) & _IOC_READ
)
62 err
= !access_ok(VERIFY_WRITE
, (void __user
*)arg
, _IOC_SIZE(cmd
));
64 else if (_IOC_DIR(cmd
) & _IOC_WRITE
)
66 err
= !access_ok(VERIFY_READ
, (void __user
*)arg
, _IOC_SIZE(cmd
));
71 printk("tpd: access error: %08X, (%2d, %2d)\n", cmd
, _IOC_DIR(cmd
), _IOC_SIZE(cmd
));
77 case TPD_GET_VELOCITY_CUSTOM_X
:
78 data
= (void __user
*) arg
;
86 if (copy_to_user(data
, &tpd_v_magnify_x
, sizeof(tpd_v_magnify_x
)))
94 case TPD_GET_VELOCITY_CUSTOM_Y
:
95 data
= (void __user
*) arg
;
103 if (copy_to_user(data
, &tpd_v_magnify_y
, sizeof(tpd_v_magnify_y
)))
112 printk("tpd: unknown IOCTL: 0x%08x\n", cmd
);
122 static struct file_operations tpd_fops
=
124 // .owner = THIS_MODULE,
125 .open
= tpd_misc_open
,
126 .release
= tpd_misc_release
,
127 .unlocked_ioctl
= tpd_unlocked_ioctl
,
129 /*----------------------------------------------------------------------------*/
130 static struct miscdevice tpd_misc_device
=
132 .minor
= MISC_DYNAMIC_MINOR
,
137 //**********************************************
141 /* function definitions */
142 static int __init
tpd_device_init(void);
143 static void __exit
tpd_device_exit(void);
144 static int tpd_probe(struct platform_device
*pdev
);
145 static int tpd_remove(struct platform_device
*pdev
);
147 extern void tpd_suspend(struct early_suspend
*h
);
148 extern void tpd_resume(struct early_suspend
*h
);
149 extern void tpd_button_init(void);
151 //int tpd_load_status = 0; //0: failed, 1: sucess
152 int tpd_register_flag
=0;
153 /* global variable definitions */
154 struct tpd_device
*tpd
= 0;
155 static struct tpd_driver_t tpd_driver_list
[TP_DRV_MAX_COUNT
] ;//= {0};
157 static struct platform_driver tpd_driver
= {
158 .remove
= tpd_remove
,
161 #ifndef CONFIG_HAS_EARLYSUSPEND
170 /*20091105, Kelvin, re-locate touch screen driver to earlysuspend*/
171 #ifdef CONFIG_HAS_EARLYSUSPEND
172 static struct early_suspend MTK_TS_early_suspend_handler
=
174 .level
= EARLY_SUSPEND_LEVEL_STOP_DRAWING
-1,
180 static struct tpd_driver_t
*g_tpd_drv
= NULL
;
181 /* Add driver: if find TPD_TYPE_CAPACITIVE driver sucessfully, loading it */
182 int tpd_driver_add(struct tpd_driver_t
*tpd_drv
)
186 if(g_tpd_drv
!= NULL
)
188 TPD_DMESG("touch driver exist \n");
191 /* check parameter */
197 if(strcmp(tpd_drv
->tpd_device_name
, "generic") == 0)
199 tpd_driver_list
[0].tpd_device_name
= tpd_drv
->tpd_device_name
;
200 tpd_driver_list
[0].tpd_local_init
= tpd_drv
->tpd_local_init
;
201 tpd_driver_list
[0].suspend
= tpd_drv
->suspend
;
202 tpd_driver_list
[0].resume
= tpd_drv
->resume
;
203 tpd_driver_list
[0].tpd_have_button
= tpd_drv
->tpd_have_button
;
206 for(i
= 1; i
< TP_DRV_MAX_COUNT
; i
++)
208 /* add tpd driver into list */
209 if(tpd_driver_list
[i
].tpd_device_name
== NULL
)
211 tpd_driver_list
[i
].tpd_device_name
= tpd_drv
->tpd_device_name
;
212 tpd_driver_list
[i
].tpd_local_init
= tpd_drv
->tpd_local_init
;
213 tpd_driver_list
[i
].suspend
= tpd_drv
->suspend
;
214 tpd_driver_list
[i
].resume
= tpd_drv
->resume
;
215 tpd_driver_list
[i
].tpd_have_button
= tpd_drv
->tpd_have_button
;
216 tpd_driver_list
[i
].attrs
= tpd_drv
->attrs
;
218 if(tpd_drv
->tpd_local_init()==0)
220 TPD_DMESG("load %s sucessfully\n", tpd_driver_list
[i
].tpd_device_name
);
221 g_tpd_drv
= &tpd_driver_list
[i
];
226 if(strcmp(tpd_driver_list
[i
].tpd_device_name
, tpd_drv
->tpd_device_name
) == 0)
228 return 1; // driver exist
235 int tpd_driver_remove(struct tpd_driver_t
*tpd_drv
)
238 /* check parameter */
243 for(i
= 0; i
< TP_DRV_MAX_COUNT
; i
++)
246 if (strcmp(tpd_driver_list
[i
].tpd_device_name
, tpd_drv
->tpd_device_name
) == 0)
248 memset(&tpd_driver_list
[i
], 0, sizeof(struct tpd_driver_t
));
255 static void tpd_create_attributes(struct device
*dev
, struct tpd_attrs
*attrs
)
257 int num
= attrs
->num
;
260 device_create_file(dev
, attrs
->attr
[--num
]);
263 /* touch panel probe */
264 static int tpd_probe(struct platform_device
*pdev
) {
265 int touch_type
= 1; // 0:R-touch, 1: Cap-touch
267 TPD_DMESG("enter %s, %d\n", __FUNCTION__
, __LINE__
);
269 // if(g_tpd_drv == NULL||tpd_load_status == 0)
271 if(g_tpd_drv
== NULL
)
273 g_tpd_drv
= &tpd_driver_list
[0];
274 /* touch_type:0: r-touch, 1: C-touch */
276 TPD_DMESG("Generic touch panel driver\n");
279 #ifdef CONFIG_HAS_EARLYSUSPEND
280 MTK_TS_early_suspend_handler
.suspend
= g_tpd_drv
->suspend
;
281 MTK_TS_early_suspend_handler
.resume
= g_tpd_drv
->resume
;
282 register_early_suspend(&MTK_TS_early_suspend_handler
);
286 if (misc_register(&tpd_misc_device
))
288 printk("mtk_tpd: tpd_misc_device register failed\n");
291 if((tpd
=(struct tpd_device
*)kmalloc(sizeof(struct tpd_device
), GFP_KERNEL
))==NULL
) return -ENOMEM
;
292 memset(tpd
, 0, sizeof(struct tpd_device
));
294 /* allocate input device */
295 if((tpd
->dev
=input_allocate_device())==NULL
) { kfree(tpd
); return -ENOMEM
; }
297 //TPD_RES_X = simple_strtoul(LCM_WIDTH, NULL, 0);
298 //TPD_RES_Y = simple_strtoul(LCM_HEIGHT, NULL, 0);
299 TPD_RES_X
= DISP_GetScreenWidth();
300 TPD_RES_Y
= DISP_GetScreenHeight();
303 printk("mtk_tpd: TPD_RES_X = %d, TPD_RES_Y = %d\n", TPD_RES_X
, TPD_RES_Y
);
305 tpd_mode
= TPD_MODE_NORMAL
;
307 tpd_mode_min
= TPD_RES_Y
/2;
308 tpd_mode_max
= TPD_RES_Y
;
309 tpd_mode_keypad_tolerance
= TPD_RES_X
*TPD_RES_X
/1600;
310 /* struct input_dev dev initialization and registration */
311 tpd
->dev
->name
= TPD_DEVICE
;
312 set_bit(EV_ABS
, tpd
->dev
->evbit
);
313 set_bit(EV_KEY
, tpd
->dev
->evbit
);
314 set_bit(ABS_X
, tpd
->dev
->absbit
);
315 set_bit(ABS_Y
, tpd
->dev
->absbit
);
316 set_bit(ABS_PRESSURE
, tpd
->dev
->absbit
);
317 set_bit(BTN_TOUCH
, tpd
->dev
->keybit
);
318 set_bit(INPUT_PROP_DIRECT
, tpd
->dev
->propbit
);
320 for(i
= 1; i
< TP_DRV_MAX_COUNT
; i
++)
322 /* add tpd driver into list */
323 if(tpd_driver_list
[i
].tpd_device_name
!= NULL
)
325 tpd_driver_list
[i
].tpd_local_init();
327 if(tpd_load_status
==1) {
328 TPD_DMESG("[mtk-tpd]tpd_probe, tpd_driver_name=%s\n", tpd_driver_list
[i
].tpd_device_name
);
329 g_tpd_drv
= &tpd_driver_list
[i
];
334 if(g_tpd_drv
== NULL
) {
335 if(tpd_driver_list
[0].tpd_device_name
!= NULL
) {
336 g_tpd_drv
= &tpd_driver_list
[0];
337 /* touch_type:0: r-touch, 1: C-touch */
339 g_tpd_drv
->tpd_local_init();
340 TPD_DMESG("[mtk-tpd]Generic touch panel driver\n");
342 TPD_DMESG("[mtk-tpd]cap touch and Generic touch both are not loaded!!\n");
346 #ifdef CONFIG_HAS_EARLYSUSPEND
347 MTK_TS_early_suspend_handler
.suspend
= g_tpd_drv
->suspend
;
348 MTK_TS_early_suspend_handler
.resume
= g_tpd_drv
->resume
;
349 register_early_suspend(&MTK_TS_early_suspend_handler
);
352 //#ifdef TPD_TYPE_CAPACITIVE
353 /* TPD_TYPE_CAPACITIVE handle */
356 set_bit(ABS_MT_TRACKING_ID
, tpd
->dev
->absbit
);
357 set_bit(ABS_MT_TOUCH_MAJOR
, tpd
->dev
->absbit
);
358 set_bit(ABS_MT_TOUCH_MINOR
, tpd
->dev
->absbit
);
359 set_bit(ABS_MT_POSITION_X
, tpd
->dev
->absbit
);
360 set_bit(ABS_MT_POSITION_Y
, tpd
->dev
->absbit
);
361 #if 0 // linux kernel update from 2.6.35 --> 3.0
362 tpd
->dev
->absmax
[ABS_MT_POSITION_X
] = TPD_RES_X
;
363 tpd
->dev
->absmin
[ABS_MT_POSITION_X
] = 0;
364 tpd
->dev
->absmax
[ABS_MT_POSITION_Y
] = TPD_RES_Y
;
365 tpd
->dev
->absmin
[ABS_MT_POSITION_Y
] = 0;
366 tpd
->dev
->absmax
[ABS_MT_TOUCH_MAJOR
] = 100;
367 tpd
->dev
->absmin
[ABS_MT_TOUCH_MINOR
] = 0;
369 input_set_abs_params(tpd
->dev
, ABS_MT_POSITION_X
, 0, TPD_RES_X
, 0, 0);
370 input_set_abs_params(tpd
->dev
, ABS_MT_POSITION_Y
, 0, TPD_RES_Y
, 0, 0);
371 input_set_abs_params(tpd
->dev
, ABS_MT_TOUCH_MAJOR
, 0, 100, 0, 0);
372 input_set_abs_params(tpd
->dev
, ABS_MT_TOUCH_MINOR
, 0, 100, 0, 0);
374 TPD_DMESG("Cap touch panel driver\n");
377 #if 0 //linux kernel update from 2.6.35 --> 3.0
378 tpd
->dev
->absmax
[ABS_X
] = TPD_RES_X
;
379 tpd
->dev
->absmin
[ABS_X
] = 0;
380 tpd
->dev
->absmax
[ABS_Y
] = TPD_RES_Y
;
381 tpd
->dev
->absmin
[ABS_Y
] = 0;
383 tpd
->dev
->absmax
[ABS_PRESSURE
] = 255;
384 tpd
->dev
->absmin
[ABS_PRESSURE
] = 0;
386 input_set_abs_params(tpd
->dev
, ABS_X
, 0, TPD_RES_X
, 0, 0);
387 input_set_abs_params(tpd
->dev
, ABS_Y
, 0, TPD_RES_Y
, 0, 0);
388 input_abs_set_res(tpd
->dev
, ABS_X
, TPD_RES_X
);
389 input_abs_set_res(tpd
->dev
, ABS_Y
, TPD_RES_Y
);
390 input_set_abs_params(tpd
->dev
, ABS_PRESSURE
, 0, 255, 0, 0);
393 if(input_register_device(tpd
->dev
))
394 TPD_DMESG("input_register_device failed.(tpd)\n");
396 tpd_register_flag
= 1;
401 g_tpd_drv
->tpd_local_init();
404 if(g_tpd_drv
->tpd_have_button
)
409 if (g_tpd_drv
->attrs
.num
)
410 tpd_create_attributes(&pdev
->dev
, &g_tpd_drv
->attrs
);
415 static int tpd_remove(struct platform_device
*pdev
)
417 input_unregister_device(tpd
->dev
);
418 #ifdef CONFIG_HAS_EARLYSUSPEND
419 unregister_early_suspend(&MTK_TS_early_suspend_handler
);
424 /* called when loaded into kernel */
425 static int __init
tpd_device_init(void) {
426 printk("MediaTek touch panel driver init\n");
427 if(platform_driver_register(&tpd_driver
)!=0) {
428 TPD_DMESG("unable to register touch panel driver.\n");
434 /* should never be called */
435 static void __exit
tpd_device_exit(void) {
436 TPD_DMESG("MediaTek touch panel driver exit\n");
437 //input_unregister_device(tpd->dev);
438 platform_driver_unregister(&tpd_driver
);
439 #ifdef CONFIG_HAS_EARLYSUSPEND
440 unregister_early_suspend(&MTK_TS_early_suspend_handler
);
444 module_init(tpd_device_init
);
445 module_exit(tpd_device_exit
);
447 MODULE_LICENSE("GPL");
448 MODULE_DESCRIPTION("MediaTek touch panel driver");
449 MODULE_AUTHOR("Kirby Wu<kirby.wu@mediatek.com>");