xref: /OK3568_Linux_fs/kernel/drivers/input/touchscreen/gt9xx/gt9xx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* drivers/input/touchscreen/gt9xx.c
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  * 2010 - 2013 Goodix Technology.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or modify
6*4882a593Smuzhiyun  * it under the terms of the GNU General Public License as published by
7*4882a593Smuzhiyun  * the Free Software Foundation; either version 2 of the License, or
8*4882a593Smuzhiyun  * (at your option) any later version.
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * This program is distributed in the hope that it will be a reference
11*4882a593Smuzhiyun  * to you, when you are integrating the GOODiX's CTP IC into your system,
12*4882a593Smuzhiyun  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*4882a593Smuzhiyun  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*4882a593Smuzhiyun  * General Public License for more details.
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * Version: 2.2
17*4882a593Smuzhiyun  * Authors: andrew@goodix.com, meta@goodix.com
18*4882a593Smuzhiyun  * Release Date: 2014/01/14
19*4882a593Smuzhiyun  * Revision record:
20*4882a593Smuzhiyun  *      V1.0:
21*4882a593Smuzhiyun  *          first Release. By Andrew, 2012/08/31
22*4882a593Smuzhiyun  *      V1.2:
23*4882a593Smuzhiyun  *          modify gtp_reset_guitar,slot report,tracking_id & 0x0F. By Andrew, 2012/10/15
24*4882a593Smuzhiyun  *      V1.4:
25*4882a593Smuzhiyun  *          modify gt9xx_update.c. By Andrew, 2012/12/12
26*4882a593Smuzhiyun  *      V1.6:
27*4882a593Smuzhiyun  *          1. new heartbeat/esd_protect mechanism(add external watchdog)
28*4882a593Smuzhiyun  *          2. doze mode, sliding wakeup
29*4882a593Smuzhiyun  *          3. 3 more cfg_group(GT9 Sensor_ID: 0~5)
30*4882a593Smuzhiyun  *          3. config length verification
31*4882a593Smuzhiyun  *          4. names & comments
32*4882a593Smuzhiyun  *                  By Meta, 2013/03/11
33*4882a593Smuzhiyun  *      V1.8:
34*4882a593Smuzhiyun  *          1. pen/stylus identification
35*4882a593Smuzhiyun  *          2. read double check & fixed config support
36*4882a593Smuzhiyun  *          3. new esd & slide wakeup optimization
37*4882a593Smuzhiyun  *                  By Meta, 2013/06/08
38*4882a593Smuzhiyun  *      V2.0:
39*4882a593Smuzhiyun  *          1. compatible with GT9XXF
40*4882a593Smuzhiyun  *          2. send config after resume
41*4882a593Smuzhiyun  *                  By Meta, 2013/08/06
42*4882a593Smuzhiyun  *      V2.2:
43*4882a593Smuzhiyun  *          1. gt9xx_config for debug
44*4882a593Smuzhiyun  *          2. gesture wakeup
45*4882a593Smuzhiyun  *          3. pen separate input device, active-pen button support
46*4882a593Smuzhiyun  *          4. coordinates & keys optimization
47*4882a593Smuzhiyun  *                  By Meta, 2014/01/14
48*4882a593Smuzhiyun  */
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #include <linux/irq.h>
51*4882a593Smuzhiyun #include "gt9xx.h"
52*4882a593Smuzhiyun #include "gt9xx_cfg.h"
53*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #if GTP_ICS_SLOT_REPORT
56*4882a593Smuzhiyun     #include <linux/input/mt.h>
57*4882a593Smuzhiyun #endif
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun static u8 m89or101 = TRUE;
60*4882a593Smuzhiyun static u8 bgt911 = FALSE;
61*4882a593Smuzhiyun static u8 bgt9110 = FALSE;
62*4882a593Smuzhiyun static u8 bgt9111 = FALSE;
63*4882a593Smuzhiyun static u8 bgt970 = FALSE;
64*4882a593Smuzhiyun static u8 bgt910 = FALSE;
65*4882a593Smuzhiyun static u8 gtp_change_x2y = TRUE;
66*4882a593Smuzhiyun static u8 gtp_x_reverse = FALSE;
67*4882a593Smuzhiyun static u8 gtp_y_reverse = TRUE;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun static const char *goodix_ts_name = "goodix-ts";
70*4882a593Smuzhiyun static struct workqueue_struct *goodix_wq;
71*4882a593Smuzhiyun struct i2c_client * i2c_connect_client = NULL;
72*4882a593Smuzhiyun u8 config[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH]
73*4882a593Smuzhiyun                 = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff};
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun #if GTP_HAVE_TOUCH_KEY
76*4882a593Smuzhiyun     static const u16 touch_key_array[] = GTP_KEY_TAB;
77*4882a593Smuzhiyun     #define GTP_MAX_KEY_NUM  (sizeof(touch_key_array)/sizeof(touch_key_array[0]))
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun #if GTP_DEBUG_ON
80*4882a593Smuzhiyun     static const int  key_codes[] = {KEY_HOME, KEY_BACK, KEY_MENU, KEY_SEARCH};
81*4882a593Smuzhiyun     static const char *key_names[] = {"Key_Home", "Key_Back", "Key_Menu", "Key_Search"};
82*4882a593Smuzhiyun #endif
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun #endif
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun static s8 gtp_i2c_test(struct i2c_client *client);
87*4882a593Smuzhiyun void gtp_reset_guitar(struct i2c_client *client, s32 ms);
88*4882a593Smuzhiyun s32 gtp_send_cfg(struct i2c_client *client);
89*4882a593Smuzhiyun void gtp_int_sync(s32 ms, struct goodix_ts_data *ts);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun static ssize_t gt91xx_config_read_proc(struct file *, char __user *, size_t, loff_t *);
92*4882a593Smuzhiyun static ssize_t gt91xx_config_write_proc(struct file *, const char __user *, size_t, loff_t *);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun static struct proc_dir_entry *gt91xx_config_proc = NULL;
95*4882a593Smuzhiyun static const struct file_operations config_proc_ops = {
96*4882a593Smuzhiyun     .owner = THIS_MODULE,
97*4882a593Smuzhiyun     .read = gt91xx_config_read_proc,
98*4882a593Smuzhiyun     .write = gt91xx_config_write_proc,
99*4882a593Smuzhiyun };
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun #if GTP_CREATE_WR_NODE
102*4882a593Smuzhiyun extern s32 init_wr_node(struct i2c_client*);
103*4882a593Smuzhiyun extern void uninit_wr_node(void);
104*4882a593Smuzhiyun #endif
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun #if GTP_AUTO_UPDATE
107*4882a593Smuzhiyun extern u8 gup_init_update_proc(struct goodix_ts_data *);
108*4882a593Smuzhiyun #endif
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun #if GTP_ESD_PROTECT
111*4882a593Smuzhiyun static struct delayed_work gtp_esd_check_work;
112*4882a593Smuzhiyun static struct workqueue_struct * gtp_esd_check_workqueue = NULL;
113*4882a593Smuzhiyun static void gtp_esd_check_func(struct work_struct *);
114*4882a593Smuzhiyun static s32 gtp_init_ext_watchdog(struct i2c_client *client);
115*4882a593Smuzhiyun void gtp_esd_switch(struct i2c_client *, s32);
116*4882a593Smuzhiyun #endif
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun //*********** For GT9XXF Start **********//
119*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
120*4882a593Smuzhiyun extern s32 i2c_read_bytes(struct i2c_client *client, u16 addr, u8 *buf, s32 len);
121*4882a593Smuzhiyun extern s32 i2c_write_bytes(struct i2c_client *client, u16 addr, u8 *buf, s32 len);
122*4882a593Smuzhiyun extern s32 gup_clk_calibration(void);
123*4882a593Smuzhiyun extern s32 gup_fw_download_proc(void *dir, u8 dwn_mode);
124*4882a593Smuzhiyun extern u8 gup_check_fs_mounted(char *path_name);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun void gtp_recovery_reset(struct i2c_client *client);
127*4882a593Smuzhiyun static s32 gtp_esd_recovery(struct i2c_client *client);
128*4882a593Smuzhiyun s32 gtp_fw_startup(struct i2c_client *client);
129*4882a593Smuzhiyun static s32 gtp_main_clk_proc(struct goodix_ts_data *ts);
130*4882a593Smuzhiyun static s32 gtp_bak_ref_proc(struct goodix_ts_data *ts, u8 mode);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun #endif
133*4882a593Smuzhiyun //********** For GT9XXF End **********//
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun #if GTP_GESTURE_WAKEUP
136*4882a593Smuzhiyun typedef enum
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun     DOZE_DISABLED = 0,
139*4882a593Smuzhiyun     DOZE_ENABLED = 1,
140*4882a593Smuzhiyun     DOZE_WAKEUP = 2,
141*4882a593Smuzhiyun }DOZE_T;
142*4882a593Smuzhiyun static DOZE_T doze_status = DOZE_DISABLED;
143*4882a593Smuzhiyun static s8 gtp_enter_doze(struct goodix_ts_data *ts);
144*4882a593Smuzhiyun #endif
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun u8 grp_cfg_version = 0;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun /*******************************************************
149*4882a593Smuzhiyun Function:
150*4882a593Smuzhiyun     Read data from the i2c slave device.
151*4882a593Smuzhiyun Input:
152*4882a593Smuzhiyun     client:     i2c device.
153*4882a593Smuzhiyun     buf[0~1]:   read start address.
154*4882a593Smuzhiyun     buf[2~len-1]:   read data buffer.
155*4882a593Smuzhiyun     len:    GTP_ADDR_LENGTH + read bytes count
156*4882a593Smuzhiyun Output:
157*4882a593Smuzhiyun     numbers of i2c_msgs to transfer:
158*4882a593Smuzhiyun       2: succeed, otherwise: failed
159*4882a593Smuzhiyun *********************************************************/
gtp_i2c_read(struct i2c_client * client,u8 * buf,s32 len)160*4882a593Smuzhiyun s32 gtp_i2c_read(struct i2c_client *client, u8 *buf, s32 len)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun     struct i2c_msg msgs[2];
163*4882a593Smuzhiyun     s32 ret=-1;
164*4882a593Smuzhiyun     s32 retries = 0;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun     msgs[0].flags = !I2C_M_RD;
169*4882a593Smuzhiyun     msgs[0].addr  = client->addr;
170*4882a593Smuzhiyun     msgs[0].len   = GTP_ADDR_LENGTH;
171*4882a593Smuzhiyun     msgs[0].buf   = &buf[0];
172*4882a593Smuzhiyun #ifdef CONFIG_I2C_ROCKCHIP_COMPAT
173*4882a593Smuzhiyun     msgs[0].scl_rate=200 * 1000;
174*4882a593Smuzhiyun     //msgs[0].scl_rate = 300 * 1000;    // for Rockchip, etc.
175*4882a593Smuzhiyun #endif
176*4882a593Smuzhiyun     msgs[1].flags = I2C_M_RD;
177*4882a593Smuzhiyun     msgs[1].addr  = client->addr;
178*4882a593Smuzhiyun     msgs[1].len   = len - GTP_ADDR_LENGTH;
179*4882a593Smuzhiyun     msgs[1].buf   = &buf[GTP_ADDR_LENGTH];
180*4882a593Smuzhiyun #ifdef CONFIG_I2C_ROCKCHIP_COMPAT
181*4882a593Smuzhiyun     msgs[1].scl_rate=200 * 1000;
182*4882a593Smuzhiyun     //msgs[1].scl_rate = 300 * 1000;    // for Rockchip, etc.
183*4882a593Smuzhiyun #endif
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun     while(retries < 5)
186*4882a593Smuzhiyun     {
187*4882a593Smuzhiyun         ret = i2c_transfer(client->adapter, msgs, 2);
188*4882a593Smuzhiyun         if(ret == 2)break;
189*4882a593Smuzhiyun         retries++;
190*4882a593Smuzhiyun     }
191*4882a593Smuzhiyun     if((retries >= 5))
192*4882a593Smuzhiyun     {
193*4882a593Smuzhiyun     #if GTP_COMPATIBLE_MODE
194*4882a593Smuzhiyun         struct goodix_ts_data *ts = i2c_get_clientdata(client);
195*4882a593Smuzhiyun     #endif
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun     #if GTP_GESTURE_WAKEUP
198*4882a593Smuzhiyun         // reset chip would quit doze mode
199*4882a593Smuzhiyun         if (DOZE_ENABLED == doze_status)
200*4882a593Smuzhiyun         {
201*4882a593Smuzhiyun             return ret;
202*4882a593Smuzhiyun         }
203*4882a593Smuzhiyun     #endif
204*4882a593Smuzhiyun         GTP_ERROR("I2C Read: 0x%04X, %d bytes failed, errcode: %d! Process reset.", (((u16)(buf[0] << 8)) | buf[1]), len-2, ret);
205*4882a593Smuzhiyun     #if GTP_COMPATIBLE_MODE
206*4882a593Smuzhiyun         if (CHIP_TYPE_GT9F == ts->chip_type)
207*4882a593Smuzhiyun         {
208*4882a593Smuzhiyun             gtp_recovery_reset(client);
209*4882a593Smuzhiyun         }
210*4882a593Smuzhiyun         else
211*4882a593Smuzhiyun     #endif
212*4882a593Smuzhiyun         {
213*4882a593Smuzhiyun             gtp_reset_guitar(client, 10);
214*4882a593Smuzhiyun         }
215*4882a593Smuzhiyun     }
216*4882a593Smuzhiyun     return ret;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun /*******************************************************
222*4882a593Smuzhiyun Function:
223*4882a593Smuzhiyun     Write data to the i2c slave device.
224*4882a593Smuzhiyun Input:
225*4882a593Smuzhiyun     client:     i2c device.
226*4882a593Smuzhiyun     buf[0~1]:   write start address.
227*4882a593Smuzhiyun     buf[2~len-1]:   data buffer
228*4882a593Smuzhiyun     len:    GTP_ADDR_LENGTH + write bytes count
229*4882a593Smuzhiyun Output:
230*4882a593Smuzhiyun     numbers of i2c_msgs to transfer:
231*4882a593Smuzhiyun         1: succeed, otherwise: failed
232*4882a593Smuzhiyun *********************************************************/
gtp_i2c_write(struct i2c_client * client,u8 * buf,s32 len)233*4882a593Smuzhiyun s32 gtp_i2c_write(struct i2c_client *client,u8 *buf,s32 len)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun     struct i2c_msg msg;
236*4882a593Smuzhiyun     s32 ret = -1;
237*4882a593Smuzhiyun     s32 retries = 0;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun     msg.flags = !I2C_M_RD;
242*4882a593Smuzhiyun     msg.addr  = client->addr;
243*4882a593Smuzhiyun     msg.len   = len;
244*4882a593Smuzhiyun     msg.buf   = buf;
245*4882a593Smuzhiyun #ifdef CONFIG_I2C_ROCKCHIP_COMPAT
246*4882a593Smuzhiyun     msg.scl_rate=200 * 1000;
247*4882a593Smuzhiyun     //msg.scl_rate = 300 * 1000;    // for Rockchip, etc
248*4882a593Smuzhiyun #endif
249*4882a593Smuzhiyun     while(retries < 5)
250*4882a593Smuzhiyun     {
251*4882a593Smuzhiyun         ret = i2c_transfer(client->adapter, &msg, 1);
252*4882a593Smuzhiyun         if (ret == 1)break;
253*4882a593Smuzhiyun         retries++;
254*4882a593Smuzhiyun     }
255*4882a593Smuzhiyun     if((retries >= 5))
256*4882a593Smuzhiyun     {
257*4882a593Smuzhiyun     #if GTP_COMPATIBLE_MODE
258*4882a593Smuzhiyun         struct goodix_ts_data *ts = i2c_get_clientdata(client);
259*4882a593Smuzhiyun     #endif
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun     #if GTP_GESTURE_WAKEUP
262*4882a593Smuzhiyun         if (DOZE_ENABLED == doze_status)
263*4882a593Smuzhiyun         {
264*4882a593Smuzhiyun             return ret;
265*4882a593Smuzhiyun         }
266*4882a593Smuzhiyun     #endif
267*4882a593Smuzhiyun         GTP_ERROR("I2C Write: 0x%04X, %d bytes failed, errcode: %d! Process reset.", (((u16)(buf[0] << 8)) | buf[1]), len-2, ret);
268*4882a593Smuzhiyun     #if GTP_COMPATIBLE_MODE
269*4882a593Smuzhiyun         if (CHIP_TYPE_GT9F == ts->chip_type)
270*4882a593Smuzhiyun         {
271*4882a593Smuzhiyun             gtp_recovery_reset(client);
272*4882a593Smuzhiyun         }
273*4882a593Smuzhiyun         else
274*4882a593Smuzhiyun     #endif
275*4882a593Smuzhiyun         {
276*4882a593Smuzhiyun             gtp_reset_guitar(client, 10);
277*4882a593Smuzhiyun         }
278*4882a593Smuzhiyun     }
279*4882a593Smuzhiyun     return ret;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun /*******************************************************
284*4882a593Smuzhiyun Function:
285*4882a593Smuzhiyun     i2c read twice, compare the results
286*4882a593Smuzhiyun Input:
287*4882a593Smuzhiyun     client:  i2c device
288*4882a593Smuzhiyun     addr:    operate address
289*4882a593Smuzhiyun     rxbuf:   read data to store, if compare successful
290*4882a593Smuzhiyun     len:     bytes to read
291*4882a593Smuzhiyun Output:
292*4882a593Smuzhiyun     FAIL:    read failed
293*4882a593Smuzhiyun     SUCCESS: read successful
294*4882a593Smuzhiyun *********************************************************/
gtp_i2c_read_dbl_check(struct i2c_client * client,u16 addr,u8 * rxbuf,int len)295*4882a593Smuzhiyun s32 gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr, u8 *rxbuf, int len)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun     u8 buf[16] = {0};
298*4882a593Smuzhiyun     u8 confirm_buf[16] = {0};
299*4882a593Smuzhiyun     u8 retry = 0;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun     while (retry++ < 3)
302*4882a593Smuzhiyun     {
303*4882a593Smuzhiyun         memset(buf, 0xAA, 16);
304*4882a593Smuzhiyun         buf[0] = (u8)(addr >> 8);
305*4882a593Smuzhiyun         buf[1] = (u8)(addr & 0xFF);
306*4882a593Smuzhiyun         gtp_i2c_read(client, buf, len + 2);
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun         memset(confirm_buf, 0xAB, 16);
309*4882a593Smuzhiyun         confirm_buf[0] = (u8)(addr >> 8);
310*4882a593Smuzhiyun         confirm_buf[1] = (u8)(addr & 0xFF);
311*4882a593Smuzhiyun         gtp_i2c_read(client, confirm_buf, len + 2);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun         if (!memcmp(buf, confirm_buf, len+2))
314*4882a593Smuzhiyun         {
315*4882a593Smuzhiyun             memcpy(rxbuf, confirm_buf+2, len);
316*4882a593Smuzhiyun             return SUCCESS;
317*4882a593Smuzhiyun         }
318*4882a593Smuzhiyun     }
319*4882a593Smuzhiyun     GTP_ERROR("I2C read 0x%04X, %d bytes, double check failed!", addr, len);
320*4882a593Smuzhiyun     return FAIL;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun /*******************************************************
324*4882a593Smuzhiyun Function:
325*4882a593Smuzhiyun     Send config.
326*4882a593Smuzhiyun Input:
327*4882a593Smuzhiyun     client: i2c device.
328*4882a593Smuzhiyun Output:
329*4882a593Smuzhiyun     result of i2c write operation.
330*4882a593Smuzhiyun         1: succeed, otherwise: failed
331*4882a593Smuzhiyun *********************************************************/
332*4882a593Smuzhiyun 
gtp_send_cfg(struct i2c_client * client)333*4882a593Smuzhiyun s32 gtp_send_cfg(struct i2c_client *client)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun     s32 ret = 2;
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun #if GTP_DRIVER_SEND_CFG
338*4882a593Smuzhiyun     s32 retry = 0;
339*4882a593Smuzhiyun     struct goodix_ts_data *ts = i2c_get_clientdata(client);
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun     if (ts->fixed_cfg)
342*4882a593Smuzhiyun     {
343*4882a593Smuzhiyun         GTP_INFO("Ic fixed config, no config sent!");
344*4882a593Smuzhiyun         return 0;
345*4882a593Smuzhiyun     }
346*4882a593Smuzhiyun     else if (ts->pnl_init_error)
347*4882a593Smuzhiyun     {
348*4882a593Smuzhiyun         GTP_INFO("Error occured in init_panel, no config sent");
349*4882a593Smuzhiyun         return 0;
350*4882a593Smuzhiyun     }
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun     GTP_INFO("Driver send config.");
353*4882a593Smuzhiyun     for (retry = 0; retry < 5; retry++)
354*4882a593Smuzhiyun     {
355*4882a593Smuzhiyun         ret = gtp_i2c_write(client, config , GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);
356*4882a593Smuzhiyun         if (ret > 0)
357*4882a593Smuzhiyun         {
358*4882a593Smuzhiyun             break;
359*4882a593Smuzhiyun         }
360*4882a593Smuzhiyun     }
361*4882a593Smuzhiyun #endif
362*4882a593Smuzhiyun     return ret;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun /*******************************************************
365*4882a593Smuzhiyun Function:
366*4882a593Smuzhiyun     Disable irq function
367*4882a593Smuzhiyun Input:
368*4882a593Smuzhiyun     ts: goodix i2c_client private data
369*4882a593Smuzhiyun Output:
370*4882a593Smuzhiyun     None.
371*4882a593Smuzhiyun *********************************************************/
gtp_irq_disable(struct goodix_ts_data * ts)372*4882a593Smuzhiyun void gtp_irq_disable(struct goodix_ts_data *ts)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun     unsigned long irqflags;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun     spin_lock_irqsave(&ts->irq_lock, irqflags);
379*4882a593Smuzhiyun     if (!ts->irq_is_disable)
380*4882a593Smuzhiyun     {
381*4882a593Smuzhiyun         ts->irq_is_disable = 1;
382*4882a593Smuzhiyun         disable_irq_nosync(ts->client->irq);
383*4882a593Smuzhiyun     }
384*4882a593Smuzhiyun     spin_unlock_irqrestore(&ts->irq_lock, irqflags);
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun /*******************************************************
388*4882a593Smuzhiyun Function:
389*4882a593Smuzhiyun     Enable irq function
390*4882a593Smuzhiyun Input:
391*4882a593Smuzhiyun     ts: goodix i2c_client private data
392*4882a593Smuzhiyun Output:
393*4882a593Smuzhiyun     None.
394*4882a593Smuzhiyun *********************************************************/
gtp_irq_enable(struct goodix_ts_data * ts)395*4882a593Smuzhiyun void gtp_irq_enable(struct goodix_ts_data *ts)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun     unsigned long irqflags = 0;
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun     spin_lock_irqsave(&ts->irq_lock, irqflags);
402*4882a593Smuzhiyun     if (ts->irq_is_disable)
403*4882a593Smuzhiyun     {
404*4882a593Smuzhiyun         enable_irq(ts->client->irq);
405*4882a593Smuzhiyun         ts->irq_is_disable = 0;
406*4882a593Smuzhiyun     }
407*4882a593Smuzhiyun     spin_unlock_irqrestore(&ts->irq_lock, irqflags);
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun /*******************************************************
412*4882a593Smuzhiyun Function:
413*4882a593Smuzhiyun     Report touch point event
414*4882a593Smuzhiyun Input:
415*4882a593Smuzhiyun     ts: goodix i2c_client private data
416*4882a593Smuzhiyun     id: trackId
417*4882a593Smuzhiyun     x:  input x coordinate
418*4882a593Smuzhiyun     y:  input y coordinate
419*4882a593Smuzhiyun     w:  input pressure
420*4882a593Smuzhiyun Output:
421*4882a593Smuzhiyun     None.
422*4882a593Smuzhiyun *********************************************************/
gtp_touch_down(struct goodix_ts_data * ts,s32 id,s32 x,s32 y,s32 w)423*4882a593Smuzhiyun static void gtp_touch_down(struct goodix_ts_data* ts,s32 id,s32 x,s32 y,s32 w)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun 	if (gtp_change_x2y)
426*4882a593Smuzhiyun 		GTP_SWAP(x, y);
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	if (!bgt911 && !bgt970) {
429*4882a593Smuzhiyun 		if (gtp_x_reverse)
430*4882a593Smuzhiyun 			x = ts->abs_x_max - x;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 		if (gtp_y_reverse)
433*4882a593Smuzhiyun 			y = ts->abs_y_max - y;
434*4882a593Smuzhiyun 	}
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun #if GTP_ICS_SLOT_REPORT
437*4882a593Smuzhiyun     input_mt_slot(ts->input_dev, id);
438*4882a593Smuzhiyun     input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
439*4882a593Smuzhiyun     input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
440*4882a593Smuzhiyun     input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
441*4882a593Smuzhiyun     input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
442*4882a593Smuzhiyun     input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
443*4882a593Smuzhiyun #else
444*4882a593Smuzhiyun     input_report_key(ts->input_dev, BTN_TOUCH, 1);
445*4882a593Smuzhiyun     input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
446*4882a593Smuzhiyun     input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
447*4882a593Smuzhiyun     input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
448*4882a593Smuzhiyun     input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
449*4882a593Smuzhiyun     input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
450*4882a593Smuzhiyun     input_mt_sync(ts->input_dev);
451*4882a593Smuzhiyun #endif
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun     GTP_DEBUG("ID:%d, X:%d, Y:%d, W:%d", id, x, y, w);
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun /*******************************************************
457*4882a593Smuzhiyun Function:
458*4882a593Smuzhiyun     Report touch release event
459*4882a593Smuzhiyun Input:
460*4882a593Smuzhiyun     ts: goodix i2c_client private data
461*4882a593Smuzhiyun Output:
462*4882a593Smuzhiyun     None.
463*4882a593Smuzhiyun *********************************************************/
gtp_touch_up(struct goodix_ts_data * ts,s32 id)464*4882a593Smuzhiyun static void gtp_touch_up(struct goodix_ts_data* ts, s32 id)
465*4882a593Smuzhiyun {
466*4882a593Smuzhiyun #if GTP_ICS_SLOT_REPORT
467*4882a593Smuzhiyun     input_mt_slot(ts->input_dev, id);
468*4882a593Smuzhiyun     input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
469*4882a593Smuzhiyun     GTP_DEBUG("Touch id[%2d] release!", id);
470*4882a593Smuzhiyun #else
471*4882a593Smuzhiyun     input_report_key(ts->input_dev, BTN_TOUCH, 0);
472*4882a593Smuzhiyun #endif
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun #if GTP_WITH_PEN
476*4882a593Smuzhiyun 
gtp_pen_init(struct goodix_ts_data * ts)477*4882a593Smuzhiyun static void gtp_pen_init(struct goodix_ts_data *ts)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun     s32 ret = 0;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun     GTP_INFO("Request input device for pen/stylus.");
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun     ts->pen_dev = input_allocate_device();
484*4882a593Smuzhiyun     if (ts->pen_dev == NULL)
485*4882a593Smuzhiyun     {
486*4882a593Smuzhiyun         GTP_ERROR("Failed to allocate input device for pen/stylus.");
487*4882a593Smuzhiyun         return;
488*4882a593Smuzhiyun     }
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun     ts->pen_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun #if GTP_ICS_SLOT_REPORT
493*4882a593Smuzhiyun     input_mt_init_slots(ts->pen_dev, 16, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
494*4882a593Smuzhiyun #else
495*4882a593Smuzhiyun     ts->pen_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
496*4882a593Smuzhiyun #endif
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun     set_bit(BTN_TOOL_PEN, ts->pen_dev->keybit);
499*4882a593Smuzhiyun     set_bit(INPUT_PROP_DIRECT, ts->pen_dev->propbit);
500*4882a593Smuzhiyun     //set_bit(INPUT_PROP_POINTER, ts->pen_dev->propbit);
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun #if GTP_PEN_HAVE_BUTTON
503*4882a593Smuzhiyun     input_set_capability(ts->pen_dev, EV_KEY, BTN_STYLUS);
504*4882a593Smuzhiyun     input_set_capability(ts->pen_dev, EV_KEY, BTN_STYLUS2);
505*4882a593Smuzhiyun #endif
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun     input_set_abs_params(ts->pen_dev, ABS_MT_POSITION_X, 0, ts->abs_x_max, 0, 0);
508*4882a593Smuzhiyun     input_set_abs_params(ts->pen_dev, ABS_MT_POSITION_Y, 0, ts->abs_y_max, 0, 0);
509*4882a593Smuzhiyun     input_set_abs_params(ts->pen_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
510*4882a593Smuzhiyun     input_set_abs_params(ts->pen_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
511*4882a593Smuzhiyun     input_set_abs_params(ts->pen_dev, ABS_MT_TRACKING_ID, 0, 255, 0, 0);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun     ts->pen_dev->name = "goodix-pen";
514*4882a593Smuzhiyun     ts->pen_dev->id.bustype = BUS_I2C;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun     ret = input_register_device(ts->pen_dev);
517*4882a593Smuzhiyun     if (ret)
518*4882a593Smuzhiyun     {
519*4882a593Smuzhiyun         GTP_ERROR("Register %s input device failed", ts->pen_dev->name);
520*4882a593Smuzhiyun         return;
521*4882a593Smuzhiyun     }
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun 
gtp_pen_down(s32 x,s32 y,s32 w,s32 id)524*4882a593Smuzhiyun static void gtp_pen_down(s32 x, s32 y, s32 w, s32 id)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun     struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	if (gtp_change_x2y)
529*4882a593Smuzhiyun 		GTP_SWAP(x, y);
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 
532*4882a593Smuzhiyun     input_report_key(ts->pen_dev, BTN_TOOL_PEN, 1);
533*4882a593Smuzhiyun #if GTP_ICS_SLOT_REPORT
534*4882a593Smuzhiyun     input_mt_slot(ts->pen_dev, id);
535*4882a593Smuzhiyun     input_report_abs(ts->pen_dev, ABS_MT_TRACKING_ID, id);
536*4882a593Smuzhiyun     input_report_abs(ts->pen_dev, ABS_MT_POSITION_X, x);
537*4882a593Smuzhiyun     input_report_abs(ts->pen_dev, ABS_MT_POSITION_Y, y);
538*4882a593Smuzhiyun     input_report_abs(ts->pen_dev, ABS_MT_PRESSURE, w);
539*4882a593Smuzhiyun     input_report_abs(ts->pen_dev, ABS_MT_TOUCH_MAJOR, w);
540*4882a593Smuzhiyun #else
541*4882a593Smuzhiyun     input_report_key(ts->pen_dev, BTN_TOUCH, 1);
542*4882a593Smuzhiyun     input_report_abs(ts->pen_dev, ABS_MT_POSITION_X, x);
543*4882a593Smuzhiyun     input_report_abs(ts->pen_dev, ABS_MT_POSITION_Y, y);
544*4882a593Smuzhiyun     input_report_abs(ts->pen_dev, ABS_MT_PRESSURE, w);
545*4882a593Smuzhiyun     input_report_abs(ts->pen_dev, ABS_MT_TOUCH_MAJOR, w);
546*4882a593Smuzhiyun     input_report_abs(ts->pen_dev, ABS_MT_TRACKING_ID, id);
547*4882a593Smuzhiyun     input_mt_sync(ts->pen_dev);
548*4882a593Smuzhiyun #endif
549*4882a593Smuzhiyun     GTP_DEBUG("(%d)(%d, %d)[%d]", id, x, y, w);
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun 
gtp_pen_up(s32 id)552*4882a593Smuzhiyun static void gtp_pen_up(s32 id)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun     struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun     input_report_key(ts->pen_dev, BTN_TOOL_PEN, 0);
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun #if GTP_ICS_SLOT_REPORT
559*4882a593Smuzhiyun     input_mt_slot(ts->pen_dev, id);
560*4882a593Smuzhiyun     input_report_abs(ts->pen_dev, ABS_MT_TRACKING_ID, -1);
561*4882a593Smuzhiyun #else
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun     input_report_key(ts->pen_dev, BTN_TOUCH, 0);
564*4882a593Smuzhiyun #endif
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun #endif
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun /*******************************************************
570*4882a593Smuzhiyun Function:
571*4882a593Smuzhiyun     Goodix touchscreen work function
572*4882a593Smuzhiyun Input:
573*4882a593Smuzhiyun     work: work struct of goodix_workqueue
574*4882a593Smuzhiyun Output:
575*4882a593Smuzhiyun     None.
576*4882a593Smuzhiyun *********************************************************/
goodix_ts_work_func(struct work_struct * work)577*4882a593Smuzhiyun static void goodix_ts_work_func(struct work_struct *work)
578*4882a593Smuzhiyun {
579*4882a593Smuzhiyun     u8  end_cmd[3] = {GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF, 0};
580*4882a593Smuzhiyun     u8  point_data[2 + 1 + 8 * GTP_MAX_TOUCH + 1]={GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF};
581*4882a593Smuzhiyun     u8  touch_num = 0;
582*4882a593Smuzhiyun     u8  finger = 0;
583*4882a593Smuzhiyun     static u16 pre_touch = 0;
584*4882a593Smuzhiyun     static u8 pre_key = 0;
585*4882a593Smuzhiyun #if GTP_WITH_PEN
586*4882a593Smuzhiyun     u8 pen_active = 0;
587*4882a593Smuzhiyun     static u8 pre_pen = 0;
588*4882a593Smuzhiyun #endif
589*4882a593Smuzhiyun     u8  key_value = 0;
590*4882a593Smuzhiyun     u8* coor_data = NULL;
591*4882a593Smuzhiyun     s32 input_x = 0;
592*4882a593Smuzhiyun     s32 input_y = 0;
593*4882a593Smuzhiyun     s32 input_w = 0;
594*4882a593Smuzhiyun     s32 id = 0;
595*4882a593Smuzhiyun     s32 i  = 0;
596*4882a593Smuzhiyun     s32 ret = -1;
597*4882a593Smuzhiyun     struct goodix_ts_data *ts = NULL;
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
600*4882a593Smuzhiyun     u8 rqst_buf[3] = {0x80, 0x43};  // for GT9XXF
601*4882a593Smuzhiyun #endif
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun #if GTP_GESTURE_WAKEUP
604*4882a593Smuzhiyun     u8 doze_buf[3] = {0x81, 0x4B};
605*4882a593Smuzhiyun #endif
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
608*4882a593Smuzhiyun     ts = container_of(work, struct goodix_ts_data, work);
609*4882a593Smuzhiyun     if (ts->enter_update)
610*4882a593Smuzhiyun     {
611*4882a593Smuzhiyun         goto release_wakeup_lock;
612*4882a593Smuzhiyun     }
613*4882a593Smuzhiyun #if GTP_GESTURE_WAKEUP
614*4882a593Smuzhiyun     if (DOZE_ENABLED == doze_status)
615*4882a593Smuzhiyun     {
616*4882a593Smuzhiyun         ret = gtp_i2c_read(i2c_connect_client, doze_buf, 3);
617*4882a593Smuzhiyun         GTP_DEBUG("0x814B = 0x%02X", doze_buf[2]);
618*4882a593Smuzhiyun         if (ret > 0)
619*4882a593Smuzhiyun         {
620*4882a593Smuzhiyun             if ((doze_buf[2] == 'a') || (doze_buf[2] == 'b') || (doze_buf[2] == 'c') ||
621*4882a593Smuzhiyun                 (doze_buf[2] == 'd') || (doze_buf[2] == 'e') || (doze_buf[2] == 'g') ||
622*4882a593Smuzhiyun                 (doze_buf[2] == 'h') || (doze_buf[2] == 'm') || (doze_buf[2] == 'o') ||
623*4882a593Smuzhiyun                 (doze_buf[2] == 'q') || (doze_buf[2] == 's') || (doze_buf[2] == 'v') ||
624*4882a593Smuzhiyun                 (doze_buf[2] == 'w') || (doze_buf[2] == 'y') || (doze_buf[2] == 'z') ||
625*4882a593Smuzhiyun                 (doze_buf[2] == 0x5E) /* ^ */
626*4882a593Smuzhiyun                 )
627*4882a593Smuzhiyun             {
628*4882a593Smuzhiyun                 if (doze_buf[2] != 0x5E)
629*4882a593Smuzhiyun                 {
630*4882a593Smuzhiyun                     GTP_INFO("Wakeup by gesture(%c), light up the screen!", doze_buf[2]);
631*4882a593Smuzhiyun                 }
632*4882a593Smuzhiyun                 else
633*4882a593Smuzhiyun                 {
634*4882a593Smuzhiyun                     GTP_INFO("Wakeup by gesture(^), light up the screen!");
635*4882a593Smuzhiyun                 }
636*4882a593Smuzhiyun                 doze_status = DOZE_WAKEUP;
637*4882a593Smuzhiyun                 input_report_key(ts->input_dev, KEY_POWER, 1);
638*4882a593Smuzhiyun                 input_sync(ts->input_dev);
639*4882a593Smuzhiyun                 input_report_key(ts->input_dev, KEY_POWER, 0);
640*4882a593Smuzhiyun                 input_sync(ts->input_dev);
641*4882a593Smuzhiyun                 // clear 0x814B
642*4882a593Smuzhiyun                 doze_buf[2] = 0x00;
643*4882a593Smuzhiyun                 gtp_i2c_write(i2c_connect_client, doze_buf, 3);
644*4882a593Smuzhiyun 			}
645*4882a593Smuzhiyun 			else if ( (doze_buf[2] == 0xAA) || (doze_buf[2] == 0xBB) ||
646*4882a593Smuzhiyun 				(doze_buf[2] == 0xAB) || (doze_buf[2] == 0xBA) )
647*4882a593Smuzhiyun             {
648*4882a593Smuzhiyun                 char *direction[4] = {"Right", "Down", "Up", "Left"};
649*4882a593Smuzhiyun                 u8 type = ((doze_buf[2] & 0x0F) - 0x0A) + (((doze_buf[2] >> 4) & 0x0F) - 0x0A) * 2;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun                 GTP_INFO("%s slide to light up the screen!", direction[type]);
652*4882a593Smuzhiyun                 doze_status = DOZE_WAKEUP;
653*4882a593Smuzhiyun                 input_report_key(ts->input_dev, KEY_POWER, 1);
654*4882a593Smuzhiyun                 input_sync(ts->input_dev);
655*4882a593Smuzhiyun                 input_report_key(ts->input_dev, KEY_POWER, 0);
656*4882a593Smuzhiyun                 input_sync(ts->input_dev);
657*4882a593Smuzhiyun                 // clear 0x814B
658*4882a593Smuzhiyun                 doze_buf[2] = 0x00;
659*4882a593Smuzhiyun                 gtp_i2c_write(i2c_connect_client, doze_buf, 3);
660*4882a593Smuzhiyun             }
661*4882a593Smuzhiyun             else if (0xCC == doze_buf[2])
662*4882a593Smuzhiyun             {
663*4882a593Smuzhiyun                 GTP_INFO("Double click to light up the screen!");
664*4882a593Smuzhiyun                 doze_status = DOZE_WAKEUP;
665*4882a593Smuzhiyun                 input_report_key(ts->input_dev, KEY_POWER, 1);
666*4882a593Smuzhiyun                 input_sync(ts->input_dev);
667*4882a593Smuzhiyun                 input_report_key(ts->input_dev, KEY_POWER, 0);
668*4882a593Smuzhiyun                 input_sync(ts->input_dev);
669*4882a593Smuzhiyun                 // clear 0x814B
670*4882a593Smuzhiyun                 doze_buf[2] = 0x00;
671*4882a593Smuzhiyun                 gtp_i2c_write(i2c_connect_client, doze_buf, 3);
672*4882a593Smuzhiyun             }
673*4882a593Smuzhiyun             else
674*4882a593Smuzhiyun             {
675*4882a593Smuzhiyun                 // clear 0x814B
676*4882a593Smuzhiyun                 doze_buf[2] = 0x00;
677*4882a593Smuzhiyun                 gtp_i2c_write(i2c_connect_client, doze_buf, 3);
678*4882a593Smuzhiyun                 gtp_enter_doze(ts);
679*4882a593Smuzhiyun             }
680*4882a593Smuzhiyun         }
681*4882a593Smuzhiyun         if (ts->use_irq)
682*4882a593Smuzhiyun         {
683*4882a593Smuzhiyun             gtp_irq_enable(ts);
684*4882a593Smuzhiyun         }
685*4882a593Smuzhiyun         goto release_wakeup_lock;
686*4882a593Smuzhiyun     }
687*4882a593Smuzhiyun #endif
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun     ret = gtp_i2c_read(ts->client, point_data, 12);
690*4882a593Smuzhiyun     if (ret < 0)
691*4882a593Smuzhiyun     {
692*4882a593Smuzhiyun         GTP_ERROR("I2C transfer error. errno:%d\n ", ret);
693*4882a593Smuzhiyun         if (ts->use_irq)
694*4882a593Smuzhiyun         {
695*4882a593Smuzhiyun             gtp_irq_enable(ts);
696*4882a593Smuzhiyun         }
697*4882a593Smuzhiyun         goto release_wakeup_lock;
698*4882a593Smuzhiyun     }
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun     finger = point_data[GTP_ADDR_LENGTH];
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
703*4882a593Smuzhiyun     // GT9XXF
704*4882a593Smuzhiyun     if ((finger == 0x00) && (CHIP_TYPE_GT9F == ts->chip_type))     // request arrived
705*4882a593Smuzhiyun     {
706*4882a593Smuzhiyun         ret = gtp_i2c_read(ts->client, rqst_buf, 3);
707*4882a593Smuzhiyun         if (ret < 0)
708*4882a593Smuzhiyun         {
709*4882a593Smuzhiyun            GTP_ERROR("Read request status error!");
710*4882a593Smuzhiyun            goto exit_work_func;
711*4882a593Smuzhiyun         }
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun         switch (rqst_buf[2])
714*4882a593Smuzhiyun         {
715*4882a593Smuzhiyun         case GTP_RQST_CONFIG:
716*4882a593Smuzhiyun             GTP_INFO("Request for config.");
717*4882a593Smuzhiyun             ret = gtp_send_cfg(ts->client);
718*4882a593Smuzhiyun             if (ret < 0)
719*4882a593Smuzhiyun             {
720*4882a593Smuzhiyun                 GTP_ERROR("Request for config unresponded!");
721*4882a593Smuzhiyun             }
722*4882a593Smuzhiyun             else
723*4882a593Smuzhiyun             {
724*4882a593Smuzhiyun                 rqst_buf[2] = GTP_RQST_RESPONDED;
725*4882a593Smuzhiyun                 gtp_i2c_write(ts->client, rqst_buf, 3);
726*4882a593Smuzhiyun                 GTP_INFO("Request for config responded!");
727*4882a593Smuzhiyun             }
728*4882a593Smuzhiyun             break;
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun         case GTP_RQST_BAK_REF:
731*4882a593Smuzhiyun 			/*
732*4882a593Smuzhiyun             GTP_INFO("Request for backup reference.");
733*4882a593Smuzhiyun             ts->rqst_processing = 1;
734*4882a593Smuzhiyun             ret = gtp_bak_ref_proc(ts, GTP_BAK_REF_SEND);
735*4882a593Smuzhiyun             if (SUCCESS == ret)
736*4882a593Smuzhiyun             {
737*4882a593Smuzhiyun                 rqst_buf[2] = GTP_RQST_RESPONDED;
738*4882a593Smuzhiyun                 gtp_i2c_write(ts->client, rqst_buf, 3);
739*4882a593Smuzhiyun                 ts->rqst_processing = 0;
740*4882a593Smuzhiyun                 GTP_INFO("Request for backup reference responded!");
741*4882a593Smuzhiyun             }
742*4882a593Smuzhiyun             else
743*4882a593Smuzhiyun             {
744*4882a593Smuzhiyun                 GTP_ERROR("Requeset for backup reference unresponed!");
745*4882a593Smuzhiyun             }
746*4882a593Smuzhiyun 			*/
747*4882a593Smuzhiyun             break;
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun         case GTP_RQST_RESET:
750*4882a593Smuzhiyun             GTP_INFO("Request for reset.");
751*4882a593Smuzhiyun             gtp_recovery_reset(ts->client);
752*4882a593Smuzhiyun             break;
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun         case GTP_RQST_MAIN_CLOCK:
755*4882a593Smuzhiyun             GTP_INFO("Request for main clock.");
756*4882a593Smuzhiyun             ts->rqst_processing = 1;
757*4882a593Smuzhiyun             ret = gtp_main_clk_proc(ts);
758*4882a593Smuzhiyun             if (FAIL == ret)
759*4882a593Smuzhiyun             {
760*4882a593Smuzhiyun                 GTP_ERROR("Request for main clock unresponded!");
761*4882a593Smuzhiyun             }
762*4882a593Smuzhiyun             else
763*4882a593Smuzhiyun             {
764*4882a593Smuzhiyun                 GTP_INFO("Request for main clock responded!");
765*4882a593Smuzhiyun                 rqst_buf[2] = GTP_RQST_RESPONDED;
766*4882a593Smuzhiyun                 gtp_i2c_write(ts->client, rqst_buf, 3);
767*4882a593Smuzhiyun                 ts->rqst_processing = 0;
768*4882a593Smuzhiyun                 ts->clk_chk_fs_times = 0;
769*4882a593Smuzhiyun             }
770*4882a593Smuzhiyun             break;
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun         default:
773*4882a593Smuzhiyun             GTP_INFO("Undefined request: 0x%02X", rqst_buf[2]);
774*4882a593Smuzhiyun             rqst_buf[2] = GTP_RQST_RESPONDED;
775*4882a593Smuzhiyun             gtp_i2c_write(ts->client, rqst_buf, 3);
776*4882a593Smuzhiyun             break;
777*4882a593Smuzhiyun         }
778*4882a593Smuzhiyun     }
779*4882a593Smuzhiyun #endif
780*4882a593Smuzhiyun     if (finger == 0x00)
781*4882a593Smuzhiyun     {
782*4882a593Smuzhiyun         if (ts->use_irq)
783*4882a593Smuzhiyun         {
784*4882a593Smuzhiyun             gtp_irq_enable(ts);
785*4882a593Smuzhiyun         }
786*4882a593Smuzhiyun         goto release_wakeup_lock;
787*4882a593Smuzhiyun     }
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun     if((finger & 0x80) == 0)
790*4882a593Smuzhiyun     {
791*4882a593Smuzhiyun         goto exit_work_func;
792*4882a593Smuzhiyun     }
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun     touch_num = finger & 0x0f;
795*4882a593Smuzhiyun     if (touch_num > GTP_MAX_TOUCH)
796*4882a593Smuzhiyun     {
797*4882a593Smuzhiyun         goto exit_work_func;
798*4882a593Smuzhiyun     }
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun     if (touch_num > 1)
801*4882a593Smuzhiyun     {
802*4882a593Smuzhiyun         u8 buf[8 * GTP_MAX_TOUCH] = {(GTP_READ_COOR_ADDR + 10) >> 8, (GTP_READ_COOR_ADDR + 10) & 0xff};
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun         ret = gtp_i2c_read(ts->client, buf, 2 + 8 * (touch_num - 1));
805*4882a593Smuzhiyun         memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));
806*4882a593Smuzhiyun     }
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun #if (GTP_HAVE_TOUCH_KEY || GTP_PEN_HAVE_BUTTON)
809*4882a593Smuzhiyun     key_value = point_data[3 + 8 * touch_num];
810*4882a593Smuzhiyun 
811*4882a593Smuzhiyun     if(key_value || pre_key)
812*4882a593Smuzhiyun     {
813*4882a593Smuzhiyun     #if GTP_PEN_HAVE_BUTTON
814*4882a593Smuzhiyun         if (key_value == 0x40)
815*4882a593Smuzhiyun         {
816*4882a593Smuzhiyun             GTP_DEBUG("BTN_STYLUS & BTN_STYLUS2 Down.");
817*4882a593Smuzhiyun             input_report_key(ts->pen_dev, BTN_STYLUS, 1);
818*4882a593Smuzhiyun             input_report_key(ts->pen_dev, BTN_STYLUS2, 1);
819*4882a593Smuzhiyun             pen_active = 1;
820*4882a593Smuzhiyun         }
821*4882a593Smuzhiyun         else if (key_value == 0x10)
822*4882a593Smuzhiyun         {
823*4882a593Smuzhiyun             GTP_DEBUG("BTN_STYLUS Down, BTN_STYLUS2 Up.");
824*4882a593Smuzhiyun             input_report_key(ts->pen_dev, BTN_STYLUS, 1);
825*4882a593Smuzhiyun             input_report_key(ts->pen_dev, BTN_STYLUS2, 0);
826*4882a593Smuzhiyun             pen_active = 1;
827*4882a593Smuzhiyun         }
828*4882a593Smuzhiyun         else if (key_value == 0x20)
829*4882a593Smuzhiyun         {
830*4882a593Smuzhiyun             GTP_DEBUG("BTN_STYLUS Up, BTN_STYLUS2 Down.");
831*4882a593Smuzhiyun             input_report_key(ts->pen_dev, BTN_STYLUS, 0);
832*4882a593Smuzhiyun             input_report_key(ts->pen_dev, BTN_STYLUS2, 1);
833*4882a593Smuzhiyun             pen_active = 1;
834*4882a593Smuzhiyun         }
835*4882a593Smuzhiyun         else
836*4882a593Smuzhiyun         {
837*4882a593Smuzhiyun             GTP_DEBUG("BTN_STYLUS & BTN_STYLUS2 Up.");
838*4882a593Smuzhiyun             input_report_key(ts->pen_dev, BTN_STYLUS, 0);
839*4882a593Smuzhiyun             input_report_key(ts->pen_dev, BTN_STYLUS2, 0);
840*4882a593Smuzhiyun             if ( (pre_key == 0x40) || (pre_key == 0x20) ||
841*4882a593Smuzhiyun                  (pre_key == 0x10)
842*4882a593Smuzhiyun                )
843*4882a593Smuzhiyun             {
844*4882a593Smuzhiyun                 pen_active = 1;
845*4882a593Smuzhiyun             }
846*4882a593Smuzhiyun         }
847*4882a593Smuzhiyun         if (pen_active)
848*4882a593Smuzhiyun         {
849*4882a593Smuzhiyun             touch_num = 0;      // shield pen point
850*4882a593Smuzhiyun             //pre_touch = 0;    // clear last pen status
851*4882a593Smuzhiyun         }
852*4882a593Smuzhiyun     #endif
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun     #if GTP_HAVE_TOUCH_KEY
855*4882a593Smuzhiyun         if (!pre_touch)
856*4882a593Smuzhiyun         {
857*4882a593Smuzhiyun             for (i = 0; i < GTP_MAX_KEY_NUM; i++)
858*4882a593Smuzhiyun             {
859*4882a593Smuzhiyun             #if GTP_DEBUG_ON
860*4882a593Smuzhiyun                 for (ret = 0; ret < 4; ++ret)
861*4882a593Smuzhiyun                 {
862*4882a593Smuzhiyun                     if (key_codes[ret] == touch_key_array[i])
863*4882a593Smuzhiyun                     {
864*4882a593Smuzhiyun                         GTP_DEBUG("Key: %s %s", key_names[ret], (key_value & (0x01 << i)) ? "Down" : "Up");
865*4882a593Smuzhiyun                         break;
866*4882a593Smuzhiyun                     }
867*4882a593Smuzhiyun                 }
868*4882a593Smuzhiyun             #endif
869*4882a593Smuzhiyun                 input_report_key(ts->input_dev, touch_key_array[i], key_value & (0x01<<i));
870*4882a593Smuzhiyun             }
871*4882a593Smuzhiyun             touch_num = 0;  // shield fingers
872*4882a593Smuzhiyun         }
873*4882a593Smuzhiyun     #endif
874*4882a593Smuzhiyun     }
875*4882a593Smuzhiyun #endif
876*4882a593Smuzhiyun     pre_key = key_value;
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun     GTP_DEBUG("pre_touch:%02x, finger:%02x.", pre_touch, finger);
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun #if GTP_ICS_SLOT_REPORT
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun #if GTP_WITH_PEN
883*4882a593Smuzhiyun     if (pre_pen && (touch_num == 0))
884*4882a593Smuzhiyun     {
885*4882a593Smuzhiyun         GTP_DEBUG("Pen touch UP(Slot)!");
886*4882a593Smuzhiyun         gtp_pen_up(0);
887*4882a593Smuzhiyun         pen_active = 1;
888*4882a593Smuzhiyun         pre_pen = 0;
889*4882a593Smuzhiyun     }
890*4882a593Smuzhiyun #endif
891*4882a593Smuzhiyun     if (pre_touch || touch_num)
892*4882a593Smuzhiyun     {
893*4882a593Smuzhiyun         s32 pos = 0;
894*4882a593Smuzhiyun         u16 touch_index = 0;
895*4882a593Smuzhiyun         u8 report_num = 0;
896*4882a593Smuzhiyun         coor_data = &point_data[3];
897*4882a593Smuzhiyun 
898*4882a593Smuzhiyun         if(touch_num)
899*4882a593Smuzhiyun         {
900*4882a593Smuzhiyun             id = coor_data[pos] & 0x0F;
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun         #if GTP_WITH_PEN
903*4882a593Smuzhiyun             id = coor_data[pos];
904*4882a593Smuzhiyun             if ((id & 0x80))
905*4882a593Smuzhiyun             {
906*4882a593Smuzhiyun                 GTP_DEBUG("Pen touch DOWN(Slot)!");
907*4882a593Smuzhiyun                 input_x  = coor_data[pos + 1] | (coor_data[pos + 2] << 8);
908*4882a593Smuzhiyun                 input_y  = coor_data[pos + 3] | (coor_data[pos + 4] << 8);
909*4882a593Smuzhiyun                 input_w  = coor_data[pos + 5] | (coor_data[pos + 6] << 8);
910*4882a593Smuzhiyun 
911*4882a593Smuzhiyun                 gtp_pen_down(input_x, input_y, input_w, 0);
912*4882a593Smuzhiyun                 pre_pen = 1;
913*4882a593Smuzhiyun                 pre_touch = 0;
914*4882a593Smuzhiyun                 pen_active = 1;
915*4882a593Smuzhiyun             }
916*4882a593Smuzhiyun         #endif
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun             touch_index |= (0x01<<id);
919*4882a593Smuzhiyun         }
920*4882a593Smuzhiyun 
921*4882a593Smuzhiyun         GTP_DEBUG("id = %d,touch_index = 0x%x, pre_touch = 0x%x\n",id, touch_index,pre_touch);
922*4882a593Smuzhiyun         for (i = 0; i < GTP_MAX_TOUCH; i++)
923*4882a593Smuzhiyun         {
924*4882a593Smuzhiyun         #if GTP_WITH_PEN
925*4882a593Smuzhiyun             if (pre_pen == 1)
926*4882a593Smuzhiyun             {
927*4882a593Smuzhiyun                 break;
928*4882a593Smuzhiyun             }
929*4882a593Smuzhiyun         #endif
930*4882a593Smuzhiyun 
931*4882a593Smuzhiyun             if ((touch_index & (0x01<<i)))
932*4882a593Smuzhiyun             {
933*4882a593Smuzhiyun                 input_x  = coor_data[pos + 1] | (coor_data[pos + 2] << 8);
934*4882a593Smuzhiyun                 input_y  = coor_data[pos + 3] | (coor_data[pos + 4] << 8);
935*4882a593Smuzhiyun                 input_w  = coor_data[pos + 5] | (coor_data[pos + 6] << 8);
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun                 gtp_touch_down(ts, id, input_x, input_y, input_w);
938*4882a593Smuzhiyun                 pre_touch |= 0x01 << i;
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun                 report_num++;
941*4882a593Smuzhiyun                 if (report_num < touch_num)
942*4882a593Smuzhiyun                 {
943*4882a593Smuzhiyun                     pos += 8;
944*4882a593Smuzhiyun                     id = coor_data[pos] & 0x0F;
945*4882a593Smuzhiyun                     touch_index |= (0x01<<id);
946*4882a593Smuzhiyun                 }
947*4882a593Smuzhiyun             }
948*4882a593Smuzhiyun             else
949*4882a593Smuzhiyun             {
950*4882a593Smuzhiyun                 gtp_touch_up(ts, i);
951*4882a593Smuzhiyun                 pre_touch &= ~(0x01 << i);
952*4882a593Smuzhiyun             }
953*4882a593Smuzhiyun         }
954*4882a593Smuzhiyun     }
955*4882a593Smuzhiyun #else   //end if GTP_ICS_SLOT_REPORT
956*4882a593Smuzhiyun 
957*4882a593Smuzhiyun     if (touch_num)
958*4882a593Smuzhiyun     {
959*4882a593Smuzhiyun         for (i = 0; i < touch_num; i++)
960*4882a593Smuzhiyun         {
961*4882a593Smuzhiyun             coor_data = &point_data[i * 8 + 3];
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun             id = coor_data[0] & 0x0F;
964*4882a593Smuzhiyun             input_x  = coor_data[1] | (coor_data[2] << 8);
965*4882a593Smuzhiyun             input_y  = coor_data[3] | (coor_data[4] << 8);
966*4882a593Smuzhiyun             input_w  = coor_data[5] | (coor_data[6] << 8);
967*4882a593Smuzhiyun 
968*4882a593Smuzhiyun         #if GTP_WITH_PEN
969*4882a593Smuzhiyun             id = coor_data[0];
970*4882a593Smuzhiyun             if (id & 0x80)
971*4882a593Smuzhiyun             {
972*4882a593Smuzhiyun                 GTP_DEBUG("Pen touch DOWN!");
973*4882a593Smuzhiyun                 gtp_pen_down(input_x, input_y, input_w, 0);
974*4882a593Smuzhiyun                 pre_pen = 1;
975*4882a593Smuzhiyun                 pen_active = 1;
976*4882a593Smuzhiyun                 break;
977*4882a593Smuzhiyun             }
978*4882a593Smuzhiyun             else
979*4882a593Smuzhiyun         #endif
980*4882a593Smuzhiyun             {
981*4882a593Smuzhiyun                 gtp_touch_down(ts, id, input_x, input_y, input_w);
982*4882a593Smuzhiyun             }
983*4882a593Smuzhiyun         }
984*4882a593Smuzhiyun     }
985*4882a593Smuzhiyun     else if (pre_touch)
986*4882a593Smuzhiyun     {
987*4882a593Smuzhiyun     #if GTP_WITH_PEN
988*4882a593Smuzhiyun         if (pre_pen == 1)
989*4882a593Smuzhiyun         {
990*4882a593Smuzhiyun             GTP_DEBUG("Pen touch UP!");
991*4882a593Smuzhiyun             gtp_pen_up(0);
992*4882a593Smuzhiyun             pre_pen = 0;
993*4882a593Smuzhiyun             pen_active = 1;
994*4882a593Smuzhiyun         }
995*4882a593Smuzhiyun         else
996*4882a593Smuzhiyun     #endif
997*4882a593Smuzhiyun         {
998*4882a593Smuzhiyun             GTP_DEBUG("Touch Release!");
999*4882a593Smuzhiyun             gtp_touch_up(ts, 0);
1000*4882a593Smuzhiyun         }
1001*4882a593Smuzhiyun     }
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun     pre_touch = touch_num;
1004*4882a593Smuzhiyun #endif
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun #if GTP_WITH_PEN
1007*4882a593Smuzhiyun     if (pen_active)
1008*4882a593Smuzhiyun     {
1009*4882a593Smuzhiyun         pen_active = 0;
1010*4882a593Smuzhiyun         input_sync(ts->pen_dev);
1011*4882a593Smuzhiyun     }
1012*4882a593Smuzhiyun     else
1013*4882a593Smuzhiyun #endif
1014*4882a593Smuzhiyun     {
1015*4882a593Smuzhiyun         input_sync(ts->input_dev);
1016*4882a593Smuzhiyun     }
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun exit_work_func:
1019*4882a593Smuzhiyun     if(!ts->gtp_rawdiff_mode)
1020*4882a593Smuzhiyun     {
1021*4882a593Smuzhiyun         ret = gtp_i2c_write(ts->client, end_cmd, 3);
1022*4882a593Smuzhiyun         if (ret < 0)
1023*4882a593Smuzhiyun         {
1024*4882a593Smuzhiyun             GTP_INFO("I2C write end_cmd error!");
1025*4882a593Smuzhiyun         }
1026*4882a593Smuzhiyun     }
1027*4882a593Smuzhiyun     if (ts->use_irq)
1028*4882a593Smuzhiyun     {
1029*4882a593Smuzhiyun         gtp_irq_enable(ts);
1030*4882a593Smuzhiyun     }
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun release_wakeup_lock:
1033*4882a593Smuzhiyun     if (device_can_wakeup(&ts->client->dev))
1034*4882a593Smuzhiyun         pm_relax(&ts->client->dev);
1035*4882a593Smuzhiyun }
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun /*******************************************************
1038*4882a593Smuzhiyun Function:
1039*4882a593Smuzhiyun     Timer interrupt service routine for polling mode.
1040*4882a593Smuzhiyun Input:
1041*4882a593Smuzhiyun     timer: timer struct pointer
1042*4882a593Smuzhiyun Output:
1043*4882a593Smuzhiyun     Timer work mode.
1044*4882a593Smuzhiyun         HRTIMER_NORESTART: no restart mode
1045*4882a593Smuzhiyun *********************************************************/
goodix_ts_timer_handler(struct hrtimer * timer)1046*4882a593Smuzhiyun static enum hrtimer_restart goodix_ts_timer_handler(struct hrtimer *timer)
1047*4882a593Smuzhiyun {
1048*4882a593Smuzhiyun     struct goodix_ts_data *ts = container_of(timer, struct goodix_ts_data, timer);
1049*4882a593Smuzhiyun 
1050*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1051*4882a593Smuzhiyun 
1052*4882a593Smuzhiyun     queue_work(goodix_wq, &ts->work);
1053*4882a593Smuzhiyun     hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME+6)*1000000), HRTIMER_MODE_REL);
1054*4882a593Smuzhiyun     return HRTIMER_NORESTART;
1055*4882a593Smuzhiyun }
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun /*******************************************************
1058*4882a593Smuzhiyun Function:
1059*4882a593Smuzhiyun     External interrupt service routine for interrupt mode.
1060*4882a593Smuzhiyun Input:
1061*4882a593Smuzhiyun     irq:  interrupt number.
1062*4882a593Smuzhiyun     dev_id: private data pointer
1063*4882a593Smuzhiyun Output:
1064*4882a593Smuzhiyun     Handle Result.
1065*4882a593Smuzhiyun         IRQ_HANDLED: interrupt handled successfully
1066*4882a593Smuzhiyun *********************************************************/
goodix_ts_irq_handler(int irq,void * dev_id)1067*4882a593Smuzhiyun static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
1068*4882a593Smuzhiyun {
1069*4882a593Smuzhiyun     struct goodix_ts_data *ts = dev_id;
1070*4882a593Smuzhiyun 
1071*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1072*4882a593Smuzhiyun 
1073*4882a593Smuzhiyun     gtp_irq_disable(ts);
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun     if (device_can_wakeup(&ts->client->dev))
1076*4882a593Smuzhiyun         pm_stay_awake(&ts->client->dev);
1077*4882a593Smuzhiyun 
1078*4882a593Smuzhiyun     queue_work(goodix_wq, &ts->work);
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun     return IRQ_HANDLED;
1081*4882a593Smuzhiyun }
1082*4882a593Smuzhiyun /*******************************************************
1083*4882a593Smuzhiyun Function:
1084*4882a593Smuzhiyun     Synchronization.
1085*4882a593Smuzhiyun Input:
1086*4882a593Smuzhiyun     ms: synchronization time in millisecond.
1087*4882a593Smuzhiyun Output:
1088*4882a593Smuzhiyun     None.
1089*4882a593Smuzhiyun *******************************************************/
gtp_int_sync(s32 ms,struct goodix_ts_data * ts)1090*4882a593Smuzhiyun void gtp_int_sync(s32 ms, struct goodix_ts_data *ts)
1091*4882a593Smuzhiyun {
1092*4882a593Smuzhiyun     GTP_GPIO_OUTPUT(ts->irq_pin, 0);
1093*4882a593Smuzhiyun     msleep(ms);
1094*4882a593Smuzhiyun     //GTP_GPIO_AS_INT(GTP_INT_PORT);
1095*4882a593Smuzhiyun     gpio_direction_input(ts->irq_pin);
1096*4882a593Smuzhiyun     //s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
1097*4882a593Smuzhiyun     //s3c_gpio_cfgpin(pin, GTP_INT_CFG);
1098*4882a593Smuzhiyun }
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun /*******************************************************
1102*4882a593Smuzhiyun Function:
1103*4882a593Smuzhiyun     Reset chip.
1104*4882a593Smuzhiyun Input:
1105*4882a593Smuzhiyun     ms: reset time in millisecond
1106*4882a593Smuzhiyun Output:
1107*4882a593Smuzhiyun     None.
1108*4882a593Smuzhiyun *******************************************************/
gtp_reset_guitar(struct i2c_client * client,s32 ms)1109*4882a593Smuzhiyun void gtp_reset_guitar(struct i2c_client *client, s32 ms)
1110*4882a593Smuzhiyun {
1111*4882a593Smuzhiyun     struct goodix_ts_data *ts = i2c_get_clientdata(client);
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1114*4882a593Smuzhiyun     GTP_INFO("Guitar reset");
1115*4882a593Smuzhiyun     GTP_GPIO_OUTPUT(ts->rst_pin, 0);   // begin select I2C slave addr
1116*4882a593Smuzhiyun     msleep(ms);                         // T2: > 10ms
1117*4882a593Smuzhiyun     // HIGH: 0x28/0x29, LOW: 0xBA/0xBB
1118*4882a593Smuzhiyun     GTP_GPIO_OUTPUT(ts->irq_pin, client->addr == 0x14);
1119*4882a593Smuzhiyun 
1120*4882a593Smuzhiyun     msleep(2);                          // T3: > 100us
1121*4882a593Smuzhiyun     GTP_GPIO_OUTPUT(ts->rst_pin, 1);
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun     msleep(6);                          // T4: > 5ms
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun     //GTP_GPIO_AS_INPUT(GTP_RST_PORT);    // end select I2C slave addr
1126*4882a593Smuzhiyun     gpio_direction_input(ts->rst_pin);
1127*4882a593Smuzhiyun     //s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
1128*4882a593Smuzhiyun 
1129*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
1130*4882a593Smuzhiyun     if (CHIP_TYPE_GT9F == ts->chip_type)
1131*4882a593Smuzhiyun     {
1132*4882a593Smuzhiyun         return;
1133*4882a593Smuzhiyun     }
1134*4882a593Smuzhiyun #endif
1135*4882a593Smuzhiyun 
1136*4882a593Smuzhiyun     gtp_int_sync(50, ts);
1137*4882a593Smuzhiyun #if GTP_ESD_PROTECT
1138*4882a593Smuzhiyun     gtp_init_ext_watchdog(client);
1139*4882a593Smuzhiyun #endif
1140*4882a593Smuzhiyun }
1141*4882a593Smuzhiyun 
1142*4882a593Smuzhiyun #if GTP_GESTURE_WAKEUP
1143*4882a593Smuzhiyun /*******************************************************
1144*4882a593Smuzhiyun Function:
1145*4882a593Smuzhiyun     Enter doze mode for sliding wakeup.
1146*4882a593Smuzhiyun Input:
1147*4882a593Smuzhiyun     ts: goodix tp private data
1148*4882a593Smuzhiyun Output:
1149*4882a593Smuzhiyun     1: succeed, otherwise failed
1150*4882a593Smuzhiyun *******************************************************/
gtp_enter_doze(struct goodix_ts_data * ts)1151*4882a593Smuzhiyun static s8 gtp_enter_doze(struct goodix_ts_data *ts)
1152*4882a593Smuzhiyun {
1153*4882a593Smuzhiyun     s8 ret = -1;
1154*4882a593Smuzhiyun     s8 retry = 0;
1155*4882a593Smuzhiyun     u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8), (u8)GTP_REG_SLEEP, 8};
1156*4882a593Smuzhiyun 
1157*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1158*4882a593Smuzhiyun 
1159*4882a593Smuzhiyun     GTP_DEBUG("Entering gesture mode.");
1160*4882a593Smuzhiyun     while(retry++ < 5)
1161*4882a593Smuzhiyun     {
1162*4882a593Smuzhiyun         i2c_control_buf[0] = 0x80;
1163*4882a593Smuzhiyun         i2c_control_buf[1] = 0x46;
1164*4882a593Smuzhiyun         ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
1165*4882a593Smuzhiyun         if (ret < 0)
1166*4882a593Smuzhiyun         {
1167*4882a593Smuzhiyun             GTP_DEBUG("failed to set doze flag into 0x8046, %d", retry);
1168*4882a593Smuzhiyun             continue;
1169*4882a593Smuzhiyun         }
1170*4882a593Smuzhiyun         i2c_control_buf[0] = 0x80;
1171*4882a593Smuzhiyun         i2c_control_buf[1] = 0x40;
1172*4882a593Smuzhiyun         ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
1173*4882a593Smuzhiyun         if (ret > 0)
1174*4882a593Smuzhiyun         {
1175*4882a593Smuzhiyun             doze_status = DOZE_ENABLED;
1176*4882a593Smuzhiyun             GTP_INFO("Gesture mode enabled.");
1177*4882a593Smuzhiyun             return ret;
1178*4882a593Smuzhiyun         }
1179*4882a593Smuzhiyun         msleep(10);
1180*4882a593Smuzhiyun     }
1181*4882a593Smuzhiyun     GTP_ERROR("GTP send gesture cmd failed.");
1182*4882a593Smuzhiyun     return ret;
1183*4882a593Smuzhiyun }
1184*4882a593Smuzhiyun #else
1185*4882a593Smuzhiyun /*******************************************************
1186*4882a593Smuzhiyun Function:
1187*4882a593Smuzhiyun     Enter sleep mode.
1188*4882a593Smuzhiyun Input:
1189*4882a593Smuzhiyun     ts: private data.
1190*4882a593Smuzhiyun Output:
1191*4882a593Smuzhiyun     Executive outcomes.
1192*4882a593Smuzhiyun        1: succeed, otherwise failed.
1193*4882a593Smuzhiyun *******************************************************/
gtp_enter_sleep(struct goodix_ts_data * ts)1194*4882a593Smuzhiyun static s8 gtp_enter_sleep(struct goodix_ts_data * ts)
1195*4882a593Smuzhiyun {
1196*4882a593Smuzhiyun     s8 ret = -1;
1197*4882a593Smuzhiyun     s8 retry = 0;
1198*4882a593Smuzhiyun     u8 i2c_control_buf[3] = {(u8)(GTP_REG_SLEEP >> 8), (u8)GTP_REG_SLEEP, 5};
1199*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
1200*4882a593Smuzhiyun     u8 status_buf[3] = {0x80, 0x44};
1201*4882a593Smuzhiyun #endif
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
1206*4882a593Smuzhiyun     if (CHIP_TYPE_GT9F == ts->chip_type)
1207*4882a593Smuzhiyun     {
1208*4882a593Smuzhiyun         // GT9XXF: host interact with ic
1209*4882a593Smuzhiyun         ret = gtp_i2c_read(ts->client, status_buf, 3);
1210*4882a593Smuzhiyun         if (ret < 0)
1211*4882a593Smuzhiyun         {
1212*4882a593Smuzhiyun             GTP_ERROR("failed to get backup-reference status");
1213*4882a593Smuzhiyun         }
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun         if (status_buf[2] & 0x80)
1216*4882a593Smuzhiyun         {
1217*4882a593Smuzhiyun             ret = gtp_bak_ref_proc(ts, GTP_BAK_REF_STORE);
1218*4882a593Smuzhiyun             if (FAIL == ret)
1219*4882a593Smuzhiyun             {
1220*4882a593Smuzhiyun                 GTP_ERROR("failed to store bak_ref");
1221*4882a593Smuzhiyun             }
1222*4882a593Smuzhiyun         }
1223*4882a593Smuzhiyun     }
1224*4882a593Smuzhiyun #endif
1225*4882a593Smuzhiyun 
1226*4882a593Smuzhiyun     GTP_GPIO_OUTPUT(ts->irq_pin, 0);
1227*4882a593Smuzhiyun     msleep(5);
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun     while(retry++ < 5)
1230*4882a593Smuzhiyun     {
1231*4882a593Smuzhiyun         ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
1232*4882a593Smuzhiyun         if (ret > 0)
1233*4882a593Smuzhiyun         {
1234*4882a593Smuzhiyun             GTP_INFO("GTP enter sleep!");
1235*4882a593Smuzhiyun 
1236*4882a593Smuzhiyun             return ret;
1237*4882a593Smuzhiyun         }
1238*4882a593Smuzhiyun         msleep(10);
1239*4882a593Smuzhiyun     }
1240*4882a593Smuzhiyun     GTP_ERROR("GTP send sleep cmd failed.");
1241*4882a593Smuzhiyun     return ret;
1242*4882a593Smuzhiyun }
1243*4882a593Smuzhiyun #endif
1244*4882a593Smuzhiyun /*******************************************************
1245*4882a593Smuzhiyun Function:
1246*4882a593Smuzhiyun     Wakeup from sleep.
1247*4882a593Smuzhiyun Input:
1248*4882a593Smuzhiyun     ts: private data.
1249*4882a593Smuzhiyun Output:
1250*4882a593Smuzhiyun     Executive outcomes.
1251*4882a593Smuzhiyun         >0: succeed, otherwise: failed.
1252*4882a593Smuzhiyun *******************************************************/
gtp_wakeup_sleep(struct goodix_ts_data * ts)1253*4882a593Smuzhiyun static s8 gtp_wakeup_sleep(struct goodix_ts_data * ts)
1254*4882a593Smuzhiyun {
1255*4882a593Smuzhiyun     u8 retry = 0;
1256*4882a593Smuzhiyun     s8 ret = -1;
1257*4882a593Smuzhiyun 
1258*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1259*4882a593Smuzhiyun 
1260*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
1261*4882a593Smuzhiyun     if (CHIP_TYPE_GT9F == ts->chip_type)
1262*4882a593Smuzhiyun     {
1263*4882a593Smuzhiyun         u8 opr_buf[3] = {0x41, 0x80};
1264*4882a593Smuzhiyun 
1265*4882a593Smuzhiyun         GTP_GPIO_OUTPUT(ts->irq_pin, 1);
1266*4882a593Smuzhiyun         msleep(5);
1267*4882a593Smuzhiyun 
1268*4882a593Smuzhiyun         for (retry = 0; retry < 10; ++retry)
1269*4882a593Smuzhiyun         {
1270*4882a593Smuzhiyun             // hold ss51 & dsp
1271*4882a593Smuzhiyun             opr_buf[2] = 0x0C;
1272*4882a593Smuzhiyun             ret = gtp_i2c_write(ts->client, opr_buf, 3);
1273*4882a593Smuzhiyun             if (FAIL == ret)
1274*4882a593Smuzhiyun             {
1275*4882a593Smuzhiyun                 GTP_ERROR("failed to hold ss51 & dsp!");
1276*4882a593Smuzhiyun                 continue;
1277*4882a593Smuzhiyun             }
1278*4882a593Smuzhiyun             opr_buf[2] = 0x00;
1279*4882a593Smuzhiyun             ret = gtp_i2c_read(ts->client, opr_buf, 3);
1280*4882a593Smuzhiyun             if (FAIL == ret)
1281*4882a593Smuzhiyun             {
1282*4882a593Smuzhiyun                 GTP_ERROR("failed to get ss51 & dsp status!");
1283*4882a593Smuzhiyun                 continue;
1284*4882a593Smuzhiyun             }
1285*4882a593Smuzhiyun             if (0x0C != opr_buf[2])
1286*4882a593Smuzhiyun             {
1287*4882a593Smuzhiyun                 GTP_DEBUG("ss51 & dsp not been hold, %d", retry+1);
1288*4882a593Smuzhiyun                 continue;
1289*4882a593Smuzhiyun             }
1290*4882a593Smuzhiyun             GTP_DEBUG("ss51 & dsp confirmed hold");
1291*4882a593Smuzhiyun 
1292*4882a593Smuzhiyun             ret = gtp_fw_startup(ts->client);
1293*4882a593Smuzhiyun             if (FAIL == ret)
1294*4882a593Smuzhiyun             {
1295*4882a593Smuzhiyun                 GTP_ERROR("failed to startup GT9XXF, process recovery");
1296*4882a593Smuzhiyun                 gtp_esd_recovery(ts->client);
1297*4882a593Smuzhiyun             }
1298*4882a593Smuzhiyun             break;
1299*4882a593Smuzhiyun         }
1300*4882a593Smuzhiyun         if (retry >= 10)
1301*4882a593Smuzhiyun         {
1302*4882a593Smuzhiyun             GTP_ERROR("failed to wakeup, processing esd recovery");
1303*4882a593Smuzhiyun             gtp_esd_recovery(ts->client);
1304*4882a593Smuzhiyun         }
1305*4882a593Smuzhiyun         else
1306*4882a593Smuzhiyun         {
1307*4882a593Smuzhiyun             GTP_INFO("GT9XXF gtp wakeup success");
1308*4882a593Smuzhiyun         }
1309*4882a593Smuzhiyun         return ret;
1310*4882a593Smuzhiyun     }
1311*4882a593Smuzhiyun #endif
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun #if GTP_POWER_CTRL_SLEEP
1314*4882a593Smuzhiyun     while(retry++ < 5)
1315*4882a593Smuzhiyun     {
1316*4882a593Smuzhiyun         gtp_reset_guitar(ts->client, 20);
1317*4882a593Smuzhiyun 
1318*4882a593Smuzhiyun         GTP_INFO("GTP wakeup sleep.");
1319*4882a593Smuzhiyun         return 1;
1320*4882a593Smuzhiyun     }
1321*4882a593Smuzhiyun #else
1322*4882a593Smuzhiyun     while(retry++ < 10)
1323*4882a593Smuzhiyun     {
1324*4882a593Smuzhiyun     #if GTP_GESTURE_WAKEUP
1325*4882a593Smuzhiyun         if (DOZE_WAKEUP != doze_status)
1326*4882a593Smuzhiyun         {
1327*4882a593Smuzhiyun             GTP_INFO("Powerkey wakeup.");
1328*4882a593Smuzhiyun         }
1329*4882a593Smuzhiyun         else
1330*4882a593Smuzhiyun         {
1331*4882a593Smuzhiyun             GTP_INFO("Gesture wakeup.");
1332*4882a593Smuzhiyun         }
1333*4882a593Smuzhiyun         doze_status = DOZE_DISABLED;
1334*4882a593Smuzhiyun         gtp_irq_disable(ts);
1335*4882a593Smuzhiyun         gtp_reset_guitar(ts->client, 10);
1336*4882a593Smuzhiyun         gtp_irq_enable(ts);
1337*4882a593Smuzhiyun 
1338*4882a593Smuzhiyun     #else
1339*4882a593Smuzhiyun         GTP_GPIO_OUTPUT(ts->irq_pin, 1);
1340*4882a593Smuzhiyun         msleep(5);
1341*4882a593Smuzhiyun     #endif
1342*4882a593Smuzhiyun 
1343*4882a593Smuzhiyun         ret = gtp_i2c_test(ts->client);
1344*4882a593Smuzhiyun         if (ret > 0)
1345*4882a593Smuzhiyun         {
1346*4882a593Smuzhiyun             GTP_INFO("GTP wakeup sleep.");
1347*4882a593Smuzhiyun 
1348*4882a593Smuzhiyun         #if (!GTP_GESTURE_WAKEUP)
1349*4882a593Smuzhiyun             {
1350*4882a593Smuzhiyun                 gtp_int_sync(25, ts);
1351*4882a593Smuzhiyun             #if GTP_ESD_PROTECT
1352*4882a593Smuzhiyun                 gtp_init_ext_watchdog(ts->client);
1353*4882a593Smuzhiyun             #endif
1354*4882a593Smuzhiyun             }
1355*4882a593Smuzhiyun         #endif
1356*4882a593Smuzhiyun 
1357*4882a593Smuzhiyun             return ret;
1358*4882a593Smuzhiyun         }
1359*4882a593Smuzhiyun         gtp_reset_guitar(ts->client, 20);
1360*4882a593Smuzhiyun     }
1361*4882a593Smuzhiyun #endif
1362*4882a593Smuzhiyun 
1363*4882a593Smuzhiyun     GTP_ERROR("GTP wakeup sleep failed.");
1364*4882a593Smuzhiyun     return ret;
1365*4882a593Smuzhiyun }
1366*4882a593Smuzhiyun #if GTP_DRIVER_SEND_CFG
gtp_get_info(struct goodix_ts_data * ts)1367*4882a593Smuzhiyun static s32 gtp_get_info(struct goodix_ts_data *ts)
1368*4882a593Smuzhiyun {
1369*4882a593Smuzhiyun     u8 opr_buf[6] = {0};
1370*4882a593Smuzhiyun     s32 ret = 0;
1371*4882a593Smuzhiyun 
1372*4882a593Smuzhiyun     //ts->abs_x_max = GTP_MAX_WIDTH;
1373*4882a593Smuzhiyun     //ts->abs_y_max = GTP_MAX_HEIGHT;
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun     ts->int_trigger_type = GTP_INT_TRIGGER;
1376*4882a593Smuzhiyun 
1377*4882a593Smuzhiyun     opr_buf[0] = (u8)((GTP_REG_CONFIG_DATA+1) >> 8);
1378*4882a593Smuzhiyun     opr_buf[1] = (u8)((GTP_REG_CONFIG_DATA+1) & 0xFF);
1379*4882a593Smuzhiyun 
1380*4882a593Smuzhiyun     ret = gtp_i2c_read(ts->client, opr_buf, 6);
1381*4882a593Smuzhiyun     if (ret < 0)
1382*4882a593Smuzhiyun     {
1383*4882a593Smuzhiyun         return FAIL;
1384*4882a593Smuzhiyun     }
1385*4882a593Smuzhiyun 
1386*4882a593Smuzhiyun     ts->abs_x_max = (opr_buf[3] << 8) + opr_buf[2];
1387*4882a593Smuzhiyun     ts->abs_y_max = (opr_buf[5] << 8) + opr_buf[4];
1388*4882a593Smuzhiyun 
1389*4882a593Smuzhiyun     opr_buf[0] = (u8)((GTP_REG_CONFIG_DATA+6) >> 8);
1390*4882a593Smuzhiyun     opr_buf[1] = (u8)((GTP_REG_CONFIG_DATA+6) & 0xFF);
1391*4882a593Smuzhiyun 
1392*4882a593Smuzhiyun     ret = gtp_i2c_read(ts->client, opr_buf, 3);
1393*4882a593Smuzhiyun     if (ret < 0)
1394*4882a593Smuzhiyun     {
1395*4882a593Smuzhiyun         return FAIL;
1396*4882a593Smuzhiyun     }
1397*4882a593Smuzhiyun     ts->int_trigger_type = opr_buf[2] & 0x03;
1398*4882a593Smuzhiyun 
1399*4882a593Smuzhiyun     GTP_INFO("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",
1400*4882a593Smuzhiyun             ts->abs_x_max,ts->abs_y_max,ts->int_trigger_type);
1401*4882a593Smuzhiyun 
1402*4882a593Smuzhiyun     return SUCCESS;
1403*4882a593Smuzhiyun }
1404*4882a593Smuzhiyun #endif
1405*4882a593Smuzhiyun 
1406*4882a593Smuzhiyun /*******************************************************
1407*4882a593Smuzhiyun Function:
1408*4882a593Smuzhiyun     Initialize gtp.
1409*4882a593Smuzhiyun Input:
1410*4882a593Smuzhiyun     ts: goodix private data
1411*4882a593Smuzhiyun Output:
1412*4882a593Smuzhiyun     Executive outcomes.
1413*4882a593Smuzhiyun         0: succeed, otherwise: failed
1414*4882a593Smuzhiyun *******************************************************/
gtp_init_panel(struct goodix_ts_data * ts)1415*4882a593Smuzhiyun static s32 gtp_init_panel(struct goodix_ts_data *ts)
1416*4882a593Smuzhiyun {
1417*4882a593Smuzhiyun     s32 ret = -1;
1418*4882a593Smuzhiyun #if GTP_DRIVER_SEND_CFG
1419*4882a593Smuzhiyun     s32 i = 0;
1420*4882a593Smuzhiyun     u8 check_sum = 0;
1421*4882a593Smuzhiyun     u8 opr_buf[16] = {0};
1422*4882a593Smuzhiyun     u8 sensor_id = 0;
1423*4882a593Smuzhiyun 
1424*4882a593Smuzhiyun     u8 cfg_info_group2[] = CTP_CFG_GROUP2;
1425*4882a593Smuzhiyun     u8 cfg_info_group3[] = CTP_CFG_GROUP3;
1426*4882a593Smuzhiyun     u8 cfg_info_group4[] = CTP_CFG_GROUP4;
1427*4882a593Smuzhiyun     u8 cfg_info_group5[] = CTP_CFG_GROUP5;
1428*4882a593Smuzhiyun     u8 cfg_info_group6[] = CTP_CFG_GROUP6;
1429*4882a593Smuzhiyun     u8 *send_cfg_buf[] = {gtp_dat_10_1, cfg_info_group2, cfg_info_group3,
1430*4882a593Smuzhiyun                             cfg_info_group4, cfg_info_group5, cfg_info_group6};
1431*4882a593Smuzhiyun     u8 cfg_info_len[] = { CFG_GROUP_LEN(gtp_dat_10_1),
1432*4882a593Smuzhiyun                               CFG_GROUP_LEN(cfg_info_group2),
1433*4882a593Smuzhiyun                               CFG_GROUP_LEN(cfg_info_group3),
1434*4882a593Smuzhiyun                               CFG_GROUP_LEN(cfg_info_group4),
1435*4882a593Smuzhiyun                               CFG_GROUP_LEN(cfg_info_group5),
1436*4882a593Smuzhiyun                               CFG_GROUP_LEN(cfg_info_group6)};;
1437*4882a593Smuzhiyun 
1438*4882a593Smuzhiyun     GTP_INFO("  <%s>_%d \n", __func__, __LINE__);
1439*4882a593Smuzhiyun 
1440*4882a593Smuzhiyun     if(m89or101){
1441*4882a593Smuzhiyun 	    if (ts->cfg_file_num) {
1442*4882a593Smuzhiyun 		    send_cfg_buf[0] = gtp_dat_8_9_1;
1443*4882a593Smuzhiyun 		    cfg_info_len[0] =  CFG_GROUP_LEN(gtp_dat_8_9_1);
1444*4882a593Smuzhiyun 	    } else {
1445*4882a593Smuzhiyun 		    send_cfg_buf[0] = gtp_dat_8_9;
1446*4882a593Smuzhiyun 		    cfg_info_len[0] =  CFG_GROUP_LEN(gtp_dat_8_9);
1447*4882a593Smuzhiyun 	    }
1448*4882a593Smuzhiyun     }
1449*4882a593Smuzhiyun 
1450*4882a593Smuzhiyun     if (bgt911) {
1451*4882a593Smuzhiyun     	send_cfg_buf[0] = gtp_dat_gt11;
1452*4882a593Smuzhiyun 		cfg_info_len[0] =  CFG_GROUP_LEN(gtp_dat_gt11);
1453*4882a593Smuzhiyun     }
1454*4882a593Smuzhiyun 
1455*4882a593Smuzhiyun     if (bgt9110) {
1456*4882a593Smuzhiyun 	    send_cfg_buf[0] = gtp_dat_gt9110;
1457*4882a593Smuzhiyun 	    cfg_info_len[0] =  CFG_GROUP_LEN(gtp_dat_gt9110);
1458*4882a593Smuzhiyun     }
1459*4882a593Smuzhiyun 
1460*4882a593Smuzhiyun 	if (bgt9111) {
1461*4882a593Smuzhiyun 		send_cfg_buf[0] = gtp_dat_gt9111;
1462*4882a593Smuzhiyun 		cfg_info_len[0] =  CFG_GROUP_LEN(gtp_dat_gt9111);
1463*4882a593Smuzhiyun 	}
1464*4882a593Smuzhiyun 
1465*4882a593Smuzhiyun 	if (bgt970) {
1466*4882a593Smuzhiyun 		send_cfg_buf[0] = gtp_dat_9_7;
1467*4882a593Smuzhiyun 		cfg_info_len[0] = CFG_GROUP_LEN(gtp_dat_9_7);
1468*4882a593Smuzhiyun 	}
1469*4882a593Smuzhiyun 
1470*4882a593Smuzhiyun 	if (bgt910) {
1471*4882a593Smuzhiyun 		send_cfg_buf[0] = gtp_dat_7;
1472*4882a593Smuzhiyun 		cfg_info_len[0] = CFG_GROUP_LEN(gtp_dat_7);
1473*4882a593Smuzhiyun 	}
1474*4882a593Smuzhiyun 
1475*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1476*4882a593Smuzhiyun     GTP_DEBUG("Config Groups\' Lengths: %d, %d, %d, %d, %d, %d",
1477*4882a593Smuzhiyun         cfg_info_len[0], cfg_info_len[1], cfg_info_len[2], cfg_info_len[3],
1478*4882a593Smuzhiyun         cfg_info_len[4], cfg_info_len[5]);
1479*4882a593Smuzhiyun 
1480*4882a593Smuzhiyun 
1481*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
1482*4882a593Smuzhiyun     if (CHIP_TYPE_GT9F == ts->chip_type)
1483*4882a593Smuzhiyun     {
1484*4882a593Smuzhiyun         ts->fw_error = 0;
1485*4882a593Smuzhiyun     }
1486*4882a593Smuzhiyun     else
1487*4882a593Smuzhiyun #endif
1488*4882a593Smuzhiyun     {
1489*4882a593Smuzhiyun         ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);
1490*4882a593Smuzhiyun         if (SUCCESS == ret)
1491*4882a593Smuzhiyun         {
1492*4882a593Smuzhiyun             if (opr_buf[0] != 0xBE)
1493*4882a593Smuzhiyun             {
1494*4882a593Smuzhiyun                 ts->fw_error = 1;
1495*4882a593Smuzhiyun                 GTP_ERROR("Firmware error, no config sent!");
1496*4882a593Smuzhiyun                 return -1;
1497*4882a593Smuzhiyun             }
1498*4882a593Smuzhiyun         }
1499*4882a593Smuzhiyun     }
1500*4882a593Smuzhiyun 
1501*4882a593Smuzhiyun     if ((!cfg_info_len[1]) && (!cfg_info_len[2]) &&
1502*4882a593Smuzhiyun         (!cfg_info_len[3]) && (!cfg_info_len[4]) &&
1503*4882a593Smuzhiyun         (!cfg_info_len[5]))
1504*4882a593Smuzhiyun     {
1505*4882a593Smuzhiyun         sensor_id = 0;
1506*4882a593Smuzhiyun     }
1507*4882a593Smuzhiyun     else
1508*4882a593Smuzhiyun     {
1509*4882a593Smuzhiyun     #if GTP_COMPATIBLE_MODE
1510*4882a593Smuzhiyun         msleep(50);
1511*4882a593Smuzhiyun     #endif
1512*4882a593Smuzhiyun         ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID, &sensor_id, 1);
1513*4882a593Smuzhiyun         if (SUCCESS == ret)
1514*4882a593Smuzhiyun         {
1515*4882a593Smuzhiyun             if (sensor_id >= 0x06)
1516*4882a593Smuzhiyun             {
1517*4882a593Smuzhiyun                 GTP_ERROR("Invalid sensor_id(0x%02X), No Config Sent!", sensor_id);
1518*4882a593Smuzhiyun                 ts->pnl_init_error = 1;
1519*4882a593Smuzhiyun                 return -1;
1520*4882a593Smuzhiyun             }
1521*4882a593Smuzhiyun         }
1522*4882a593Smuzhiyun         else
1523*4882a593Smuzhiyun         {
1524*4882a593Smuzhiyun             GTP_ERROR("Failed to get sensor_id, No config sent!");
1525*4882a593Smuzhiyun             ts->pnl_init_error = 1;
1526*4882a593Smuzhiyun             return -1;
1527*4882a593Smuzhiyun         }
1528*4882a593Smuzhiyun         GTP_INFO("Sensor_ID: %d", sensor_id);
1529*4882a593Smuzhiyun     }
1530*4882a593Smuzhiyun     ts->gtp_cfg_len = cfg_info_len[sensor_id];
1531*4882a593Smuzhiyun     GTP_INFO("CTP_CONFIG_GROUP%d used, config length: %d", sensor_id + 1, ts->gtp_cfg_len);
1532*4882a593Smuzhiyun 
1533*4882a593Smuzhiyun     if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH)
1534*4882a593Smuzhiyun     {
1535*4882a593Smuzhiyun         GTP_ERROR("Config Group%d is INVALID CONFIG GROUP(Len: %d)! NO Config Sent! You need to check you header file CFG_GROUP section!", sensor_id+1, ts->gtp_cfg_len);
1536*4882a593Smuzhiyun         ts->pnl_init_error = 1;
1537*4882a593Smuzhiyun         return -1;
1538*4882a593Smuzhiyun     }
1539*4882a593Smuzhiyun 
1540*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
1541*4882a593Smuzhiyun     if (CHIP_TYPE_GT9F == ts->chip_type)
1542*4882a593Smuzhiyun     {
1543*4882a593Smuzhiyun         ts->fixed_cfg = 0;
1544*4882a593Smuzhiyun     }
1545*4882a593Smuzhiyun     else
1546*4882a593Smuzhiyun #endif
1547*4882a593Smuzhiyun     {
1548*4882a593Smuzhiyun         ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, &opr_buf[0], 1);
1549*4882a593Smuzhiyun 
1550*4882a593Smuzhiyun         if (ret == SUCCESS)
1551*4882a593Smuzhiyun         {
1552*4882a593Smuzhiyun             GTP_DEBUG("CFG_GROUP%d Config Version: %d, 0x%02X; IC Config Version: %d, 0x%02X", sensor_id+1,
1553*4882a593Smuzhiyun                         send_cfg_buf[sensor_id][0], send_cfg_buf[sensor_id][0], opr_buf[0], opr_buf[0]);
1554*4882a593Smuzhiyun 
1555*4882a593Smuzhiyun             if (opr_buf[0] < 90)
1556*4882a593Smuzhiyun             {
1557*4882a593Smuzhiyun                 GTP_INFO("  <%s>_%d \n", __func__, __LINE__);
1558*4882a593Smuzhiyun                 grp_cfg_version = send_cfg_buf[sensor_id][0];       // backup group config version
1559*4882a593Smuzhiyun                 send_cfg_buf[sensor_id][0] = 0x00;
1560*4882a593Smuzhiyun                 ts->fixed_cfg = 0;
1561*4882a593Smuzhiyun             }
1562*4882a593Smuzhiyun             else        // treated as fixed config, not send config
1563*4882a593Smuzhiyun             {
1564*4882a593Smuzhiyun                 GTP_INFO("Ic fixed config with config version(%d, 0x%02X)", opr_buf[0], opr_buf[0]);
1565*4882a593Smuzhiyun                 ts->fixed_cfg = 1;
1566*4882a593Smuzhiyun                 gtp_get_info(ts);
1567*4882a593Smuzhiyun                 return 0;
1568*4882a593Smuzhiyun             }
1569*4882a593Smuzhiyun         }
1570*4882a593Smuzhiyun         else
1571*4882a593Smuzhiyun         {
1572*4882a593Smuzhiyun             GTP_ERROR("Failed to get ic config version!No config sent!");
1573*4882a593Smuzhiyun             return -1;
1574*4882a593Smuzhiyun         }
1575*4882a593Smuzhiyun     }
1576*4882a593Smuzhiyun 
1577*4882a593Smuzhiyun     memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
1578*4882a593Smuzhiyun     memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id], ts->gtp_cfg_len);
1579*4882a593Smuzhiyun 
1580*4882a593Smuzhiyun #if GTP_CUSTOM_CFG
1581*4882a593Smuzhiyun     config[RESOLUTION_LOC]     = (u8)GTP_MAX_WIDTH;
1582*4882a593Smuzhiyun     config[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);
1583*4882a593Smuzhiyun     config[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;
1584*4882a593Smuzhiyun     config[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);
1585*4882a593Smuzhiyun 
1586*4882a593Smuzhiyun     if (GTP_INT_TRIGGER == 0)  //RISING
1587*4882a593Smuzhiyun     {
1588*4882a593Smuzhiyun         config[TRIGGER_LOC] &= 0xfe;
1589*4882a593Smuzhiyun     }
1590*4882a593Smuzhiyun     else if (GTP_INT_TRIGGER == 1)  //FALLING
1591*4882a593Smuzhiyun     {
1592*4882a593Smuzhiyun         config[TRIGGER_LOC] |= 0x01;
1593*4882a593Smuzhiyun     }
1594*4882a593Smuzhiyun #endif  // GTP_CUSTOM_CFG
1595*4882a593Smuzhiyun 
1596*4882a593Smuzhiyun     check_sum = 0;
1597*4882a593Smuzhiyun     for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
1598*4882a593Smuzhiyun     {
1599*4882a593Smuzhiyun         check_sum += config[i];
1600*4882a593Smuzhiyun     }
1601*4882a593Smuzhiyun     config[ts->gtp_cfg_len] = (~check_sum) + 1;
1602*4882a593Smuzhiyun 
1603*4882a593Smuzhiyun #else // driver not send config
1604*4882a593Smuzhiyun 
1605*4882a593Smuzhiyun     ts->gtp_cfg_len = GTP_CONFIG_MAX_LENGTH;
1606*4882a593Smuzhiyun     ret = gtp_i2c_read(ts->client, config, ts->gtp_cfg_len + GTP_ADDR_LENGTH);
1607*4882a593Smuzhiyun     if (ret < 0)
1608*4882a593Smuzhiyun     {
1609*4882a593Smuzhiyun         GTP_ERROR("Read Config Failed, Using Default Resolution & INT Trigger!");
1610*4882a593Smuzhiyun         //ts->abs_x_max = GTP_MAX_WIDTH;
1611*4882a593Smuzhiyun         //ts->abs_y_max = GTP_MAX_HEIGHT;
1612*4882a593Smuzhiyun         ts->int_trigger_type = GTP_INT_TRIGGER;
1613*4882a593Smuzhiyun     }
1614*4882a593Smuzhiyun 
1615*4882a593Smuzhiyun #endif // GTP_DRIVER_SEND_CFG
1616*4882a593Smuzhiyun 
1617*4882a593Smuzhiyun     if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0))
1618*4882a593Smuzhiyun     {
1619*4882a593Smuzhiyun         ts->abs_x_max = (config[RESOLUTION_LOC + 1] << 8) + config[RESOLUTION_LOC];
1620*4882a593Smuzhiyun         ts->abs_y_max = (config[RESOLUTION_LOC + 3] << 8) + config[RESOLUTION_LOC + 2];
1621*4882a593Smuzhiyun         ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03;
1622*4882a593Smuzhiyun         GTP_INFO("  <%s>_%d    <%d, %d>\n", __func__, __LINE__, ts->abs_x_max, ts->abs_y_max);
1623*4882a593Smuzhiyun     }
1624*4882a593Smuzhiyun     GTP_INFO("  <%s>_%d \n", __func__, __LINE__);
1625*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
1626*4882a593Smuzhiyun     if (CHIP_TYPE_GT9F == ts->chip_type)
1627*4882a593Smuzhiyun     {
1628*4882a593Smuzhiyun         u8 sensor_num = 0;
1629*4882a593Smuzhiyun         u8 driver_num = 0;
1630*4882a593Smuzhiyun         u8 have_key = 0;
1631*4882a593Smuzhiyun 
1632*4882a593Smuzhiyun         have_key = (config[GTP_REG_HAVE_KEY - GTP_REG_CONFIG_DATA + 2] & 0x01);
1633*4882a593Smuzhiyun 
1634*4882a593Smuzhiyun         if (1 == ts->is_950)
1635*4882a593Smuzhiyun         {
1636*4882a593Smuzhiyun             driver_num = config[GTP_REG_MATRIX_DRVNUM - GTP_REG_CONFIG_DATA + 2];
1637*4882a593Smuzhiyun             sensor_num = config[GTP_REG_MATRIX_SENNUM - GTP_REG_CONFIG_DATA + 2];
1638*4882a593Smuzhiyun             if (have_key)
1639*4882a593Smuzhiyun             {
1640*4882a593Smuzhiyun                 driver_num--;
1641*4882a593Smuzhiyun             }
1642*4882a593Smuzhiyun             ts->bak_ref_len = (driver_num * (sensor_num - 1) + 2) * 2 * 6;
1643*4882a593Smuzhiyun         }
1644*4882a593Smuzhiyun         else
1645*4882a593Smuzhiyun         {
1646*4882a593Smuzhiyun             driver_num = (config[CFG_LOC_DRVA_NUM] & 0x1F) + (config[CFG_LOC_DRVB_NUM]&0x1F);
1647*4882a593Smuzhiyun             if (have_key)
1648*4882a593Smuzhiyun             {
1649*4882a593Smuzhiyun                 driver_num--;
1650*4882a593Smuzhiyun             }
1651*4882a593Smuzhiyun             sensor_num = (config[CFG_LOC_SENS_NUM] & 0x0F) + ((config[CFG_LOC_SENS_NUM] >> 4) & 0x0F);
1652*4882a593Smuzhiyun             ts->bak_ref_len = (driver_num * (sensor_num - 2) + 2) * 2;
1653*4882a593Smuzhiyun         }
1654*4882a593Smuzhiyun 
1655*4882a593Smuzhiyun         GTP_INFO("Drv * Sen: %d * %d(key: %d), X_MAX: %d, Y_MAX: %d, TRIGGER: 0x%02x",
1656*4882a593Smuzhiyun            driver_num, sensor_num, have_key, ts->abs_x_max,ts->abs_y_max,ts->int_trigger_type);
1657*4882a593Smuzhiyun         return 0;
1658*4882a593Smuzhiyun     }
1659*4882a593Smuzhiyun     else
1660*4882a593Smuzhiyun #endif
1661*4882a593Smuzhiyun     {
1662*4882a593Smuzhiyun     #if GTP_DRIVER_SEND_CFG
1663*4882a593Smuzhiyun         GTP_INFO("  <%s>_%d \n", __func__, __LINE__);
1664*4882a593Smuzhiyun         ret = gtp_send_cfg(ts->client);
1665*4882a593Smuzhiyun         if (ret < 0)
1666*4882a593Smuzhiyun         {
1667*4882a593Smuzhiyun             GTP_ERROR("Send config error.");
1668*4882a593Smuzhiyun         }
1669*4882a593Smuzhiyun         // set config version to CTP_CFG_GROUP, for resume to send config
1670*4882a593Smuzhiyun         config[GTP_ADDR_LENGTH] = grp_cfg_version;
1671*4882a593Smuzhiyun         check_sum = 0;
1672*4882a593Smuzhiyun         for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
1673*4882a593Smuzhiyun         {
1674*4882a593Smuzhiyun             check_sum += config[i];
1675*4882a593Smuzhiyun         }
1676*4882a593Smuzhiyun         config[ts->gtp_cfg_len] = (~check_sum) + 1;
1677*4882a593Smuzhiyun     #endif
1678*4882a593Smuzhiyun         GTP_INFO("X_MAX: %d, Y_MAX: %d, TRIGGER: 0x%02x", ts->abs_x_max,ts->abs_y_max,ts->int_trigger_type);
1679*4882a593Smuzhiyun     }
1680*4882a593Smuzhiyun 
1681*4882a593Smuzhiyun     msleep(10);
1682*4882a593Smuzhiyun     return 0;
1683*4882a593Smuzhiyun }
1684*4882a593Smuzhiyun 
1685*4882a593Smuzhiyun 
gt91xx_config_read_proc(struct file * file,char __user * page,size_t size,loff_t * ppos)1686*4882a593Smuzhiyun static ssize_t gt91xx_config_read_proc(struct file *file, char __user *page, size_t size, loff_t *ppos)
1687*4882a593Smuzhiyun {
1688*4882a593Smuzhiyun     char *ptr = page;
1689*4882a593Smuzhiyun 	u8 temp_data[GTP_CONFIG_MAX_LENGTH + 2] = {0x80, 0x47};
1690*4882a593Smuzhiyun     int i;
1691*4882a593Smuzhiyun 
1692*4882a593Smuzhiyun     if (*ppos)
1693*4882a593Smuzhiyun     {
1694*4882a593Smuzhiyun         return 0;
1695*4882a593Smuzhiyun     }
1696*4882a593Smuzhiyun     ptr += sprintf(ptr, "==== GT9XX config init value====\n");
1697*4882a593Smuzhiyun 
1698*4882a593Smuzhiyun     for (i = 0 ; i < GTP_CONFIG_MAX_LENGTH ; i++)
1699*4882a593Smuzhiyun     {
1700*4882a593Smuzhiyun         ptr += sprintf(ptr, "0x%02X ", config[i + 2]);
1701*4882a593Smuzhiyun 
1702*4882a593Smuzhiyun         if (i % 8 == 7)
1703*4882a593Smuzhiyun             ptr += sprintf(ptr, "\n");
1704*4882a593Smuzhiyun     }
1705*4882a593Smuzhiyun 
1706*4882a593Smuzhiyun     ptr += sprintf(ptr, "\n");
1707*4882a593Smuzhiyun 
1708*4882a593Smuzhiyun     ptr += sprintf(ptr, "==== GT9XX config real value====\n");
1709*4882a593Smuzhiyun     gtp_i2c_read(i2c_connect_client, temp_data, GTP_CONFIG_MAX_LENGTH + 2);
1710*4882a593Smuzhiyun     for (i = 0 ; i < GTP_CONFIG_MAX_LENGTH ; i++)
1711*4882a593Smuzhiyun     {
1712*4882a593Smuzhiyun         ptr += sprintf(ptr, "0x%02X ", temp_data[i+2]);
1713*4882a593Smuzhiyun 
1714*4882a593Smuzhiyun         if (i % 8 == 7)
1715*4882a593Smuzhiyun             ptr += sprintf(ptr, "\n");
1716*4882a593Smuzhiyun     }
1717*4882a593Smuzhiyun     *ppos += ptr - page;
1718*4882a593Smuzhiyun     return (ptr - page);
1719*4882a593Smuzhiyun }
1720*4882a593Smuzhiyun 
gt91xx_config_write_proc(struct file * filp,const char __user * buffer,size_t count,loff_t * off)1721*4882a593Smuzhiyun static ssize_t gt91xx_config_write_proc(struct file *filp, const char __user *buffer, size_t count, loff_t *off)
1722*4882a593Smuzhiyun {
1723*4882a593Smuzhiyun     s32 ret = 0;
1724*4882a593Smuzhiyun 
1725*4882a593Smuzhiyun     if (count > GTP_CONFIG_MAX_LENGTH)
1726*4882a593Smuzhiyun     {
1727*4882a593Smuzhiyun         GTP_ERROR("size not match [%d:%zu]\n", GTP_CONFIG_MAX_LENGTH, count);
1728*4882a593Smuzhiyun         return -EFAULT;
1729*4882a593Smuzhiyun     }
1730*4882a593Smuzhiyun 
1731*4882a593Smuzhiyun     if (copy_from_user(&config[2], buffer, count))
1732*4882a593Smuzhiyun     {
1733*4882a593Smuzhiyun         GTP_ERROR("copy from user fail\n");
1734*4882a593Smuzhiyun         return -EFAULT;
1735*4882a593Smuzhiyun     }
1736*4882a593Smuzhiyun 
1737*4882a593Smuzhiyun     ret = gtp_send_cfg(i2c_connect_client);
1738*4882a593Smuzhiyun 
1739*4882a593Smuzhiyun     if (ret < 0)
1740*4882a593Smuzhiyun     {
1741*4882a593Smuzhiyun         GTP_ERROR("send config failed.");
1742*4882a593Smuzhiyun     }
1743*4882a593Smuzhiyun 
1744*4882a593Smuzhiyun     return count;
1745*4882a593Smuzhiyun }
1746*4882a593Smuzhiyun /*******************************************************
1747*4882a593Smuzhiyun Function:
1748*4882a593Smuzhiyun     Read chip version.
1749*4882a593Smuzhiyun Input:
1750*4882a593Smuzhiyun     client:  i2c device
1751*4882a593Smuzhiyun     version: buffer to keep ic firmware version
1752*4882a593Smuzhiyun Output:
1753*4882a593Smuzhiyun     read operation return.
1754*4882a593Smuzhiyun         2: succeed, otherwise: failed
1755*4882a593Smuzhiyun *******************************************************/
gtp_read_version(struct i2c_client * client,u16 * version)1756*4882a593Smuzhiyun s32 gtp_read_version(struct i2c_client *client, u16* version)
1757*4882a593Smuzhiyun {
1758*4882a593Smuzhiyun     s32 ret = -1;
1759*4882a593Smuzhiyun     u8 buf[8] = {GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff};
1760*4882a593Smuzhiyun 
1761*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1762*4882a593Smuzhiyun 
1763*4882a593Smuzhiyun     ret = gtp_i2c_read(client, buf, sizeof(buf));
1764*4882a593Smuzhiyun     if (ret < 0)
1765*4882a593Smuzhiyun     {
1766*4882a593Smuzhiyun         GTP_ERROR("GTP read version failed");
1767*4882a593Smuzhiyun         return ret;
1768*4882a593Smuzhiyun     }
1769*4882a593Smuzhiyun 
1770*4882a593Smuzhiyun     if (version)
1771*4882a593Smuzhiyun     {
1772*4882a593Smuzhiyun         *version = (buf[7] << 8) | buf[6];
1773*4882a593Smuzhiyun     }
1774*4882a593Smuzhiyun     if (buf[5] == 0x00)
1775*4882a593Smuzhiyun     {
1776*4882a593Smuzhiyun         GTP_INFO("IC Version: %c%c%c_%02x%02x", buf[2], buf[3], buf[4], buf[7], buf[6]);
1777*4882a593Smuzhiyun     }
1778*4882a593Smuzhiyun     else
1779*4882a593Smuzhiyun     {
1780*4882a593Smuzhiyun         GTP_INFO("IC Version: %c%c%c%c_%02x%02x", buf[2], buf[3], buf[4], buf[5], buf[7], buf[6]);
1781*4882a593Smuzhiyun     }
1782*4882a593Smuzhiyun     return ret;
1783*4882a593Smuzhiyun }
1784*4882a593Smuzhiyun 
1785*4882a593Smuzhiyun /*******************************************************
1786*4882a593Smuzhiyun Function:
1787*4882a593Smuzhiyun     I2c test Function.
1788*4882a593Smuzhiyun Input:
1789*4882a593Smuzhiyun     client:i2c client.
1790*4882a593Smuzhiyun Output:
1791*4882a593Smuzhiyun     Executive outcomes.
1792*4882a593Smuzhiyun         2: succeed, otherwise failed.
1793*4882a593Smuzhiyun *******************************************************/
gtp_i2c_test(struct i2c_client * client)1794*4882a593Smuzhiyun static s8 gtp_i2c_test(struct i2c_client *client)
1795*4882a593Smuzhiyun {
1796*4882a593Smuzhiyun     u8 test[3] = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff};
1797*4882a593Smuzhiyun     u8 retry = 0;
1798*4882a593Smuzhiyun     s8 ret = -1;
1799*4882a593Smuzhiyun 
1800*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1801*4882a593Smuzhiyun 
1802*4882a593Smuzhiyun     while(retry++ < 5)
1803*4882a593Smuzhiyun     {
1804*4882a593Smuzhiyun         ret = gtp_i2c_read(client, test, 3);
1805*4882a593Smuzhiyun         if (ret > 0)
1806*4882a593Smuzhiyun         {
1807*4882a593Smuzhiyun             return ret;
1808*4882a593Smuzhiyun         }
1809*4882a593Smuzhiyun         GTP_ERROR("GTP i2c test failed time %d.",retry);
1810*4882a593Smuzhiyun         msleep(10);
1811*4882a593Smuzhiyun     }
1812*4882a593Smuzhiyun     return ret;
1813*4882a593Smuzhiyun }
1814*4882a593Smuzhiyun 
1815*4882a593Smuzhiyun /*******************************************************
1816*4882a593Smuzhiyun Function:
1817*4882a593Smuzhiyun     Request gpio(INT & RST) ports.
1818*4882a593Smuzhiyun Input:
1819*4882a593Smuzhiyun     ts: private data.
1820*4882a593Smuzhiyun Output:
1821*4882a593Smuzhiyun     Executive outcomes.
1822*4882a593Smuzhiyun         >= 0: succeed, < 0: failed
1823*4882a593Smuzhiyun *******************************************************/
gtp_request_io_port(struct goodix_ts_data * ts)1824*4882a593Smuzhiyun static s8 gtp_request_io_port(struct goodix_ts_data *ts)
1825*4882a593Smuzhiyun {
1826*4882a593Smuzhiyun     s32 ret = 0;
1827*4882a593Smuzhiyun 
1828*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1829*4882a593Smuzhiyun /*
1830*4882a593Smuzhiyun     ret = GTP_GPIO_REQUEST(ts->tp_select_pin, "GTP_tp_select_PORT");
1831*4882a593Smuzhiyun     if (ret < 0)
1832*4882a593Smuzhiyun     {
1833*4882a593Smuzhiyun         GTP_ERROR("1Failed to request GPIO:%d, ERRNO:%d",(s32)ts->tp_select_pin, ret);
1834*4882a593Smuzhiyun         return -ENODEV;
1835*4882a593Smuzhiyun     }
1836*4882a593Smuzhiyun     else
1837*4882a593Smuzhiyun     {
1838*4882a593Smuzhiyun     	gpio_direction_input(ts->tp_select_pin);
1839*4882a593Smuzhiyun     }
1840*4882a593Smuzhiyun */
1841*4882a593Smuzhiyun     ret = GTP_GPIO_REQUEST(ts->rst_pin, "GTP_RST_PORT");
1842*4882a593Smuzhiyun     if (ret < 0)
1843*4882a593Smuzhiyun     {
1844*4882a593Smuzhiyun         GTP_ERROR("2Failed to request GPIO:%d, ERRNO:%d",(s32)ts->rst_pin, ret);
1845*4882a593Smuzhiyun 		GTP_GPIO_FREE(ts->rst_pin);
1846*4882a593Smuzhiyun         return -ENODEV;
1847*4882a593Smuzhiyun     }
1848*4882a593Smuzhiyun 
1849*4882a593Smuzhiyun     ret = GTP_GPIO_REQUEST(ts->irq_pin, "GTP_INT_IRQ");
1850*4882a593Smuzhiyun     if (ret < 0)
1851*4882a593Smuzhiyun     {
1852*4882a593Smuzhiyun         GTP_ERROR("3Failed to request GPIO:%d, ERRNO:%d", (s32)ts->irq_pin, ret);
1853*4882a593Smuzhiyun 		GTP_GPIO_FREE(ts->irq_pin);
1854*4882a593Smuzhiyun         return -ENODEV;
1855*4882a593Smuzhiyun     }
1856*4882a593Smuzhiyun     else
1857*4882a593Smuzhiyun     {
1858*4882a593Smuzhiyun         //GTP_GPIO_AS_INT(GTP_INT_PORT);
1859*4882a593Smuzhiyun         gpio_direction_input(ts->irq_pin);
1860*4882a593Smuzhiyun         //s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
1861*4882a593Smuzhiyun         //s3c_gpio_cfgpin(pin, GTP_INT_CFG);
1862*4882a593Smuzhiyun 
1863*4882a593Smuzhiyun         //ts->client->irq = ts->irq_pin;
1864*4882a593Smuzhiyun     }
1865*4882a593Smuzhiyun 
1866*4882a593Smuzhiyun     //GTP_GPIO_AS_INPUT(ts->rst_pin);
1867*4882a593Smuzhiyun     gpio_direction_input(ts->rst_pin);
1868*4882a593Smuzhiyun     //s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
1869*4882a593Smuzhiyun 
1870*4882a593Smuzhiyun     gtp_reset_guitar(ts->client, 20);
1871*4882a593Smuzhiyun 
1872*4882a593Smuzhiyun     return ret;
1873*4882a593Smuzhiyun }
1874*4882a593Smuzhiyun 
1875*4882a593Smuzhiyun /*******************************************************
1876*4882a593Smuzhiyun Function:
1877*4882a593Smuzhiyun     Request interrupt.
1878*4882a593Smuzhiyun Input:
1879*4882a593Smuzhiyun     ts: private data.
1880*4882a593Smuzhiyun Output:
1881*4882a593Smuzhiyun     Executive outcomes.
1882*4882a593Smuzhiyun         0: succeed, -1: failed.
1883*4882a593Smuzhiyun *******************************************************/
gtp_request_irq(struct goodix_ts_data * ts)1884*4882a593Smuzhiyun static s8 gtp_request_irq(struct goodix_ts_data *ts)
1885*4882a593Smuzhiyun {
1886*4882a593Smuzhiyun     s32 ret = -1;
1887*4882a593Smuzhiyun 
1888*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1889*4882a593Smuzhiyun     GTP_DEBUG("INT trigger type:%x", ts->int_trigger_type);
1890*4882a593Smuzhiyun 
1891*4882a593Smuzhiyun     ts->irq=gpio_to_irq(ts->irq_pin);       //If not defined in client
1892*4882a593Smuzhiyun     if (ts->irq)
1893*4882a593Smuzhiyun     {
1894*4882a593Smuzhiyun         ts->client->irq = ts->irq;
1895*4882a593Smuzhiyun         ret = devm_request_threaded_irq(&(ts->client->dev), ts->irq, NULL,
1896*4882a593Smuzhiyun             goodix_ts_irq_handler, ts->irq_flags | IRQF_ONESHOT /*irq_table[ts->int_trigger_type]*/,
1897*4882a593Smuzhiyun             ts->client->name, ts);
1898*4882a593Smuzhiyun         if (ret != 0) {
1899*4882a593Smuzhiyun             GTP_ERROR("Cannot allocate ts INT!ERRNO:%d\n", ret);
1900*4882a593Smuzhiyun             goto test_pit;
1901*4882a593Smuzhiyun         }
1902*4882a593Smuzhiyun         //gtp_irq_disable(ts->irq);
1903*4882a593Smuzhiyun         GTP_INFO("  <%s>_%d     ts->irq=%d   ret = %d\n", __func__, __LINE__, ts->irq, ret);
1904*4882a593Smuzhiyun     }else{
1905*4882a593Smuzhiyun         GTP_ERROR("   ts->irq  error \n");
1906*4882a593Smuzhiyun         ret = 1;
1907*4882a593Smuzhiyun         goto test_pit;
1908*4882a593Smuzhiyun     }
1909*4882a593Smuzhiyun /*
1910*4882a593Smuzhiyun     ret  = request_irq(ts->client->irq,
1911*4882a593Smuzhiyun                        goodix_ts_irq_handler,
1912*4882a593Smuzhiyun                        irq_table[ts->int_trigger_type],
1913*4882a593Smuzhiyun                        ts->client->name,
1914*4882a593Smuzhiyun                        ts);
1915*4882a593Smuzhiyun */
1916*4882a593Smuzhiyun test_pit:
1917*4882a593Smuzhiyun     if (ret)
1918*4882a593Smuzhiyun     {
1919*4882a593Smuzhiyun         GTP_ERROR("Request IRQ failed!ERRNO:%d.", ret);
1920*4882a593Smuzhiyun         //GTP_GPIO_AS_INPUT(GTP_INT_PORT);
1921*4882a593Smuzhiyun         gpio_direction_input(ts->irq_pin);
1922*4882a593Smuzhiyun         //s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
1923*4882a593Smuzhiyun 
1924*4882a593Smuzhiyun         GTP_GPIO_FREE(ts->irq_pin);
1925*4882a593Smuzhiyun 
1926*4882a593Smuzhiyun         hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1927*4882a593Smuzhiyun         ts->timer.function = goodix_ts_timer_handler;
1928*4882a593Smuzhiyun         hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
1929*4882a593Smuzhiyun         return -1;
1930*4882a593Smuzhiyun     }
1931*4882a593Smuzhiyun     else
1932*4882a593Smuzhiyun     {
1933*4882a593Smuzhiyun         GTP_INFO("  <%s>_%d     ts->irq=%d   ret = %d\n", __func__, __LINE__, ts->irq, ret);
1934*4882a593Smuzhiyun         gtp_irq_disable(ts);
1935*4882a593Smuzhiyun         ts->use_irq = 1;
1936*4882a593Smuzhiyun         return 0;
1937*4882a593Smuzhiyun     }
1938*4882a593Smuzhiyun }
1939*4882a593Smuzhiyun 
1940*4882a593Smuzhiyun /*******************************************************
1941*4882a593Smuzhiyun Function:
1942*4882a593Smuzhiyun     Early suspend function.
1943*4882a593Smuzhiyun Input:
1944*4882a593Smuzhiyun     h: early_suspend struct.
1945*4882a593Smuzhiyun Output:
1946*4882a593Smuzhiyun     None.
1947*4882a593Smuzhiyun *******************************************************/
goodix_ts_early_suspend(struct tp_device * tp_d)1948*4882a593Smuzhiyun static int goodix_ts_early_suspend(struct tp_device *tp_d)
1949*4882a593Smuzhiyun {
1950*4882a593Smuzhiyun     struct goodix_ts_data *ts;
1951*4882a593Smuzhiyun     s8 ret = -1;
1952*4882a593Smuzhiyun     int reg = 0;
1953*4882a593Smuzhiyun 
1954*4882a593Smuzhiyun     ts = container_of(tp_d, struct goodix_ts_data, tp);
1955*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
1956*4882a593Smuzhiyun 
1957*4882a593Smuzhiyun     GTP_INFO("System suspend.");
1958*4882a593Smuzhiyun 
1959*4882a593Smuzhiyun     ts->gtp_is_suspend = 1;
1960*4882a593Smuzhiyun #if GTP_ESD_PROTECT
1961*4882a593Smuzhiyun     gtp_esd_switch(ts->client, SWITCH_OFF);
1962*4882a593Smuzhiyun #endif
1963*4882a593Smuzhiyun 
1964*4882a593Smuzhiyun #if GTP_GESTURE_WAKEUP
1965*4882a593Smuzhiyun     ret = gtp_enter_doze(ts);
1966*4882a593Smuzhiyun #else
1967*4882a593Smuzhiyun     if (ts->use_irq)
1968*4882a593Smuzhiyun     {
1969*4882a593Smuzhiyun         gtp_irq_disable(ts);
1970*4882a593Smuzhiyun     }
1971*4882a593Smuzhiyun     else
1972*4882a593Smuzhiyun     {
1973*4882a593Smuzhiyun         hrtimer_cancel(&ts->timer);
1974*4882a593Smuzhiyun     }
1975*4882a593Smuzhiyun     ret = gtp_enter_sleep(ts);
1976*4882a593Smuzhiyun #endif
1977*4882a593Smuzhiyun     if (ret < 0)
1978*4882a593Smuzhiyun     {
1979*4882a593Smuzhiyun         printk("GTP early suspend failed.");
1980*4882a593Smuzhiyun     }
1981*4882a593Smuzhiyun     // to avoid waking up while not sleeping
1982*4882a593Smuzhiyun     //  delay 48 + 10ms to ensure reliability
1983*4882a593Smuzhiyun     msleep(58);
1984*4882a593Smuzhiyun 
1985*4882a593Smuzhiyun 	reg = regulator_disable(ts->tp_regulator);
1986*4882a593Smuzhiyun 	if (reg < 0)
1987*4882a593Smuzhiyun 		GTP_ERROR("failed to disable tp regulator\n");
1988*4882a593Smuzhiyun 	msleep(20);
1989*4882a593Smuzhiyun 	return 0;
1990*4882a593Smuzhiyun }
1991*4882a593Smuzhiyun 
1992*4882a593Smuzhiyun /*******************************************************
1993*4882a593Smuzhiyun Function:
1994*4882a593Smuzhiyun     Late resume function.
1995*4882a593Smuzhiyun Input:
1996*4882a593Smuzhiyun     h: early_suspend struct.
1997*4882a593Smuzhiyun Output:
1998*4882a593Smuzhiyun     None.
1999*4882a593Smuzhiyun *******************************************************/
goodix_ts_early_resume(struct tp_device * tp_d)2000*4882a593Smuzhiyun static int goodix_ts_early_resume(struct tp_device *tp_d)
2001*4882a593Smuzhiyun {
2002*4882a593Smuzhiyun     struct goodix_ts_data *ts;
2003*4882a593Smuzhiyun     s8 ret = -1;
2004*4882a593Smuzhiyun     int reg = 0;
2005*4882a593Smuzhiyun     ts = container_of(tp_d, struct goodix_ts_data, tp);
2006*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
2007*4882a593Smuzhiyun 
2008*4882a593Smuzhiyun     GTP_INFO("System resume.");
2009*4882a593Smuzhiyun 
2010*4882a593Smuzhiyun 	reg = regulator_enable(ts->tp_regulator);
2011*4882a593Smuzhiyun 	if (reg < 0)
2012*4882a593Smuzhiyun 		GTP_ERROR("failed to enable tp regulator\n");
2013*4882a593Smuzhiyun 	msleep(10);
2014*4882a593Smuzhiyun 
2015*4882a593Smuzhiyun     ret = gtp_wakeup_sleep(ts);
2016*4882a593Smuzhiyun 
2017*4882a593Smuzhiyun #if GTP_GESTURE_WAKEUP
2018*4882a593Smuzhiyun     doze_status = DOZE_DISABLED;
2019*4882a593Smuzhiyun #endif
2020*4882a593Smuzhiyun 
2021*4882a593Smuzhiyun     if (ret < 0)
2022*4882a593Smuzhiyun     {
2023*4882a593Smuzhiyun         GTP_ERROR("GTP later resume failed.");
2024*4882a593Smuzhiyun     }
2025*4882a593Smuzhiyun #if (GTP_COMPATIBLE_MODE)
2026*4882a593Smuzhiyun     if (CHIP_TYPE_GT9F == ts->chip_type)
2027*4882a593Smuzhiyun     {
2028*4882a593Smuzhiyun         // do nothing
2029*4882a593Smuzhiyun     }
2030*4882a593Smuzhiyun     else
2031*4882a593Smuzhiyun #endif
2032*4882a593Smuzhiyun     {
2033*4882a593Smuzhiyun         gtp_send_cfg(ts->client);
2034*4882a593Smuzhiyun     }
2035*4882a593Smuzhiyun 
2036*4882a593Smuzhiyun     if (ts->use_irq)
2037*4882a593Smuzhiyun     {
2038*4882a593Smuzhiyun         gtp_irq_enable(ts);
2039*4882a593Smuzhiyun     }
2040*4882a593Smuzhiyun     else
2041*4882a593Smuzhiyun     {
2042*4882a593Smuzhiyun         hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
2043*4882a593Smuzhiyun     }
2044*4882a593Smuzhiyun 
2045*4882a593Smuzhiyun     ts->gtp_is_suspend = 0;
2046*4882a593Smuzhiyun #if GTP_ESD_PROTECT
2047*4882a593Smuzhiyun     gtp_esd_switch(ts->client, SWITCH_ON);
2048*4882a593Smuzhiyun #endif
2049*4882a593Smuzhiyun 
2050*4882a593Smuzhiyun 	return 0;
2051*4882a593Smuzhiyun }
2052*4882a593Smuzhiyun 
2053*4882a593Smuzhiyun /*******************************************************
2054*4882a593Smuzhiyun Function:
2055*4882a593Smuzhiyun     Request input device Function.
2056*4882a593Smuzhiyun Input:
2057*4882a593Smuzhiyun     ts:private data.
2058*4882a593Smuzhiyun Output:
2059*4882a593Smuzhiyun     Executive outcomes.
2060*4882a593Smuzhiyun         0: succeed, otherwise: failed.
2061*4882a593Smuzhiyun *******************************************************/
gtp_request_input_dev(struct i2c_client * client,struct goodix_ts_data * ts)2062*4882a593Smuzhiyun static s8 gtp_request_input_dev(struct i2c_client *client,
2063*4882a593Smuzhiyun                                 struct goodix_ts_data *ts)
2064*4882a593Smuzhiyun {
2065*4882a593Smuzhiyun     s8 ret = -1;
2066*4882a593Smuzhiyun     s8 phys[32];
2067*4882a593Smuzhiyun #if GTP_HAVE_TOUCH_KEY
2068*4882a593Smuzhiyun     u8 index = 0;
2069*4882a593Smuzhiyun #endif
2070*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
2071*4882a593Smuzhiyun 
2072*4882a593Smuzhiyun     ts->input_dev = devm_input_allocate_device(&client->dev);
2073*4882a593Smuzhiyun     if (ts->input_dev == NULL)
2074*4882a593Smuzhiyun     {
2075*4882a593Smuzhiyun         GTP_ERROR("Failed to allocate input device.");
2076*4882a593Smuzhiyun         return -ENOMEM;
2077*4882a593Smuzhiyun     }
2078*4882a593Smuzhiyun 
2079*4882a593Smuzhiyun     ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
2080*4882a593Smuzhiyun #if GTP_ICS_SLOT_REPORT
2081*4882a593Smuzhiyun     input_mt_init_slots(ts->input_dev, 16, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);     // in case of "out of memory"
2082*4882a593Smuzhiyun #else
2083*4882a593Smuzhiyun     ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
2084*4882a593Smuzhiyun #endif
2085*4882a593Smuzhiyun     __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
2086*4882a593Smuzhiyun 
2087*4882a593Smuzhiyun #if GTP_HAVE_TOUCH_KEY
2088*4882a593Smuzhiyun     for (index = 0; index < GTP_MAX_KEY_NUM; index++)
2089*4882a593Smuzhiyun     {
2090*4882a593Smuzhiyun         input_set_capability(ts->input_dev, EV_KEY, touch_key_array[index]);
2091*4882a593Smuzhiyun     }
2092*4882a593Smuzhiyun #endif
2093*4882a593Smuzhiyun 
2094*4882a593Smuzhiyun #if GTP_GESTURE_WAKEUP
2095*4882a593Smuzhiyun     input_set_capability(ts->input_dev, EV_KEY, KEY_POWER);
2096*4882a593Smuzhiyun #endif
2097*4882a593Smuzhiyun 
2098*4882a593Smuzhiyun 	if (gtp_change_x2y)
2099*4882a593Smuzhiyun 		GTP_SWAP(ts->abs_x_max, ts->abs_y_max);
2100*4882a593Smuzhiyun 
2101*4882a593Smuzhiyun #if defined(CONFIG_CHROME_PLATFORMS)
2102*4882a593Smuzhiyun     input_set_abs_params(ts->input_dev, ABS_X, 0, ts->abs_x_max, 0, 0);
2103*4882a593Smuzhiyun     input_set_abs_params(ts->input_dev, ABS_Y, 0, ts->abs_y_max, 0, 0);
2104*4882a593Smuzhiyun #endif
2105*4882a593Smuzhiyun     input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, ts->abs_x_max, 0, 0);
2106*4882a593Smuzhiyun     input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, ts->abs_y_max, 0, 0);
2107*4882a593Smuzhiyun     input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
2108*4882a593Smuzhiyun     input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
2109*4882a593Smuzhiyun     input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, 255, 0, 0);
2110*4882a593Smuzhiyun 
2111*4882a593Smuzhiyun     sprintf(phys, "input/ts");
2112*4882a593Smuzhiyun     ts->input_dev->name = goodix_ts_name;
2113*4882a593Smuzhiyun     ts->input_dev->phys = phys;
2114*4882a593Smuzhiyun     ts->input_dev->id.bustype = BUS_I2C;
2115*4882a593Smuzhiyun     ts->input_dev->id.vendor = 0xDEAD;
2116*4882a593Smuzhiyun     ts->input_dev->id.product = 0xBEEF;
2117*4882a593Smuzhiyun     ts->input_dev->id.version = 10427;
2118*4882a593Smuzhiyun 
2119*4882a593Smuzhiyun     ret = input_register_device(ts->input_dev);
2120*4882a593Smuzhiyun     if (ret)
2121*4882a593Smuzhiyun     {
2122*4882a593Smuzhiyun         GTP_ERROR("Register %s input device failed", ts->input_dev->name);
2123*4882a593Smuzhiyun         return -ENODEV;
2124*4882a593Smuzhiyun     }
2125*4882a593Smuzhiyun 
2126*4882a593Smuzhiyun     ts->tp.tp_resume = goodix_ts_early_resume;
2127*4882a593Smuzhiyun     ts->tp.tp_suspend = goodix_ts_early_suspend;
2128*4882a593Smuzhiyun     tp_register_fb(&ts->tp);
2129*4882a593Smuzhiyun 
2130*4882a593Smuzhiyun #if GTP_WITH_PEN
2131*4882a593Smuzhiyun     gtp_pen_init(ts);
2132*4882a593Smuzhiyun #endif
2133*4882a593Smuzhiyun 
2134*4882a593Smuzhiyun     return 0;
2135*4882a593Smuzhiyun }
2136*4882a593Smuzhiyun 
2137*4882a593Smuzhiyun //************** For GT9XXF Start *************//
2138*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
2139*4882a593Smuzhiyun 
gtp_fw_startup(struct i2c_client * client)2140*4882a593Smuzhiyun s32 gtp_fw_startup(struct i2c_client *client)
2141*4882a593Smuzhiyun {
2142*4882a593Smuzhiyun     u8 opr_buf[4];
2143*4882a593Smuzhiyun     s32 ret = 0;
2144*4882a593Smuzhiyun     struct goodix_ts_data *ts = i2c_get_clientdata(client);
2145*4882a593Smuzhiyun     //init sw WDT
2146*4882a593Smuzhiyun 	opr_buf[0] = 0xAA;
2147*4882a593Smuzhiyun 	ret = i2c_write_bytes(client, 0x8041, opr_buf, 1);
2148*4882a593Smuzhiyun     if (ret < 0)
2149*4882a593Smuzhiyun     {
2150*4882a593Smuzhiyun         return FAIL;
2151*4882a593Smuzhiyun     }
2152*4882a593Smuzhiyun 
2153*4882a593Smuzhiyun     //release SS51 & DSP
2154*4882a593Smuzhiyun     opr_buf[0] = 0x00;
2155*4882a593Smuzhiyun     ret = i2c_write_bytes(client, 0x4180, opr_buf, 1);
2156*4882a593Smuzhiyun     if (ret < 0)
2157*4882a593Smuzhiyun     {
2158*4882a593Smuzhiyun         return FAIL;
2159*4882a593Smuzhiyun     }
2160*4882a593Smuzhiyun     //int sync
2161*4882a593Smuzhiyun     gtp_int_sync(25, ts);
2162*4882a593Smuzhiyun 
2163*4882a593Smuzhiyun     //check fw run status
2164*4882a593Smuzhiyun     ret = i2c_read_bytes(client, 0x8041, opr_buf, 1);
2165*4882a593Smuzhiyun     if (ret < 0)
2166*4882a593Smuzhiyun     {
2167*4882a593Smuzhiyun         return FAIL;
2168*4882a593Smuzhiyun     }
2169*4882a593Smuzhiyun     if(0xAA == opr_buf[0])
2170*4882a593Smuzhiyun     {
2171*4882a593Smuzhiyun         GTP_ERROR("IC works abnormally,startup failed.");
2172*4882a593Smuzhiyun         return FAIL;
2173*4882a593Smuzhiyun     }
2174*4882a593Smuzhiyun     else
2175*4882a593Smuzhiyun     {
2176*4882a593Smuzhiyun         GTP_INFO("IC works normally, Startup success.");
2177*4882a593Smuzhiyun         opr_buf[0] = 0xAA;
2178*4882a593Smuzhiyun         i2c_write_bytes(client, 0x8041, opr_buf, 1);
2179*4882a593Smuzhiyun         return SUCCESS;
2180*4882a593Smuzhiyun     }
2181*4882a593Smuzhiyun }
2182*4882a593Smuzhiyun 
gtp_esd_recovery(struct i2c_client * client)2183*4882a593Smuzhiyun static s32 gtp_esd_recovery(struct i2c_client *client)
2184*4882a593Smuzhiyun {
2185*4882a593Smuzhiyun     s32 retry = 0;
2186*4882a593Smuzhiyun     s32 ret = 0;
2187*4882a593Smuzhiyun     struct goodix_ts_data *ts;
2188*4882a593Smuzhiyun 
2189*4882a593Smuzhiyun     ts = i2c_get_clientdata(client);
2190*4882a593Smuzhiyun 
2191*4882a593Smuzhiyun     gtp_irq_disable(ts);
2192*4882a593Smuzhiyun 
2193*4882a593Smuzhiyun     GTP_INFO("GT9XXF esd recovery mode");
2194*4882a593Smuzhiyun     for (retry = 0; retry < 5; retry++)
2195*4882a593Smuzhiyun     {
2196*4882a593Smuzhiyun         ret = gup_fw_download_proc(NULL, GTP_FL_ESD_RECOVERY);
2197*4882a593Smuzhiyun         if (FAIL == ret)
2198*4882a593Smuzhiyun         {
2199*4882a593Smuzhiyun             GTP_ERROR("esd recovery failed %d", retry+1);
2200*4882a593Smuzhiyun             continue;
2201*4882a593Smuzhiyun         }
2202*4882a593Smuzhiyun         ret = gtp_fw_startup(ts->client);
2203*4882a593Smuzhiyun         if (FAIL == ret)
2204*4882a593Smuzhiyun         {
2205*4882a593Smuzhiyun             GTP_ERROR("GT9XXF start up failed %d", retry+1);
2206*4882a593Smuzhiyun             continue;
2207*4882a593Smuzhiyun         }
2208*4882a593Smuzhiyun         break;
2209*4882a593Smuzhiyun     }
2210*4882a593Smuzhiyun     gtp_irq_enable(ts);
2211*4882a593Smuzhiyun 
2212*4882a593Smuzhiyun     if (retry >= 5)
2213*4882a593Smuzhiyun     {
2214*4882a593Smuzhiyun         GTP_ERROR("failed to esd recovery");
2215*4882a593Smuzhiyun         return FAIL;
2216*4882a593Smuzhiyun     }
2217*4882a593Smuzhiyun 
2218*4882a593Smuzhiyun     GTP_INFO("Esd recovery successful");
2219*4882a593Smuzhiyun     return SUCCESS;
2220*4882a593Smuzhiyun }
2221*4882a593Smuzhiyun 
gtp_recovery_reset(struct i2c_client * client)2222*4882a593Smuzhiyun void gtp_recovery_reset(struct i2c_client *client)
2223*4882a593Smuzhiyun {
2224*4882a593Smuzhiyun #if GTP_ESD_PROTECT
2225*4882a593Smuzhiyun     gtp_esd_switch(client, SWITCH_OFF);
2226*4882a593Smuzhiyun #endif
2227*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
2228*4882a593Smuzhiyun 
2229*4882a593Smuzhiyun     gtp_esd_recovery(client);
2230*4882a593Smuzhiyun 
2231*4882a593Smuzhiyun #if GTP_ESD_PROTECT
2232*4882a593Smuzhiyun     gtp_esd_switch(client, SWITCH_ON);
2233*4882a593Smuzhiyun #endif
2234*4882a593Smuzhiyun }
2235*4882a593Smuzhiyun 
gtp_bak_ref_proc(struct goodix_ts_data * ts,u8 mode)2236*4882a593Smuzhiyun static s32 gtp_bak_ref_proc(struct goodix_ts_data *ts, u8 mode)
2237*4882a593Smuzhiyun {
2238*4882a593Smuzhiyun     s32 ret = 0;
2239*4882a593Smuzhiyun     s32 i = 0;
2240*4882a593Smuzhiyun     s32 j = 0;
2241*4882a593Smuzhiyun     u16 ref_sum = 0;
2242*4882a593Smuzhiyun     u16 learn_cnt = 0;
2243*4882a593Smuzhiyun     u16 chksum = 0;
2244*4882a593Smuzhiyun     s32 ref_seg_len = 0;
2245*4882a593Smuzhiyun     s32 ref_grps = 0;
2246*4882a593Smuzhiyun     struct file *ref_filp = NULL;
2247*4882a593Smuzhiyun     u8 *p_bak_ref;
2248*4882a593Smuzhiyun 
2249*4882a593Smuzhiyun     ret = gup_check_fs_mounted("/data");
2250*4882a593Smuzhiyun     if (FAIL == ret)
2251*4882a593Smuzhiyun     {
2252*4882a593Smuzhiyun         ts->ref_chk_fs_times++;
2253*4882a593Smuzhiyun         GTP_DEBUG("Ref check /data times/MAX_TIMES: %d / %d", ts->ref_chk_fs_times, GTP_CHK_FS_MNT_MAX);
2254*4882a593Smuzhiyun         if (ts->ref_chk_fs_times < GTP_CHK_FS_MNT_MAX)
2255*4882a593Smuzhiyun         {
2256*4882a593Smuzhiyun             msleep(50);
2257*4882a593Smuzhiyun             GTP_INFO("/data not mounted.");
2258*4882a593Smuzhiyun             return FAIL;
2259*4882a593Smuzhiyun         }
2260*4882a593Smuzhiyun         GTP_INFO("check /data mount timeout...");
2261*4882a593Smuzhiyun     }
2262*4882a593Smuzhiyun     else
2263*4882a593Smuzhiyun     {
2264*4882a593Smuzhiyun         GTP_INFO("/data mounted!!!(%d/%d)", ts->ref_chk_fs_times, GTP_CHK_FS_MNT_MAX);
2265*4882a593Smuzhiyun     }
2266*4882a593Smuzhiyun 
2267*4882a593Smuzhiyun 	p_bak_ref = kzalloc(ts->bak_ref_len, GFP_KERNEL);
2268*4882a593Smuzhiyun 
2269*4882a593Smuzhiyun     if (NULL == p_bak_ref)
2270*4882a593Smuzhiyun     {
2271*4882a593Smuzhiyun         GTP_ERROR("Allocate memory for p_bak_ref failed!");
2272*4882a593Smuzhiyun         return FAIL;
2273*4882a593Smuzhiyun     }
2274*4882a593Smuzhiyun 
2275*4882a593Smuzhiyun     if (ts->is_950)
2276*4882a593Smuzhiyun     {
2277*4882a593Smuzhiyun         ref_seg_len = ts->bak_ref_len / 6;
2278*4882a593Smuzhiyun         ref_grps = 6;
2279*4882a593Smuzhiyun     }
2280*4882a593Smuzhiyun     else
2281*4882a593Smuzhiyun     {
2282*4882a593Smuzhiyun         ref_seg_len = ts->bak_ref_len;
2283*4882a593Smuzhiyun         ref_grps = 1;
2284*4882a593Smuzhiyun     }
2285*4882a593Smuzhiyun     ref_filp = filp_open(GTP_BAK_REF_PATH, O_RDWR | O_CREAT, 0666);
2286*4882a593Smuzhiyun     if (IS_ERR(ref_filp))
2287*4882a593Smuzhiyun     {
2288*4882a593Smuzhiyun         GTP_ERROR("Failed to open/create %s.", GTP_BAK_REF_PATH);
2289*4882a593Smuzhiyun         if (GTP_BAK_REF_SEND == mode)
2290*4882a593Smuzhiyun         {
2291*4882a593Smuzhiyun             goto bak_ref_default;
2292*4882a593Smuzhiyun         }
2293*4882a593Smuzhiyun         else
2294*4882a593Smuzhiyun         {
2295*4882a593Smuzhiyun             goto bak_ref_exit;
2296*4882a593Smuzhiyun         }
2297*4882a593Smuzhiyun     }
2298*4882a593Smuzhiyun 
2299*4882a593Smuzhiyun     switch (mode)
2300*4882a593Smuzhiyun     {
2301*4882a593Smuzhiyun     case GTP_BAK_REF_SEND:
2302*4882a593Smuzhiyun         GTP_INFO("Send backup-reference");
2303*4882a593Smuzhiyun         ref_filp->f_op->llseek(ref_filp, 0, SEEK_SET);
2304*4882a593Smuzhiyun         ret = ref_filp->f_op->read(ref_filp, (char*)p_bak_ref, ts->bak_ref_len, &ref_filp->f_pos);
2305*4882a593Smuzhiyun         if (ret < 0)
2306*4882a593Smuzhiyun         {
2307*4882a593Smuzhiyun             GTP_ERROR("failed to read bak_ref info from file, sending defualt bak_ref");
2308*4882a593Smuzhiyun             goto bak_ref_default;
2309*4882a593Smuzhiyun         }
2310*4882a593Smuzhiyun         for (j = 0; j < ref_grps; ++j)
2311*4882a593Smuzhiyun         {
2312*4882a593Smuzhiyun             ref_sum = 0;
2313*4882a593Smuzhiyun             for (i = 0; i < (ref_seg_len); i += 2)
2314*4882a593Smuzhiyun             {
2315*4882a593Smuzhiyun                 ref_sum += (p_bak_ref[i + j * ref_seg_len] << 8) + p_bak_ref[i+1 + j * ref_seg_len];
2316*4882a593Smuzhiyun             }
2317*4882a593Smuzhiyun             learn_cnt = (p_bak_ref[j * ref_seg_len + ref_seg_len -4] << 8) + (p_bak_ref[j * ref_seg_len + ref_seg_len -3]);
2318*4882a593Smuzhiyun             chksum = (p_bak_ref[j * ref_seg_len + ref_seg_len -2] << 8) + (p_bak_ref[j * ref_seg_len + ref_seg_len -1]);
2319*4882a593Smuzhiyun             GTP_DEBUG("learn count = %d", learn_cnt);
2320*4882a593Smuzhiyun             GTP_DEBUG("chksum = %d", chksum);
2321*4882a593Smuzhiyun             GTP_DEBUG("ref_sum = 0x%04X", ref_sum & 0xFFFF);
2322*4882a593Smuzhiyun             // Sum(1~ref_seg_len) == 1
2323*4882a593Smuzhiyun             if (1 != ref_sum)
2324*4882a593Smuzhiyun             {
2325*4882a593Smuzhiyun                 GTP_INFO("wrong chksum for bak_ref, reset to 0x00 bak_ref");
2326*4882a593Smuzhiyun                 memset(&p_bak_ref[j * ref_seg_len], 0, ref_seg_len);
2327*4882a593Smuzhiyun                 p_bak_ref[ref_seg_len + j * ref_seg_len - 1] = 0x01;
2328*4882a593Smuzhiyun             }
2329*4882a593Smuzhiyun             else
2330*4882a593Smuzhiyun             {
2331*4882a593Smuzhiyun                 if (j == (ref_grps - 1))
2332*4882a593Smuzhiyun                 {
2333*4882a593Smuzhiyun                     GTP_INFO("backup-reference data in %s used", GTP_BAK_REF_PATH);
2334*4882a593Smuzhiyun                 }
2335*4882a593Smuzhiyun             }
2336*4882a593Smuzhiyun         }
2337*4882a593Smuzhiyun         ret = i2c_write_bytes(ts->client, GTP_REG_BAK_REF, p_bak_ref, ts->bak_ref_len);
2338*4882a593Smuzhiyun         if (FAIL == ret)
2339*4882a593Smuzhiyun         {
2340*4882a593Smuzhiyun             GTP_ERROR("failed to send bak_ref because of iic comm error");
2341*4882a593Smuzhiyun             goto bak_ref_exit;
2342*4882a593Smuzhiyun         }
2343*4882a593Smuzhiyun         break;
2344*4882a593Smuzhiyun 
2345*4882a593Smuzhiyun     case GTP_BAK_REF_STORE:
2346*4882a593Smuzhiyun         GTP_INFO("Store backup-reference");
2347*4882a593Smuzhiyun         ret = i2c_read_bytes(ts->client, GTP_REG_BAK_REF, p_bak_ref, ts->bak_ref_len);
2348*4882a593Smuzhiyun         if (ret < 0)
2349*4882a593Smuzhiyun         {
2350*4882a593Smuzhiyun             GTP_ERROR("failed to read bak_ref info, sending default back-reference");
2351*4882a593Smuzhiyun             goto bak_ref_default;
2352*4882a593Smuzhiyun         }
2353*4882a593Smuzhiyun         ref_filp->f_op->llseek(ref_filp, 0, SEEK_SET);
2354*4882a593Smuzhiyun         ref_filp->f_op->write(ref_filp, (char*)p_bak_ref, ts->bak_ref_len, &ref_filp->f_pos);
2355*4882a593Smuzhiyun         break;
2356*4882a593Smuzhiyun 
2357*4882a593Smuzhiyun     default:
2358*4882a593Smuzhiyun         GTP_ERROR("invalid backup-reference request");
2359*4882a593Smuzhiyun         break;
2360*4882a593Smuzhiyun     }
2361*4882a593Smuzhiyun     ret = SUCCESS;
2362*4882a593Smuzhiyun     goto bak_ref_exit;
2363*4882a593Smuzhiyun 
2364*4882a593Smuzhiyun bak_ref_default:
2365*4882a593Smuzhiyun 
2366*4882a593Smuzhiyun     for (j = 0; j < ref_grps; ++j)
2367*4882a593Smuzhiyun     {
2368*4882a593Smuzhiyun         memset(&p_bak_ref[j * ref_seg_len], 0, ref_seg_len);
2369*4882a593Smuzhiyun         p_bak_ref[j * ref_seg_len + ref_seg_len - 1] = 0x01;  // checksum = 1
2370*4882a593Smuzhiyun     }
2371*4882a593Smuzhiyun     ret = i2c_write_bytes(ts->client, GTP_REG_BAK_REF, p_bak_ref, ts->bak_ref_len);
2372*4882a593Smuzhiyun     if (!IS_ERR(ref_filp))
2373*4882a593Smuzhiyun     {
2374*4882a593Smuzhiyun         GTP_INFO("write backup-reference data into %s", GTP_BAK_REF_PATH);
2375*4882a593Smuzhiyun         ref_filp->f_op->llseek(ref_filp, 0, SEEK_SET);
2376*4882a593Smuzhiyun         ref_filp->f_op->write(ref_filp, (char*)p_bak_ref, ts->bak_ref_len, &ref_filp->f_pos);
2377*4882a593Smuzhiyun     }
2378*4882a593Smuzhiyun     if (ret == FAIL)
2379*4882a593Smuzhiyun     {
2380*4882a593Smuzhiyun         GTP_ERROR("failed to load the default backup reference");
2381*4882a593Smuzhiyun     }
2382*4882a593Smuzhiyun 
2383*4882a593Smuzhiyun bak_ref_exit:
2384*4882a593Smuzhiyun 
2385*4882a593Smuzhiyun     if (p_bak_ref)
2386*4882a593Smuzhiyun     {
2387*4882a593Smuzhiyun         kfree(p_bak_ref);
2388*4882a593Smuzhiyun     }
2389*4882a593Smuzhiyun     if (ref_filp && !IS_ERR(ref_filp))
2390*4882a593Smuzhiyun     {
2391*4882a593Smuzhiyun         filp_close(ref_filp, NULL);
2392*4882a593Smuzhiyun     }
2393*4882a593Smuzhiyun     return ret;
2394*4882a593Smuzhiyun }
2395*4882a593Smuzhiyun 
2396*4882a593Smuzhiyun 
gtp_verify_main_clk(u8 * p_main_clk)2397*4882a593Smuzhiyun static s32 gtp_verify_main_clk(u8 *p_main_clk)
2398*4882a593Smuzhiyun {
2399*4882a593Smuzhiyun     u8 chksum = 0;
2400*4882a593Smuzhiyun     u8 main_clock = p_main_clk[0];
2401*4882a593Smuzhiyun     s32 i = 0;
2402*4882a593Smuzhiyun 
2403*4882a593Smuzhiyun     if (main_clock < 50 || main_clock > 120)
2404*4882a593Smuzhiyun     {
2405*4882a593Smuzhiyun         return FAIL;
2406*4882a593Smuzhiyun     }
2407*4882a593Smuzhiyun 
2408*4882a593Smuzhiyun     for (i = 0; i < 5; ++i)
2409*4882a593Smuzhiyun     {
2410*4882a593Smuzhiyun         if (main_clock != p_main_clk[i])
2411*4882a593Smuzhiyun         {
2412*4882a593Smuzhiyun             return FAIL;
2413*4882a593Smuzhiyun         }
2414*4882a593Smuzhiyun         chksum += p_main_clk[i];
2415*4882a593Smuzhiyun     }
2416*4882a593Smuzhiyun     chksum += p_main_clk[5];
2417*4882a593Smuzhiyun     if ( (chksum) == 0)
2418*4882a593Smuzhiyun     {
2419*4882a593Smuzhiyun         return SUCCESS;
2420*4882a593Smuzhiyun     }
2421*4882a593Smuzhiyun     else
2422*4882a593Smuzhiyun     {
2423*4882a593Smuzhiyun         return FAIL;
2424*4882a593Smuzhiyun     }
2425*4882a593Smuzhiyun }
2426*4882a593Smuzhiyun 
gtp_main_clk_proc(struct goodix_ts_data * ts)2427*4882a593Smuzhiyun static s32 gtp_main_clk_proc(struct goodix_ts_data *ts)
2428*4882a593Smuzhiyun {
2429*4882a593Smuzhiyun 	s32 ret = 0;
2430*4882a593Smuzhiyun 	s32 i = 0;
2431*4882a593Smuzhiyun 	s32 clk_chksum = 0;
2432*4882a593Smuzhiyun 	struct file *clk_filp = NULL;
2433*4882a593Smuzhiyun 
2434*4882a593Smuzhiyun 	#if GTP_USE_FIXED_CLK
2435*4882a593Smuzhiyun 	u8 p_main_clk[6] = {69, 69, 69, 69, 69, 167};
2436*4882a593Smuzhiyun 	#else
2437*4882a593Smuzhiyun 	u8 p_main_clk[6] = {0};
2438*4882a593Smuzhiyun 	#endif
2439*4882a593Smuzhiyun 
2440*4882a593Smuzhiyun 	#if GTP_USE_FIXED_CLK
2441*4882a593Smuzhiyun 	/*
2442*4882a593Smuzhiyun 	 * here check kernel /data is not same as android /data,
2443*4882a593Smuzhiyun 	 * so modify it to reduce fw download
2444*4882a593Smuzhiyun 	 */
2445*4882a593Smuzhiyun 	ret = gtp_verify_main_clk(p_main_clk);
2446*4882a593Smuzhiyun 	if (ret == FAIL) {
2447*4882a593Smuzhiyun 		GTP_ERROR("main clock data verify error");
2448*4882a593Smuzhiyun 	} else {
2449*4882a593Smuzhiyun 		GTP_INFO("main clock data used fix freq: %d", p_main_clk[0]);
2450*4882a593Smuzhiyun 		goto update_main_clk;
2451*4882a593Smuzhiyun 	}
2452*4882a593Smuzhiyun 	#else
2453*4882a593Smuzhiyun     ret = gup_check_fs_mounted("/data");
2454*4882a593Smuzhiyun     if (FAIL == ret)
2455*4882a593Smuzhiyun     {
2456*4882a593Smuzhiyun         ts->clk_chk_fs_times++;
2457*4882a593Smuzhiyun         GTP_DEBUG("Clock check /data times/MAX_TIMES: %d / %d", ts->clk_chk_fs_times, GTP_CHK_FS_MNT_MAX);
2458*4882a593Smuzhiyun         if (ts->clk_chk_fs_times < GTP_CHK_FS_MNT_MAX)
2459*4882a593Smuzhiyun         {
2460*4882a593Smuzhiyun             msleep(50);
2461*4882a593Smuzhiyun             GTP_INFO("/data not mounted.");
2462*4882a593Smuzhiyun             return FAIL;
2463*4882a593Smuzhiyun         }
2464*4882a593Smuzhiyun         GTP_INFO("Check /data mount timeout!");
2465*4882a593Smuzhiyun     }
2466*4882a593Smuzhiyun     else
2467*4882a593Smuzhiyun     {
2468*4882a593Smuzhiyun         GTP_INFO("/data mounted!!!(%d/%d)", ts->clk_chk_fs_times, GTP_CHK_FS_MNT_MAX);
2469*4882a593Smuzhiyun     }
2470*4882a593Smuzhiyun 
2471*4882a593Smuzhiyun     clk_filp = filp_open(GTP_MAIN_CLK_PATH, O_RDWR | O_CREAT, 0666);
2472*4882a593Smuzhiyun     if (IS_ERR(clk_filp))
2473*4882a593Smuzhiyun     {
2474*4882a593Smuzhiyun         GTP_ERROR("%s is unavailable, calculate main clock", GTP_MAIN_CLK_PATH);
2475*4882a593Smuzhiyun     }
2476*4882a593Smuzhiyun     else
2477*4882a593Smuzhiyun     {
2478*4882a593Smuzhiyun         clk_filp->f_op->llseek(clk_filp, 0, SEEK_SET);
2479*4882a593Smuzhiyun         clk_filp->f_op->read(clk_filp, (char *)p_main_clk, 6, &clk_filp->f_pos);
2480*4882a593Smuzhiyun 
2481*4882a593Smuzhiyun         ret = gtp_verify_main_clk(p_main_clk);
2482*4882a593Smuzhiyun         if (FAIL == ret)
2483*4882a593Smuzhiyun         {
2484*4882a593Smuzhiyun             // recalculate main clock & rewrite main clock data to file
2485*4882a593Smuzhiyun             GTP_ERROR("main clock data in %s is wrong, recalculate main clock", GTP_MAIN_CLK_PATH);
2486*4882a593Smuzhiyun         }
2487*4882a593Smuzhiyun         else
2488*4882a593Smuzhiyun         {
2489*4882a593Smuzhiyun             GTP_INFO("main clock data in %s used, main clock freq: %d", GTP_MAIN_CLK_PATH, p_main_clk[0]);
2490*4882a593Smuzhiyun             filp_close(clk_filp, NULL);
2491*4882a593Smuzhiyun             goto update_main_clk;
2492*4882a593Smuzhiyun         }
2493*4882a593Smuzhiyun     }
2494*4882a593Smuzhiyun 	#endif
2495*4882a593Smuzhiyun 
2496*4882a593Smuzhiyun #if GTP_ESD_PROTECT
2497*4882a593Smuzhiyun     gtp_esd_switch(ts->client, SWITCH_OFF);
2498*4882a593Smuzhiyun #endif
2499*4882a593Smuzhiyun     ret = gup_clk_calibration();
2500*4882a593Smuzhiyun     gtp_esd_recovery(ts->client);
2501*4882a593Smuzhiyun 
2502*4882a593Smuzhiyun #if GTP_ESD_PROTECT
2503*4882a593Smuzhiyun     gtp_esd_switch(ts->client, SWITCH_ON);
2504*4882a593Smuzhiyun #endif
2505*4882a593Smuzhiyun 
2506*4882a593Smuzhiyun     GTP_INFO("calibrate main clock: %d", ret);
2507*4882a593Smuzhiyun     if (ret < 50 || ret > 120)
2508*4882a593Smuzhiyun     {
2509*4882a593Smuzhiyun         GTP_ERROR("wrong main clock: %d", ret);
2510*4882a593Smuzhiyun         goto exit_main_clk;
2511*4882a593Smuzhiyun     }
2512*4882a593Smuzhiyun 
2513*4882a593Smuzhiyun     // Sum{0x8020~0x8025} = 0
2514*4882a593Smuzhiyun     for (i = 0; i < 5; ++i)
2515*4882a593Smuzhiyun     {
2516*4882a593Smuzhiyun         p_main_clk[i] = ret;
2517*4882a593Smuzhiyun         clk_chksum += p_main_clk[i];
2518*4882a593Smuzhiyun     }
2519*4882a593Smuzhiyun     p_main_clk[5] = 0 - clk_chksum;
2520*4882a593Smuzhiyun 
2521*4882a593Smuzhiyun     if (!IS_ERR(clk_filp))
2522*4882a593Smuzhiyun     {
2523*4882a593Smuzhiyun         GTP_DEBUG("write main clock data into %s", GTP_MAIN_CLK_PATH);
2524*4882a593Smuzhiyun         clk_filp->f_op->llseek(clk_filp, 0, SEEK_SET);
2525*4882a593Smuzhiyun         clk_filp->f_op->write(clk_filp, (char *)p_main_clk, 6, &clk_filp->f_pos);
2526*4882a593Smuzhiyun         filp_close(clk_filp, NULL);
2527*4882a593Smuzhiyun     }
2528*4882a593Smuzhiyun 
2529*4882a593Smuzhiyun update_main_clk:
2530*4882a593Smuzhiyun     ret = i2c_write_bytes(ts->client, GTP_REG_MAIN_CLK, p_main_clk, 6);
2531*4882a593Smuzhiyun     if (FAIL == ret)
2532*4882a593Smuzhiyun     {
2533*4882a593Smuzhiyun         GTP_ERROR("update main clock failed!");
2534*4882a593Smuzhiyun         return FAIL;
2535*4882a593Smuzhiyun     }
2536*4882a593Smuzhiyun     return SUCCESS;
2537*4882a593Smuzhiyun 
2538*4882a593Smuzhiyun exit_main_clk:
2539*4882a593Smuzhiyun     if (!IS_ERR(clk_filp))
2540*4882a593Smuzhiyun     {
2541*4882a593Smuzhiyun         filp_close(clk_filp, NULL);
2542*4882a593Smuzhiyun     }
2543*4882a593Smuzhiyun     return FAIL;
2544*4882a593Smuzhiyun }
2545*4882a593Smuzhiyun 
2546*4882a593Smuzhiyun 
gtp_gt9xxf_init(struct i2c_client * client)2547*4882a593Smuzhiyun s32 gtp_gt9xxf_init(struct i2c_client *client)
2548*4882a593Smuzhiyun {
2549*4882a593Smuzhiyun     s32 ret = 0;
2550*4882a593Smuzhiyun 
2551*4882a593Smuzhiyun     ret = gup_fw_download_proc(NULL, GTP_FL_FW_BURN);
2552*4882a593Smuzhiyun     if (FAIL == ret)
2553*4882a593Smuzhiyun     {
2554*4882a593Smuzhiyun         return FAIL;
2555*4882a593Smuzhiyun     }
2556*4882a593Smuzhiyun 
2557*4882a593Smuzhiyun     ret = gtp_fw_startup(client);
2558*4882a593Smuzhiyun     if (FAIL == ret)
2559*4882a593Smuzhiyun     {
2560*4882a593Smuzhiyun         return FAIL;
2561*4882a593Smuzhiyun     }
2562*4882a593Smuzhiyun     return SUCCESS;
2563*4882a593Smuzhiyun }
2564*4882a593Smuzhiyun 
gtp_get_chip_type(struct goodix_ts_data * ts)2565*4882a593Smuzhiyun void gtp_get_chip_type(struct goodix_ts_data *ts)
2566*4882a593Smuzhiyun {
2567*4882a593Smuzhiyun     u8 opr_buf[10] = {0x00};
2568*4882a593Smuzhiyun     s32 ret = 0;
2569*4882a593Smuzhiyun 
2570*4882a593Smuzhiyun     msleep(10);
2571*4882a593Smuzhiyun 
2572*4882a593Smuzhiyun     ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CHIP_TYPE, opr_buf, 10);
2573*4882a593Smuzhiyun 
2574*4882a593Smuzhiyun     if (FAIL == ret)
2575*4882a593Smuzhiyun     {
2576*4882a593Smuzhiyun         GTP_ERROR("Failed to get chip-type, set chip type default: GOODIX_GT9");
2577*4882a593Smuzhiyun         ts->chip_type = CHIP_TYPE_GT9;
2578*4882a593Smuzhiyun         return;
2579*4882a593Smuzhiyun     }
2580*4882a593Smuzhiyun 
2581*4882a593Smuzhiyun     if (!memcmp(opr_buf, "GOODIX_GT9", 10))
2582*4882a593Smuzhiyun     {
2583*4882a593Smuzhiyun         ts->chip_type = CHIP_TYPE_GT9;
2584*4882a593Smuzhiyun     }
2585*4882a593Smuzhiyun     else if (bgt9110)
2586*4882a593Smuzhiyun     {
2587*4882a593Smuzhiyun 	  ts->chip_type = CHIP_TYPE_GT9110;
2588*4882a593Smuzhiyun 	  GTP_INFO("Chip Type: GOODIX_GT9110");
2589*4882a593Smuzhiyun 	  return;
2590*4882a593Smuzhiyun     }
2591*4882a593Smuzhiyun     else // GT9XXF
2592*4882a593Smuzhiyun     {
2593*4882a593Smuzhiyun         ts->chip_type = CHIP_TYPE_GT9F;
2594*4882a593Smuzhiyun     }
2595*4882a593Smuzhiyun     GTP_INFO("Chip Type: %s", (ts->chip_type == CHIP_TYPE_GT9) ? "GOODIX_GT9" : "GOODIX_GT9F");
2596*4882a593Smuzhiyun }
2597*4882a593Smuzhiyun 
2598*4882a593Smuzhiyun #endif
2599*4882a593Smuzhiyun //************* For GT9XXF End ************//
2600*4882a593Smuzhiyun 
2601*4882a593Smuzhiyun /*******************************************************
2602*4882a593Smuzhiyun Function:
2603*4882a593Smuzhiyun     I2c probe.
2604*4882a593Smuzhiyun Input:
2605*4882a593Smuzhiyun     client: i2c device struct.
2606*4882a593Smuzhiyun     id: device id.
2607*4882a593Smuzhiyun Output:
2608*4882a593Smuzhiyun     Executive outcomes.
2609*4882a593Smuzhiyun         0: succeed.
2610*4882a593Smuzhiyun *******************************************************/
goodix_ts_probe(struct i2c_client * client,const struct i2c_device_id * id)2611*4882a593Smuzhiyun static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
2612*4882a593Smuzhiyun {
2613*4882a593Smuzhiyun     s32 ret = -1;
2614*4882a593Smuzhiyun     struct goodix_ts_data *ts;
2615*4882a593Smuzhiyun     u16 version_info;
2616*4882a593Smuzhiyun 
2617*4882a593Smuzhiyun     struct device_node *np = client->dev.of_node;
2618*4882a593Smuzhiyun     enum of_gpio_flags rst_flags, pwr_flags;
2619*4882a593Smuzhiyun     u32 val;
2620*4882a593Smuzhiyun 	printk("%s() start\n", __func__);
2621*4882a593Smuzhiyun 
2622*4882a593Smuzhiyun 
2623*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
2624*4882a593Smuzhiyun 
2625*4882a593Smuzhiyun     //do NOT remove these logs
2626*4882a593Smuzhiyun     GTP_INFO("GTP Driver Version: %s", GTP_DRIVER_VERSION);
2627*4882a593Smuzhiyun     GTP_INFO("GTP I2C Address: 0x%02x", client->addr);
2628*4882a593Smuzhiyun 
2629*4882a593Smuzhiyun     i2c_connect_client = client;
2630*4882a593Smuzhiyun 
2631*4882a593Smuzhiyun     if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
2632*4882a593Smuzhiyun     {
2633*4882a593Smuzhiyun         GTP_ERROR("I2C check functionality failed.");
2634*4882a593Smuzhiyun         return -ENODEV;
2635*4882a593Smuzhiyun     }
2636*4882a593Smuzhiyun     ts = kzalloc(sizeof(*ts), GFP_KERNEL);
2637*4882a593Smuzhiyun     if (ts == NULL)
2638*4882a593Smuzhiyun     {
2639*4882a593Smuzhiyun         GTP_ERROR("Alloc GFP_KERNEL memory failed.");
2640*4882a593Smuzhiyun         return -ENOMEM;
2641*4882a593Smuzhiyun     }
2642*4882a593Smuzhiyun 
2643*4882a593Smuzhiyun     memset(ts, 0, sizeof(*ts));
2644*4882a593Smuzhiyun 
2645*4882a593Smuzhiyun     if (!np) {
2646*4882a593Smuzhiyun     	dev_err(&client->dev, "no device tree\n");
2647*4882a593Smuzhiyun     	return -EINVAL;
2648*4882a593Smuzhiyun     }
2649*4882a593Smuzhiyun     if (of_property_read_u32(np, "tp-size", &val)) {
2650*4882a593Smuzhiyun     	dev_err(&client->dev, "no max-x defined\n");
2651*4882a593Smuzhiyun     	return -EINVAL;
2652*4882a593Smuzhiyun     }
2653*4882a593Smuzhiyun 
2654*4882a593Smuzhiyun 	if (val == 89) {
2655*4882a593Smuzhiyun 		m89or101 = TRUE;
2656*4882a593Smuzhiyun 		gtp_change_x2y = TRUE;
2657*4882a593Smuzhiyun 		gtp_x_reverse = FALSE;
2658*4882a593Smuzhiyun 		gtp_y_reverse = TRUE;
2659*4882a593Smuzhiyun 	} else if (val == 101) {
2660*4882a593Smuzhiyun 		m89or101 = FALSE;
2661*4882a593Smuzhiyun 		gtp_change_x2y = TRUE;
2662*4882a593Smuzhiyun 		gtp_x_reverse = TRUE;
2663*4882a593Smuzhiyun 		gtp_y_reverse = FALSE;
2664*4882a593Smuzhiyun 	} else if (val == 911) {
2665*4882a593Smuzhiyun 		m89or101 = FALSE;
2666*4882a593Smuzhiyun 		bgt911 = TRUE;
2667*4882a593Smuzhiyun 		gtp_change_x2y = TRUE;
2668*4882a593Smuzhiyun 		gtp_x_reverse = FALSE;
2669*4882a593Smuzhiyun 		gtp_y_reverse = TRUE;
2670*4882a593Smuzhiyun 	} else if (val == 9110) {
2671*4882a593Smuzhiyun 		m89or101 = FALSE;
2672*4882a593Smuzhiyun 		bgt9110 = TRUE;
2673*4882a593Smuzhiyun 		gtp_change_x2y = TRUE;
2674*4882a593Smuzhiyun 		gtp_x_reverse = TRUE;
2675*4882a593Smuzhiyun 		gtp_y_reverse = FALSE;
2676*4882a593Smuzhiyun 	} else if (val == 9111) {
2677*4882a593Smuzhiyun 		m89or101 = FALSE;
2678*4882a593Smuzhiyun 		bgt9111 = TRUE;
2679*4882a593Smuzhiyun 		gtp_change_x2y = TRUE;
2680*4882a593Smuzhiyun 		gtp_x_reverse = FALSE;
2681*4882a593Smuzhiyun 		gtp_y_reverse = FALSE;
2682*4882a593Smuzhiyun 	} else if (val == 970) {
2683*4882a593Smuzhiyun 		m89or101 = FALSE;
2684*4882a593Smuzhiyun 		bgt911 = FALSE;
2685*4882a593Smuzhiyun 		bgt970 = TRUE;
2686*4882a593Smuzhiyun 		gtp_change_x2y = FALSE;
2687*4882a593Smuzhiyun 		gtp_x_reverse = FALSE;
2688*4882a593Smuzhiyun 		gtp_y_reverse = TRUE;
2689*4882a593Smuzhiyun 	} else if (val == 910) {
2690*4882a593Smuzhiyun 		m89or101 = FALSE;
2691*4882a593Smuzhiyun 		bgt911 = FALSE;
2692*4882a593Smuzhiyun 		bgt970 = FALSE;
2693*4882a593Smuzhiyun 		bgt910 = TRUE;
2694*4882a593Smuzhiyun 		gtp_change_x2y = TRUE;
2695*4882a593Smuzhiyun 		gtp_x_reverse = FALSE;
2696*4882a593Smuzhiyun 		gtp_y_reverse = TRUE;
2697*4882a593Smuzhiyun 	}
2698*4882a593Smuzhiyun 
2699*4882a593Smuzhiyun 	ts->tp_regulator = devm_regulator_get(&client->dev, "tp");
2700*4882a593Smuzhiyun 	if (IS_ERR(ts->tp_regulator)) {
2701*4882a593Smuzhiyun 		dev_err(&client->dev, "failed to get regulator, %ld\n",
2702*4882a593Smuzhiyun 			PTR_ERR(ts->tp_regulator));
2703*4882a593Smuzhiyun 		return PTR_ERR(ts->tp_regulator);
2704*4882a593Smuzhiyun 	}
2705*4882a593Smuzhiyun 
2706*4882a593Smuzhiyun 	ret = regulator_enable(ts->tp_regulator);
2707*4882a593Smuzhiyun 	if (ret < 0)
2708*4882a593Smuzhiyun 		GTP_ERROR("failed to enable tp regulator\n");
2709*4882a593Smuzhiyun 	msleep(20);
2710*4882a593Smuzhiyun 
2711*4882a593Smuzhiyun     ts->irq_pin = of_get_named_gpio_flags(np, "touch-gpio", 0, (enum of_gpio_flags *)(&ts->irq_flags));
2712*4882a593Smuzhiyun     ts->rst_pin = of_get_named_gpio_flags(np, "reset-gpio", 0, &rst_flags);
2713*4882a593Smuzhiyun     ts->pwr_pin = of_get_named_gpio_flags(np, "power-gpio", 0, &pwr_flags);
2714*4882a593Smuzhiyun     //ts->tp_select_pin = of_get_named_gpio_flags(np, "tp-select-gpio", 0, &tp_select_flags);
2715*4882a593Smuzhiyun     if (of_property_read_u32(np, "max-x", &val)) {
2716*4882a593Smuzhiyun     	dev_err(&client->dev, "no max-x defined\n");
2717*4882a593Smuzhiyun     	return -EINVAL;
2718*4882a593Smuzhiyun     }
2719*4882a593Smuzhiyun     //ts->abs_x_max = val;
2720*4882a593Smuzhiyun     if (of_property_read_u32(np, "max-y", &val)) {
2721*4882a593Smuzhiyun     	dev_err(&client->dev, "no max-y defined\n");
2722*4882a593Smuzhiyun     	return -EINVAL;
2723*4882a593Smuzhiyun     }
2724*4882a593Smuzhiyun     //ts->abs_y_max = val;
2725*4882a593Smuzhiyun     if (of_property_read_u32(np, "configfile-num", &val)) {
2726*4882a593Smuzhiyun 	    ts->cfg_file_num = 0;
2727*4882a593Smuzhiyun     } else {
2728*4882a593Smuzhiyun 	    ts->cfg_file_num = val;
2729*4882a593Smuzhiyun     }
2730*4882a593Smuzhiyun     ts->pendown =PEN_RELEASE;
2731*4882a593Smuzhiyun     ts->client = client;
2732*4882a593Smuzhiyun 
2733*4882a593Smuzhiyun 
2734*4882a593Smuzhiyun     INIT_WORK(&ts->work, goodix_ts_work_func);
2735*4882a593Smuzhiyun     ts->client = client;
2736*4882a593Smuzhiyun     spin_lock_init(&ts->irq_lock);          // 2.6.39 later
2737*4882a593Smuzhiyun     // ts->irq_lock = SPIN_LOCK_UNLOCKED;   // 2.6.39 & before
2738*4882a593Smuzhiyun #if GTP_ESD_PROTECT
2739*4882a593Smuzhiyun     ts->clk_tick_cnt = 2 * HZ;      // HZ: clock ticks in 1 second generated by system
2740*4882a593Smuzhiyun     GTP_DEBUG("Clock ticks for an esd cycle: %d", ts->clk_tick_cnt);
2741*4882a593Smuzhiyun     spin_lock_init(&ts->esd_lock);
2742*4882a593Smuzhiyun     // ts->esd_lock = SPIN_LOCK_UNLOCKED;
2743*4882a593Smuzhiyun #endif
2744*4882a593Smuzhiyun 
2745*4882a593Smuzhiyun     i2c_set_clientdata(client, ts);
2746*4882a593Smuzhiyun 
2747*4882a593Smuzhiyun     ts->gtp_rawdiff_mode = 0;
2748*4882a593Smuzhiyun 
2749*4882a593Smuzhiyun     ret = gtp_request_io_port(ts);
2750*4882a593Smuzhiyun     if (ret < 0)
2751*4882a593Smuzhiyun     {
2752*4882a593Smuzhiyun         GTP_ERROR("GTP request IO port failed.");
2753*4882a593Smuzhiyun         //return ret;
2754*4882a593Smuzhiyun         goto probe_init_error_requireio;
2755*4882a593Smuzhiyun     }
2756*4882a593Smuzhiyun /*
2757*4882a593Smuzhiyun     if(gpio_get_value(ts->tp_select_pin))//WGJ
2758*4882a593Smuzhiyun     {
2759*4882a593Smuzhiyun     	printk("tp 11111111111111111111111111111 WGJ\n\n");
2760*4882a593Smuzhiyun 		gtp_x_reverse = FALSE;
2761*4882a593Smuzhiyun 		gtp_y_reverse = TRUE;
2762*4882a593Smuzhiyun     }
2763*4882a593Smuzhiyun     else//DPT
2764*4882a593Smuzhiyun     {
2765*4882a593Smuzhiyun     	printk("tp 00000000000000000000000000000 DPT\n\n");
2766*4882a593Smuzhiyun 		gtp_x_reverse = TRUE;//FALSE;
2767*4882a593Smuzhiyun 		gtp_y_reverse = TRUE;
2768*4882a593Smuzhiyun     }
2769*4882a593Smuzhiyun  */
2770*4882a593Smuzhiyun #if GTP_COMPATIBLE_MODE
2771*4882a593Smuzhiyun     gtp_get_chip_type(ts);
2772*4882a593Smuzhiyun 
2773*4882a593Smuzhiyun     if (CHIP_TYPE_GT9F == ts->chip_type)
2774*4882a593Smuzhiyun     {
2775*4882a593Smuzhiyun         ret = gtp_gt9xxf_init(ts->client);
2776*4882a593Smuzhiyun         if (FAIL == ret)
2777*4882a593Smuzhiyun         {
2778*4882a593Smuzhiyun             GTP_INFO("Failed to init GT9XXF.");
2779*4882a593Smuzhiyun         }
2780*4882a593Smuzhiyun     }
2781*4882a593Smuzhiyun #endif
2782*4882a593Smuzhiyun 
2783*4882a593Smuzhiyun     ret = gtp_i2c_test(client);
2784*4882a593Smuzhiyun     if (ret < 0)
2785*4882a593Smuzhiyun     {
2786*4882a593Smuzhiyun         printk("<%s>_%d    I2C communication ERROR!\n", __func__, __LINE__);
2787*4882a593Smuzhiyun         goto probe_init_error;
2788*4882a593Smuzhiyun     }
2789*4882a593Smuzhiyun 
2790*4882a593Smuzhiyun     ret = gtp_read_version(client, &version_info);
2791*4882a593Smuzhiyun     if (ret < 0)
2792*4882a593Smuzhiyun     {
2793*4882a593Smuzhiyun         GTP_ERROR("Read version failed.");
2794*4882a593Smuzhiyun     }
2795*4882a593Smuzhiyun 
2796*4882a593Smuzhiyun     ret = gtp_init_panel(ts);
2797*4882a593Smuzhiyun     if (ret < 0)
2798*4882a593Smuzhiyun     {
2799*4882a593Smuzhiyun         GTP_ERROR("GTP init panel failed.");
2800*4882a593Smuzhiyun         //ts->abs_x_max = GTP_MAX_WIDTH;
2801*4882a593Smuzhiyun         //ts->abs_y_max = GTP_MAX_HEIGHT;
2802*4882a593Smuzhiyun         ts->int_trigger_type = GTP_INT_TRIGGER;
2803*4882a593Smuzhiyun     }
2804*4882a593Smuzhiyun 
2805*4882a593Smuzhiyun     ts->irq_flags = ts->int_trigger_type ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
2806*4882a593Smuzhiyun     // Create proc file system
2807*4882a593Smuzhiyun 	gt91xx_config_proc = proc_create(GT91XX_CONFIG_PROC_FILE, 0664, NULL, &config_proc_ops);
2808*4882a593Smuzhiyun     if (gt91xx_config_proc == NULL)
2809*4882a593Smuzhiyun     {
2810*4882a593Smuzhiyun         GTP_ERROR("create_proc_entry %s failed\n", GT91XX_CONFIG_PROC_FILE);
2811*4882a593Smuzhiyun     }
2812*4882a593Smuzhiyun     else
2813*4882a593Smuzhiyun     {
2814*4882a593Smuzhiyun         GTP_INFO("create proc entry %s success", GT91XX_CONFIG_PROC_FILE);
2815*4882a593Smuzhiyun     }
2816*4882a593Smuzhiyun 
2817*4882a593Smuzhiyun #if GTP_AUTO_UPDATE
2818*4882a593Smuzhiyun     ret = gup_init_update_proc(ts);
2819*4882a593Smuzhiyun     if (ret < 0)
2820*4882a593Smuzhiyun     {
2821*4882a593Smuzhiyun         GTP_ERROR("Create update thread error.");
2822*4882a593Smuzhiyun     }
2823*4882a593Smuzhiyun #endif
2824*4882a593Smuzhiyun 
2825*4882a593Smuzhiyun     ret = gtp_request_input_dev(client, ts);
2826*4882a593Smuzhiyun     if (ret < 0)
2827*4882a593Smuzhiyun     {
2828*4882a593Smuzhiyun         GTP_ERROR("GTP request input dev failed");
2829*4882a593Smuzhiyun     }
2830*4882a593Smuzhiyun     ret = gtp_request_irq(ts);
2831*4882a593Smuzhiyun     if (ret < 0)
2832*4882a593Smuzhiyun     {
2833*4882a593Smuzhiyun         GTP_INFO("GTP works in polling mode.");
2834*4882a593Smuzhiyun     }
2835*4882a593Smuzhiyun     else
2836*4882a593Smuzhiyun     {
2837*4882a593Smuzhiyun         GTP_INFO("GTP works in interrupt mode.");
2838*4882a593Smuzhiyun     }
2839*4882a593Smuzhiyun 
2840*4882a593Smuzhiyun     if (ts->use_irq)
2841*4882a593Smuzhiyun     {
2842*4882a593Smuzhiyun         gtp_irq_enable(ts);
2843*4882a593Smuzhiyun     }
2844*4882a593Smuzhiyun 
2845*4882a593Smuzhiyun     if (of_property_read_bool(np, "wakeup-source"))
2846*4882a593Smuzhiyun     {
2847*4882a593Smuzhiyun         device_init_wakeup(&client->dev, 1);
2848*4882a593Smuzhiyun         enable_irq_wake(ts->irq);
2849*4882a593Smuzhiyun     }
2850*4882a593Smuzhiyun 
2851*4882a593Smuzhiyun #if GTP_CREATE_WR_NODE
2852*4882a593Smuzhiyun     init_wr_node(client);
2853*4882a593Smuzhiyun #endif
2854*4882a593Smuzhiyun 
2855*4882a593Smuzhiyun #if GTP_ESD_PROTECT
2856*4882a593Smuzhiyun     gtp_esd_switch(client, SWITCH_ON);
2857*4882a593Smuzhiyun #endif
2858*4882a593Smuzhiyun     return 0;
2859*4882a593Smuzhiyun 
2860*4882a593Smuzhiyun probe_init_error:
2861*4882a593Smuzhiyun     printk("   <%s>_%d  prob error !!!!!!!!!!!!!!!\n", __func__, __LINE__);
2862*4882a593Smuzhiyun     GTP_GPIO_FREE(ts->rst_pin);
2863*4882a593Smuzhiyun     GTP_GPIO_FREE(ts->irq_pin);
2864*4882a593Smuzhiyun probe_init_error_requireio:
2865*4882a593Smuzhiyun     tp_unregister_fb(&ts->tp);
2866*4882a593Smuzhiyun     kfree(ts);
2867*4882a593Smuzhiyun     return ret;
2868*4882a593Smuzhiyun }
2869*4882a593Smuzhiyun 
2870*4882a593Smuzhiyun 
2871*4882a593Smuzhiyun /*******************************************************
2872*4882a593Smuzhiyun Function:
2873*4882a593Smuzhiyun     Goodix touchscreen driver release function.
2874*4882a593Smuzhiyun Input:
2875*4882a593Smuzhiyun     client: i2c device struct.
2876*4882a593Smuzhiyun Output:
2877*4882a593Smuzhiyun     Executive outcomes. 0---succeed.
2878*4882a593Smuzhiyun *******************************************************/
goodix_ts_remove(struct i2c_client * client)2879*4882a593Smuzhiyun static int goodix_ts_remove(struct i2c_client *client)
2880*4882a593Smuzhiyun {
2881*4882a593Smuzhiyun     struct goodix_ts_data *ts = i2c_get_clientdata(client);
2882*4882a593Smuzhiyun 
2883*4882a593Smuzhiyun     tp_unregister_fb(&ts->tp);
2884*4882a593Smuzhiyun 
2885*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
2886*4882a593Smuzhiyun 
2887*4882a593Smuzhiyun #if GTP_CREATE_WR_NODE
2888*4882a593Smuzhiyun     uninit_wr_node();
2889*4882a593Smuzhiyun #endif
2890*4882a593Smuzhiyun 
2891*4882a593Smuzhiyun #if GTP_ESD_PROTECT
2892*4882a593Smuzhiyun     destroy_workqueue(gtp_esd_check_workqueue);
2893*4882a593Smuzhiyun #endif
2894*4882a593Smuzhiyun 
2895*4882a593Smuzhiyun     if (ts)
2896*4882a593Smuzhiyun     {
2897*4882a593Smuzhiyun         if (ts->use_irq)
2898*4882a593Smuzhiyun         {
2899*4882a593Smuzhiyun             //GTP_GPIO_AS_INPUT(GTP_INT_PORT);
2900*4882a593Smuzhiyun 
2901*4882a593Smuzhiyun             gpio_direction_input(ts->irq_pin);
2902*4882a593Smuzhiyun             //s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
2903*4882a593Smuzhiyun 
2904*4882a593Smuzhiyun             GTP_GPIO_FREE(ts->irq_pin);
2905*4882a593Smuzhiyun             free_irq(client->irq, ts);
2906*4882a593Smuzhiyun         }
2907*4882a593Smuzhiyun         else
2908*4882a593Smuzhiyun         {
2909*4882a593Smuzhiyun             hrtimer_cancel(&ts->timer);
2910*4882a593Smuzhiyun         }
2911*4882a593Smuzhiyun 		GTP_INFO("GTP driver removing...");
2912*4882a593Smuzhiyun 		i2c_set_clientdata(client, NULL);
2913*4882a593Smuzhiyun 		input_unregister_device(ts->input_dev);
2914*4882a593Smuzhiyun 		kfree(ts);
2915*4882a593Smuzhiyun 	}
2916*4882a593Smuzhiyun 
2917*4882a593Smuzhiyun     return 0;
2918*4882a593Smuzhiyun }
2919*4882a593Smuzhiyun 
2920*4882a593Smuzhiyun 
2921*4882a593Smuzhiyun 
2922*4882a593Smuzhiyun 
2923*4882a593Smuzhiyun 
2924*4882a593Smuzhiyun #if GTP_ESD_PROTECT
gtp_i2c_read_no_rst(struct i2c_client * client,u8 * buf,s32 len)2925*4882a593Smuzhiyun s32 gtp_i2c_read_no_rst(struct i2c_client *client, u8 *buf, s32 len)
2926*4882a593Smuzhiyun {
2927*4882a593Smuzhiyun     struct i2c_msg msgs[2];
2928*4882a593Smuzhiyun     s32 ret=-1;
2929*4882a593Smuzhiyun     s32 retries = 0;
2930*4882a593Smuzhiyun 
2931*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
2932*4882a593Smuzhiyun 
2933*4882a593Smuzhiyun     msgs[0].flags = !I2C_M_RD;
2934*4882a593Smuzhiyun     msgs[0].addr  = client->addr;
2935*4882a593Smuzhiyun     msgs[0].len   = GTP_ADDR_LENGTH;
2936*4882a593Smuzhiyun     msgs[0].buf   = &buf[0];
2937*4882a593Smuzhiyun     //msgs[0].scl_rate = 300 * 1000;    // for Rockchip, etc.
2938*4882a593Smuzhiyun 
2939*4882a593Smuzhiyun     msgs[1].flags = I2C_M_RD;
2940*4882a593Smuzhiyun     msgs[1].addr  = client->addr;
2941*4882a593Smuzhiyun     msgs[1].len   = len - GTP_ADDR_LENGTH;
2942*4882a593Smuzhiyun     msgs[1].buf   = &buf[GTP_ADDR_LENGTH];
2943*4882a593Smuzhiyun     //msgs[1].scl_rate = 300 * 1000;
2944*4882a593Smuzhiyun 
2945*4882a593Smuzhiyun     while(retries < 5)
2946*4882a593Smuzhiyun     {
2947*4882a593Smuzhiyun         ret = i2c_transfer(client->adapter, msgs, 2);
2948*4882a593Smuzhiyun         if(ret == 2)break;
2949*4882a593Smuzhiyun         retries++;
2950*4882a593Smuzhiyun     }
2951*4882a593Smuzhiyun     if ((retries >= 5))
2952*4882a593Smuzhiyun     {
2953*4882a593Smuzhiyun         GTP_ERROR("I2C Read: 0x%04X, %d bytes failed, errcode: %d!", (((u16)(buf[0] << 8)) | buf[1]), len-2, ret);
2954*4882a593Smuzhiyun     }
2955*4882a593Smuzhiyun     return ret;
2956*4882a593Smuzhiyun }
2957*4882a593Smuzhiyun 
gtp_i2c_write_no_rst(struct i2c_client * client,u8 * buf,s32 len)2958*4882a593Smuzhiyun s32 gtp_i2c_write_no_rst(struct i2c_client *client,u8 *buf,s32 len)
2959*4882a593Smuzhiyun {
2960*4882a593Smuzhiyun     struct i2c_msg msg;
2961*4882a593Smuzhiyun     s32 ret = -1;
2962*4882a593Smuzhiyun     s32 retries = 0;
2963*4882a593Smuzhiyun 
2964*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
2965*4882a593Smuzhiyun 
2966*4882a593Smuzhiyun     msg.flags = !I2C_M_RD;
2967*4882a593Smuzhiyun     msg.addr  = client->addr;
2968*4882a593Smuzhiyun     msg.len   = len;
2969*4882a593Smuzhiyun     msg.buf   = buf;
2970*4882a593Smuzhiyun     //msg.scl_rate = 300 * 1000;    // for Rockchip, etc
2971*4882a593Smuzhiyun 
2972*4882a593Smuzhiyun     while(retries < 5)
2973*4882a593Smuzhiyun     {
2974*4882a593Smuzhiyun         ret = i2c_transfer(client->adapter, &msg, 1);
2975*4882a593Smuzhiyun         if (ret == 1)break;
2976*4882a593Smuzhiyun         retries++;
2977*4882a593Smuzhiyun     }
2978*4882a593Smuzhiyun     if((retries >= 5))
2979*4882a593Smuzhiyun     {
2980*4882a593Smuzhiyun         GTP_ERROR("I2C Write: 0x%04X, %d bytes failed, errcode: %d!", (((u16)(buf[0] << 8)) | buf[1]), len-2, ret);
2981*4882a593Smuzhiyun     }
2982*4882a593Smuzhiyun     return ret;
2983*4882a593Smuzhiyun }
2984*4882a593Smuzhiyun /*******************************************************
2985*4882a593Smuzhiyun Function:
2986*4882a593Smuzhiyun     switch on & off esd delayed work
2987*4882a593Smuzhiyun Input:
2988*4882a593Smuzhiyun     client:  i2c device
2989*4882a593Smuzhiyun     on:      SWITCH_ON / SWITCH_OFF
2990*4882a593Smuzhiyun Output:
2991*4882a593Smuzhiyun     void
2992*4882a593Smuzhiyun *********************************************************/
gtp_esd_switch(struct i2c_client * client,s32 on)2993*4882a593Smuzhiyun void gtp_esd_switch(struct i2c_client *client, s32 on)
2994*4882a593Smuzhiyun {
2995*4882a593Smuzhiyun     struct goodix_ts_data *ts;
2996*4882a593Smuzhiyun 
2997*4882a593Smuzhiyun     ts = i2c_get_clientdata(client);
2998*4882a593Smuzhiyun     spin_lock(&ts->esd_lock);
2999*4882a593Smuzhiyun 
3000*4882a593Smuzhiyun     if (SWITCH_ON == on)     // switch on esd
3001*4882a593Smuzhiyun     {
3002*4882a593Smuzhiyun         if (!ts->esd_running)
3003*4882a593Smuzhiyun         {
3004*4882a593Smuzhiyun             ts->esd_running = 1;
3005*4882a593Smuzhiyun             spin_unlock(&ts->esd_lock);
3006*4882a593Smuzhiyun             GTP_INFO("Esd started");
3007*4882a593Smuzhiyun             queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work, ts->clk_tick_cnt);
3008*4882a593Smuzhiyun         }
3009*4882a593Smuzhiyun         else
3010*4882a593Smuzhiyun         {
3011*4882a593Smuzhiyun             spin_unlock(&ts->esd_lock);
3012*4882a593Smuzhiyun         }
3013*4882a593Smuzhiyun     }
3014*4882a593Smuzhiyun     else    // switch off esd
3015*4882a593Smuzhiyun     {
3016*4882a593Smuzhiyun         if (ts->esd_running)
3017*4882a593Smuzhiyun         {
3018*4882a593Smuzhiyun             ts->esd_running = 0;
3019*4882a593Smuzhiyun             spin_unlock(&ts->esd_lock);
3020*4882a593Smuzhiyun             GTP_INFO("Esd cancelled");
3021*4882a593Smuzhiyun             cancel_delayed_work_sync(&gtp_esd_check_work);
3022*4882a593Smuzhiyun         }
3023*4882a593Smuzhiyun         else
3024*4882a593Smuzhiyun         {
3025*4882a593Smuzhiyun             spin_unlock(&ts->esd_lock);
3026*4882a593Smuzhiyun         }
3027*4882a593Smuzhiyun     }
3028*4882a593Smuzhiyun }
3029*4882a593Smuzhiyun 
3030*4882a593Smuzhiyun /*******************************************************
3031*4882a593Smuzhiyun Function:
3032*4882a593Smuzhiyun     Initialize external watchdog for esd protect
3033*4882a593Smuzhiyun Input:
3034*4882a593Smuzhiyun     client:  i2c device.
3035*4882a593Smuzhiyun Output:
3036*4882a593Smuzhiyun     result of i2c write operation.
3037*4882a593Smuzhiyun         1: succeed, otherwise: failed
3038*4882a593Smuzhiyun *********************************************************/
gtp_init_ext_watchdog(struct i2c_client * client)3039*4882a593Smuzhiyun static s32 gtp_init_ext_watchdog(struct i2c_client *client)
3040*4882a593Smuzhiyun {
3041*4882a593Smuzhiyun     u8 opr_buffer[3] = {0x80, 0x41, 0xAA};
3042*4882a593Smuzhiyun     GTP_DEBUG("[Esd]Init external watchdog");
3043*4882a593Smuzhiyun     return gtp_i2c_write_no_rst(client, opr_buffer, 3);
3044*4882a593Smuzhiyun }
3045*4882a593Smuzhiyun 
3046*4882a593Smuzhiyun /*******************************************************
3047*4882a593Smuzhiyun Function:
3048*4882a593Smuzhiyun     Esd protect function.
3049*4882a593Smuzhiyun     External watchdog added by meta, 2013/03/07
3050*4882a593Smuzhiyun Input:
3051*4882a593Smuzhiyun     work: delayed work
3052*4882a593Smuzhiyun Output:
3053*4882a593Smuzhiyun     None.
3054*4882a593Smuzhiyun *******************************************************/
gtp_esd_check_func(struct work_struct * work)3055*4882a593Smuzhiyun static void gtp_esd_check_func(struct work_struct *work)
3056*4882a593Smuzhiyun {
3057*4882a593Smuzhiyun     s32 i;
3058*4882a593Smuzhiyun     s32 ret = -1;
3059*4882a593Smuzhiyun     struct goodix_ts_data *ts = NULL;
3060*4882a593Smuzhiyun     u8 esd_buf[5] = {0x80, 0x40};
3061*4882a593Smuzhiyun 
3062*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
3063*4882a593Smuzhiyun 
3064*4882a593Smuzhiyun     ts = i2c_get_clientdata(i2c_connect_client);
3065*4882a593Smuzhiyun 
3066*4882a593Smuzhiyun     if (ts->gtp_is_suspend)
3067*4882a593Smuzhiyun     {
3068*4882a593Smuzhiyun         GTP_INFO("Esd suspended!");
3069*4882a593Smuzhiyun         return;
3070*4882a593Smuzhiyun     }
3071*4882a593Smuzhiyun 
3072*4882a593Smuzhiyun     for (i = 0; i < 3; i++)
3073*4882a593Smuzhiyun     {
3074*4882a593Smuzhiyun         ret = gtp_i2c_read_no_rst(ts->client, esd_buf, 4);
3075*4882a593Smuzhiyun 
3076*4882a593Smuzhiyun         GTP_DEBUG("[Esd]0x8040 = 0x%02X, 0x8041 = 0x%02X", esd_buf[2], esd_buf[3]);
3077*4882a593Smuzhiyun         if ((ret < 0))
3078*4882a593Smuzhiyun         {
3079*4882a593Smuzhiyun             // IIC communication problem
3080*4882a593Smuzhiyun             continue;
3081*4882a593Smuzhiyun         }
3082*4882a593Smuzhiyun         else
3083*4882a593Smuzhiyun         {
3084*4882a593Smuzhiyun             if ((esd_buf[2] == 0xAA) || (esd_buf[3] != 0xAA))
3085*4882a593Smuzhiyun             {
3086*4882a593Smuzhiyun                 // IC works abnormally..
3087*4882a593Smuzhiyun                 u8 chk_buf[4] = {0x80, 0x40};
3088*4882a593Smuzhiyun 
3089*4882a593Smuzhiyun                 gtp_i2c_read_no_rst(ts->client, chk_buf, 4);
3090*4882a593Smuzhiyun 
3091*4882a593Smuzhiyun                 GTP_DEBUG("[Check]0x8040 = 0x%02X, 0x8041 = 0x%02X", chk_buf[2], chk_buf[3]);
3092*4882a593Smuzhiyun 
3093*4882a593Smuzhiyun                 if ((chk_buf[2] == 0xAA) || (chk_buf[3] != 0xAA))
3094*4882a593Smuzhiyun                 {
3095*4882a593Smuzhiyun                     i = 3;
3096*4882a593Smuzhiyun                     break;
3097*4882a593Smuzhiyun                 }
3098*4882a593Smuzhiyun                 else
3099*4882a593Smuzhiyun                 {
3100*4882a593Smuzhiyun                     continue;
3101*4882a593Smuzhiyun                 }
3102*4882a593Smuzhiyun             }
3103*4882a593Smuzhiyun             else
3104*4882a593Smuzhiyun             {
3105*4882a593Smuzhiyun                 // IC works normally, Write 0x8040 0xAA, feed the dog
3106*4882a593Smuzhiyun                 esd_buf[2] = 0xAA;
3107*4882a593Smuzhiyun                 gtp_i2c_write_no_rst(ts->client, esd_buf, 3);
3108*4882a593Smuzhiyun                 break;
3109*4882a593Smuzhiyun             }
3110*4882a593Smuzhiyun         }
3111*4882a593Smuzhiyun     }
3112*4882a593Smuzhiyun     if (i >= 3)
3113*4882a593Smuzhiyun     {
3114*4882a593Smuzhiyun     #if GTP_COMPATIBLE_MODE
3115*4882a593Smuzhiyun         if (CHIP_TYPE_GT9F == ts->chip_type)
3116*4882a593Smuzhiyun         {
3117*4882a593Smuzhiyun             if (ts->rqst_processing)
3118*4882a593Smuzhiyun             {
3119*4882a593Smuzhiyun                 GTP_INFO("Request processing, no esd recovery");
3120*4882a593Smuzhiyun             }
3121*4882a593Smuzhiyun             else
3122*4882a593Smuzhiyun             {
3123*4882a593Smuzhiyun                 GTP_ERROR("IC working abnormally! Process esd recovery.");
3124*4882a593Smuzhiyun                 esd_buf[0] = 0x42;
3125*4882a593Smuzhiyun                 esd_buf[1] = 0x26;
3126*4882a593Smuzhiyun                 esd_buf[2] = 0x01;
3127*4882a593Smuzhiyun                 esd_buf[3] = 0x01;
3128*4882a593Smuzhiyun                 esd_buf[4] = 0x01;
3129*4882a593Smuzhiyun                 gtp_i2c_write_no_rst(ts->client, esd_buf, 5);
3130*4882a593Smuzhiyun                 msleep(50);
3131*4882a593Smuzhiyun                 gtp_esd_recovery(ts->client);
3132*4882a593Smuzhiyun             }
3133*4882a593Smuzhiyun         }
3134*4882a593Smuzhiyun         else
3135*4882a593Smuzhiyun     #endif
3136*4882a593Smuzhiyun         {
3137*4882a593Smuzhiyun             GTP_ERROR("IC working abnormally! Process reset guitar.");
3138*4882a593Smuzhiyun             esd_buf[0] = 0x42;
3139*4882a593Smuzhiyun             esd_buf[1] = 0x26;
3140*4882a593Smuzhiyun             esd_buf[2] = 0x01;
3141*4882a593Smuzhiyun             esd_buf[3] = 0x01;
3142*4882a593Smuzhiyun             esd_buf[4] = 0x01;
3143*4882a593Smuzhiyun             gtp_i2c_write_no_rst(ts->client, esd_buf, 5);
3144*4882a593Smuzhiyun             msleep(50);
3145*4882a593Smuzhiyun             gtp_reset_guitar(ts->client, 50);
3146*4882a593Smuzhiyun             msleep(50);
3147*4882a593Smuzhiyun             gtp_send_cfg(ts->client);
3148*4882a593Smuzhiyun         }
3149*4882a593Smuzhiyun     }
3150*4882a593Smuzhiyun 
3151*4882a593Smuzhiyun     if(!ts->gtp_is_suspend)
3152*4882a593Smuzhiyun     {
3153*4882a593Smuzhiyun         queue_delayed_work(gtp_esd_check_workqueue, &gtp_esd_check_work, ts->clk_tick_cnt);
3154*4882a593Smuzhiyun     }
3155*4882a593Smuzhiyun     else
3156*4882a593Smuzhiyun     {
3157*4882a593Smuzhiyun         GTP_INFO("Esd suspended!");
3158*4882a593Smuzhiyun     }
3159*4882a593Smuzhiyun     return;
3160*4882a593Smuzhiyun }
3161*4882a593Smuzhiyun #endif
3162*4882a593Smuzhiyun 
3163*4882a593Smuzhiyun static const struct i2c_device_id goodix_ts_id[] = {
3164*4882a593Smuzhiyun     { GTP_I2C_NAME, 0 },
3165*4882a593Smuzhiyun     { }
3166*4882a593Smuzhiyun };
3167*4882a593Smuzhiyun 
3168*4882a593Smuzhiyun static struct of_device_id goodix_ts_dt_ids[] = {
3169*4882a593Smuzhiyun     { .compatible = "goodix,gt9xx" },
3170*4882a593Smuzhiyun     { }
3171*4882a593Smuzhiyun };
3172*4882a593Smuzhiyun 
3173*4882a593Smuzhiyun static struct i2c_driver goodix_ts_driver = {
3174*4882a593Smuzhiyun     .probe      = goodix_ts_probe,
3175*4882a593Smuzhiyun     .remove     = goodix_ts_remove,
3176*4882a593Smuzhiyun     .id_table   = goodix_ts_id,
3177*4882a593Smuzhiyun     .driver = {
3178*4882a593Smuzhiyun         .name     = GTP_I2C_NAME,
3179*4882a593Smuzhiyun 	 .of_match_table = of_match_ptr(goodix_ts_dt_ids),
3180*4882a593Smuzhiyun     },
3181*4882a593Smuzhiyun };
3182*4882a593Smuzhiyun 
3183*4882a593Smuzhiyun /*******************************************************
3184*4882a593Smuzhiyun Function:
3185*4882a593Smuzhiyun     Driver Install function.
3186*4882a593Smuzhiyun Input:
3187*4882a593Smuzhiyun     None.
3188*4882a593Smuzhiyun Output:
3189*4882a593Smuzhiyun     Executive Outcomes. 0---succeed.
3190*4882a593Smuzhiyun ********************************************************/
goodix_ts_init(void)3191*4882a593Smuzhiyun static int goodix_ts_init(void)
3192*4882a593Smuzhiyun {
3193*4882a593Smuzhiyun     s32 ret;
3194*4882a593Smuzhiyun 
3195*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
3196*4882a593Smuzhiyun     GTP_INFO("GTP driver installing...");
3197*4882a593Smuzhiyun     goodix_wq = create_singlethread_workqueue("goodix_wq");
3198*4882a593Smuzhiyun     if (!goodix_wq)
3199*4882a593Smuzhiyun     {
3200*4882a593Smuzhiyun         GTP_ERROR("Creat workqueue failed.");
3201*4882a593Smuzhiyun         return -ENOMEM;
3202*4882a593Smuzhiyun     }
3203*4882a593Smuzhiyun #if GTP_ESD_PROTECT
3204*4882a593Smuzhiyun     INIT_DELAYED_WORK(&gtp_esd_check_work, gtp_esd_check_func);
3205*4882a593Smuzhiyun     gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");
3206*4882a593Smuzhiyun #endif
3207*4882a593Smuzhiyun     ret = i2c_add_driver(&goodix_ts_driver);
3208*4882a593Smuzhiyun     return ret;
3209*4882a593Smuzhiyun }
3210*4882a593Smuzhiyun 
3211*4882a593Smuzhiyun /*******************************************************
3212*4882a593Smuzhiyun Function:
3213*4882a593Smuzhiyun     Driver uninstall function.
3214*4882a593Smuzhiyun Input:
3215*4882a593Smuzhiyun     None.
3216*4882a593Smuzhiyun Output:
3217*4882a593Smuzhiyun     Executive Outcomes. 0---succeed.
3218*4882a593Smuzhiyun ********************************************************/
goodix_ts_exit(void)3219*4882a593Smuzhiyun static void goodix_ts_exit(void)
3220*4882a593Smuzhiyun {
3221*4882a593Smuzhiyun     GTP_DEBUG_FUNC();
3222*4882a593Smuzhiyun     GTP_INFO("GTP driver exited.");
3223*4882a593Smuzhiyun     i2c_del_driver(&goodix_ts_driver);
3224*4882a593Smuzhiyun     if (goodix_wq)
3225*4882a593Smuzhiyun     {
3226*4882a593Smuzhiyun         destroy_workqueue(goodix_wq);
3227*4882a593Smuzhiyun     }
3228*4882a593Smuzhiyun }
3229*4882a593Smuzhiyun //late_initcall(goodix_ts_init);
3230*4882a593Smuzhiyun module_init(goodix_ts_init);
3231*4882a593Smuzhiyun 
3232*4882a593Smuzhiyun module_exit(goodix_ts_exit);
3233*4882a593Smuzhiyun 
3234*4882a593Smuzhiyun MODULE_DESCRIPTION("GTP Series Driver");
3235*4882a593Smuzhiyun MODULE_LICENSE("GPL");
3236