Merge tag 'v3.10.55' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / tpw8127_c_mlc / 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
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);
41
42 static int tpd_misc_open(struct inode *inode, struct file *file)
43 {
44 return nonseekable_open(inode, file);
45 }
46
47 static int tpd_misc_release(struct inode *inode, struct file *file)
48 {
49 return 0;
50 }
51
52 static long tpd_unlocked_ioctl(struct file *file, unsigned int cmd,
53 unsigned long arg)
54 {
55 //char strbuf[256];
56 void __user *data;
57
58 long err = 0;
59
60 if (_IOC_DIR(cmd) & _IOC_READ)
61 {
62 err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
63 }
64 else if (_IOC_DIR(cmd) & _IOC_WRITE)
65 {
66 err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
67 }
68
69 if (err)
70 {
71 printk("tpd: access error: %08X, (%2d, %2d)\n", cmd, _IOC_DIR(cmd), _IOC_SIZE(cmd));
72 return -EFAULT;
73 }
74
75 switch (cmd)
76 {
77 case TPD_GET_VELOCITY_CUSTOM_X:
78 data = (void __user *) arg;
79
80 if (data == NULL)
81 {
82 err = -EINVAL;
83 break;
84 }
85
86 if (copy_to_user(data, &tpd_v_magnify_x, sizeof(tpd_v_magnify_x)))
87 {
88 err = -EFAULT;
89 break;
90 }
91
92 break;
93
94 case TPD_GET_VELOCITY_CUSTOM_Y:
95 data = (void __user *) arg;
96
97 if (data == NULL)
98 {
99 err = -EINVAL;
100 break;
101 }
102
103 if (copy_to_user(data, &tpd_v_magnify_y, sizeof(tpd_v_magnify_y)))
104 {
105 err = -EFAULT;
106 break;
107 }
108
109 break;
110
111 default:
112 printk("tpd: unknown IOCTL: 0x%08x\n", cmd);
113 err = -ENOIOCTLCMD;
114 break;
115
116 }
117
118 return err;
119 }
120
121
122 static struct file_operations tpd_fops =
123 {
124 // .owner = THIS_MODULE,
125 .open = tpd_misc_open,
126 .release = tpd_misc_release,
127 .unlocked_ioctl = tpd_unlocked_ioctl,
128 };
129 /*----------------------------------------------------------------------------*/
130 static struct miscdevice tpd_misc_device =
131 {
132 .minor = MISC_DYNAMIC_MINOR,
133 .name = "touch",
134 .fops = &tpd_fops,
135 };
136
137 //**********************************************
138 //#endif
139
140
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);
146
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);
150
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};
156
157 static struct platform_driver tpd_driver = {
158 .remove = tpd_remove,
159 .shutdown = NULL,
160 .probe = tpd_probe,
161 #ifndef CONFIG_HAS_EARLYSUSPEND
162 .suspend = NULL,
163 .resume = NULL,
164 #endif
165 .driver = {
166 .name = TPD_DEVICE,
167 },
168 };
169
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 =
173 {
174 .level = EARLY_SUSPEND_LEVEL_STOP_DRAWING-1,
175 .suspend = NULL,
176 .resume = NULL,
177 };
178 #endif
179
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)
183 {
184 int i;
185
186 if(g_tpd_drv != NULL)
187 {
188 TPD_DMESG("touch driver exist \n");
189 return -1;
190 }
191 /* check parameter */
192 if(tpd_drv == NULL)
193 {
194 return -1;
195 }
196 /* R-touch */
197 if(strcmp(tpd_drv->tpd_device_name, "generic") == 0)
198 {
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;
204 return 0;
205 }
206 for(i = 1; i < TP_DRV_MAX_COUNT; i++)
207 {
208 /* add tpd driver into list */
209 if(tpd_driver_list[i].tpd_device_name == NULL)
210 {
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;
217 #if 0
218 if(tpd_drv->tpd_local_init()==0)
219 {
220 TPD_DMESG("load %s sucessfully\n", tpd_driver_list[i].tpd_device_name);
221 g_tpd_drv = &tpd_driver_list[i];
222 }
223 #endif
224 break;
225 }
226 if(strcmp(tpd_driver_list[i].tpd_device_name, tpd_drv->tpd_device_name) == 0)
227 {
228 return 1; // driver exist
229 }
230 }
231
232 return 0;
233 }
234
235 int tpd_driver_remove(struct tpd_driver_t *tpd_drv)
236 {
237 int i = 0;
238 /* check parameter */
239 if(tpd_drv == NULL)
240 {
241 return -1;
242 }
243 for(i = 0; i < TP_DRV_MAX_COUNT; i++)
244 {
245 /* find it */
246 if (strcmp(tpd_driver_list[i].tpd_device_name, tpd_drv->tpd_device_name) == 0)
247 {
248 memset(&tpd_driver_list[i], 0, sizeof(struct tpd_driver_t));
249 break;
250 }
251 }
252 return 0;
253 }
254
255 static void tpd_create_attributes(struct device *dev, struct tpd_attrs *attrs)
256 {
257 int num = attrs->num;
258
259 for (; num>0;)
260 device_create_file(dev, attrs->attr[--num]);
261 }
262
263 /* touch panel probe */
264 static int tpd_probe(struct platform_device *pdev) {
265 int touch_type = 1; // 0:R-touch, 1: Cap-touch
266 int i=0;
267 TPD_DMESG("enter %s, %d\n", __FUNCTION__, __LINE__);
268 /* Select R-Touch */
269 // if(g_tpd_drv == NULL||tpd_load_status == 0)
270 #if 0
271 if(g_tpd_drv == NULL)
272 {
273 g_tpd_drv = &tpd_driver_list[0];
274 /* touch_type:0: r-touch, 1: C-touch */
275 touch_type = 0;
276 TPD_DMESG("Generic touch panel driver\n");
277 }
278
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);
283 #endif
284 #endif
285
286 if (misc_register(&tpd_misc_device))
287 {
288 printk("mtk_tpd: tpd_misc_device register failed\n");
289 }
290
291 if((tpd=(struct tpd_device*)kmalloc(sizeof(struct tpd_device), GFP_KERNEL))==NULL) return -ENOMEM;
292 memset(tpd, 0, sizeof(struct tpd_device));
293
294 /* allocate input device */
295 if((tpd->dev=input_allocate_device())==NULL) { kfree(tpd); return -ENOMEM; }
296
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();
301
302
303 printk("mtk_tpd: TPD_RES_X = %d, TPD_RES_Y = %d\n", TPD_RES_X, TPD_RES_Y);
304
305 tpd_mode = TPD_MODE_NORMAL;
306 tpd_mode_axis = 0;
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);
319 #if 1
320 for(i = 1; i < TP_DRV_MAX_COUNT; i++)
321 {
322 /* add tpd driver into list */
323 if(tpd_driver_list[i].tpd_device_name != NULL)
324 {
325 tpd_driver_list[i].tpd_local_init();
326 //msleep(1);
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];
330 break;
331 }
332 }
333 }
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 */
338 touch_type = 0;
339 g_tpd_drv->tpd_local_init();
340 TPD_DMESG("[mtk-tpd]Generic touch panel driver\n");
341 } else {
342 TPD_DMESG("[mtk-tpd]cap touch and Generic touch both are not loaded!!\n");
343 return 0;
344 }
345 }
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);
350 #endif
351 #endif
352 //#ifdef TPD_TYPE_CAPACITIVE
353 /* TPD_TYPE_CAPACITIVE handle */
354 if(touch_type == 1){
355
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;
368 #else
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);
373 #endif
374 TPD_DMESG("Cap touch panel driver\n");
375 }
376 //#endif
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;
382
383 tpd->dev->absmax[ABS_PRESSURE] = 255;
384 tpd->dev->absmin[ABS_PRESSURE] = 0;
385 #else
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);
391
392 #endif
393 if(input_register_device(tpd->dev))
394 TPD_DMESG("input_register_device failed.(tpd)\n");
395 else
396 tpd_register_flag = 1;
397 /* init R-Touch */
398 #if 0
399 if(touch_type == 0)
400 {
401 g_tpd_drv->tpd_local_init();
402 }
403 #endif
404 if(g_tpd_drv->tpd_have_button)
405 {
406 tpd_button_init();
407 }
408
409 if (g_tpd_drv->attrs.num)
410 tpd_create_attributes(&pdev->dev, &g_tpd_drv->attrs);
411
412 return 0;
413 }
414
415 static int tpd_remove(struct platform_device *pdev)
416 {
417 input_unregister_device(tpd->dev);
418 #ifdef CONFIG_HAS_EARLYSUSPEND
419 unregister_early_suspend(&MTK_TS_early_suspend_handler);
420 #endif
421 return 0;
422 }
423
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");
429 return -1;
430 }
431 return 0;
432 }
433
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);
441 #endif
442 }
443
444 module_init(tpd_device_init);
445 module_exit(tpd_device_exit);
446
447 MODULE_LICENSE("GPL");
448 MODULE_DESCRIPTION("MediaTek touch panel driver");
449 MODULE_AUTHOR("Kirby Wu<kirby.wu@mediatek.com>");
450