X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Finput%2Ftouchscreen%2Fgoodix_touch_82x.c;h=8012a3db48e5d9e25923df130630f6330cef202b;hb=7fe47454f2f8c73cd78c99ecef23e9d0ceca16dc;hp=a665c033ea7df3e76eadb941615d14ad7250e212;hpb=e3ee9c455c85d1edb1bd989f97835cebebc0308f;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/input/touchscreen/goodix_touch_82x.c b/drivers/input/touchscreen/goodix_touch_82x.c index a665c033ea7d..8012a3db48e5 100755 --- a/drivers/input/touchscreen/goodix_touch_82x.c +++ b/drivers/input/touchscreen/goodix_touch_82x.c @@ -5,8 +5,6 @@ * Author: Scott * Date: 2012.01.05 */ - - #include #include #include @@ -33,7 +31,6 @@ #define TRIGGER_LOC 66 //#typedef s32 int //w++ - struct goodix_ts_data { uint16_t addr; struct i2c_client *client; @@ -56,15 +53,9 @@ struct goodix_ts_data { int irq_is_disable; int interrupt_port; int reset_port; - }; struct goodix_ts_data *ts82x_temp; //w++ - - - - - static struct workqueue_struct *goodix_wq; static const char *goodix_ts_name ="Goodix TouchScreen of Guitar ";//"Goodix Capacitive TouchScreen"; @@ -87,10 +78,9 @@ static void guitar_reset( struct goodix_ts_data *ts,u8 ms); #endif static int err_gt82x = 0; //w++记载有没有此设备的检测 -//#define LONGPRESS_LOCK_SPECKEY //ÊÇ·ñʹÓ󀰎ijŒü(ÈçsearchŒü)Ëøס¹ŠÄÜŒüµÄ¹ŠÄÜ +//#define LONGPRESS_LOCK_SPECKEY #ifdef LONGPRESS_LOCK_SPECKEY #define KEY_LOCK KEY_F13 -//#define ORIGIN_KEY KEY_MENU #define LOCK_LONG_PRESS_CNT 20 static int Origin2LockPressCnt = 0; static int lockflag =0; @@ -105,13 +95,6 @@ struct timer_list longkey_timer_82x; #ifdef LONGPRESS_LOCK_SPECKEY static DRIVER_ATTR(get_lock_status, 0777, glock_status_show_gt82x, NULL); #endif -/* -struct goodix_i2c_rmi_platform_data { - uint32_t version; // Use this entry for panels with // - //reservation - -}; -*/ #if 0 #define TOUCH_MAX_HEIGHT 1024 //w++2 @@ -124,36 +107,20 @@ u16 TOUCH_MAX_WIDTH; #define GT828_I2C_RATE 200000 - -/******************************************************* -���ܣ� - ��ȡ�ӻ���� - ÿ��������������i2c_msg��ɣ���1����Ϣ���ڷ��ʹӻ��ַ�� - ��2�����ڷ��Ͷ�ȡ��ַ��ȡ����ݣ�ÿ����Ϣǰ������ʼ�ź� -���� - client: i2c�豸�����豸��ַ - buf[0]~buf[1]�� ���ֽ�Ϊ��ȡ��ַ - buf[2]~buf[len]����ݻ����� - len�� ��ȡ��ݳ��� -return�� - ִ����Ϣ�� -*********************************************************/ /*Function as i2c_master_send */ - static s32 i2c_read_bytes(struct i2c_client *client, u8 *buf, s32 len) { struct i2c_msg msgs[2]; s32 ret=-1; - //����д��ַ - msgs[0].flags=!I2C_M_RD; //д��Ϣ + msgs[0].flags=!I2C_M_RD; msgs[0].addr=client->addr; msgs[0].len=2; msgs[0].buf=&buf[0]; msgs[0].scl_rate=100000; msgs[0].udelay=2000; - //������� - msgs[1].flags=I2C_M_RD;//����Ϣ + + msgs[1].flags=I2C_M_RD; msgs[1].addr=client->addr; msgs[1].len=len - ADDR_LENGTH; msgs[1].buf=&buf[2]; @@ -165,26 +132,13 @@ static s32 i2c_read_bytes(struct i2c_client *client, u8 *buf, s32 len) return ret; } -/******************************************************* -���ܣ� - ��ӻ�д��� -���� - client: i2c�豸�����豸��ַ - buf[0]~buf[1]�� ���ֽ�Ϊд��ַ - buf[2]~buf[len]����ݻ����� - len�� ��ݳ��� -return�� - ִ����Ϣ�� -*******************************************************/ /*Function as i2c_master_send */ - static s32 i2c_write_bytes(struct i2c_client *client,u8 *data,s32 len) { struct i2c_msg msg; s32 ret=-1; - //�����豸��ַ - msg.flags=!I2C_M_RD;//д��Ϣ + msg.flags=!I2C_M_RD; msg.addr=client->addr; msg.len=len; msg.buf=data; @@ -195,14 +149,6 @@ static s32 i2c_write_bytes(struct i2c_client *client,u8 *data,s32 len) return ret; } -/******************************************************* -���ܣ� - ����ǰ׺���� - - ts: client˽����ݽṹ�� -return�� - �ɹ�����1 -*******************************************************/ static s32 i2c_pre_cmd(struct goodix_ts_data *ts) { s32 ret; @@ -212,14 +158,6 @@ static s32 i2c_pre_cmd(struct goodix_ts_data *ts) return ret;//*/ } -/******************************************************* -���ܣ� - ���ͺ�׺���� - - ts: client˽����ݽṹ�� -return�� - �ɹ�����1 -*******************************************************/ static s32 i2c_end_cmd(struct goodix_ts_data *ts) { s32 ret; @@ -229,58 +167,80 @@ static s32 i2c_end_cmd(struct goodix_ts_data *ts) return ret;//*/ } -/******************************************************* -���ܣ� - Guitar��ʼ���������ڷ���������Ϣ����ȡ�汾��Ϣ -���� - ts: client˽����ݽṹ�� -return�� - ִ�н���룬0��ʾ��ִ�� -*******************************************************/ + s32 goodix_init_panel(struct goodix_ts_data *ts, u8 send) { s32 ret = -1; u8 config_info[]= { - 0x0F,0x80,/*config address*/ + 0x0F,0x80,/*config address*/ #if 1 -// 300-N3216E-A00 -//0x02,0x11,0x03,0x12,0x04,0x13,0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x11,0x07,0x10,0x06,0x0F,0x05,0x0E,0x04,0x0D,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x03,0xE0,0x10,0x10,0x21,0x00,0x00,0x09,0x00,0x00,0x02,0x45,0x2D,0x1C,0x03,0x00,0x05,0x00,0x02,0x58,0x03,0x20,0x25,0x29,0x27,0x2B,0x25,0x00,0x06,0x19,0x25,0x14,0x10,0x00,0x13,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 +// 300-N3216E-A00 +/* + 0x02,0x11,0x03,0x12,0x04,0x13,0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x11,0x07,0x10,0x06,0x0F,0x05,0x0E,0x04,0x0D,0x03,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x03,0xE0,0x10,0x10,0x21,0x00,0x00,0x09,0x00, + 0x00,0x02,0x45,0x2D,0x1C,0x03,0x00,0x05,0x00,0x02,0x58,0x03,0x20,0x25,0x29, + 0x27,0x2B,0x25,0x00,0x06,0x19,0x25,0x14,0x10,0x00,0x13,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01 +*/ //300-N3788E-A00-V1.0 1024*768 -//0x02,0x11,0x03,0x12,0x04,0x13,0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09,0x18,0x0A,0x19,0xFF,0x13,0xFF,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x12,0x08,0x11,0x07,0x10,0x06,0x0F,0x05,0x0E,0x04,0x0D,0x03,0xFF,0x00,0xFF,0x0E,0x0F,0x10,0x11,0x12,0x09,0x03,0x88,0x88,0x88,0x25,0x00,0x00,0x08,0x00,0x00,0x02,0x3C,0x28,0x1C,0x03,0x00,0x05,0x00,0x02,0x58,0x03,0x20,0x33,0x38,0x30,0x35,0x25,0x00,0x25,0x19,0x05,0x14,0x10,0x02,0x30,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 -0x02,0x11,0x03,0x12,0x04,0x13,0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09,0x18,0x0A,0x19,0x0B,0x1A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x12,0x08,0x11,0x07,0x10,0x06,0x0F,0x05,0x0E,0x04,0x0D,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x03,0xE0,0x10,0x10,0x19,0x00,0x00,0x08,0x00,0x00,0x02,0x45,0x2D,0x1C,0x03,0x00,0x05,0x00,0x02,0x58,0x03,0x20,0x2D,0x38,0x2F,0x3B,0x25,0x00,0x06,0x19,0x25,0x14,0x10,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 +/* + 0x02,0x11,0x03,0x12,0x04,0x13,0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09, + 0x18,0x0A,0x19,0xFF,0x13,0xFF,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C, + 0x12,0x08,0x11,0x07,0x10,0x06,0x0F,0x05,0x0E,0x04,0x0D,0x03,0xFF,0x00,0xFF, + 0x0E,0x0F,0x10,0x11,0x12,0x09,0x03,0x88,0x88,0x88,0x25,0x00,0x00,0x08,0x00, + 0x00,0x02,0x3C,0x28,0x1C,0x03,0x00,0x05,0x00,0x02,0x58,0x03,0x20,0x33,0x38, + 0x30,0x35,0x25,0x00,0x25,0x19,0x05,0x14,0x10,0x02,0x30,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01 +*/ + 0x02,0x11,0x03,0x12,0x04,0x13,0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09, + 0x18,0x0A,0x19,0x0B,0x1A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x12,0x08,0x11,0x07,0x10,0x06,0x0F,0x05,0x0E,0x04,0x0D,0x03,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x03,0xE0,0x10,0x10,0x19,0x00,0x00,0x08,0x00, + 0x00,0x02,0x45,0x2D,0x1C,0x03,0x00,0x05,0x00,0x02,0x58,0x03,0x20,0x2D,0x38, + 0x2F,0x3B,0x25,0x00,0x06,0x19,0x25,0x14,0x10,0x00,0x01,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01 #else -0x02,0x11,0x03,0x12,0x04,0x13,0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09,0x18,0x0A,0x19,0x0B,0x1A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x12,0x08,0x11,0x07,0x10,0x06,0x0F,0x05,0x0E,0x04,0x0D,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x03,0xE0,0x10,0x10,0x19,0x00,0x00,0x08,0x00,0x00,0x02,0x45,0x2D,0x1C,0x03,0x00,0x05,0x00,0x02,0x58,0x03,0x20,0x2D,0x38,0x2F,0x3B,0x25,0x00,0x06,0x19,0x25,0x14,0x10,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 + 0x02,0x11,0x03,0x12,0x04,0x13,0x05,0x14,0x06,0x15,0x07,0x16,0x08,0x17,0x09, + 0x18,0x0A,0x19,0x0B,0x1A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x12,0x08,0x11,0x07,0x10,0x06,0x0F,0x05,0x0E,0x04,0x0D,0x03,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x03,0xE0,0x10,0x10,0x19,0x00,0x00,0x08,0x00, + 0x00,0x02,0x45,0x2D,0x1C,0x03,0x00,0x05,0x00,0x02,0x58,0x03,0x20,0x2D,0x38, + 0x2F,0x3B,0x25,0x00,0x06,0x19,0x25,0x14,0x10,0x00,0x01,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01 #endif }; #ifdef AUTO_SET - TOUCH_MAX_WIDTH = ((config_info[RESOLUTION_LOC] << 8)|config_info[RESOLUTION_LOC + 1]); - TOUCH_MAX_HEIGHT = ((config_info[RESOLUTION_LOC + 2] << 8)|config_info[RESOLUTION_LOC + 3]); - - GTDEBUG_MSG("TOUCH_MAX_WIDTH : 0x%d\n", (s32)TOUCH_MAX_WIDTH); - GTDEBUG_MSG("TOUCH_MAX_HEIGHT : 0x%d\n", (s32)TOUCH_MAX_HEIGHT); + TOUCH_MAX_WIDTH = ((config_info[RESOLUTION_LOC] << 8)|config_info[RESOLUTION_LOC + 1]); + TOUCH_MAX_HEIGHT = ((config_info[RESOLUTION_LOC + 2] << 8)|config_info[RESOLUTION_LOC + 3]); + + GTDEBUG_MSG("TOUCH_MAX_WIDTH : 0x%d\n", (s32)TOUCH_MAX_WIDTH); + GTDEBUG_MSG("TOUCH_MAX_HEIGHT : 0x%d\n", (s32)TOUCH_MAX_HEIGHT); #else -/* config_info[RESOLUTION_LOC] = TOUCH_MAX_WIDTH >> 8; - config_info[RESOLUTION_LOC + 1] = TOUCH_MAX_WIDTH & 0xff; - config_info[RESOLUTION_LOC + 2] = TOUCH_MAX_HEIGHT >> 8; - config_info[RESOLUTION_LOC + 3] = TOUCH_MAX_HEIGHT & 0xff;*/ +/* + config_info[RESOLUTION_LOC] = TOUCH_MAX_WIDTH >> 8; + config_info[RESOLUTION_LOC + 1] = TOUCH_MAX_WIDTH & 0xff; + config_info[RESOLUTION_LOC + 2] = TOUCH_MAX_HEIGHT >> 8; + config_info[RESOLUTION_LOC + 3] = TOUCH_MAX_HEIGHT & 0xff; +*/ #endif - if (INT_TRIGGER == GT_IRQ_FALLING) - { + if (INT_TRIGGER == GT_IRQ_FALLING) { config_info[TRIGGER_LOC] &= 0xf7; - } - else if (INT_TRIGGER == GT_IRQ_RISING) - { + } else if (INT_TRIGGER == GT_IRQ_RISING) { config_info[TRIGGER_LOC] |= 0x08; } - if (send) - { + if (send) { ret=i2c_write_bytes(ts->client,config_info, (sizeof(config_info)/sizeof(config_info[0]))); - if (ret <= 0) - { + if (ret <= 0) { return fail; } i2c_end_cmd(ts); @@ -293,10 +253,8 @@ static s32 touch_num(u8 value, s32 max) { s32 tmp = 0; - while((tmp < max) && value) - { - if ((value & 0x01) == 1) - { + while((tmp < max) && value) { + if ((value & 0x01) == 1) { tmp++; } value = value >> 1; @@ -305,31 +263,21 @@ static s32 touch_num(u8 value, s32 max) return tmp; } -/******************************************************* -���ܣ� - �������������� - ���жϴ���������1�������ݣ�У����ٷ������ -���� - ts: client˽����ݽṹ�� -return�� - void -********************************************************/ #ifdef LONGPRESS_LOCK_SPECKEY //w++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ static void open_longkey_timer_82x(unsigned long data) { - if((++Origin2LockPressCnt>LOCK_LONG_PRESS_CNT)&&(Origin2LockPressCntinput_dev, KEY_LOCK, 1); - lockflag = (lockflag)? 0 : 1; - input_sync(ts82x_temp->input_dev); - //} - } - longkey_timer_82x.expires=jiffies+msecs_to_jiffies(100); - add_timer(&longkey_timer_82x); - printk("w++++++++ Origin2LockPressCnt = %d\n",Origin2LockPressCnt); - printk("lockflag = %d\n",lockflag); + if((++Origin2LockPressCnt>LOCK_LONG_PRESS_CNT)&&(Origin2LockPressCntinput_dev, KEY_LOCK, 1); + lockflag = (lockflag)? 0 : 1; + input_sync(ts82x_temp->input_dev); + //} + } + longkey_timer_82x.expires=jiffies+msecs_to_jiffies(100); + add_timer(&longkey_timer_82x); + printk("w++++++++ Origin2LockPressCnt = %d\n",Origin2LockPressCnt); + printk("lockflag = %d\n",lockflag); } #endif @@ -349,8 +297,8 @@ static void goodix_ts_work_func(struct work_struct *work) s32 i; u8 *coor_point; u8 touch_data[2 + 2 + 5*MAX_FINGER_NUM + 1] = {READ_TOUCH_ADDR_H,READ_TOUCH_ADDR_L,0, 0}; - static u8 finger_last[MAX_FINGER_NUM]={0}; //�ϴδ����������ָ���� - u8 finger_current[MAX_FINGER_NUM] = {0}; //��ǰ�����������ָ���� + static u8 finger_last[MAX_FINGER_NUM]={0}; + u8 finger_current[MAX_FINGER_NUM] = {0}; struct goodix_ts_data *ts = container_of(work, struct goodix_ts_data, work); struct i2c_client *client = ts->client; @@ -359,17 +307,14 @@ static void goodix_ts_work_func(struct work_struct *work) #ifndef INT_PORT COORDINATE_POLL: #endif - if( tmp > 9) - { + if( tmp > 9) { dev_info(&(ts->client->dev), "Because of transfer error,touchscreen stop working.\n"); goto XFER_ERROR ; } - //���齫���һ���Զ�ȡ�� ret=i2c_read_bytes(ts->client, touch_data,sizeof(touch_data)/sizeof(touch_data[0])); i2c_end_cmd(ts); - if(ret <= 0) - { + if(ret <= 0) { dev_err(&(ts->client->dev),"I2C transfer error. Number:%d\n ", ret); ts->bad_data = 1; tmp ++; @@ -380,141 +325,109 @@ COORDINATE_POLL: #endif } - if(ts->bad_data) - { + if(ts->bad_data) { //TODO:Is sending config once again (to reset the chip) useful? ts->bad_data = 0; msleep(20); } - if((touch_data[2]&0xC0)!=0x80) - { + if((touch_data[2]&0xC0)!=0x80) { goto DATA_NO_READY; } key = touch_data[3]&0x0f; // 1, 2, 4, 8 - if (key == 0x0f) - { - if (fail == goodix_init_panel(ts, 1)) - { -/**/ GTDEBUG_COOR("Reload config failed!\n"); - } - else - { - GTDEBUG_COOR("Reload config successfully!\n"); + if (key == 0x0f) { + if (fail == goodix_init_panel(ts, 1)) { + GTDEBUG_COOR("Reload config failed!\n"); + } else { + GTDEBUG_COOR("Reload config successfully!\n"); } goto XFER_ERROR; } finger = (u8)touch_num(touch_data[2]&0x1f, MAX_FINGER_NUM); -/**/GTDEBUG_COOR("touch num:%x\n", finger); + GTDEBUG_COOR("touch num:%x\n", finger); - for (i = 0;i < MAX_FINGER_NUM; i++) - { + for (i = 0;i < MAX_FINGER_NUM; i++) { finger_current[i] = !!(touch_data[2] & (0x01<<(i))); } - - //����У��� coor_point = &touch_data[4]; chk_sum = 0; - for ( i = 0; i < 5*finger; i++) - { + for ( i = 0; i < 5*finger; i++) { chk_sum += coor_point[i]; -/**/ // GTDEBUG_COOR("%5x", coor_point[i]); + //GTDEBUG_COOR("%5x", coor_point[i]); } -/**///GTDEBUG_COOR("\ncheck sum:%x\n", chk_sum); -/**///GTDEBUG_COOR("check sum byte:%x\n", coor_point[5*finger]); - if (chk_sum != coor_point[5*finger]) - { + //GTDEBUG_COOR("\ncheck sum:%x\n", chk_sum); + //GTDEBUG_COOR("check sum byte:%x\n", coor_point[5*finger]); + if (chk_sum != coor_point[5*finger]) { goto XFER_ERROR; } - //�������// - if (finger) - { - for(i = 0, position=0;position < MAX_FINGER_NUM; position++) - { - if(finger_current[position]) - { - X_value = (coor_point[i] << 8) | coor_point[i + 1]; - Y_value = (coor_point[i + 2] << 8) | coor_point[i + 3]; - - input_mt_slot(ts->input_dev, position); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, FLAG_DOWN); + if (finger) { + for(i = 0, position=0;position < MAX_FINGER_NUM; position++) { + if(finger_current[position]) { + X_value = (coor_point[i] << 8) | coor_point[i + 1]; + Y_value = (coor_point[i + 2] << 8) | coor_point[i + 3]; - // input_report_key(ts->input_dev, BTN_TOUCH, 1); - // input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, position - 1); - if(pdata->swap_xy){ + input_mt_slot(ts->input_dev, position); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, FLAG_DOWN); + + //input_report_key(ts->input_dev, BTN_TOUCH, 1); + //input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, position - 1); + if(pdata->swap_xy) { value_tmp = X_value; X_value = Y_value; Y_value = value_tmp; } //printk("goodix_touch_82x X_value=%d,Y_value=%d\n",X_value,Y_value); - if(pdata->xpol) + if(pdata->xpol) X_value = pdata->xmax - X_value; if(pdata->ypol) Y_value = pdata->ymax - Y_value; - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, X_value); //can change x-y!!! - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, Y_value); - // input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,15); - // input_mt_sync(ts->input_dev); - i += 5; - - // /**/ GTDEBUG_COOR("FI:%x X:%04d Y:%04d\n",position, (s32)Y_value,(s32)X_value); -// printk("-----------touch_num:%d;--------FI:%x----------- X:%04d ----------Y:%04d\n",finger,position, (s32)X_value,(s32)Y_value); - /**/ // GTDEBUG_COOR("Y:%d\n", (s32)Y_value); - } - else if(finger_last[position]) - { - input_mt_slot(ts->input_dev, position); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); - GTDEBUG_COOR(" Finger %d release!!\n",position); - } - } - } - else - { - for(position=0;position < MAX_FINGER_NUM; position++) - { - if( finger_last[position]) - { - input_mt_slot(ts->input_dev, position); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); - GTDEBUG_COOR(" Finger %d release!!\n",position); - } - } - } + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, X_value); //can change x-y!!! + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, 600-Y_value); + //input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,15); + //input_mt_sync(ts->input_dev); + i += 5; + + //GTDEBUG_COOR("FI:%x X:%04d Y:%04d\n",position, (s32)Y_value,(s32)X_value); + //printk("-----------touch_num:%d;--------FI:%x----------- X:%04d ----------Y:%04d\n",finger,position, (s32)X_value,(s32)Y_value); + //GTDEBUG_COOR("Y:%d\n", (s32)Y_value); + } else if(finger_last[position]) { + input_mt_slot(ts->input_dev, position); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); + GTDEBUG_COOR(" Finger %d release!!\n",position); + } + } + } else { + for(position=0;position < MAX_FINGER_NUM; position++) { + if( finger_last[position]) { + input_mt_slot(ts->input_dev, position); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); + GTDEBUG_COOR(" Finger %d release!!\n",position); + } + } + } input_sync(ts->input_dev); - for(position=0;positionuse_irq && ts->irq_is_disable == 1) - { - ts->irq_is_disable = 0; - enable_irq(ts->client->irq); - } + if(ts->use_irq && ts->irq_is_disable == 1) { + ts->irq_is_disable = 0; + enable_irq(ts->client->irq); + } } -/******************************************************* -���ܣ� - ��ʱ����Ӧ���� - �ɼ�ʱ�����������ȴ����������������У�֮�����¼�ʱ -���� - timer����������ļ�ʱ�� -return�� - ��ʱ������ģʽ��HRTIMER_NORESTART��ʾ����Ҫ�Զ����� -********************************************************/ static enum hrtimer_restart goodix_ts_timer_func(struct hrtimer *timer) { struct goodix_ts_data *ts = container_of(timer, struct goodix_ts_data, timer); @@ -525,43 +438,24 @@ static enum hrtimer_restart goodix_ts_timer_func(struct hrtimer *timer) return HRTIMER_NORESTART; } -/******************************************************* -���ܣ� - �ж���Ӧ���� - ���жϴ��������ȴ��������?������ -���� -return�� - IRQ_HANDLED:interrupt was handled by this device -********************************************************/ static irqreturn_t goodix_ts_irq_handler(s32 irq, void *dev_id) { - struct goodix_ts_data *ts = (struct goodix_ts_data*)dev_id; + struct goodix_ts_data *ts = (struct goodix_ts_data*)dev_id; - if (ts->use_irq && (!ts->irq_is_disable)) - { - disable_irq_nosync(ts->client->irq); - ts->irq_is_disable = 1; - } - - queue_work(goodix_wq, &ts->work); - - return IRQ_HANDLED; + if (ts->use_irq && (!ts->irq_is_disable)) { + disable_irq_nosync(ts->client->irq); + ts->irq_is_disable = 1; + } + + queue_work(goodix_wq, &ts->work); + + return IRQ_HANDLED; } -/******************************************************* -���ܣ� - �����Դ������IC����˯�߻��份�� -���� - on: 0��ʾʹ��˯�ߣ�1Ϊ���� -return�� - �Ƿ����óɹ���successΪ�ɹ� - �����룺-1Ϊi2c����-2ΪGPIO����-EINVALΪ����on���� -********************************************************/ //#if defined(INT_PORT) // 0 : sleep 1 wake up static s32 goodix_ts_power(struct goodix_ts_data * ts, s32 on) { s32 ret = -1; - u8 i2c_control_buf[3] = {0x0f,0xf2,0xc0}; //suspend cmd if(ts == NULL || !ts->use_irq) @@ -579,7 +473,6 @@ static s32 goodix_ts_power(struct goodix_ts_data * ts, s32 on) GPIO_SET_VALUE(ts->interrupt_port, 1); GPIO_DIRECTION_INPUT(ts->interrupt_port); GPIO_PULL_UPDOWN(ts->interrupt_port, 0); - return success; default: @@ -601,11 +494,10 @@ static s32 init_input_dev(struct goodix_ts_data *ts) return fail; } -// ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); -// ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - // ts->input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);// absolute coor (x,y) - - + //ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + //ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + //ts->input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);// absolute coor (x,y) + goodix_init_panel(ts, 0); #ifdef GOODIX_MULTI_TOUCH @@ -617,12 +509,13 @@ static s32 init_input_dev(struct goodix_ts_data *ts) input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, TOUCH_MAX_HEIGHT, 0, 0); input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, TOUCH_MAX_WIDTH, 0, 0); - /* input_mt_init_slots(ts->input_dev, MAX_FINGER_NUM); - input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, TOUCH_MAX_HEIGHT, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, TOUCH_MAX_WIDTH, 0, 0); - */ + /* + input_mt_init_slots(ts->input_dev, MAX_FINGER_NUM); + input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, TOUCH_MAX_HEIGHT, 0, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, TOUCH_MAX_WIDTH, 0, 0); + */ #else input_set_abs_params(ts->input_dev, ABS_X, 0, TOUCH_MAX_HEIGHT, 0, 0); input_set_abs_params(ts->input_dev, ABS_Y, 0, TOUCH_MAX_WIDTH, 0, 0); @@ -641,8 +534,7 @@ static s32 init_input_dev(struct goodix_ts_data *ts) set_bit(KEY_LOCK, ts->input_dev->keybit); #endif ret = input_register_device(ts->input_dev); - if (ret) - { + if (ret) { dev_err(&ts->client->dev,"Probe: Unable to register %s input device\n", ts->input_dev->name); input_free_device(ts->input_dev); return fail; @@ -656,46 +548,37 @@ static s32 set_pins(struct goodix_ts_data *ts) { s32 ret = -1; - // ts->client->irq=TS_INT; //If not defined in client - if (ts->client->irq) - { - ret = GPIO_REQUEST(ts->interrupt_port, "TS_INT"); //Request IO - if (ret < 0) - { - dev_err(&ts->client->dev, "Failed to request GPIO:%d, ERRNO:%d\n",(s32)ts->interrupt_port,ret); - goto err_gpio_request_failed; - } - GTDEBUG_MSG("Request int port successfully!\n"); - - GPIO_DIRECTION_INPUT(ts->interrupt_port); - GPIO_PULL_UPDOWN(ts->interrupt_port, 0); -// GPIO_CFG_PIN(INT_PORT, INT_CFG); //Set IO port function - - -ret = request_irq(gpio_to_irq(ts->interrupt_port), goodix_ts_irq_handler, + //ts->client->irq=TS_INT; //If not defined in client + if (ts->client->irq) { + ret = GPIO_REQUEST(ts->interrupt_port, "TS_INT"); //Request IO + if (ret < 0) { + dev_err(&ts->client->dev, "Failed to request GPIO:%d, ERRNO:%d\n",(s32)ts->interrupt_port,ret); + goto err_gpio_request_failed; + } + GTDEBUG_MSG("Request int port successfully!\n"); + + GPIO_DIRECTION_INPUT(ts->interrupt_port); + GPIO_PULL_UPDOWN(ts->interrupt_port, 0); + //GPIO_CFG_PIN(INT_PORT, INT_CFG); //Set IO port function + + ret = request_irq(gpio_to_irq(ts->interrupt_port), goodix_ts_irq_handler, IRQF_TRIGGER_FALLING, ts->client->name, ts); - // ret = request_irq(ts->client->irq, goodix_ts_irq_handler, INT_TRIGGER, ts->client->name, ts); - - if (ret != 0) - { - dev_err(&ts->client->dev,"Cannot allocate ts INT!ERRNO:%d\n", ret); - GPIO_DIRECTION_INPUT(ts->interrupt_port); - GPIO_FREE(ts->interrupt_port); - goto err_gpio_request_failed; - } - else - { - disable_irq(ts->client->irq); - ts->use_irq = 1; - ts->irq_is_disable = 1; - dev_dbg(&ts->client->dev, "Reques EIRQ %d successed on GPIO:%d\n", gpio_to_irq(ts->interrupt_port), ts->interrupt_port); - } - } + if (ret != 0) { + dev_err(&ts->client->dev,"Cannot allocate ts INT!ERRNO:%d\n", ret); + GPIO_DIRECTION_INPUT(ts->interrupt_port); + GPIO_FREE(ts->interrupt_port); + goto err_gpio_request_failed; + } else { + disable_irq(ts->client->irq); + ts->use_irq = 1; + ts->irq_is_disable = 1; + dev_dbg(&ts->client->dev, "Reques EIRQ %d successed on GPIO:%d\n", gpio_to_irq(ts->interrupt_port), ts->interrupt_port); + } + } err_gpio_request_failed: - if (!ts->use_irq) - { + if (!ts->use_irq) { hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ts->timer.function = goodix_ts_timer_func; hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); @@ -703,16 +586,13 @@ err_gpio_request_failed: } ret = GPIO_REQUEST(ts->reset_port, "TS_RESET"); //Request IO - if (ret < 0) - { + if (ret < 0) { dev_err(&ts->client->dev, "Failed to request GPIO:%d, ERRNO:%d\n",(s32)ts->reset_port,ret); - } - else - { + } else { ts->use_reset = 1; GPIO_DIRECTION_OUTPUT(ts->reset_port,1); GPIO_PULL_UPDOWN(ts->reset_port, 0); - GTDEBUG_MSG("Request reset port successfully!\n"); + GTDEBUG_MSG("Request reset port successfully!\n"); } dev_info(&ts->client->dev,"Start %s in %s mode\n", @@ -721,49 +601,31 @@ err_gpio_request_failed: return ts->use_irq; } -/******************************************************* -���ܣ� - ������̽�⺯�� - ��ע����ʱ����(Ҫ����ڶ�Ӧ��client)�� - ����IO,�жϵ���Դ���룻�豸ע�᣻��������ʼ���ȹ��� -���� - client��������豸�ṹ�� - id���豸ID -return�� - ִ�н���룬0��ʾ��ִ�� -********************************************************/ static s32 goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { s32 ret = 0; s32 retry=0; struct goodix_ts_data *ts = NULL; struct goodix_i2c_rmi_platform_data *pdata = client->dev.platform_data; - //struct ft5406_platform_data *pdata = pdata = client->dev.platform_data; + //struct ft5406_platform_data *pdata = pdata = client->dev.platform_data; printk("w++++++goodix_ts_probe gt28x "); - if (pdata->init_platform_hw) - { + if (pdata->init_platform_hw) { pdata->init_platform_hw(); } -// GTDEBUG("Start to install Goodix Capacitive TouchScreen driver.\n"); -// GTDEBUG("*DRIVER INFORMATION\n"); -// GTDEBUG("**RELEASE DATE:%s.\n", RELEASE_DATE); -// GTDEBUG("**COMPILE TIME:%s, %s.\n", __DATE__, __TIME__); -// printk("gt82x---0000000000000000\n"); + //printk("gt82x---0000000000000000\n"); //Check I2C function - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) - { + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n"); return -ENODEV; } ts = kzalloc(sizeof(*ts), GFP_KERNEL); - if (ts == NULL) - { + if (ts == NULL) { return -ENOMEM; } - pdata = client->dev.platform_data; + pdata = client->dev.platform_data; INIT_WORK(&ts->work, goodix_ts_work_func); //init work_struct ts->client = client; @@ -776,8 +638,8 @@ static s32 goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id ts->reset_port=pdata->gpio_reset; i2c_set_clientdata(client, ts); - if (fail == init_input_dev(ts)) - { kfree(ts); + if (fail == init_input_dev(ts)) { + kfree(ts); return -1; } set_pins(ts); @@ -791,8 +653,7 @@ static s32 goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id init_wr_node(client); #endif #ifdef AUTO_UPDATE_GUITAR - if (0xff == init_update_proc(ts)) - { + if (0xff == init_update_proc(ts)) { GTDEBUG_MSG("Need update!\n"); return 0; } @@ -802,42 +663,35 @@ static s32 goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id #endif //Test I2C connection. -// GTDEBUG_MSG("GT82X++++++ Testing I2C connection...\n"); - for(retry = 0;retry < 3; retry++) - while(1) //For GTDEBUG use! - { - ret = i2c_pre_cmd(ts); - if (ret > 0) - break; - msleep(20); - } - if(ret <= 0) - { - dev_err(&client->dev, "Warnning: I2C communication might be ERROR!\n"); - GTDEBUG_MSG("I2C test failed. I2C addr:%x\n", client->addr); - goodix_ts_remove(ts->client); kfree(ts); - return -1; - } -// printk("gt82x---777777777777777\n"); - //Send config - for (retry = 0; retry < 3; retry++) - { - if (success == goodix_init_panel(ts, 1)) - { - GTDEBUG_MSG("Initialize successfully!\n"); - break; - } - } - if (retry >= 3) - { + //GTDEBUG_MSG("GT82X++++++ Testing I2C connection...\n"); + for(retry = 0;retry < 3; retry++) { + ret = i2c_pre_cmd(ts); + if (ret > 0) + break; + msleep(20); + } + if(ret <= 0) { + dev_err(&client->dev, "Warnning: I2C communication might be ERROR!\n"); + GTDEBUG_MSG("I2C test failed. I2C addr:%x\n", client->addr); + goodix_ts_remove(ts->client); + return -1; + } + //printk("gt82x---777777777777777\n"); + //Send config + for (retry = 0; retry < 3; retry++) { + if (success == goodix_init_panel(ts, 1)) { + GTDEBUG_MSG("Initialize successfully!\n"); + break; + } + } + if (retry >= 3) { ts->bad_data=1; GTDEBUG_MSG("Initialize failed!\n"); - goodix_ts_remove(ts->client); kfree(ts); + goodix_ts_remove(ts->client); return -1; } //Enable interrupt - if(ts->use_irq && ts->irq_is_disable == 1) - { + if(ts->use_irq && ts->irq_is_disable == 1) { ts->irq_is_disable = 0; enable_irq(client->irq); } @@ -845,15 +699,6 @@ static s32 goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id return 0; } - -/******************************************************* -���ܣ� - ����Դ�ͷ� -���� - client���豸�ṹ�� -return�� - ִ�н���룬success��ʾ��ִ�� -********************************************************/ static s32 goodix_ts_remove(struct i2c_client *client) { struct goodix_ts_data *ts = i2c_get_clientdata(client); @@ -868,17 +713,15 @@ static s32 goodix_ts_remove(struct i2c_client *client) uninit_wr_node(); #endif - if (ts && ts->use_irq) - { + if (ts && ts->use_irq) { free_irq(client->irq, ts); GPIO_DIRECTION_INPUT(ts->interrupt_port); GPIO_FREE(ts->interrupt_port); - } - else if(ts) + } else if(ts) { hrtimer_cancel(&ts->timer); + } - if (ts && ts->use_reset) - { + if (ts && ts->use_reset) { GPIO_DIRECTION_INPUT(ts->reset_port); GPIO_FREE(ts->interrupt_port); } @@ -890,37 +733,30 @@ static s32 goodix_ts_remove(struct i2c_client *client) return success; } -//ͣ���豸 static s32 goodix_ts_suspend(struct i2c_client *client, pm_message_t mesg) { s32 ret; struct goodix_ts_data *ts = i2c_get_clientdata(client); - if (ts->irq_is_disable == 2) - { + if (ts->irq_is_disable == 2) { return 0; } - if (ts->use_irq) - { - if (!ts->irq_is_disable) - { + if (ts->use_irq) { + if (!ts->irq_is_disable) { disable_irq(client->irq); ts->irq_is_disable = 1; } - } - else - { + } else { hrtimer_cancel(&ts->timer); } - if (ts->power) - { + if (ts->power) { ret = ts->power(ts, 0); if (ret <= 0) GTDEBUG_MSG(KERN_ERR "goodix_ts_resume power off failed\n"); - } - printk("-----gt813------suspend.\n"); + } + printk("-----gt813------suspend.\n"); return 0; } @@ -929,28 +765,23 @@ static s32 goodix_ts_resume(struct i2c_client *client) s32 ret; struct goodix_ts_data *ts = i2c_get_clientdata(client); - if (ts->irq_is_disable == 2) - { + if (ts->irq_is_disable == 2) { return 0; } - if (ts->power) - { + if (ts->power) { ret = ts->power(ts, 1); if (ret <= 0) GTDEBUG_MSG(KERN_ERR "goodix_ts_resume power on failed\n"); } - if (ts->use_irq) - { + if (ts->use_irq) { ts->irq_is_disable = 0; enable_irq(client->irq); - } - else - { + } else { hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); } - printk("-----gt813------goodix_ts_resume.\n"); + printk("-----gt813------goodix_ts_resume.\n"); return success; } @@ -970,17 +801,16 @@ static void goodix_ts_late_resume(struct early_suspend *h) goodix_ts_resume(ts->client); } #endif -//******************************Begin of firmware update surpport******************************* +//******************************Begin of firmware update surpport******************************* #ifndef AUTO_UPDATE_GUITAR static void guitar_reset( struct goodix_ts_data *ts,u8 ms) { - GPIO_DIRECTION_OUTPUT(ts->reset_port, 0); GPIO_SET_VALUE(ts->reset_port, 0); msleep(ms); - // GPIO_DIRECTION_OUTPUT(ts->reset_port); + //GPIO_DIRECTION_OUTPUT(ts->reset_port); GPIO_SET_VALUE(ts->reset_port, 1); GPIO_PULL_UPDOWN(ts->reset_port, 0); @@ -990,15 +820,12 @@ err_gpio_request_failed: } #endif - -//�����ڸ���� �豸���豸ID �б� //only one client static const struct i2c_device_id goodix_ts_id[] = { {"Goodix-TS-82X", 0 }, { } }; -//�豸��ṹ�� static struct i2c_driver goodix_ts_driver = { .probe = goodix_ts_probe, .remove = goodix_ts_remove, @@ -1012,27 +839,21 @@ static struct i2c_driver goodix_ts_driver = { .owner = THIS_MODULE, }, }; -/******************************************************* -���ܣ� - ����غ��� -return�� - ִ�н���룬0��ʾ��ִ�� -********************************************************/ + static s32 __devinit goodix_ts_init(void) { int ret; - printk("+++++++++++++++++++++++++++++liqing.\n"); + + printk("+++++++++++++++++++++++++++++liqing.\n"); goodix_wq = create_workqueue("goodix_wq"); //create a work queue and worker thread - if (!goodix_wq) - { - GTDEBUG_MSG(KERN_ALERT "creat workqueue faiked\n"); - return -ENOMEM; + if (!goodix_wq) { + GTDEBUG_MSG(KERN_ALERT "creat workqueue faiked\n"); + return -ENOMEM; } ret = i2c_add_driver(&goodix_ts_driver); - if (ret) - { - printk("Register raydium_ts driver failed gt82x.\n"); - return ret; //w++ + if (ret) { + printk("Register raydium_ts driver failed gt82x.\n"); + return ret; //w++ } #ifdef LONGPRESS_LOCK_SPECKEY if(err_gt82x>=0) //w++ @@ -1042,24 +863,18 @@ static s32 __devinit goodix_ts_init(void) return ret; } -/******************************************************* -���ܣ� - ��ж�غ��� -���� - client���豸�ṹ�� -********************************************************/ static void __exit goodix_ts_exit(void) { - GTDEBUG_MSG(KERN_ALERT "Touchscreen driver of guitar exited.\n"); - i2c_del_driver(&goodix_ts_driver); - if (goodix_wq) - destroy_workqueue(goodix_wq); //release our work queue + GTDEBUG_MSG(KERN_ALERT "Touchscreen driver of guitar exited.\n"); + i2c_del_driver(&goodix_ts_driver); + if (goodix_wq) + destroy_workqueue(goodix_wq); //release our work queue #ifdef LONGPRESS_LOCK_SPECKEY //w++ driver_remove_file(&goodix_ts_driver.driver, &driver_attr_get_lock_status); #endif } -module_init(goodix_ts_init); //����ʼ���� +module_init(goodix_ts_init); module_exit(goodix_ts_exit); MODULE_DESCRIPTION("Goodix Touchscreen Driver");