2 * drivers/input/touchscreen/ft5x0x_ts.c
4 * FocalTech ft5x0x TouchScreen driver.
6 * Copyright (c) 2010 Focal tech Ltd.
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 * note: only support mulititouch Wenfs 2010-10-01
20 #include <linux/module.h>
21 #include <linux/delay.h>
22 #include <linux/hrtimer.h>
23 #include <linux/i2c.h>
24 #include <linux/input.h>
25 #include <linux/interrupt.h>
27 #include <linux/platform_device.h>
28 #include <linux/async.h>
29 #include <linux/workqueue.h>
30 #include <linux/slab.h>
31 #include <mach/gpio.h>
32 #include <linux/irq.h>
33 #include <mach/board.h>
34 #include <linux/input/mt.h>
37 #ifdef CONFIG_HAS_EARLYSUSPEND
38 #include <linux/earlysuspend.h>
42 #define CONFIG_FT5X0X_MULTITOUCH 1
43 #define CONFIG_TOUCH_PANEL_KEY 1
46 #define LONGPRESS_LOCK_SPECKEY //是否使用长按某键(如search键)锁住功能键的功能
47 #ifdef LONGPRESS_LOCK_SPECKEY
49 #define ORIGIN_KEY KEY_SEARCH
50 #define LOCK_LONG_PRESS_CNT 100
51 static int Origin2LockPressCnt = 0;
52 static int lockflag =0;
53 static int touch_key_hold_press = 0;
55 ssize_t glock_status_show(struct device *dev, char *buf)
57 printk("lockflag === %d\n",lockflag);
58 return sprintf(buf, "%d", lockflag);
63 static int err_ft5X06 = 0; //w++记载有没有此设备
65 module_param(debug1, int, S_IRUGO|S_IWUSR);
67 static int gpress = 0;
68 extern void gpio_enable1();
69 static int Motoenble = 0;
70 module_param(Motoenble, int, S_IRUGO|S_IWUSR);
71 static int MotoStart = 0;
74 * Added by yick @RockChip
75 * Compatible with both types of firmware
76 * default: point - only pressdown finger num
77 * event - both down and up event
81 uint16_t down_table = 0;
82 uint16_t up_table = ~0;
85 #define SCREEN_MAX_X 480
86 #define SCREEN_MAX_Y 800
89 #define FT5X0X_NAME "ft5x0x_ts"
90 #define MAX_CONTACTS 5
92 FT5X0X_REG_PMODE = 0xA5, /* Power Consume Mode */
98 int touch_key_press[] = {0, 0, 0, 0};
99 //int touch_key_code[] = { KEY_BACK,KEY_HOME, KEY_MENU};
100 //int touch_key_min[KEY_NUM] ={-1,59,105};
101 //int touch_key_max[KEY_NUM] ={2,73,121};
103 int touch_key_code[] = {KEY_MENU, KEY_HOMEPAGE, KEY_BACK, KEY_SEARCH};
104 int touch_key_min[KEY_NUM] ={30,150,270,390};
105 int touch_key_max[KEY_NUM] ={90,210,330,450};
108 #define PMODE_ACTIVE 0x00
109 #define PMODE_MONITOR 0x01
110 #define PMODE_STANDBY 0x02
111 #define PMODE_HIBERNATE 0x03
113 #ifndef ABS_MT_TOUCH_MAJOR
114 #define ABS_MT_TOUCH_MAJOR 0x30 /* touching ellipse */
115 #define ABS_MT_TOUCH_MINOR 0x31 /* (omit if circular) */
116 #define ABS_MT_WIDTH_MAJOR 0x32 /* approaching ellipse */
117 #define ABS_MT_WIDTH_MINOR 0x33 /* (omit if circular) */
118 #define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
119 #define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
120 #define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
121 #define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
122 #define ABS_MT_BLOB_ID 0x38 /* Group set of pkts as blob */
123 #endif /* ABS_MT_TOUCH_MAJOR */
134 struct point_data point[5];
137 struct ft5x0x_ts_dev {
138 struct i2c_client *client;
139 struct input_dev *input_dev;
141 struct ts_event event;
142 struct work_struct pen_event_work;
143 struct workqueue_struct *ts_workqueue;
144 struct early_suspend early_suspend;
147 struct timer_list timer;
151 static struct ft5x0x_ts_dev *g_dev;
152 static bool rember_point_into = true;
155 static ssize_t Moto_status(struct device_driver *_drv,char *_buf)
157 //printk("Moto_status Motoenble==%d\n", Motoenble);
159 return sprintf(_buf, "Ledlevel is Low\n");
161 return sprintf(_buf, "Ledlevel is High\n");
163 static ssize_t Moto_control(struct device_driver *_drv, const char *_buf, size_t _count)
166 //printk("Read data from Android: %s\n", _buf);
167 strncpy(temp, _buf, 1);
168 Motoenble = simple_strtol(temp, NULL, 10);
169 //printk("Moto_control Motoenble=%d\n", Motoenble);
173 static int ft5x0x_i2c_rxdata(char *rxdata, int length)
177 struct i2c_msg msgs[] = {
179 .addr = g_dev->client->addr,
183 .scl_rate = 200 * 1000,
186 .addr = g_dev->client->addr,
190 .scl_rate = 200 * 1000,
194 ret = i2c_transfer(g_dev->client->adapter, msgs, 2);
196 pr_err("msg %s i2c read error: %d\n", __func__, ret);
201 static int ft5x0x_i2c_txdata(char *txdata, int length)
205 struct i2c_msg msg[] = {
207 .addr = g_dev->client->addr,
211 .scl_rate = 200 * 1000,
215 ret = i2c_transfer(g_dev->client->adapter, msg, 1);
217 pr_err("%s i2c write error: %d\n", __func__, ret);
222 static int ft5x0x_set_reg(u8 addr, u8 para)
229 ret = ft5x0x_i2c_txdata(buf, 2);
231 pr_err("write reg failed! %#x ret: %d", buf[0], ret);
238 static int ft5x0x_read_data(void)
240 struct ft5x0x_ts_dev *data = i2c_get_clientdata(g_dev->client);
241 struct ft5x0x_platform_data *pdata = g_dev->client->dev.platform_data;
242 struct ts_event *event = &data->event;
244 u8 buf[32]= {0};//set send addr to 0x00 *important*
253 //printk("the moto is enable!\n");
260 ret = ft5x0x_i2c_rxdata(buf, 32);
263 printk("%s read_data i2c_rxdata failed: %d\n", __func__, ret);
266 #if 0 // Just for debug
272 uc_ecc ^= buf[3+6*i];
273 uc_ecc ^= buf[4+6*i];
274 uc_ecc ^= buf[5+6*i];
275 uc_ecc ^= buf[6+6*i];
277 // if (uc_ecc == buf[1]) break;
281 if (uc_ecc != buf[1])
283 printk("ecc check error uc_ecc=0x%x, buf[1]=0x%x.\n",uc_ecc, buf[1]);
289 memset(event, ~0x00, sizeof(struct ts_event));
292 event->touch_point = buf[2] & 0x07;// 0000 1111
294 event->touch_point = buf[2] >>4;// 0000 1111
296 if (event->touch_point == 0) {
297 rember_point_into = false;
298 #ifdef LONGPRESS_LOCK_SPECKEY
299 if(Origin2LockPressCnt)
301 if(Origin2LockPressCnt < LOCK_LONG_PRESS_CNT)
305 input_report_key(data->input_dev,KEY_SEARCH,1); //158 //MENU
306 input_sync(data->input_dev);
307 input_report_key(data->input_dev,KEY_SEARCH,0); //158 //MENU
308 input_sync(data->input_dev);
309 //printk("menu is up ==========================\n");
314 //printk("release long press !!!!!!!!!!!!!!!!!\n");
315 input_report_key(data->input_dev, KEY_LOCK, 0);
316 //printk("up::KEY_LOCK: %d\n", KEY_LOCK);
317 input_sync(data->input_dev);
319 Origin2LockPressCnt = 0;
320 touch_key_hold_press = 0;
324 if(touch_key_hold_press)
326 touch_key_hold_press = 0;
327 for(key=0; key<sizeof(touch_key_code)/sizeof(touch_key_code[0]); key++)
329 if(touch_key_press[key])
331 input_report_key(data->input_dev, touch_key_code[key], 0);
332 touch_key_press[key] = 0;
333 input_sync(data->input_dev);
334 //printk("up::KEY: %d\n", touch_key_code[key]);
341 //printk("release point !!!!!!!!!!!!!!!!!\n");
342 //ft5x0x_ts_release(data);
344 //event->penddown = Release;
349 #ifdef CONFIG_FT5X0X_MULTITOUCH
350 switch (event->touch_point) {
352 event->point[4].status = (buf[0x1b] & 0xc0)>>6;
353 event->point[4].id = (buf[0x1d] & 0xf0)>>4;
354 event->point[4].x = (s16)(buf[0x1b] & 0x07)<<8 | (s16)buf[0x1c];
355 event->point[4].y = (s16)(buf[0x1d] & 0x07)<<8 | (s16)buf[0x1e];
357 event->point[3].status = (buf[0x15] & 0xc0)>>6;
358 event->point[3].id = (buf[0x17] & 0xf0)>>4;
359 event->point[3].x = (s16)(buf[0x15] & 0x07)<<8 | (s16)buf[0x16];
360 event->point[3].y = (s16)(buf[0x17] & 0x07)<<8 | (s16)buf[0x18];
362 event->point[2].status = (buf[0x0f] & 0xc0)>>6;
363 event->point[2].id = (buf[0x11] & 0xf0)>>4;
364 event->point[2].x = (s16)(buf[0x0f] & 0x07)<<8 | (s16)buf[0x10];
365 event->point[2].y = (s16)(buf[0x11] & 0x07)<<8 | (s16)buf[0x12];
367 event->point[1].status = (buf[0x09] & 0xc0)>>6;
368 event->point[1].id = (buf[0x0b] & 0xf0)>>4;
369 event->point[1].x = (s16)(buf[0x09] & 0x07)<<8 | (s16)buf[0x0a];
370 event->point[1].y = (s16)(buf[0x0b] & 0x07)<<8 | (s16)buf[0x0c];
372 event->point[0].status = (buf[0x03] & 0xc0)>>6;
373 event->point[0].id = (buf[0x05] & 0xf0)>>4;
374 event->point[0].x = (s16)(buf[0x03] & 0x0f)<<8 | (s16)buf[0x04];
375 event->point[0].y = (s16)(buf[0x05] & 0x0f)<<8 | (s16)buf[0x06];
377 if(event->point[0].x < 0){
378 event->point[0].x = 0;
382 for(i=0; i<event->touch_point; i++)
386 swap(event->point[i].x, event->point[i].y);
391 event->point[i].x = pdata->max_x - event->point[i].x;
396 event->point[i].y = pdata->max_y - event->point[i].y;
408 static void ft5x0x_report_value(void)
410 struct ft5x0x_ts_dev *data = i2c_get_clientdata(g_dev->client);
411 struct ft5x0x_platform_data *pdata = g_dev->client->dev.platform_data;
412 struct ts_event *event = &data->event;
417 printk("point is %d x0 is %d y0 is %d\n",
418 //P1 status is %x ID1 is %x x1 is 0x%x y1 is 0x%x\n\n",
420 //event->point[0].status, //event->point[0].id,
421 event->point[0].y, event->point[0].x);
422 //event->point[1].status, event->point[1].id,
423 //event->point[1].x, event->point[1].y);
428 for(i=0; i<event->touch_point; i++) {
430 //printk("event->x[%d]:%d,event->y[%d]:%d\n", i,event->x[i],i,event->y[i]);
431 if((event->point[i].y > pdata->key_min_x) && (debug1)/*&&(posx[i]<KEY_MAX_X)*/)
433 for(j=0;j<KEY_NUM;j++)
435 //printk("i === %d,event->point[i].x==%d,event->point[i].y===%d\n",i,event->point[i].x,event->point[i].y);
436 if((event->point[i].x >touch_key_min[j])&&(event->point[i].x <touch_key_max[j]))
439 // printk("touch_key_hold_press = %d\n",touch_key_hold_press);
440 if((touch_key_press[key_id] == 0) && (touch_key_hold_press == 0))
442 #ifdef LONGPRESS_LOCK_SPECKEY
443 // printk("touch_key_code[%d]:%d\n",key_id,touch_key_code[key_id]);
445 if(touch_key_code[key_id] == ORIGIN_KEY)
447 if(++Origin2LockPressCnt>LOCK_LONG_PRESS_CNT)
449 Origin2LockPressCnt = LOCK_LONG_PRESS_CNT + 2;
450 input_report_key(data->input_dev, KEY_LOCK, 1);
451 touch_key_hold_press = 1;
457 Origin2LockPressCnt=1;
463 input_report_key(data->input_dev, touch_key_code[key_id], 1);
464 touch_key_press[key_id] = 1;
465 touch_key_hold_press = 1;
466 // printk("down::KEY: %d\n", touch_key_code[key_id]);
474 input_mt_slot(data->input_dev, event->point[i].id);
476 input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->point[i].id);
478 down_table |= 1 << event->point[i].id;
479 input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 1);
480 input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->point[i].x);
481 input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->point[i].y);
482 input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
483 //printk("ABS_MT_TRACKING_ID == %d, ABS_MT_POSITION_X == %d, ABS_MT_POSITION_Y == %d\n",event->point[i].id,event->point[i].x,event->point[i].y);
490 for(i=0; i<MAX_CONTACTS; i++) {
491 if( ( (~down_table) & 1<<i) && !(up_table & 1<<i) )
493 input_mt_slot(data->input_dev, i);
494 input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, -1);
495 /*printk("ABS_MT_TRACKING_ID == %d, ABS_MT_POSITION_X == %d, ABS_MT_POSITION_Y == %d\n",event->point[i]
496 .id,event->point[i].y,event->point[i].x);*/
499 up_table = ~down_table;
500 input_sync(data->input_dev);
503 for(i=0; i<event->touch_point; i++) {
504 if(event->point[i].status == 0 || event->point[i].status == 2 ) {
505 input_mt_slot(data->input_dev, event->point[i].id);
506 input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->point[i].id);
507 input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 1);
508 input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->point[i].x);
509 input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->point[i].y);
510 input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 1);
512 else if(event->point[i].status == 1) {
513 input_mt_slot(data->input_dev, event->point[i].id);
514 input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, -1);
517 input_sync(data->input_dev);
526 data->timer.expires = jiffies +8;
527 add_timer(&data->timer);
535 } /*end ft5x0x_report_value*/
537 static void ft5x0x_ts_pen_irq_work(struct work_struct *work)
540 //printk("==ft5x0x_ts_pen_work =\n");
541 ret = ft5x0x_read_data();
543 ft5x0x_report_value();
545 enable_irq(g_dev->irq);
548 static irqreturn_t ft5x0x_ts_interrupt(int irq, void *dev_id)
550 struct ft5x0x_ts_dev *ft5x0x_ts = dev_id;
554 del_timer(&ft5x0x_ts->timer);
556 disable_irq_nosync(g_dev->irq);
557 //printk("==ft5x0x_ts_interrupt =\n");
558 queue_work(ft5x0x_ts->ts_workqueue, &ft5x0x_ts->pen_event_work);
563 #ifdef CONFIG_HAS_EARLYSUSPEND
564 static void ft5x0x_ts_suspend(struct early_suspend *handler)
567 struct ft5x0x_ts_dev *ts;
568 ts = container_of(handler, struct ft5x0x_ts_dev, early_suspend);
571 disable_irq_nosync(ts->irq);
573 ret = cancel_work_sync(&ts->pen_event_work);
574 if (ret && ts->irq) /* if work was pending disable-count is now 2 */
577 // ft5x0x_set_reg(FT5X0X_REG_PMODE, PMODE_HIBERNATE);
580 static void ft5x0x_ts_resume(struct early_suspend *handler)
582 struct ft5x0x_ts_dev *ts;
583 ts = container_of(handler, struct ft5x0x_ts_dev, early_suspend);
585 // gpio_direction_output(RK29_PIN6_PC3, 0);
586 // gpio_set_value(RK29_PIN6_PC3,GPIO_LOW);
588 // gpio_set_value(RK29_PIN6_PC3,GPIO_HIGH);
598 #endif //CONFIG_HAS_EARLYSUSPEND
600 static void Touch_timer_release(unsigned long ft_ts_pdev)
603 struct ft5x0x_ts_dev *data = ft_ts_pdev;
606 /*if(rember_point_into)
608 for(i=0;i<MAX_CONTACTS;i++)
610 printk("hand to modefy with up !!!!!!\n");
612 input_mt_slot(data->input_dev, i);
613 input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, -1);
617 input_sync(data->input_dev);
618 rember_point_into = true;
621 for(i=0; i<MAX_CONTACTS; i++) {
622 if( ( (~down_table) & 1<<i) && !(up_table & 1<<i) )
624 printk("%d is up !!!!!!\n",i);
625 input_mt_slot(data->input_dev, i);
626 input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, -1);
630 if(inflag==1)input_sync(data->input_dev);
632 //===================================
633 #ifdef LONGPRESS_LOCK_SPECKEY
635 if(Origin2LockPressCnt)
637 if(Origin2LockPressCnt < LOCK_LONG_PRESS_CNT)
641 input_report_key(data->input_dev,KEY_SEARCH,1); //158 //MENU
642 input_sync(data->input_dev);
643 input_report_key(data->input_dev,KEY_SEARCH,0); //158 //MENU
644 input_sync(data->input_dev);
645 //printk("menu is up ==========================\n");
650 //printk("release long press !!!!!!!!!!!!!!!!!\n");
651 //input_report_key(data->input_dev, KEY_LOCK, 0);
652 //printk("up::KEY_LOCK: %d\n", KEY_LOCK);
653 //input_sync(data->input_dev);
655 Origin2LockPressCnt = 0;
656 touch_key_hold_press = 0;
660 if((touch_key_hold_press)&&(debug1))
662 touch_key_hold_press = 0;
663 for(key=0; key<sizeof(touch_key_code)/sizeof(touch_key_code[0]); key++)
665 if(touch_key_press[key])
667 input_report_key(data->input_dev, touch_key_code[key], 0);
668 touch_key_press[key] = 0;
669 input_sync(data->input_dev);
670 //printk("up::KEY: %d\n", touch_key_code[key]);
676 //===================================
684 static int ft5x0x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
686 struct ft5x0x_ts_dev *ft5x0x_ts;
687 struct ft5x0x_platform_data *pdata = client->dev.platform_data;
688 struct input_dev *input_dev;
696 dev_err(&client->dev, "%s: platform data is null\n", __func__);
697 goto exit_platform_data_null;
700 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
702 goto exit_check_functionality_failed;
705 if (pdata->init_platform_hw)
706 pdata->init_platform_hw();
709 err_ft5X06=i2c_master_reg8_recv(client, 0x02, buf, 2, 200*1000); //w++6
710 //err_ft5X06 = i2c_master_reg8_recv(client, 0x00, buf, 2, 200 * 1000); //w++5
713 //err_ft5X06 = ft5x0x_i2c_rxdata(buf,1);
715 printk("%s:i2c_transfer fail =%d\n",__FUNCTION__,err);
719 /*pdata->max_x and pdata->max_y should be read from touch*/
721 ft5x0x_ts = (struct ft5x0x_ts_dev *)kzalloc(sizeof(*ft5x0x_ts), GFP_KERNEL);
724 goto exit_alloc_data_failed;
727 input_dev = input_allocate_device();
730 dev_err(&client->dev, "failed to allocate input device\n");
731 goto exit_input_dev_alloc_failed;
734 ft5x0x_ts->input_dev = input_dev;
735 ft5x0x_ts->client = client;
736 ft5x0x_ts->irq = client->irq;
738 __set_bit(EV_ABS, input_dev->evbit);
739 __set_bit(EV_KEY, input_dev->evbit);
740 __set_bit(EV_REP, input_dev->evbit);
741 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
742 set_bit(ABS_MT_POSITION_X, input_dev->absbit);
743 set_bit(ABS_MT_POSITION_Y, input_dev->absbit);
744 set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit);
745 set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit);
747 input_mt_init_slots(input_dev, MAX_CONTACTS);
749 if((pdata->max_x <= 0) || (pdata->max_y <= 0))
751 pdata->max_x = SCREEN_MAX_X;
752 pdata->max_y = SCREEN_MAX_Y;
755 if(pdata->key_min_x <= 0)
757 pdata->key_min_x = KEY_MIN_X;
760 input_set_abs_params(input_dev,ABS_MT_POSITION_X, 0, pdata->max_x, 0, 0);
761 input_set_abs_params(input_dev,ABS_MT_POSITION_Y, 0, pdata->max_y, 0, 0);
762 input_set_abs_params(input_dev,ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0);
763 input_set_abs_params(input_dev,ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
764 #if CONFIG_TOUCH_PANEL_KEY
765 set_bit(KEY_HOMEPAGE, input_dev->keybit);
766 set_bit(KEY_MENU, input_dev->keybit);
767 set_bit(KEY_BACK, input_dev->keybit);
768 set_bit(KEY_SEARCH, input_dev->keybit);
769 #ifdef LONGPRESS_LOCK_SPECKEY
770 // set_bit(KEY_SEARCH, input_dev->keybit);
771 set_bit(KEY_LOCK, input_dev->keybit);
775 input_dev->name = FT5X0X_NAME; //dev_name(&client->dev)
776 err = input_register_device(input_dev);
778 dev_err(&client->dev,
779 "ft5x0x_ts_probe: failed to register input device: %s\n",
780 dev_name(&client->dev));
781 goto exit_input_register_device_failed;
786 i2c_set_clientdata(client, ft5x0x_ts);
787 INIT_WORK(&ft5x0x_ts->pen_event_work, ft5x0x_ts_pen_irq_work);
788 ft5x0x_ts->ts_workqueue = create_workqueue(FT5X0X_NAME);
789 if (!ft5x0x_ts->ts_workqueue) {
791 goto exit_create_singlethread;
794 //if(pdata->init_platform_hw)
795 // pdata->init_platform_hw();
797 //ft5x0x_set_reg(0x80,0x64);
801 dev_dbg(&ft5x0x_ts->client->dev, "no IRQ?\n");
806 ft5x0x_ts->irq = gpio_to_irq(ft5x0x_ts->irq);
809 err = request_irq(ft5x0x_ts->irq, ft5x0x_ts_interrupt, IRQF_TRIGGER_FALLING/*IRQF_DISABLED*/, "ft5x0x_ts", ft5x0x_ts);
811 dev_err(&client->dev, "ft5x0x_probe: request irq failed\n");
812 goto exit_irq_request_failed;
815 disable_irq_nosync(g_dev->irq);
817 #ifdef CONFIG_HAS_EARLYSUSPEND
818 ft5x0x_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
819 ft5x0x_ts->early_suspend.suspend = ft5x0x_ts_suspend;
820 ft5x0x_ts->early_suspend.resume = ft5x0x_ts_resume;
821 register_early_suspend(&ft5x0x_ts->early_suspend);
824 setup_timer(&ft5x0x_ts->timer, Touch_timer_release, (unsigned long)ft5x0x_ts);
828 // __gpio_as_output(GPIO_FT5X0X_WAKE);
829 // __gpio_clear_pin(GPIO_FT5X0X_WAKE); //set wake = 0,base on system
831 // __gpio_set_pin(GPIO_FT5X0X_WAKE); //set wake = 1,base on system
833 // ft5x0x_set_reg(0x88, 0x05); //5, 6,7,8
834 // ft5x0x_set_reg(0x80, 30);
838 err = ft5x0x_set_reg(0x88,6);
839 //ft5x0x_i2c_txdata(0x88, buf_w, 1); /* adjust frequency 60Hz */
842 err = ft5x0x_i2c_rxdata(buf_r,1);
844 enable_irq(g_dev->irq);
846 printk("==ft5x0x_ts_probe = %0x,max_x=%d,max_y=%d\n", buf_r[0],pdata->max_x,pdata->max_y);
850 exit_input_register_device_failed:
851 input_free_device(input_dev);
852 exit_input_dev_alloc_failed:
853 free_irq(client->irq, ft5x0x_ts);
854 //free_irq(IRQ_EINT(6), ft5x0x_ts);
855 exit_irq_request_failed:
856 exit_platform_data_null:
857 cancel_work_sync(&ft5x0x_ts->pen_event_work);
858 destroy_workqueue(ft5x0x_ts->ts_workqueue);
859 exit_create_singlethread:
860 printk("==singlethread error =\n");
861 i2c_set_clientdata(client, NULL);
863 exit_alloc_data_failed:
864 exit_check_functionality_failed:
868 static int __devexit ft5x0x_ts_remove(struct i2c_client *client)
870 struct ft5x0x_ts_dev *ft5x0x_ts = i2c_get_clientdata(client);
871 unregister_early_suspend(&ft5x0x_ts->early_suspend);
872 free_irq(client->irq, ft5x0x_ts);
873 input_unregister_device(ft5x0x_ts->input_dev);
875 cancel_work_sync(&ft5x0x_ts->pen_event_work);
876 destroy_workqueue(ft5x0x_ts->ts_workqueue);
877 i2c_set_clientdata(client, NULL);
881 static const struct i2c_device_id ft5x0x_ts_id[] = {
882 { FT5X0X_NAME, 0 },{ }
884 MODULE_DEVICE_TABLE(i2c, ft5x0x_ts_id);
886 static struct i2c_driver ft5x0x_ts_driver = {
887 .probe = ft5x0x_ts_probe,
888 .remove = __devexit_p(ft5x0x_ts_remove),
889 .id_table = ft5x0x_ts_id,
892 .owner = THIS_MODULE,
895 #ifdef LONGPRESS_LOCK_SPECKEY
896 static DRIVER_ATTR(get_lock_status, 0777, glock_status_show, NULL);
898 static DRIVER_ATTR(MOTOenable, 0666, Moto_status, Moto_control);
900 static int __init ft5x0x_ts_init(void)
903 ret = i2c_add_driver(&ft5x0x_ts_driver);
906 printk("Register 5406_ts driver failed.\n");
909 #ifdef LONGPRESS_LOCK_SPECKEY
910 if(err_ft5X06>=0) //w++
911 ret =driver_create_file(&ft5x0x_ts_driver.driver, &driver_attr_get_lock_status);
914 ret =driver_create_file(&ft5x0x_ts_driver.driver, &driver_attr_MOTOenable);
918 static void __exit ft5x0x_ts_exit(void)
920 i2c_del_driver(&ft5x0x_ts_driver);
921 #ifdef LONGPRESS_LOCK_SPECKEY
922 driver_remove_file(&ft5x0x_ts_driver.driver, &driver_attr_get_lock_status);
924 driver_remove_file(&ft5x0x_ts_driver.driver, &driver_attr_MOTOenable);
927 module_init(ft5x0x_ts_init);
928 module_exit(ft5x0x_ts_exit);
930 MODULE_AUTHOR("<wenfs@Focaltech-systems.com>");
931 MODULE_DESCRIPTION("FocalTech ft5x0x TouchScreen driver");
932 MODULE_LICENSE("GPL");