2 * drivers/input/touchscreen/ft5x0x_ts.c
\r
4 * FocalTech ft5x0x TouchScreen driver.
\r
6 * Copyright (c) 2010 Focal tech Ltd.
\r
8 * This software is licensed under the terms of the GNU General Public
\r
9 * License version 2, as published by the Free Software Foundation, and
\r
10 * may be copied, distributed, and modified under those terms.
\r
12 * This program is distributed in the hope that it will be useful,
\r
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 * GNU General Public License for more details.
\r
18 * note: only support mulititouch Wenfs 2010-10-01
\r
21 #include <linux/input.h>
\r
22 #include <linux/module.h>
\r
23 #include <linux/init.h>
\r
24 #include <linux/interrupt.h>
\r
25 #include <linux/kernel.h>
\r
26 #include <linux/platform_device.h>
\r
27 #include <linux/spi/spi.h>
\r
28 #include <linux/slab.h>
\r
29 #include <linux/fcntl.h>
\r
30 #include <linux/delay.h>
\r
31 #include <linux/device.h>
\r
32 #include <linux/timer.h>
\r
33 #include <linux/jiffies.h>
\r
34 #include <linux/miscdevice.h>
\r
35 #include <linux/types.h>
\r
36 #include <linux/io.h>
\r
37 #include <linux/delay.h>
\r
38 #include <linux/ioport.h>
\r
39 #include <linux/input-polldev.h>
\r
40 #include <linux/i2c.h>
\r
41 #include <linux/workqueue.h>
\r
42 #ifdef CONFIG_ANDROID_POWER
\r
43 #include <linux/android_power.h>
\r
45 #include <mach/hardware.h>
\r
46 #include <asm/setup.h>
\r
47 #include <asm/mach-types.h>
\r
48 #include <asm/mach/arch.h>
\r
49 #include <asm/mach/map.h>
\r
50 #include <asm/mach/flash.h>
\r
51 #include <asm/hardware/gic.h>
\r
52 #include <mach/iomux.h>
\r
53 #include <mach/gpio.h>
\r
54 #include <mach/irqs.h>
\r
55 //#include <mach/rk29_iomap.h>
\r
56 #include <mach/board.h>
\r
57 //#include <mach/rk29_nand.h>
\r
58 //#include <mach/rk29_camera.h> /* ddl@rock-chips.com : camera support */
\r
59 #include <media/soc_camera.h> /* ddl@rock-chips.com : camera support */
\r
60 //#include <mach/vpu_mem.h>
\r
61 #include <mach/sram.h>
\r
62 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
63 #include <linux/earlysuspend.h>
\r
65 #include <linux/input/mt.h>
\r
69 #define FTprintk(x...) printk(x)
\r
71 #define FTprintk(x...) do{} while(0)
\r
74 #define CONFIG_FT5X0X_MULTITOUCH 1
\r
76 #define FT5306_IIC_SPEED 100*1000 //300*1000
\r
77 //#define TOUCH_RESET_PIN RK30_PIN1_PC0
\r
78 #define FT5X0X_REG_THRES 0x80 /* Thresshold, the threshold be low, the sensitivy will be high */
\r
79 #define FT5X0X_REG_REPORT_RATE 0x88 /* **************report rate, in unit of 10Hz **************/
\r
80 #define FT5X0X_REG_PMODE 0xA5 /* Power Consume Mode 0 -- active, 1 -- monitor, 3 -- sleep */
\r
81 #define FT5X0X_REG_FIRMID 0xA6 /* ***************firmware version **********************/
\r
82 #define FT5X0X_REG_NOISE_MODE 0xb2 /* to enable or disable power noise, 1 -- enable, 0 -- disable */
\r
83 #define SCREEN_MAX_X 1024
\r
84 #define SCREEN_MAX_Y 600
\r
85 #define PRESS_MAX 255
\r
86 #define FT5X0X_NAME "ft5x0x_ts"
\r
87 #define TOUCH_MAJOR_MAX 200
\r
88 #define WIDTH_MAJOR_MAX 200
\r
90 #define PMODE_ACTIVE 0x00
\r
91 #define PMODE_MONITOR 0x01
\r
92 #define PMODE_STANDBY 0x02
\r
93 #define PMODE_HIBERNATE 0x03
\r
95 /* zhengxing@rock-chips: avoid to firmwarm upgrade directly cause barrage when startup. */
\r
96 #define FT5X0X_FW_UPGRADE_ASYNC (1)
\r
97 #define FT5X0X_FW_UPGRADE_DIRECTLY (2)
\r
99 #ifdef CONFIG_MACH_RK3066B_M701
\r
100 #define FT5X0X_FW_UPGRADE_MODE FT5X0X_FW_UPGRADE_ASYNC
\r
102 #define FT5X0X_FW_UPGRADE_MODE FT5X0X_FW_UPGRADE_DIRECTLY
\r
135 struct ft5x0x_ts_data {
\r
136 struct i2c_client *client;
\r
137 struct input_dev *input_dev;
\r
139 int (*platform_sleep)(void);
\r
140 int (*platform_wakeup)(void);
\r
141 struct ts_event event;
\r
142 struct work_struct pen_event_work;
\r
143 struct workqueue_struct *ts_workqueue;
\r
144 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
145 struct early_suspend ft5306_early_suspend;
\r
147 #if (FT5X0X_FW_UPGRADE_MODE == FT5X0X_FW_UPGRADE_ASYNC)
\r
148 struct work_struct fw_upgrade_work;
\r
149 struct workqueue_struct *fw_workqueue;
\r
152 static struct i2c_client *this_client;
\r
154 /***********************************************************************/
\r
156 #define FTS_PACKET_LENGTH 128
\r
159 static u8 CTPM_FW[]=
\r
161 #include "ft5306_ts_av.cfg"
\r
173 ERR_DL_PROGRAM_FAIL,
\r
175 }E_UPGRADE_ERR_TYPE;
\r
177 /***********************************************************************/
\r
179 /***********************************************************************
\r
181 callback: send data to ctpm by i2c interface;
\r
183 txdata[in]: data buffer which is used to send data;
\r
184 length[in]: the length of the data buffer;
\r
188 ************************************************************************/
\r
189 static int fts_i2c_txdata(u8 *txdata, int length)
\r
193 struct i2c_msg msg;
\r
195 msg.addr = this_client->addr;
\r
199 msg.scl_rate = FT5306_IIC_SPEED;
\r
200 ret = i2c_transfer(this_client->adapter, &msg, 1);
\r
202 pr_err("%s i2c write error: %d\n", __func__, ret);
\r
207 /***********************************************************************
\r
209 callback: write data to ctpm by i2c interface;
\r
211 buffer[in]: data buffer;
\r
212 length[in]: the length of the data buffer;
\r
216 ************************************************************************/
\r
217 static bool i2c_write_interface(u8* pbt_buf, int dw_lenth)
\r
220 ret=i2c_master_send(this_client, pbt_buf, dw_lenth);
\r
223 FTprintk("[TSP]i2c_write_interface error line = %d, ret = %d\n", __LINE__, ret);
\r
230 /***********************************************************************
\r
232 callback: read register value ftom ctpm by i2c interface;
\r
234 reg_name[in]: the register which you want to write;
\r
235 tx_buf[in]: buffer which is contained of the writing value;
\r
239 ************************************************************************/
\r
240 static bool fts_register_write(u8 reg_name, u8* tx_buf)
\r
242 u8 write_cmd[2] = {0};
\r
244 write_cmd[0] = reg_name;
\r
245 write_cmd[1] = *tx_buf;
\r
247 /*call the write callback function*/
\r
248 return i2c_write_interface(write_cmd, 2);
\r
251 /***********************************************************************
\r
253 callback: send a command to ctpm.
\r
255 btcmd[in]: command code;
\r
256 btPara1[in]: parameter 1;
\r
257 btPara2[in]: parameter 2;
\r
258 btPara3[in]: parameter 3;
\r
259 num[in]: the valid input parameter numbers,
\r
260 if only command code needed and no
\r
261 parameters followed,then the num is 1;
\r
264 FTS_FALSE: io fail;
\r
265 ************************************************************************/
\r
266 static bool cmd_write(u8 btcmd,u8 btPara1,u8 btPara2,u8 btPara3,u8 num)
\r
268 u8 write_cmd[4] = {0};
\r
270 write_cmd[0] = btcmd;
\r
271 write_cmd[1] = btPara1;
\r
272 write_cmd[2] = btPara2;
\r
273 write_cmd[3] = btPara3;
\r
274 return i2c_write_interface(write_cmd, num);
\r
277 /***********************************************************************
\r
279 callback: read data from ctpm by i2c interface;
\r
281 buffer[in]: data buffer;
\r
282 length[in]: the length of the data buffer;
\r
286 ************************************************************************/
\r
287 static bool i2c_read_interface(u8* pbt_buf, int dw_lenth)
\r
291 ret=i2c_master_recv(this_client, pbt_buf, dw_lenth);
\r
295 FTprintk("[TSP]i2c_read_interface error\n");
\r
303 /***********************************************************************
\r
305 callback: read a byte data from ctpm;
\r
307 buffer[in]: read buffer;
\r
308 length[in]: the size of read data;
\r
311 FTS_FALSE: io fail;
\r
312 ************************************************************************/
\r
313 static bool byte_read(u8* buffer, int length)
\r
315 return i2c_read_interface(buffer, length);
\r
318 /***********************************************************************
\r
320 callback: write a byte data to ctpm;
\r
322 buffer[in]: write buffer;
\r
323 length[in]: the size of write data;
\r
326 FTS_FALSE: io fail;
\r
327 ************************************************************************/
\r
328 static bool byte_write(u8* buffer, int length)
\r
331 return i2c_write_interface(buffer, length);
\r
334 /***********************************************************************
\r
336 callback: read register value ftom ctpm by i2c interface;
\r
338 reg_name[in]: the register which you want to read;
\r
339 rx_buf[in]: data buffer which is used to store register value;
\r
340 rx_length[in]: the length of the data buffer;
\r
344 ************************************************************************/
\r
345 static bool fts_register_read(u8 reg_name, u8* rx_buf, int rx_length)
\r
347 u8 read_cmd[2]= {0};
\r
350 read_cmd[0] = reg_name;
\r
353 /*send register addr*/
\r
354 if(!i2c_write_interface(&read_cmd[0], cmd_len))
\r
359 /*call the read callback function to get the register value*/
\r
360 if(!i2c_read_interface(rx_buf, rx_length))
\r
369 /***********************************************************************
\r
371 callback: burn the FW to ctpm.
\r
373 pbt_buf[in]: point to Head+FW ;
\r
374 dw_lenth[in]: the length of the FW + 6(the Head length);
\r
377 ERR_MODE: fail to switch to UPDATE mode;
\r
378 ERR_READID: read id fail;
\r
379 ERR_ERASE: erase chip fail;
\r
380 ERR_STATUS: status error;
\r
381 ERR_ECC: ecc error.
\r
382 ************************************************************************/
\r
383 E_UPGRADE_ERR_TYPE fts_ctpm_fw_upgrade(u8* pbt_buf, int dw_lenth)
\r
385 u8 cmd,reg_val[2] = {0};
\r
386 u8 buffer[2] = {0};
\r
387 u8 packet_buf[FTS_PACKET_LENGTH + 6];
\r
388 u8 auc_i2c_write_buf[10];
\r
391 int j,temp,lenght,i_ret,packet_number, i = 0;
\r
392 int i_is_new_protocol = 0;
\r
395 /******write 0xaa to register 0xfc******/
\r
397 fts_register_write(0xfc,&cmd);
\r
400 /******write 0x55 to register 0xfc******/
\r
402 fts_register_write(0xfc,&cmd);
\r
403 FTprintk("[TSP] Step 1: Reset CTPM test\n");
\r
408 /*******Step 2:Enter upgrade mode ****/
\r
409 FTprintk("\n[TSP] Step 2:enter new update mode\n");
\r
410 auc_i2c_write_buf[0] = 0x55;
\r
411 auc_i2c_write_buf[1] = 0xaa;
\r
415 i_ret = fts_i2c_txdata(auc_i2c_write_buf, 2);
\r
417 }while(i_ret <= 0 && i < 10 );
\r
421 i_is_new_protocol = 1;
\r
424 /********Step 3:check READ-ID********/
\r
425 cmd_write(0x90,0x00,0x00,0x00,4);
\r
426 byte_read(reg_val,2);
\r
427 if (reg_val[0] == 0x79 && reg_val[1] == 0x3)
\r
429 FTprintk("[TSP] Step 3: CTPM ID,ID1 = 0x%x,ID2 = 0x%x\n",reg_val[0],reg_val[1]);
\r
434 //i_is_new_protocol = 1;
\r
438 /*********Step 4:erase app**********/
\r
439 if (i_is_new_protocol)
\r
441 cmd_write(0x61,0x00,0x00,0x00,1);
\r
445 cmd_write(0x60,0x00,0x00,0x00,1);
\r
448 FTprintk("[TSP] Step 4: erase. \n");
\r
452 /*Step 5:write firmware(FW) to ctpm flash*/
\r
454 FTprintk("[TSP] Step 5: start upgrade. \n");
\r
455 dw_lenth = dw_lenth - 8;
\r
456 packet_number = (dw_lenth) / FTS_PACKET_LENGTH;
\r
457 packet_buf[0] = 0xbf;
\r
458 packet_buf[1] = 0x00;
\r
459 FTprintk("[TSP] packet_number = %d\n",packet_number);
\r
460 for (j=0;j<packet_number;j++)
\r
462 temp = j * FTS_PACKET_LENGTH;
\r
463 packet_buf[2] = (u8)(temp>>8);
\r
464 packet_buf[3] = (u8)temp;
\r
465 lenght = FTS_PACKET_LENGTH;
\r
466 packet_buf[4] = (u8)(lenght>>8);
\r
467 packet_buf[5] = (u8)lenght;
\r
469 for (i=0;i<FTS_PACKET_LENGTH;i++)
\r
471 packet_buf[6+i] = pbt_buf[j*FTS_PACKET_LENGTH + i];
\r
472 bt_ecc ^= packet_buf[6+i];
\r
475 byte_write(&packet_buf[0],FTS_PACKET_LENGTH + 6);
\r
476 mdelay(FTS_PACKET_LENGTH/6 + 1);
\r
477 if ((j * FTS_PACKET_LENGTH % 1024) == 0)
\r
479 FTprintk("[TSP] upgrade the 0x%x th byte.\n", ((unsigned int)j) * FTS_PACKET_LENGTH);
\r
483 if ((dw_lenth) % FTS_PACKET_LENGTH > 0)
\r
485 temp = packet_number * FTS_PACKET_LENGTH;
\r
486 packet_buf[2] = (u8)(temp>>8);
\r
487 packet_buf[3] = (u8)temp;
\r
489 temp = (dw_lenth) % FTS_PACKET_LENGTH;
\r
490 packet_buf[4] = (u8)(temp>>8);
\r
491 packet_buf[5] = (u8)temp;
\r
493 for (i=0;i<temp;i++)
\r
495 packet_buf[6+i] = pbt_buf[ packet_number*FTS_PACKET_LENGTH + i];
\r
496 bt_ecc ^= packet_buf[6+i];
\r
499 byte_write(&packet_buf[0],temp+6);
\r
503 /***********send the last six byte**********/
\r
504 for (i = 0; i<6; i++)
\r
507 packet_buf[2] = (u8)(temp>>8);
\r
508 packet_buf[3] = (u8)temp;
\r
510 packet_buf[4] = (u8)(temp>>8);
\r
511 packet_buf[5] = (u8)temp;
\r
512 packet_buf[6] = pbt_buf[ dw_lenth + i];
\r
513 bt_ecc ^= packet_buf[6];
\r
515 byte_write(&packet_buf[0],7);
\r
519 /********send the opration head************/
\r
520 cmd_write(0xcc,0x00,0x00,0x00,1);
\r
521 byte_read(reg_val,1);
\r
522 FTprintk("[TSP] Step 6: ecc read 0x%x, new firmware 0x%x. \n", reg_val[0], bt_ecc);
\r
523 if(reg_val[0] != bt_ecc)
\r
528 /*******Step 7: reset the new FW**********/
\r
529 cmd_write(0x07,0x00,0x00,0x00,1);
\r
530 mdelay(100);//100ms
\r
531 fts_register_read(0xfc, buffer, 1);
\r
532 if (buffer[0] == 1)
\r
535 fts_register_write(0xfc, &cmd);
\r
536 mdelay(2500);//2500ms
\r
539 fts_register_read(0xfc, buffer, 1);
\r
540 mdelay(100);//100ms
\r
541 }while (buffer[0] != 1);
\r
547 /***********************************************************************/
\r
549 int fts_ctpm_fw_upgrade_with_i_file(void)
\r
555 i_ret = fts_ctpm_fw_upgrade(pbt_buf,sizeof(CTPM_FW));
\r
560 /***********************************************************************/
\r
562 unsigned char fts_ctpm_get_upg_ver(void)
\r
564 unsigned int ui_sz;
\r
566 ui_sz = sizeof(CTPM_FW);
\r
569 return CTPM_FW[ui_sz - 2];
\r
576 /*read the it7260 register ,used i2c bus*/
\r
577 static int ft5306_read_regs(struct i2c_client *client, u8 reg, u8 *buf, unsigned len)
\r
580 ret = i2c_master_reg8_recv(client, reg, buf, len, FT5306_IIC_SPEED);
\r
584 /* set the it7260 registe,used i2c bus*/
\r
585 static int ft5306_set_regs(struct i2c_client *client, u8 reg, u8 *buf, unsigned short len)
\r
588 ret = i2c_master_reg8_send(client, reg, buf, (int)len, FT5306_IIC_SPEED);
\r
592 #if (FT5X0X_FW_UPGRADE_MODE == FT5X0X_FW_UPGRADE_ASYNC)
\r
593 static void ft5306_firmware_upgrade_work(struct work_struct *work)
\r
595 struct ft5x0x_ts_data *data = container_of(work, struct ft5x0x_ts_data, fw_upgrade_work);
\r
597 unsigned char reg_value;
\r
598 unsigned char reg_version;
\r
600 printk("<-- %s --> enter\n", __FUNCTION__);
\r
602 fts_register_read(FT5X0X_REG_FIRMID, ®_version,1);
\r
603 printk("cdy == [TSP] firmware version = 0x%2x\n", reg_version);
\r
605 fts_register_read(FT5X0X_REG_FIRMID, ®_version,1);
\r
606 FTprintk("[TSP] firmware version = 0x%2x\n", reg_version);
\r
607 if (fts_ctpm_get_upg_ver() != reg_version)
\r
609 FTprintk("[TSP] start upgrade new verison 0x%2x\n", fts_ctpm_get_upg_ver());
\r
611 err = fts_ctpm_fw_upgrade_with_i_file();
\r
614 FTprintk("[TSP] ugrade successfuly.\n");
\r
616 fts_register_read(FT5X0X_REG_FIRMID, ®_value,1);
\r
617 FTprintk("FTS_DBG from old version 0x%2x to new version = 0x%2x\n", reg_version, reg_value);
\r
621 FTprintk("[TSP] ugrade fail err=%d, line = %d.\n",err, __LINE__);
\r
625 cancel_work_sync(&data->fw_upgrade_work);
\r
626 destroy_workqueue(data->fw_workqueue);
\r
630 static void ft5306_queue_work(struct work_struct *work)
\r
632 struct ft5x0x_ts_data *data = container_of(work, struct ft5x0x_ts_data, pen_event_work);
\r
633 struct tp_event event;
\r
636 int ret,i,offset,points;
\r
637 static u8 points_last_flag[MAX_POINT]={0};
\r
638 struct tp_event current_events[MAX_POINT];
\r
640 #if CONFIG_FT5X0X_MULTITOUCH
\r
641 ret = ft5306_read_regs(data->client,start_reg, buf, 6*MAX_POINT+1);
\r
643 ret = ft5306_read_regs(data->client,start_reg, buf, 7);
\r
646 dev_err(&data->client->dev, "ft5306_read_regs fail:%d!\n",ret);
\r
647 enable_irq(data->irq);
\r
651 for (i=0; i<32; i++) {
\r
652 FTprintk("buf[%d] = 0x%x \n", i, buf[i]);
\r
656 points = buf[2] & 0x07;
\r
657 //dev_info(&data->client->dev, "ft5306_read_and_report_data points = %d\n",points);
\r
659 #if CONFIG_FT5X0X_MULTITOUCH
\r
660 //input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 0);
\r
661 //input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 0);
\r
663 for(i=0;i<MAX_POINT;i++)
\r
665 if(points_last_flag[i]!=0)
\r
667 FTprintk("Point UP event.id=%d\n",i);
\r
668 input_mt_slot(data->input_dev, i);
\r
669 input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, false);
\r
673 memset(points_last_flag, 0, sizeof(points_last_flag));
\r
674 //input_mt_sync(data->input_dev);
\r
676 input_report_abs(data->input_dev, ABS_PRESSURE, 0);
\r
677 input_report_key(data->input_dev, BTN_TOUCH, 0);
\r
679 input_sync(data->input_dev);
\r
680 enable_irq(data->irq);
\r
683 memset(&event, 0, sizeof(struct tp_event));
\r
684 #if CONFIG_FT5X0X_MULTITOUCH
\r
685 memset(current_events, 0, sizeof(current_events));
\r
687 for(i=0;i<points;i++){
\r
689 event.x = (((s16)(buf[offset+0] & 0x0F))<<8) | ((s16)buf[offset+1]);
\r
690 event.y = (((s16)(buf[offset+2] & 0x0F))<<8) | ((s16)buf[offset+3]);
\r
691 event.id = (s16)(buf[offset+2] & 0xF0)>>4;
\r
692 event.flag = ((buf[offset+0] & 0xc0) >> 6);
\r
693 event.pressure = 200;
\r
694 FTprintk("x=%d, y=%d event.id=%d event.flag=%d\n",event.x,event.y,event.id,event.flag);
\r
695 if(event.x<=SCREEN_MAX_X && event.y<=SCREEN_MAX_Y+60){
\r
696 //dev_info(&data->client->dev,
\r
697 // "ft5306 multiple report event[%d]:x = %d,y = %d,id = %d,flag = %d,pressure = %d\n",
\r
698 // i,event.x,event.y,event.id,event.flag,event.pressure);
\r
700 memcpy(¤t_events[event.id], &event, sizeof(event));
\r
701 //points_current[event.id] = event.flag;
\r
705 for(i=0;i<MAX_POINT;i++)
\r
707 if((current_events[i].flag == 0) && (points_last_flag[i] != 0))
\r
709 FTprintk("Point UP event.id=%d\n",i);
\r
710 input_mt_slot(data->input_dev, i);
\r
711 input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, false);
\r
713 else if(current_events[i].flag)
\r
715 FTprintk("Point DN event.id=%d\n",i);
\r
716 input_mt_slot(data->input_dev, i);
\r
717 input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, true);
\r
718 input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 1);
\r
719 //input_report_abs(data->input_dev, ABS_MT_PRESSURE, event.pressure);
\r
720 input_report_abs(data->input_dev, ABS_MT_POSITION_X, current_events[i].x);
\r
721 input_report_abs(data->input_dev, ABS_MT_POSITION_Y, current_events[i].y);
\r
723 points_last_flag[i] = current_events[i].flag;
\r
726 event.x = (s16)(buf[3] & 0x0F)<<8 | (s16)buf[4];
\r
727 event.y = (s16)(buf[5] & 0x0F)<<8 | (s16)buf[6];
\r
728 event.pressure =200;
\r
729 input_report_abs(data->input_dev, ABS_X, event.x);
\r
730 input_report_abs(data->input_dev, ABS_Y, event.y);
\r
731 //input_report_abs(data->input_dev, ABS_PRESSURE, event.pressure);
\r
732 input_report_key(data->input_dev, BTN_TOUCH, 1);
\r
735 //dev_info(&data->client->dev, "ft5306 single report event:x = %d,y = %d\n",event.x,event.y);
\r
737 //printk("ft5306 sync x = %d ,y = %d\n",event.x,event.y);
\r
738 input_sync(data->input_dev);
\r
739 enable_irq(data->irq);
\r
743 static irqreturn_t ft5306_interrupt(int irq, void *dev_id)
\r
745 struct ft5x0x_ts_data *ft5x0x_ts = dev_id;
\r
746 FTprintk("[TSP] ft5306_interrupt\n");
\r
747 disable_irq_nosync(ft5x0x_ts->irq);
\r
748 if (!work_pending(&ft5x0x_ts->pen_event_work))
\r
749 queue_work(ft5x0x_ts->ts_workqueue, &ft5x0x_ts->pen_event_work);
\r
750 return IRQ_HANDLED;
\r
752 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
754 static void ft5306_suspend(struct early_suspend *h)
\r
756 struct ft5x0x_ts_data *ft5x0x_ts;
\r
757 char buf_w[1] = {3};
\r
759 ft5x0x_ts = container_of(h, struct ft5x0x_ts_data, ft5306_early_suspend);
\r
760 FTprintk("TSP ft5306_suspend\n");
\r
761 err = ft5306_set_regs(this_client, 0xA5, buf_w, 1);
\r
763 printk("ft5306_set_regs OK!!\n");
\r
767 if (ft5x0x_ts->platform_sleep){
\r
768 ft5x0x_ts->platform_sleep();
\r
771 disable_irq(ft5x0x_ts->irq);
\r
775 static void ft5306_resume(struct early_suspend *h)
\r
777 struct ft5x0x_ts_data *ft5x0x_ts;
\r
780 ft5x0x_ts = container_of(h, struct ft5x0x_ts_data, ft5306_early_suspend);
\r
781 FTprintk("TSP ft5306_resume\n");
\r
782 enable_irq(ft5x0x_ts->irq);
\r
783 if (ft5x0x_ts->platform_wakeup)
\r
784 ft5x0x_ts->platform_wakeup();
\r
786 for(trytimes = 0 ;trytimes < 5; trytimes++){
\r
787 if(ft5306_read_regs(this_client, 0x00, &val,1)<0){
\r
788 if (ft5x0x_ts->platform_sleep)
\r
789 ft5x0x_ts->platform_sleep();
\r
790 if (ft5x0x_ts->platform_wakeup)
\r
791 ft5x0x_ts->platform_wakeup();
\r
797 //gpio_set_value(TOUCH_RESET_PIN,GPIO_LOW);
\r
799 //gpio_set_value(TOUCH_RESET_PIN,GPIO_HIGH);
\r
803 static int __devexit ft5306_remove(struct i2c_client *client)
\r
805 struct ft5x0x_ts_data *ft5x0x_ts = i2c_get_clientdata(client);
\r
807 free_irq(ft5x0x_ts->irq, ft5x0x_ts);
\r
808 input_unregister_device(ft5x0x_ts->input_dev);
\r
810 cancel_work_sync(&ft5x0x_ts->pen_event_work);
\r
811 destroy_workqueue(ft5x0x_ts->ts_workqueue);
\r
812 i2c_set_clientdata(client, NULL);
\r
813 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
814 unregister_early_suspend(&ft5x0x_ts->ft5306_early_suspend);
\r
816 this_client = NULL;
\r
820 static int ft5306_probe(struct i2c_client *client ,const struct i2c_device_id *id)
\r
822 struct ft5x0x_ts_data *ft5x0x_ts;
\r
823 struct input_dev *input_dev;
\r
824 struct ft5606_platform_data *pdata = client->dev.platform_data;
\r
830 u8 buf_test[1] = {0};
\r
831 unsigned char reg_value;
\r
832 unsigned char reg_version;
\r
834 dev_info(&client->dev, "ft5306_ts_probe!\n");
\r
836 dev_err(&client->dev, "platform data is required!\n");
\r
840 if (pdata->init_platform_hw)
\r
841 pdata->init_platform_hw();
\r
842 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)){
\r
843 dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n");
\r
847 ft5x0x_ts = kzalloc(sizeof(*ft5x0x_ts), GFP_KERNEL);
\r
848 ft5x0x_ts->platform_wakeup = pdata->platform_wakeup;
\r
849 ft5x0x_ts->platform_sleep = pdata->platform_sleep;
\r
856 ret = ft5306_set_regs(client,FT5X0X_REG_PMODE, buf_test, 1);
\r
861 printk("FT5306 I2C TEST FAILED, retry = %d, ret = %d, will again...\n", retry, ret);
\r
863 if (pdata->exit_platform_hw)
\r
864 pdata->exit_platform_hw();
\r
865 if (pdata->init_platform_hw)
\r
866 pdata->init_platform_hw();
\r
868 printk("FT5306 I2C TEST OK, retry = %d, ret = %d\n", retry, ret);
\r
872 printk("FT5306 I2C TEST ERROR! retry = %d, ret = %d\n", retry, ret);
\r
874 goto exit_i2c_test_fail;
\r
877 input_dev = input_allocate_device();
\r
880 printk("failed to allocate input device\n");
\r
881 goto exit_input_dev_alloc_failed;
\r
883 ft5x0x_ts->client = this_client = client;
\r
884 ft5x0x_ts->irq = client->irq;
\r
885 ft5x0x_ts->input_dev = input_dev;
\r
887 #if CONFIG_FT5X0X_MULTITOUCH
\r
888 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
\r
889 __set_bit(EV_ABS, input_dev->evbit);
\r
891 input_mt_init_slots(input_dev, MAX_POINT);
\r
892 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
\r
893 input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0);
\r
894 input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0);
\r
895 //input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, MAX_POINT, 0, 0);
\r
896 //input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
\r
899 set_bit(ABS_X, input_dev->absbit);
\r
900 set_bit(ABS_Y, input_dev->absbit);
\r
901 set_bit(ABS_PRESSURE, input_dev->absbit);
\r
902 set_bit(BTN_TOUCH, input_dev->keybit);
\r
903 input_set_abs_params(input_dev, ABS_X, 0, SCREEN_MAX_X, 0, 0);
\r
904 input_set_abs_params(input_dev, ABS_Y, 0, SCREEN_MAX_Y, 0, 0);
\r
905 //input_set_abs_params(input_dev, ABS_PRESSURE, 0, PRESS_MAX, 0 , 0);
\r
908 //input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
\r
909 //input_dev->keybit[BIT_WORD(BTN_START)] = BIT_MASK(BTN_START);
\r
910 //set_bit(EV_ABS, input_dev->evbit);
\r
911 //set_bit(EV_KEY, input_dev->evbit);
\r
913 input_dev->name = "ft5x0x_ts-touchscreen"; //dev_name(&client->dev)
\r
914 err = input_register_device(input_dev);
\r
916 printk("ft5306_ts_probe: failed to register input device: \n");
\r
917 goto exit_input_register_device_failed;
\r
920 if (!ft5x0x_ts->irq) {
\r
922 dev_err(&ft5x0x_ts->client->dev, "no IRQ?\n");
\r
923 goto exit_no_irq_fail;
\r
925 ft5x0x_ts->irq = gpio_to_irq(ft5x0x_ts->irq);
\r
928 INIT_WORK(&ft5x0x_ts->pen_event_work, ft5306_queue_work);
\r
929 ft5x0x_ts->ts_workqueue = create_singlethread_workqueue("ft5x0x_ts");
\r
930 if (!ft5x0x_ts->ts_workqueue) {
\r
932 goto exit_create_singlethread;
\r
935 /***wait CTP to bootup normally***/
\r
939 #if (FT5X0X_FW_UPGRADE_MODE == FT5X0X_FW_UPGRADE_ASYNC)
\r
940 /* zhengxing: will upgrade firmware async */
\r
941 printk("will create ft tp firmware upgrade workqueue...\n");
\r
942 ft5x0x_ts->fw_workqueue = create_singlethread_workqueue("ft5x0x_fw");
\r
943 if (!ft5x0x_ts->fw_workqueue) {
\r
945 goto exit_create_singlethread;
\r
947 INIT_WORK(&ft5x0x_ts->fw_upgrade_work, ft5306_firmware_upgrade_work);
\r
949 /* zhengxing: will upgrade firmware directly */
\r
950 fts_register_read(FT5X0X_REG_FIRMID, ®_version,1);
\r
951 printk("cdy == [TSP] firmware version = 0x%2x\n", reg_version);
\r
953 fts_register_read(FT5X0X_REG_FIRMID, ®_version,1);
\r
954 FTprintk("[TSP] firmware version = 0x%2x\n", reg_version);
\r
955 if (fts_ctpm_get_upg_ver() != reg_version)
\r
957 FTprintk("[TSP] start upgrade new verison 0x%2x\n", fts_ctpm_get_upg_ver());
\r
959 err = fts_ctpm_fw_upgrade_with_i_file();
\r
962 FTprintk("[TSP] ugrade successfuly.\n");
\r
964 fts_register_read(FT5X0X_REG_FIRMID, ®_value,1);
\r
965 FTprintk("FTS_DBG from old version 0x%2x to new version = 0x%2x\n", reg_version, reg_value);
\r
969 FTprintk("[TSP] ugrade fail err=%d, line = %d.\n",err, __LINE__);
\r
974 ret = request_irq(ft5x0x_ts->irq, ft5306_interrupt, IRQF_TRIGGER_FALLING, client->dev.driver->name, ft5x0x_ts);
\r
976 dev_err(&client->dev, "irq %d busy?\n", ft5x0x_ts->irq);
\r
977 goto exit_irq_request_fail;
\r
979 i2c_set_clientdata(client, ft5x0x_ts);
\r
980 #ifdef CONFIG_HAS_EARLYSUSPEND
\r
981 ft5x0x_ts->ft5306_early_suspend.suspend =ft5306_suspend;
\r
982 ft5x0x_ts->ft5306_early_suspend.resume =ft5306_resume;
\r
983 ft5x0x_ts->ft5306_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;;
\r
984 register_early_suspend(&ft5x0x_ts->ft5306_early_suspend);
\r
987 err = ft5306_set_regs(client,0x88,buf_w,1);
\r
989 err = ft5306_read_regs(client,0x88,buf_r,1);
\r
990 FTprintk("read buf[0x88] = %d\n", buf_r[0]);
\r
992 #if (FT5X0X_FW_UPGRADE_MODE == FT5X0X_FW_UPGRADE_ASYNC)
\r
993 queue_work(ft5x0x_ts->fw_workqueue, &ft5x0x_ts->fw_upgrade_work);
\r
998 i2c_set_clientdata(client, NULL);
\r
999 free_irq(ft5x0x_ts->irq,ft5x0x_ts);
\r
1000 exit_irq_request_fail:
\r
1001 cancel_work_sync(&ft5x0x_ts->pen_event_work);
\r
1002 destroy_workqueue(ft5x0x_ts->ts_workqueue);
\r
1003 exit_create_singlethread:
\r
1005 input_unregister_device(input_dev);
\r
1006 exit_input_register_device_failed:
\r
1007 input_free_device(input_dev);
\r
1008 exit_input_dev_alloc_failed:
\r
1009 exit_i2c_test_fail:
\r
1010 if (pdata->exit_platform_hw)
\r
1011 pdata->exit_platform_hw();
\r
1018 static struct i2c_device_id ft5306_idtable[] = {
\r
1019 { FT5X0X_NAME, 0 },
\r
1023 MODULE_DEVICE_TABLE(i2c, ft5306_idtable);
\r
1025 static struct i2c_driver ft5306_driver = {
\r
1027 .owner = THIS_MODULE,
\r
1028 .name = FT5X0X_NAME
\r
1030 .id_table = ft5306_idtable,
\r
1031 .probe = ft5306_probe,
\r
1032 //.suspend = ft5306_suspend,
\r
1033 //.resume = ft5306_resume,
\r
1034 .remove = __devexit_p(ft5306_remove),
\r
1037 static int __init ft5306_ts_init(void)
\r
1039 return i2c_add_driver(&ft5306_driver);
\r
1042 static void __exit ft5306_ts_exit(void)
\r
1044 FTprintk("Touchscreen driver of ft5306 exited.\n");
\r
1045 i2c_del_driver(&ft5306_driver);
\r
1049 /***********************************************************************/
\r
1051 module_init(ft5306_ts_init);
\r
1052 module_exit(ft5306_ts_exit);
\r
1054 MODULE_AUTHOR("<wenfs@Focaltech-systems.com>");
\r
1055 MODULE_DESCRIPTION("FocalTech ft5x0x TouchScreen driver");
\r