blob: 52aa9835d6ae31e81cc8da629e01dfcaef80d1cc [file] [log] [blame]
Andrew Huangab45aab2013-06-27 10:06:56 +00001/* drivers/input/touchscreen/gt9xx.c
Bingzhe Cai83caeea2013-07-16 17:57:37 +08002 *
3 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
4 *
5 * Linux Foundation chooses to take subject only to the GPLv2 license
6 * terms, and distributes only under these terms.
7 *
Andrew Huangab45aab2013-06-27 10:06:56 +00008 * 2010 - 2013 Goodix Technology.
Bingzhe Cai83caeea2013-07-16 17:57:37 +08009 *
Andrew Huangab45aab2013-06-27 10:06:56 +000010 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
Bingzhe Cai83caeea2013-07-16 17:57:37 +080014 *
15 * This program is distributed in the hope that it will be a reference
16 * to you, when you are integrating the GOODiX's CTP IC into your system,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Andrew Huangab45aab2013-06-27 10:06:56 +000019 * General Public License for more details.
Bingzhe Cai83caeea2013-07-16 17:57:37 +080020 *
Andrew Huangab45aab2013-06-27 10:06:56 +000021 * Version: 1.8
22 * Authors: andrew@goodix.com, meta@goodix.com
23 * Release Date: 2013/04/25
24 * Revision record:
Bingzhe Cai83caeea2013-07-16 17:57:37 +080025 * V1.0:
26 * first Release. By Andrew, 2012/08/31
Andrew Huangab45aab2013-06-27 10:06:56 +000027 * V1.2:
Bingzhe Cai83caeea2013-07-16 17:57:37 +080028 * modify gtp_reset_guitar,slot report,tracking_id & 0x0F.
29 * By Andrew, 2012/10/15
Andrew Huangab45aab2013-06-27 10:06:56 +000030 * V1.4:
31 * modify gt9xx_update.c. By Andrew, 2012/12/12
Bingzhe Cai83caeea2013-07-16 17:57:37 +080032 * V1.6:
Andrew Huangab45aab2013-06-27 10:06:56 +000033 * 1. new heartbeat/esd_protect mechanism(add external watchdog)
Bingzhe Cai83caeea2013-07-16 17:57:37 +080034 * 2. doze mode, sliding wakeup
35 * 3. 3 more cfg_group(GT9 Sensor_ID: 0~5)
Andrew Huangab45aab2013-06-27 10:06:56 +000036 * 3. config length verification
37 * 4. names & comments
38 * By Meta, 2013/03/11
39 * V1.8:
Bingzhe Cai83caeea2013-07-16 17:57:37 +080040 * 1. pen/stylus identification
Andrew Huangab45aab2013-06-27 10:06:56 +000041 * 2. read double check & fixed config support
42 * 2. new esd & slide wakeup optimization
43 * By Meta, 2013/06/08
44 */
45
Andrew Huangab45aab2013-06-27 10:06:56 +000046#include "gt9xx.h"
47
48#if GTP_ICS_SLOT_REPORT
Bingzhe Cai83caeea2013-07-16 17:57:37 +080049#include <linux/input/mt.h>
Andrew Huangab45aab2013-06-27 10:06:56 +000050#endif
51
Bingzhe Cai83caeea2013-07-16 17:57:37 +080052#define GOODIX_DEV_NAME "Goodix Capacitive TouchScreen"
53#define CFG_MAX_TOUCH_POINTS 5
54#define GOODIX_COORDS_ARR_SIZE 4
55#define MAX_BUTTONS 4
56
57/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
58#define GTP_I2C_ADDRESS_HIGH 0x14
59#define GTP_I2C_ADDRESS_LOW 0x5D
60#define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0]))
61
62#define RESET_DELAY_T3_US 200 /* T3: > 100us */
63#define RESET_DELAY_T4 20 /* T4: > 5ms */
64
65#define PHY_BUF_SIZE 32
66
67#define GTP_MAX_TOUCH 5
68#define GTP_ESD_CHECK_CIRCLE_MS 2000
Andrew Huangab45aab2013-06-27 10:06:56 +000069
70#if GTP_HAVE_TOUCH_KEY
Bingzhe Cai83caeea2013-07-16 17:57:37 +080071static const u16 touch_key_array[] = {KEY_MENU, KEY_HOMEPAGE, KEY_BACK};
72#define GTP_MAX_KEY_NUM (sizeof(touch_key_array)/sizeof(touch_key_array[0]))
73
Andrew Huangab45aab2013-06-27 10:06:56 +000074#if GTP_DEBUG_ON
Bingzhe Cai83caeea2013-07-16 17:57:37 +080075static const int key_codes[] = {
76 KEY_HOME, KEY_BACK, KEY_MENU, KEY_SEARCH
77};
78static const char *const key_names[] = {
79 "Key_Home", "Key_Back", "Key_Menu", "Key_Search"
80};
Andrew Huangab45aab2013-06-27 10:06:56 +000081#endif
Andrew Huangab45aab2013-06-27 10:06:56 +000082#endif
83
Bingzhe Cai83caeea2013-07-16 17:57:37 +080084static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms);
85static void gtp_int_sync(struct goodix_ts_data *ts, int ms);
86static int gtp_i2c_test(struct i2c_client *client);
Andrew Huangab45aab2013-06-27 10:06:56 +000087
88#ifdef CONFIG_HAS_EARLYSUSPEND
89static void goodix_ts_early_suspend(struct early_suspend *h);
90static void goodix_ts_late_resume(struct early_suspend *h);
91#endif
Andrew Huangab45aab2013-06-27 10:06:56 +000092
93#if GTP_ESD_PROTECT
94static struct delayed_work gtp_esd_check_work;
Bingzhe Cai83caeea2013-07-16 17:57:37 +080095static struct workqueue_struct *gtp_esd_check_workqueue;
96static void gtp_esd_check_func(struct work_struct *work);
97static int gtp_init_ext_watchdog(struct i2c_client *client);
98struct i2c_client *i2c_connect_client;
Andrew Huangab45aab2013-06-27 10:06:56 +000099#endif
100
Andrew Huangab45aab2013-06-27 10:06:56 +0000101#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800102enum doze_status {
103 DOZE_DISABLED = 0,
104 DOZE_ENABLED = 1,
105 DOZE_WAKEUP = 2,
106};
107static enum doze_status = DOZE_DISABLED;
Andrew Huangab45aab2013-06-27 10:06:56 +0000108static s8 gtp_enter_doze(struct goodix_ts_data *ts);
109#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800110bool init_done;
111static u8 chip_gt9xxs; /* true if ic is gt9xxs, like gt915s */
112u8 grp_cfg_version;
Andrew Huangab45aab2013-06-27 10:06:56 +0000113
114/*******************************************************
115Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800116 Read data from the i2c slave device.
Andrew Huangab45aab2013-06-27 10:06:56 +0000117Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800118 client: i2c device.
119 buf[0~1]: read start address.
120 buf[2~len-1]: read data buffer.
121 len: GTP_ADDR_LENGTH + read bytes count
Andrew Huangab45aab2013-06-27 10:06:56 +0000122Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800123 numbers of i2c_msgs to transfer:
124 2: succeed, otherwise: failed
Andrew Huangab45aab2013-06-27 10:06:56 +0000125*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800126int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len)
Andrew Huangab45aab2013-06-27 10:06:56 +0000127{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800128 struct goodix_ts_data *ts = i2c_get_clientdata(client);
129 struct i2c_msg msgs[2];
130 int ret = -EIO;
131 int retries = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +0000132
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800133 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000134
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800135 msgs[0].flags = !I2C_M_RD;
136 msgs[0].addr = client->addr;
137 msgs[0].len = GTP_ADDR_LENGTH;
138 msgs[0].buf = &buf[0];
Andrew Huangab45aab2013-06-27 10:06:56 +0000139
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800140 msgs[1].flags = I2C_M_RD;
141 msgs[1].addr = client->addr;
142 msgs[1].len = len - GTP_ADDR_LENGTH;
143 msgs[1].buf = &buf[GTP_ADDR_LENGTH];
144
145 while (retries < 5) {
146 ret = i2c_transfer(client->adapter, msgs, 2);
147 if (ret == 2)
148 break;
149 retries++;
150 }
151 if (retries >= 5) {
152#if GTP_SLIDE_WAKEUP
153 /* reset chip would quit doze mode */
154 if (DOZE_ENABLED == doze_status)
155 return ret;
156#endif
157 GTP_DEBUG("I2C communication timeout, resetting chip...");
158 if (init_done)
159 gtp_reset_guitar(ts, 10);
160 else
161 dev_warn(&client->dev,
162 "<GTP> gtp_reset_guitar exit init_done=%d:\n",
163 init_done);
164 }
165 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000166}
167
168/*******************************************************
169Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800170 Write data to the i2c slave device.
Andrew Huangab45aab2013-06-27 10:06:56 +0000171Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800172 client: i2c device.
173 buf[0~1]: write start address.
174 buf[2~len-1]: data buffer
175 len: GTP_ADDR_LENGTH + write bytes count
Andrew Huangab45aab2013-06-27 10:06:56 +0000176Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800177 numbers of i2c_msgs to transfer:
178 1: succeed, otherwise: failed
Andrew Huangab45aab2013-06-27 10:06:56 +0000179*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800180int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len)
Andrew Huangab45aab2013-06-27 10:06:56 +0000181{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800182 struct goodix_ts_data *ts = i2c_get_clientdata(client);
183 struct i2c_msg msg;
184 int ret = -EIO;
185 int retries = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +0000186
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800187 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000188
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800189 msg.flags = !I2C_M_RD;
190 msg.addr = client->addr;
191 msg.len = len;
192 msg.buf = buf;
Andrew Huangab45aab2013-06-27 10:06:56 +0000193
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800194 while (retries < 5) {
195 ret = i2c_transfer(client->adapter, &msg, 1);
196 if (ret == 1)
197 break;
198 retries++;
199 }
200 if ((retries >= 5)) {
201#if GTP_SLIDE_WAKEUP
202 if (DOZE_ENABLED == doze_status)
203 return ret;
204#endif
205 GTP_DEBUG("I2C communication timeout, resetting chip...");
206 if (init_done)
207 gtp_reset_guitar(ts, 10);
208 else
209 dev_warn(&client->dev,
210 "<GTP> gtp_reset_guitar exit init_done=%d:\n",
211 init_done);
212 }
213 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000214}
215/*******************************************************
216Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800217 i2c read twice, compare the results
Andrew Huangab45aab2013-06-27 10:06:56 +0000218Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800219 client: i2c device
220 addr: operate address
221 rxbuf: read data to store, if compare successful
222 len: bytes to read
Andrew Huangab45aab2013-06-27 10:06:56 +0000223Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800224 FAIL: read failed
225 SUCCESS: read successful
Andrew Huangab45aab2013-06-27 10:06:56 +0000226*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800227int gtp_i2c_read_dbl_check(struct i2c_client *client,
228 u16 addr, u8 *rxbuf, int len)
Andrew Huangab45aab2013-06-27 10:06:56 +0000229{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800230 u8 buf[16] = {0};
231 u8 confirm_buf[16] = {0};
232 u8 retry = 0;
233
234 while (retry++ < 3) {
235 memset(buf, 0xAA, 16);
236 buf[0] = (u8)(addr >> 8);
237 buf[1] = (u8)(addr & 0xFF);
238 gtp_i2c_read(client, buf, len + 2);
239
240 memset(confirm_buf, 0xAB, 16);
241 confirm_buf[0] = (u8)(addr >> 8);
242 confirm_buf[1] = (u8)(addr & 0xFF);
243 gtp_i2c_read(client, confirm_buf, len + 2);
244
245 if (!memcmp(buf, confirm_buf, len + 2))
246 break;
247 }
248 if (retry < 3) {
249 memcpy(rxbuf, confirm_buf + 2, len);
250 return SUCCESS;
251 } else {
252 dev_err(&client->dev,
253 "i2c read 0x%04X, %d bytes, double check failed!",
254 addr, len);
255 return FAIL;
256 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000257}
258
259/*******************************************************
260Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800261 Send config data.
Andrew Huangab45aab2013-06-27 10:06:56 +0000262Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800263 client: i2c device.
Andrew Huangab45aab2013-06-27 10:06:56 +0000264Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800265 result of i2c write operation.
266 > 0: succeed, otherwise: failed
Andrew Huangab45aab2013-06-27 10:06:56 +0000267*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800268static int gtp_send_cfg(struct goodix_ts_data *ts)
Andrew Huangab45aab2013-06-27 10:06:56 +0000269{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800270 int ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000271#if GTP_DRIVER_SEND_CFG
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800272 int retry = 0;
273
274 if (ts->fixed_cfg) {
275 dev_dbg(&ts->client->dev,
276 "Ic fixed config, no config sent!");
277 ret = 2;
278 } else {
279 for (retry = 0; retry < 5; retry++) {
280 ret = gtp_i2c_write(ts->client,
281 ts->config_data,
282 GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);
283 if (ret > 0)
284 break;
285 }
286 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000287#endif
288
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800289 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000290}
291
292/*******************************************************
293Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800294 Disable irq function
Andrew Huangab45aab2013-06-27 10:06:56 +0000295Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800296 ts: goodix i2c_client private data
Andrew Huangab45aab2013-06-27 10:06:56 +0000297Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800298 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000299*********************************************************/
300void gtp_irq_disable(struct goodix_ts_data *ts)
301{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800302 unsigned long irqflags;
Andrew Huangab45aab2013-06-27 10:06:56 +0000303
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800304 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000305
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800306 spin_lock_irqsave(&ts->irq_lock, irqflags);
307 if (!ts->irq_is_disabled) {
308 ts->irq_is_disabled = true;
309 disable_irq_nosync(ts->client->irq);
310 }
311 spin_unlock_irqrestore(&ts->irq_lock, irqflags);
Andrew Huangab45aab2013-06-27 10:06:56 +0000312}
313
314/*******************************************************
315Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800316 Enable irq function
Andrew Huangab45aab2013-06-27 10:06:56 +0000317Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800318 ts: goodix i2c_client private data
Andrew Huangab45aab2013-06-27 10:06:56 +0000319Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800320 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000321*********************************************************/
322void gtp_irq_enable(struct goodix_ts_data *ts)
323{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800324 unsigned long irqflags = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +0000325
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800326 GTP_DEBUG_FUNC();
327
328 spin_lock_irqsave(&ts->irq_lock, irqflags);
329 if (ts->irq_is_disabled) {
330 enable_irq(ts->client->irq);
331 ts->irq_is_disabled = false;
332 }
333 spin_unlock_irqrestore(&ts->irq_lock, irqflags);
Andrew Huangab45aab2013-06-27 10:06:56 +0000334}
335
Andrew Huangab45aab2013-06-27 10:06:56 +0000336/*******************************************************
337Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800338 Report touch point event
Andrew Huangab45aab2013-06-27 10:06:56 +0000339Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800340 ts: goodix i2c_client private data
341 id: trackId
342 x: input x coordinate
343 y: input y coordinate
344 w: input pressure
Andrew Huangab45aab2013-06-27 10:06:56 +0000345Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800346 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000347*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800348static void gtp_touch_down(struct goodix_ts_data *ts, int id, int x, int y,
349 int w)
Andrew Huangab45aab2013-06-27 10:06:56 +0000350{
351#if GTP_CHANGE_X2Y
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800352 GTP_SWAP(x, y);
Andrew Huangab45aab2013-06-27 10:06:56 +0000353#endif
354
355#if GTP_ICS_SLOT_REPORT
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800356 input_mt_slot(ts->input_dev, id);
357 input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
358 input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
359 input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
360 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
361 input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
Andrew Huangab45aab2013-06-27 10:06:56 +0000362#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800363 input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
364 input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
365 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
366 input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
367 input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
368 input_mt_sync(ts->input_dev);
Andrew Huangab45aab2013-06-27 10:06:56 +0000369#endif
370
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800371 GTP_DEBUG("ID:%d, X:%d, Y:%d, W:%d", id, x, y, w);
Andrew Huangab45aab2013-06-27 10:06:56 +0000372}
373
374/*******************************************************
375Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800376 Report touch release event
Andrew Huangab45aab2013-06-27 10:06:56 +0000377Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800378 ts: goodix i2c_client private data
Andrew Huangab45aab2013-06-27 10:06:56 +0000379Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800380 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000381*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800382static void gtp_touch_up(struct goodix_ts_data *ts, int id)
Andrew Huangab45aab2013-06-27 10:06:56 +0000383{
384#if GTP_ICS_SLOT_REPORT
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800385 input_mt_slot(ts->input_dev, id);
386 input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
387 GTP_DEBUG("Touch id[%2d] release!", id);
Andrew Huangab45aab2013-06-27 10:06:56 +0000388#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800389 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
390 input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0);
391 input_mt_sync(ts->input_dev);
Andrew Huangab45aab2013-06-27 10:06:56 +0000392#endif
393}
394
395
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800396
Andrew Huangab45aab2013-06-27 10:06:56 +0000397/*******************************************************
398Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800399 Goodix touchscreen work function
Andrew Huangab45aab2013-06-27 10:06:56 +0000400Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800401 work: work struct of goodix_workqueue
Andrew Huangab45aab2013-06-27 10:06:56 +0000402Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800403 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000404*********************************************************/
405static void goodix_ts_work_func(struct work_struct *work)
406{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800407 u8 end_cmd[3] = { GTP_READ_COOR_ADDR >> 8,
408 GTP_READ_COOR_ADDR & 0xFF, 0};
409 u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH + 1] = {
410 GTP_READ_COOR_ADDR >> 8,
411 GTP_READ_COOR_ADDR & 0xFF};
412 u8 touch_num = 0;
413 u8 finger = 0;
414 static u16 pre_touch;
415 static u8 pre_key;
Andrew Huangab45aab2013-06-27 10:06:56 +0000416#if GTP_WITH_PEN
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800417 static u8 pre_pen;
Andrew Huangab45aab2013-06-27 10:06:56 +0000418#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800419 u8 key_value = 0;
420 u8 *coor_data = NULL;
421 s32 input_x = 0;
422 s32 input_y = 0;
423 s32 input_w = 0;
424 s32 id = 0;
425 s32 i = 0;
426 int ret = -1;
427 struct goodix_ts_data *ts = NULL;
Andrew Huangab45aab2013-06-27 10:06:56 +0000428
429#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800430 u8 doze_buf[3] = {0x81, 0x4B};
Andrew Huangab45aab2013-06-27 10:06:56 +0000431#endif
432
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800433 GTP_DEBUG_FUNC();
434
435 ts = container_of(work, struct goodix_ts_data, work);
436#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
437 if (ts->enter_update)
438 return;
439#endif
440
Andrew Huangab45aab2013-06-27 10:06:56 +0000441#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800442 if (DOZE_ENABLED == doze_status) {
443 ret = gtp_i2c_read(ts->client, doze_buf, 3);
444 GTP_DEBUG("0x814B = 0x%02X", doze_buf[2]);
445 if (ret > 0) {
446 if (doze_buf[2] == 0xAA) {
447 dev_dbg(&ts->client->dev,
448 "Slide(0xAA) To Light up the screen!");
449 doze_status = DOZE_WAKEUP;
450 input_report_key(
451 ts->input_dev, KEY_POWER, 1);
452 input_sync(ts->input_dev);
453 input_report_key(
454 ts->input_dev, KEY_POWER, 0);
455 input_sync(ts->input_dev);
456 /* clear 0x814B */
457 doze_buf[2] = 0x00;
458 gtp_i2c_write(ts->client, doze_buf, 3);
459 } else if (doze_buf[2] == 0xBB) {
460 dev_dbg(&ts->client->dev,
461 "Slide(0xBB) To Light up the screen!");
462 doze_status = DOZE_WAKEUP;
463 input_report_key(ts->input_dev, KEY_POWER, 1);
464 input_sync(ts->input_dev);
465 input_report_key(ts->input_dev, KEY_POWER, 0);
466 input_sync(ts->input_dev);
467 /* clear 0x814B*/
468 doze_buf[2] = 0x00;
469 gtp_i2c_write(ts->client, doze_buf, 3);
470 } else if (0xC0 == (doze_buf[2] & 0xC0)) {
471 dev_dbg(&ts->client->dev,
472 "double click to light up the screen!");
473 doze_status = DOZE_WAKEUP;
474 input_report_key(ts->input_dev, KEY_POWER, 1);
475 input_sync(ts->input_dev);
476 input_report_key(ts->input_dev, KEY_POWER, 0);
477 input_sync(ts->input_dev);
478 /* clear 0x814B */
479 doze_buf[2] = 0x00;
480 gtp_i2c_write(ts->client, doze_buf, 3);
481 } else {
482 gtp_enter_doze(ts);
483 }
484 }
485 if (ts->use_irq)
486 gtp_irq_enable(ts);
487
488 return;
489 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000490#endif
491
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800492 ret = gtp_i2c_read(ts->client, point_data, 12);
493 if (ret < 0) {
494 dev_err(&ts->client->dev,
495 "I2C transfer error. errno:%d\n ", ret);
496 goto exit_work_func;
497 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000498
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800499 finger = point_data[GTP_ADDR_LENGTH];
500 if ((finger & 0x80) == 0)
501 goto exit_work_func;
Andrew Huangab45aab2013-06-27 10:06:56 +0000502
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800503 touch_num = finger & 0x0f;
504 if (touch_num > GTP_MAX_TOUCH)
505 goto exit_work_func;
Andrew Huangab45aab2013-06-27 10:06:56 +0000506
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800507 if (touch_num > 1) {
508 u8 buf[8 * GTP_MAX_TOUCH] = { (GTP_READ_COOR_ADDR + 10) >> 8,
509 (GTP_READ_COOR_ADDR + 10) & 0xff };
Andrew Huangab45aab2013-06-27 10:06:56 +0000510
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800511 ret = gtp_i2c_read(ts->client, buf,
512 2 + 8 * (touch_num - 1));
513 memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));
514 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000515
516#if GTP_HAVE_TOUCH_KEY
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800517 key_value = point_data[3 + 8 * touch_num];
Andrew Huangab45aab2013-06-27 10:06:56 +0000518
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800519 if (key_value || pre_key) {
520 for (i = 0; i < GTP_MAX_KEY_NUM; i++) {
521#if GTP_DEBUG_ON
522 for (ret = 0; ret < 4; ++ret) {
523 if (key_codes[ret] == touch_key_array[i]) {
524 GTP_DEBUG("Key: %s %s",
525 key_names[ret],
526 (key_value & (0x01 << i))
527 ? "Down" : "Up");
528 break;
529 }
530 }
531#endif
532
533 input_report_key(ts->input_dev,
534 touch_key_array[i], key_value & (0x01<<i));
535 }
536 touch_num = 0;
537 pre_touch = 0;
538 }
539#endif
540 pre_key = key_value;
541
542 GTP_DEBUG("pre_touch:%02x, finger:%02x.", pre_touch, finger);
Andrew Huangab45aab2013-06-27 10:06:56 +0000543
544#if GTP_ICS_SLOT_REPORT
Andrew Huangab45aab2013-06-27 10:06:56 +0000545#if GTP_WITH_PEN
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800546 if (pre_pen && (touch_num == 0)) {
547 GTP_DEBUG("Pen touch UP(Slot)!");
548 input_report_key(ts->input_dev, BTN_TOOL_PEN, 0);
549 input_mt_slot(ts->input_dev, 5);
550 input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
551 pre_pen = 0;
552 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000553#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800554 if (pre_touch || touch_num) {
555 s32 pos = 0;
556 u16 touch_index = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +0000557
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800558 coor_data = &point_data[3];
559 if (touch_num) {
560 id = coor_data[pos] & 0x0F;
561#if GTP_WITH_PEN
562 id = coor_data[pos];
563 if (id == 128) {
564 GTP_DEBUG("Pen touch DOWN(Slot)!");
565 input_x = coor_data[pos + 1]
566 | (coor_data[pos + 2] << 8);
567 input_y = coor_data[pos + 3]
568 | (coor_data[pos + 4] << 8);
569 input_w = coor_data[pos + 5]
570 | (coor_data[pos + 6] << 8);
Andrew Huangab45aab2013-06-27 10:06:56 +0000571
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800572 input_report_key(ts->input_dev,
573 BTN_TOOL_PEN, 1);
574 input_mt_slot(ts->input_dev, 5);
575 input_report_abs(ts->input_dev,
576 ABS_MT_TRACKING_ID, 5);
577 input_report_abs(ts->input_dev,
578 ABS_MT_POSITION_X, input_x);
579 input_report_abs(ts->input_dev,
580 ABS_MT_POSITION_Y, input_y);
581 input_report_abs(ts->input_dev,
582 ABS_MT_TOUCH_MAJOR, input_w);
583 GTP_DEBUG("Pen/Stylus: (%d, %d)[%d]",
584 input_x, input_y, input_w);
585 pre_pen = 1;
586 pre_touch = 0;
587 }
588#endif
589
590 touch_index |= (0x01<<id);
591 }
592
593 GTP_DEBUG("id = %d,touch_index = 0x%x, pre_touch = 0x%x\n",
594 id, touch_index, pre_touch);
595 for (i = 0; i < GTP_MAX_TOUCH; i++) {
596#if GTP_WITH_PEN
597 if (pre_pen == 1)
598 break;
599#endif
600 if (touch_index & (0x01<<i)) {
601 input_x = coor_data[pos + 1] |
602 coor_data[pos + 2] << 8;
603 input_y = coor_data[pos + 3] |
604 coor_data[pos + 4] << 8;
605 input_w = coor_data[pos + 5] |
606 coor_data[pos + 6] << 8;
607
608 gtp_touch_down(ts, id,
609 input_x, input_y, input_w);
610 pre_touch |= 0x01 << i;
611
612 pos += 8;
613 id = coor_data[pos] & 0x0F;
614 touch_index |= (0x01<<id);
615 } else {
616 gtp_touch_up(ts, i);
617 pre_touch &= ~(0x01 << i);
618 }
619 }
620 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000621#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800622 input_report_key(ts->input_dev, BTN_TOUCH, (touch_num || key_value));
623 if (touch_num) {
624 for (i = 0; i < touch_num; i++) {
625 coor_data = &point_data[i * 8 + 3];
Andrew Huangab45aab2013-06-27 10:06:56 +0000626
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800627 id = coor_data[0];
628 input_x = coor_data[1] | coor_data[2] << 8;
629 input_y = coor_data[3] | coor_data[4] << 8;
630 input_w = coor_data[5] | coor_data[6] << 8;
631#if GTP_WITH_PEN
632 if (id == 128) {
633 GTP_DEBUG("Pen touch DOWN!");
634 input_report_key(ts->input_dev,
635 BTN_TOOL_PEN, 1);
636 pre_pen = 1;
637 id = 0;
638 }
639#endif
640 gtp_touch_down(ts, id, input_x, input_y, input_w);
641 }
642 } else if (pre_touch) {
643#if GTP_WITH_PEN
644 if (pre_pen == 1) {
645 GTP_DEBUG("Pen touch UP!");
646 input_report_key(ts->input_dev, BTN_TOOL_PEN, 0);
647 pre_pen = 0;
648 }
649#endif
650 GTP_DEBUG("Touch Released!");
651 gtp_touch_up(ts, 0);
652 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000653
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800654 pre_touch = touch_num;
Andrew Huangab45aab2013-06-27 10:06:56 +0000655#endif
656
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800657 input_sync(ts->input_dev);
Andrew Huangab45aab2013-06-27 10:06:56 +0000658
659exit_work_func:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800660 if (!ts->gtp_rawdiff_mode) {
661 ret = gtp_i2c_write(ts->client, end_cmd, 3);
662 if (ret < 0)
663 dev_warn(&ts->client->dev, "I2C write end_cmd error!\n");
664
665 }
666 if (ts->use_irq)
667 gtp_irq_enable(ts);
668
669 return;
Andrew Huangab45aab2013-06-27 10:06:56 +0000670}
671
672/*******************************************************
673Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800674 Timer interrupt service routine for polling mode.
Andrew Huangab45aab2013-06-27 10:06:56 +0000675Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800676 timer: timer struct pointer
Andrew Huangab45aab2013-06-27 10:06:56 +0000677Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800678 Timer work mode.
679 HRTIMER_NORESTART: no restart mode
Andrew Huangab45aab2013-06-27 10:06:56 +0000680*********************************************************/
681static enum hrtimer_restart goodix_ts_timer_handler(struct hrtimer *timer)
682{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800683 struct goodix_ts_data
684 *ts = container_of(timer, struct goodix_ts_data, timer);
Andrew Huangab45aab2013-06-27 10:06:56 +0000685
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800686 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000687
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800688 queue_work(ts->goodix_wq, &ts->work);
689 hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME + 6) * 1000000),
690 HRTIMER_MODE_REL);
691 return HRTIMER_NORESTART;
Andrew Huangab45aab2013-06-27 10:06:56 +0000692}
693
694/*******************************************************
695Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800696 External interrupt service routine for interrupt mode.
Andrew Huangab45aab2013-06-27 10:06:56 +0000697Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800698 irq: interrupt number.
699 dev_id: private data pointer
Andrew Huangab45aab2013-06-27 10:06:56 +0000700Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800701 Handle Result.
702 IRQ_HANDLED: interrupt handled successfully
Andrew Huangab45aab2013-06-27 10:06:56 +0000703*********************************************************/
704static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
705{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800706 struct goodix_ts_data *ts = dev_id;
Andrew Huangab45aab2013-06-27 10:06:56 +0000707
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800708 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000709
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800710 gtp_irq_disable(ts);
711
712 queue_work(ts->goodix_wq, &ts->work);
713
714 return IRQ_HANDLED;
Andrew Huangab45aab2013-06-27 10:06:56 +0000715}
716/*******************************************************
717Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800718 Synchronization.
Andrew Huangab45aab2013-06-27 10:06:56 +0000719Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800720 ms: synchronization time in millisecond.
Andrew Huangab45aab2013-06-27 10:06:56 +0000721Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800722 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000723*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800724void gtp_int_sync(struct goodix_ts_data *ts, int ms)
Andrew Huangab45aab2013-06-27 10:06:56 +0000725{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800726 gpio_direction_output(ts->pdata->irq_gpio, 0);
727 msleep(ms);
728 gpio_direction_input(ts->pdata->irq_gpio);
Andrew Huangab45aab2013-06-27 10:06:56 +0000729}
730
731/*******************************************************
732Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800733 Reset chip.
Andrew Huangab45aab2013-06-27 10:06:56 +0000734Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800735 ms: reset time in millisecond, must >10ms
Andrew Huangab45aab2013-06-27 10:06:56 +0000736Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800737 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000738*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800739static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms)
Andrew Huangab45aab2013-06-27 10:06:56 +0000740{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800741 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000742
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800743 /* This reset sequence will selcet I2C slave address */
744 gpio_direction_output(ts->pdata->reset_gpio, 0);
745 msleep(ms);
Andrew Huangab45aab2013-06-27 10:06:56 +0000746
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800747 if (ts->client->addr == GTP_I2C_ADDRESS_HIGH)
748 gpio_direction_output(ts->pdata->irq_gpio, 1);
749 else
750 gpio_direction_output(ts->pdata->irq_gpio, 0);
Andrew Huangab45aab2013-06-27 10:06:56 +0000751
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800752 usleep(RESET_DELAY_T3_US);
753 gpio_direction_output(ts->pdata->reset_gpio, 1);
754 msleep(RESET_DELAY_T4);
Andrew Huangab45aab2013-06-27 10:06:56 +0000755
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800756 gpio_direction_input(ts->pdata->reset_gpio);
757
758 gtp_int_sync(ts, 50);
759
Andrew Huangab45aab2013-06-27 10:06:56 +0000760#if GTP_ESD_PROTECT
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800761 gtp_init_ext_watchdog(ts->client);
Andrew Huangab45aab2013-06-27 10:06:56 +0000762#endif
763}
764
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800765#ifdef CONFIG_HAS_EARLYSUSPEND
Andrew Huangab45aab2013-06-27 10:06:56 +0000766#if GTP_SLIDE_WAKEUP
767/*******************************************************
768Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800769 Enter doze mode for sliding wakeup.
Andrew Huangab45aab2013-06-27 10:06:56 +0000770Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800771 ts: goodix tp private data
Andrew Huangab45aab2013-06-27 10:06:56 +0000772Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800773 1: succeed, otherwise failed
Andrew Huangab45aab2013-06-27 10:06:56 +0000774*******************************************************/
775static s8 gtp_enter_doze(struct goodix_ts_data *ts)
776{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800777 int ret = -1;
778 s8 retry = 0;
779 u8 i2c_control_buf[3] = {
780 (u8)(GTP_REG_SLEEP >> 8),
781 (u8)GTP_REG_SLEEP, 8};
Andrew Huangab45aab2013-06-27 10:06:56 +0000782
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800783 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000784
785#if GTP_DBL_CLK_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800786 i2c_control_buf[2] = 0x09;
Andrew Huangab45aab2013-06-27 10:06:56 +0000787#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800788 gtp_irq_disable(ts);
Andrew Huangab45aab2013-06-27 10:06:56 +0000789
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800790 GTP_DEBUG("entering doze mode...");
791 while (retry++ < 5) {
792 i2c_control_buf[0] = 0x80;
793 i2c_control_buf[1] = 0x46;
794 ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
795 if (ret < 0) {
796 GTP_DEBUG(
797 "failed to set doze flag into 0x8046, %d",
798 retry);
799 continue;
800 }
801 i2c_control_buf[0] = 0x80;
802 i2c_control_buf[1] = 0x40;
803 ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
804 if (ret > 0) {
805 doze_status = DOZE_ENABLED;
806 dev_dbg(&ts->client->dev,
807 "GTP has been working in doze mode!");
808 gtp_irq_enable(ts);
809 return ret;
810 }
811 msleep(20);
812 }
813 dev_err(&ts->client->dev, "GTP send doze cmd failed.\n");
814 gtp_irq_enable(ts);
815 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000816}
Andrew Huangab45aab2013-06-27 10:06:56 +0000817#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800818/*******************************************************
819Function:
820 Enter sleep mode.
821Input:
822 ts: private data.
823Output:
824 Executive outcomes.
825 1: succeed, otherwise failed.
826*******************************************************/
827static s8 gtp_enter_sleep(struct goodix_ts_data *ts)
828{
829 int ret = -1;
830 s8 retry = 0;
831 u8 i2c_control_buf[3] = {
832 (u8)(GTP_REG_SLEEP >> 8),
833 (u8)GTP_REG_SLEEP, 5};
Andrew Huangab45aab2013-06-27 10:06:56 +0000834
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800835 GTP_DEBUG_FUNC();
836
837 ret = gpio_direction_output(ts->pdata->irq_gpio, 0);
838 usleep(5000);
839 while (retry++ < 5) {
840 ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
841 if (ret > 0) {
842 dev_dbg(&ts->client->dev,
843 "GTP enter sleep!");
844 return ret;
845 }
846 msleep(20);
847 }
848 dev_err(&ts->client->dev, "GTP send sleep cmd failed.\n");
849 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000850}
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800851#endif
Andrew Huangab45aab2013-06-27 10:06:56 +0000852
853/*******************************************************
854Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800855 Wakeup from sleep.
Andrew Huangab45aab2013-06-27 10:06:56 +0000856Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800857 ts: private data.
Andrew Huangab45aab2013-06-27 10:06:56 +0000858Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800859 Executive outcomes.
860 >0: succeed, otherwise: failed.
Andrew Huangab45aab2013-06-27 10:06:56 +0000861*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800862static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts)
Andrew Huangab45aab2013-06-27 10:06:56 +0000863{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800864 u8 retry = 0;
865 s8 ret = -1;
866
867 GTP_DEBUG_FUNC();
868
869#if GTP_POWER_CTRL_SLEEP
870 while (retry++ < 5) {
871 gtp_reset_guitar(ts, 20);
872
873 ret = gtp_send_cfg(ts);
874 if (ret > 0) {
875 dev_dbg(&ts->client->dev,
876 "Wakeup sleep send config success.");
877 continue;
878 }
879 dev_dbg(&ts->client->dev, "GTP Wakeup!");
880 return 1;
881 }
882#else
883 while (retry++ < 10) {
884#if GTP_SLIDE_WAKEUP
885 /* wakeup not by slide */
886 if (DOZE_WAKEUP != doze_status)
887 gtp_reset_guitar(ts, 10);
888 else
889 /* wakeup by slide */
890 doze_status = DOZE_DISABLED;
891#else
892 if (chip_gt9xxs == 1) {
893 gtp_reset_guitar(ts, 10);
894 } else {
895 ret = gpio_direction_output(ts->pdata->irq_gpio, 1);
896 usleep(5000);
897 }
898#endif
899 ret = gtp_i2c_test(ts->client);
900 if (ret > 0) {
901 dev_dbg(&ts->client->dev, "GTP wakeup sleep.");
902#if (!GTP_SLIDE_WAKEUP)
903 if (chip_gt9xxs == 0) {
904 gtp_int_sync(ts, 25);
905 msleep(20);
906#if GTP_ESD_PROTECT
907 gtp_init_ext_watchdog(ts->client);
908#endif
909 }
910#endif
911 return ret;
912 }
913 gtp_reset_guitar(ts, 20);
914 }
915#endif
916
917 dev_err(&ts->client->dev, "GTP wakeup sleep failed.\n");
918 return ret;
919}
920#endif /* !CONFIG_HAS_EARLYSUSPEND */
921
922/*******************************************************
923Function:
924 Initialize gtp.
925Input:
926 ts: goodix private data
927Output:
928 Executive outcomes.
929 > =0: succeed, otherwise: failed
930*******************************************************/
931static int gtp_init_panel(struct goodix_ts_data *ts)
932{
933 struct i2c_client *client = ts->client;
934 unsigned char *config_data;
935 int ret = -EIO;
Andrew Huangab45aab2013-06-27 10:06:56 +0000936
937#if GTP_DRIVER_SEND_CFG
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800938 int i;
939 u8 check_sum = 0;
940 u8 opr_buf[16];
941 u8 sensor_id = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +0000942
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800943 u8 cfg_info_group1[] = CTP_CFG_GROUP1;
944 u8 cfg_info_group2[] = CTP_CFG_GROUP2;
945 u8 cfg_info_group3[] = CTP_CFG_GROUP3;
946 u8 cfg_info_group4[] = CTP_CFG_GROUP4;
947 u8 cfg_info_group5[] = CTP_CFG_GROUP5;
948 u8 cfg_info_group6[] = CTP_CFG_GROUP6;
949 u8 *send_cfg_buf[] = {cfg_info_group1, cfg_info_group2,
950 cfg_info_group3, cfg_info_group4,
951 cfg_info_group5, cfg_info_group6};
Andrew Huangab45aab2013-06-27 10:06:56 +0000952
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800953 u8 cfg_info_len[] = {CFG_GROUP_LEN(cfg_info_group1),
954 CFG_GROUP_LEN(cfg_info_group2),
955 CFG_GROUP_LEN(cfg_info_group3),
956 CFG_GROUP_LEN(cfg_info_group4),
957 CFG_GROUP_LEN(cfg_info_group5),
958 CFG_GROUP_LEN(cfg_info_group6)};
Andrew Huangab45aab2013-06-27 10:06:56 +0000959
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800960 GTP_DEBUG("Config Groups\' Lengths: %d, %d, %d, %d, %d, %d",
961 cfg_info_len[0], cfg_info_len[1], cfg_info_len[2],
962 cfg_info_len[3], cfg_info_len[4], cfg_info_len[5]);
Andrew Huangab45aab2013-06-27 10:06:56 +0000963
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800964 ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);
965 if (SUCCESS == ret) {
966 if (opr_buf[0] != 0xBE) {
967 ts->fw_error = 1;
968 dev_err(&client->dev,
969 "Firmware error, no config sent!");
970 return -EINVAL;
971 }
972 }
973 if ((!cfg_info_len[1]) && (!cfg_info_len[2]) && (!cfg_info_len[3])
974 && (!cfg_info_len[4]) && (!cfg_info_len[5])) {
975 sensor_id = 0;
976 } else {
977 ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID,
978 &sensor_id, 1);
979 if (SUCCESS == ret) {
980 if (sensor_id >= 0x06) {
981 dev_err(&client->dev,
982 "Invalid sensor_id(0x%02X), No Config Sent!",
983 sensor_id);
984 return -EINVAL;
985 }
986 } else {
987 dev_err(&client->dev,
988 "Failed to get sensor_id, No config sent!");
989 return -EINVAL;
990 }
991 }
992 GTP_DEBUG("Sensor_ID: %d", sensor_id);
993
994 ts->gtp_cfg_len = cfg_info_len[sensor_id];
995
996 if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH) {
997 dev_err(&client->dev,
998 "Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!\n",
999 sensor_id);
1000 return -EINVAL;
1001 }
1002 ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
1003 &opr_buf[0], 1);
1004
1005 if (ret == SUCCESS) {
1006 if (opr_buf[0] < 90) {
1007 /* backup group config version */
1008 grp_cfg_version = send_cfg_buf[sensor_id][0];
1009 send_cfg_buf[sensor_id][0] = 0x00;
1010 ts->fixed_cfg = 0;
1011 } else {
1012 /* treated as fixed config, not send config */
1013 dev_warn(&client->dev,
1014 "Ic fixed config with config version(%d, 0x%02X)",
1015 opr_buf[0], opr_buf[0]);
1016 ts->fixed_cfg = 1;
1017 }
1018 } else {
1019 dev_err(&client->dev,
1020 "Failed to get ic config version!No config sent!");
1021 return -EINVAL;
1022 }
1023
1024 config_data = devm_kzalloc(&client->dev,
1025 GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
1026 GFP_KERNEL);
1027 if (!config_data) {
1028 dev_err(&client->dev,
1029 "Not enough memory for panel config data\n");
1030 return -ENOMEM;
1031 }
1032
1033 ts->config_data = config_data;
1034 config_data[0] = GTP_REG_CONFIG_DATA >> 8;
1035 config_data[1] = GTP_REG_CONFIG_DATA & 0xff;
1036 memset(&config_data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
1037 memcpy(&config_data[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id],
1038 ts->gtp_cfg_len);
Andrew Huangab45aab2013-06-27 10:06:56 +00001039
1040#if GTP_CUSTOM_CFG
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001041 config_data[RESOLUTION_LOC] =
1042 (unsigned char)(GTP_MAX_WIDTH && 0xFF);
1043 config_data[RESOLUTION_LOC + 1] =
1044 (unsigned char)(GTP_MAX_WIDTH >> 8);
1045 config_data[RESOLUTION_LOC + 2] =
1046 (unsigned char)(GTP_MAX_HEIGHT && 0xFF);
1047 config_data[RESOLUTION_LOC + 3] =
1048 (unsigned char)(GTP_MAX_HEIGHT >> 8);
Andrew Huangab45aab2013-06-27 10:06:56 +00001049
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001050 if (GTP_INT_TRIGGER == 0)
1051 config_data[TRIGGER_LOC] &= 0xfe;
1052 else if (GTP_INT_TRIGGER == 1)
1053 config_data[TRIGGER_LOC] |= 0x01;
1054#endif /* !GTP_CUSTOM_CFG */
Andrew Huangab45aab2013-06-27 10:06:56 +00001055
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001056 check_sum = 0;
1057 for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
1058 check_sum += config_data[i];
1059
1060 config_data[ts->gtp_cfg_len] = (~check_sum) + 1;
1061
1062#else /* DRIVER NOT SEND CONFIG */
1063 ts->gtp_cfg_len = GTP_CONFIG_MAX_LENGTH;
1064 ret = gtp_i2c_read(ts->client, config_data,
1065 ts->gtp_cfg_len + GTP_ADDR_LENGTH);
1066 if (ret < 0) {
1067 dev_err(&client->dev,
1068 "Read Config Failed, Using DEFAULT Resolution & INT Trigger!\n");
1069 ts->abs_x_max = GTP_MAX_WIDTH;
1070 ts->abs_y_max = GTP_MAX_HEIGHT;
1071 ts->int_trigger_type = GTP_INT_TRIGGER;
1072 }
1073#endif /* !DRIVER NOT SEND CONFIG */
1074
1075 GTP_DEBUG_FUNC();
1076 if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0)) {
1077 ts->abs_x_max = (config_data[RESOLUTION_LOC + 1] << 8)
1078 + config_data[RESOLUTION_LOC];
1079 ts->abs_y_max = (config_data[RESOLUTION_LOC + 3] << 8)
1080 + config_data[RESOLUTION_LOC + 2];
1081 ts->int_trigger_type = (config_data[TRIGGER_LOC]) & 0x03;
1082 }
1083 ret = gtp_send_cfg(ts);
1084 if (ret < 0)
1085 dev_err(&client->dev, "%s: Send config error.\n", __func__);
1086
1087 GTP_DEBUG("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",
1088 ts->abs_x_max, ts->abs_y_max,
1089 ts->int_trigger_type);
1090
1091 msleep(20);
1092 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001093}
1094
1095/*******************************************************
1096Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001097 Read chip version.
Andrew Huangab45aab2013-06-27 10:06:56 +00001098Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001099 client: i2c device
1100 version: buffer to keep ic firmware version
Andrew Huangab45aab2013-06-27 10:06:56 +00001101Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001102 read operation return.
1103 2: succeed, otherwise: failed
Andrew Huangab45aab2013-06-27 10:06:56 +00001104*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001105int gtp_read_version(struct i2c_client *client, u16 *version)
Andrew Huangab45aab2013-06-27 10:06:56 +00001106{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001107 int ret = -EIO;
1108 u8 buf[8] = { GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff };
Andrew Huangab45aab2013-06-27 10:06:56 +00001109
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001110 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001111
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001112 ret = gtp_i2c_read(client, buf, sizeof(buf));
1113 if (ret < 0) {
1114 dev_err(&client->dev, "GTP read version failed.\n");
1115 return ret;
1116 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001117
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001118 if (version)
1119 *version = (buf[7] << 8) | buf[6];
1120
1121 if (buf[5] == 0x00) {
1122 dev_dbg(&client->dev, "IC Version: %c%c%c_%02x%02x\n", buf[2],
1123 buf[3], buf[4], buf[7], buf[6]);
1124 } else {
1125 if (buf[5] == 'S' || buf[5] == 's')
1126 chip_gt9xxs = 1;
1127 dev_dbg(&client->dev, "IC Version: %c%c%c%c_%02x%02x\n", buf[2],
1128 buf[3], buf[4], buf[5], buf[7], buf[6]);
1129 }
1130 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001131}
1132
1133/*******************************************************
1134Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001135 I2c test Function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001136Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001137 client:i2c client.
Andrew Huangab45aab2013-06-27 10:06:56 +00001138Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001139 Executive outcomes.
1140 2: succeed, otherwise failed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001141*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001142static int gtp_i2c_test(struct i2c_client *client)
Andrew Huangab45aab2013-06-27 10:06:56 +00001143{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001144 u8 buf[3] = { GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff };
1145 int retry = 5;
1146 int ret = -EIO;
1147
1148 GTP_DEBUG_FUNC();
1149
1150 while (retry--) {
1151 ret = gtp_i2c_read(client, buf, 3);
1152 if (ret > 0)
1153 return ret;
1154 dev_err(&client->dev, "GTP i2c test failed time %d.\n", retry);
1155 msleep(20);
1156 }
1157 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001158}
1159
1160/*******************************************************
1161Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001162 Request gpio(INT & RST) ports.
Andrew Huangab45aab2013-06-27 10:06:56 +00001163Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001164 ts: private data.
Andrew Huangab45aab2013-06-27 10:06:56 +00001165Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001166 Executive outcomes.
1167 = 0: succeed, != 0: failed
Andrew Huangab45aab2013-06-27 10:06:56 +00001168*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001169static int gtp_request_io_port(struct goodix_ts_data *ts)
Andrew Huangab45aab2013-06-27 10:06:56 +00001170{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001171 struct i2c_client *client = ts->client;
1172 struct goodix_ts_platform_data *pdata = ts->pdata;
1173 int ret;
1174 if (gpio_is_valid(pdata->irq_gpio)) {
1175 ret = gpio_request(pdata->irq_gpio, "goodix_ts_irq_gpio");
1176 if (ret) {
1177 dev_err(&client->dev, "irq gpio request failed\n");
1178 goto pwr_off;
1179 }
1180 ret = gpio_direction_input(pdata->irq_gpio);
1181 if (ret) {
1182 dev_err(&client->dev,
1183 "set_direction for irq gpio failed\n");
1184 goto free_irq_gpio;
1185 }
1186 } else {
1187 dev_err(&client->dev, "irq gpio is invalid!\n");
1188 ret = -EINVAL;
1189 goto free_irq_gpio;
1190 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001191
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001192 if (gpio_is_valid(pdata->reset_gpio)) {
1193 ret = gpio_request(pdata->reset_gpio, "goodix_ts__reset_gpio");
1194 if (ret) {
1195 dev_err(&client->dev, "reset gpio request failed\n");
1196 goto free_irq_gpio;
1197 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001198
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001199 ret = gpio_direction_output(pdata->reset_gpio, 0);
1200 if (ret) {
1201 dev_err(&client->dev,
1202 "set_direction for reset gpio failed\n");
1203 goto free_reset_gpio;
1204 }
1205 } else {
1206 dev_err(&client->dev, "reset gpio is invalid!\n");
1207 ret = -EINVAL;
1208 goto free_reset_gpio;
1209 }
1210 gpio_direction_input(pdata->reset_gpio);
Andrew Huangab45aab2013-06-27 10:06:56 +00001211
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001212 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001213
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001214free_reset_gpio:
1215 if (gpio_is_valid(pdata->reset_gpio))
1216 gpio_free(pdata->reset_gpio);
1217free_irq_gpio:
1218 if (gpio_is_valid(pdata->irq_gpio))
1219 gpio_free(pdata->irq_gpio);
1220pwr_off:
1221 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001222}
1223
1224/*******************************************************
1225Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001226 Request interrupt.
Andrew Huangab45aab2013-06-27 10:06:56 +00001227Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001228 ts: private data.
Andrew Huangab45aab2013-06-27 10:06:56 +00001229Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001230 Executive outcomes.
1231 0: succeed, -1: failed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001232*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001233static int gtp_request_irq(struct goodix_ts_data *ts)
Andrew Huangab45aab2013-06-27 10:06:56 +00001234{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001235 int ret;
1236 const u8 irq_table[] = GTP_IRQ_TAB;
Andrew Huangab45aab2013-06-27 10:06:56 +00001237
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001238 GTP_DEBUG("INT trigger type:%x, irq=%d", ts->int_trigger_type,
1239 ts->client->irq);
Andrew Huangab45aab2013-06-27 10:06:56 +00001240
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001241 ret = request_irq(ts->client->irq, goodix_ts_irq_handler,
1242 irq_table[ts->int_trigger_type],
1243 ts->client->name, ts);
1244 if (ret) {
1245 dev_err(&ts->client->dev, "Request IRQ failed!ERRNO:%d.\n",
1246 ret);
1247 gpio_direction_input(ts->pdata->irq_gpio);
Andrew Huangab45aab2013-06-27 10:06:56 +00001248
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001249 hrtimer_init(&ts->timer, CLOCK_MONOTONIC,
1250 HRTIMER_MODE_REL);
1251 ts->timer.function = goodix_ts_timer_handler;
1252 hrtimer_start(&ts->timer, ktime_set(1, 0),
1253 HRTIMER_MODE_REL);
1254 ts->use_irq = false;
1255 return ret;
1256 } else {
1257 gtp_irq_disable(ts);
1258 ts->use_irq = true;
1259 return 0;
1260 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001261}
1262
1263/*******************************************************
1264Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001265 Request input device Function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001266Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001267 ts:private data.
Andrew Huangab45aab2013-06-27 10:06:56 +00001268Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001269 Executive outcomes.
1270 0: succeed, otherwise: failed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001271*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001272static int gtp_request_input_dev(struct goodix_ts_data *ts)
Andrew Huangab45aab2013-06-27 10:06:56 +00001273{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001274 int ret;
1275 char phys[PHY_BUF_SIZE];
Andrew Huangab45aab2013-06-27 10:06:56 +00001276#if GTP_HAVE_TOUCH_KEY
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001277 int index = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +00001278#endif
Andrew Huangab45aab2013-06-27 10:06:56 +00001279
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001280 GTP_DEBUG_FUNC();
1281
1282 ts->input_dev = input_allocate_device();
1283 if (ts->input_dev == NULL) {
1284 dev_err(&ts->client->dev,
1285 "Failed to allocate input device.\n");
1286 return -ENOMEM;
1287 }
1288
1289 ts->input_dev->evbit[0] =
1290 BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
Andrew Huangab45aab2013-06-27 10:06:56 +00001291#if GTP_ICS_SLOT_REPORT
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001292 __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
1293 input_mt_init_slots(ts->input_dev, 10);/* in case of "out of memory" */
Andrew Huangab45aab2013-06-27 10:06:56 +00001294#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001295 ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
Andrew Huangab45aab2013-06-27 10:06:56 +00001296#endif
1297
1298#if GTP_HAVE_TOUCH_KEY
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001299 for (index = 0; index < GTP_MAX_KEY_NUM; index++) {
1300 input_set_capability(ts->input_dev,
1301 EV_KEY, touch_key_array[index]);
1302 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001303#endif
1304
1305#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001306 input_set_capability(ts->input_dev, EV_KEY, KEY_POWER);
1307#endif
Andrew Huangab45aab2013-06-27 10:06:56 +00001308
1309#if GTP_WITH_PEN
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001310 /* pen support */
1311 __set_bit(BTN_TOOL_PEN, ts->input_dev->keybit);
1312 __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
1313 __set_bit(INPUT_PROP_POINTER, ts->input_dev->propbit);
Andrew Huangab45aab2013-06-27 10:06:56 +00001314#endif
1315
1316#if GTP_CHANGE_X2Y
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001317 GTP_SWAP(ts->abs_x_max, ts->abs_y_max);
Andrew Huangab45aab2013-06-27 10:06:56 +00001318#endif
1319
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001320 input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
1321 0, ts->abs_x_max, 0, 0);
1322 input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
1323 0, ts->abs_y_max, 0, 0);
1324 input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,
1325 0, 255, 0, 0);
1326 input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,
1327 0, 255, 0, 0);
1328 input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID,
1329 0, 255, 0, 0);
Andrew Huangab45aab2013-06-27 10:06:56 +00001330
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001331 snprintf(phys, PHY_BUF_SIZE, "input/ts");
1332 ts->input_dev->name = GOODIX_DEV_NAME;
1333 ts->input_dev->phys = phys;
1334 ts->input_dev->id.bustype = BUS_I2C;
1335 ts->input_dev->id.vendor = 0xDEAD;
1336 ts->input_dev->id.product = 0xBEEF;
1337 ts->input_dev->id.version = 10427;
Andrew Huangab45aab2013-06-27 10:06:56 +00001338
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001339 ret = input_register_device(ts->input_dev);
1340 if (ret) {
1341 dev_err(&ts->client->dev,
1342 "Register %s input device failed.\n",
1343 ts->input_dev->name);
1344 goto exit_free_inputdev;
1345 }
1346
1347 return 0;
1348
1349exit_free_inputdev:
1350 input_free_device(ts->input_dev);
1351 ts->input_dev = NULL;
1352 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001353}
1354
1355/*******************************************************
1356Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001357 I2c probe.
Andrew Huangab45aab2013-06-27 10:06:56 +00001358Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001359 client: i2c device struct.
1360 id: device id.
Andrew Huangab45aab2013-06-27 10:06:56 +00001361Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001362 Executive outcomes.
1363 0: succeed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001364*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001365
1366static int goodix_ts_probe(struct i2c_client *client,
1367 const struct i2c_device_id *id)
Andrew Huangab45aab2013-06-27 10:06:56 +00001368{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001369 struct goodix_ts_data *ts;
1370 u16 version_info;
1371 int ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001372
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001373 dev_dbg(&client->dev, "GTP I2C Address: 0x%02x\n", client->addr);
Andrew Huangab45aab2013-06-27 10:06:56 +00001374
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001375#if GTP_ESD_PROTECT
1376 i2c_connect_client = client;
1377#endif
1378 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1379 dev_err(&client->dev, "GTP I2C not supported\n");
1380 return -ENODEV;
1381 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001382
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001383 ts = kzalloc(sizeof(*ts), GFP_KERNEL);
1384 if (!ts) {
1385 dev_err(&client->dev, "GTP not enough memory for ts\n");
1386 return -ENOMEM;
1387 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001388
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001389 memset(ts, 0, sizeof(*ts));
1390 ts->client = client;
1391 /* For kernel 2.6.39 later we spin_lock_init(&ts->irq_lock)
1392 * For 2.6.39 & before, use ts->irq_lock = SPIN_LOCK_UNLOCKED
1393 */
1394 spin_lock_init(&ts->irq_lock);
1395 i2c_set_clientdata(client, ts);
1396
1397 ts->gtp_rawdiff_mode = 0;
1398
1399 ret = gtp_request_io_port(ts);
1400 if (ret) {
1401 dev_err(&client->dev, "GTP request IO port failed.\n");
1402 goto exit_power_off;
1403 }
1404
1405 gtp_reset_guitar(ts, 20);
1406
1407 ret = gtp_i2c_test(client);
1408 if (ret != 2) {
1409 dev_err(&client->dev, "I2C communication ERROR!\n");
1410 goto exit_free_io_port;
1411 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001412
1413#if GTP_AUTO_UPDATE
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001414 ret = gup_init_update_proc(ts);
1415 if (ret < 0) {
1416 dev_err(&client->dev,
1417 "GTP Create firmware update thread error.\n");
1418 goto exit_free_io_port;
1419 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001420#endif
Andrew Huangab45aab2013-06-27 10:06:56 +00001421
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001422 ret = gtp_init_panel(ts);
1423 if (ret < 0) {
1424 dev_err(&client->dev, "GTP init panel failed.\n");
1425 ts->abs_x_max = GTP_MAX_WIDTH;
1426 ts->abs_y_max = GTP_MAX_HEIGHT;
1427 ts->int_trigger_type = GTP_INT_TRIGGER;
1428 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001429
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001430 ret = gtp_request_input_dev(ts);
1431 if (ret) {
1432 dev_err(&client->dev, "GTP request input dev failed.\n");
1433 goto exit_free_inputdev;
1434 }
1435
1436 ts->goodix_wq = create_singlethread_workqueue("goodix_wq");
1437 INIT_WORK(&ts->work, goodix_ts_work_func);
1438
1439 ret = gtp_request_irq(ts);
1440 if (ret < 0)
1441 dev_info(&client->dev, "GTP works in polling mode.\n");
1442 else
1443 dev_info(&client->dev, "GTP works in interrupt mode.\n");
1444
1445 ret = gtp_read_version(client, &version_info);
1446 if (ret != 2) {
1447 dev_err(&client->dev, "Read version failed.\n");
1448 goto exit_free_irq;
1449 }
1450 if (ts->use_irq)
1451 gtp_irq_enable(ts);
1452
Andrew Huangab45aab2013-06-27 10:06:56 +00001453#if GTP_CREATE_WR_NODE
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001454 init_wr_node(client);
Andrew Huangab45aab2013-06-27 10:06:56 +00001455#endif
Andrew Huangab45aab2013-06-27 10:06:56 +00001456
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001457#if GTP_ESD_PROTECT
1458 gtp_esd_switch(client, SWITCH_ON);
1459#endif
1460 init_done = true;
1461 return 0;
1462exit_free_irq:
1463 if (ts->use_irq)
1464 free_irq(client->irq, ts);
1465 else
1466 hrtimer_cancel(&ts->timer);
1467 cancel_work_sync(&ts->work);
1468 flush_workqueue(ts->goodix_wq);
1469 destroy_workqueue(ts->goodix_wq);
1470
1471 input_unregister_device(ts->input_dev);
1472 if (ts->input_dev) {
1473 input_free_device(ts->input_dev);
1474 ts->input_dev = NULL;
1475 }
1476exit_free_inputdev:
1477 kfree(ts->config_data);
1478exit_free_io_port:
1479exit_power_off:
1480 i2c_set_clientdata(client, NULL);
1481 kfree(ts);
1482 return ret;
1483}
Andrew Huangab45aab2013-06-27 10:06:56 +00001484
1485/*******************************************************
1486Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001487 Goodix touchscreen driver release function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001488Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001489 client: i2c device struct.
Andrew Huangab45aab2013-06-27 10:06:56 +00001490Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001491 Executive outcomes. 0---succeed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001492*******************************************************/
1493static int goodix_ts_remove(struct i2c_client *client)
1494{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001495 struct goodix_ts_data *ts = i2c_get_clientdata(client);
1496
1497 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001498#ifdef CONFIG_HAS_EARLYSUSPEND
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001499 unregister_early_suspend(&ts->early_suspend);
Andrew Huangab45aab2013-06-27 10:06:56 +00001500#endif
1501
1502#if GTP_CREATE_WR_NODE
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001503 uninit_wr_node();
Andrew Huangab45aab2013-06-27 10:06:56 +00001504#endif
1505
1506#if GTP_ESD_PROTECT
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001507 cancel_work_sync(gtp_esd_check_workqueue);
1508 flush_workqueue(gtp_esd_check_workqueue);
1509 destroy_workqueue(gtp_esd_check_workqueue);
Andrew Huangab45aab2013-06-27 10:06:56 +00001510#endif
1511
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001512 if (ts) {
1513 if (ts->use_irq)
1514 free_irq(client->irq, ts);
1515 else
1516 hrtimer_cancel(&ts->timer);
Andrew Huangab45aab2013-06-27 10:06:56 +00001517
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001518 cancel_work_sync(&ts->work);
1519 flush_workqueue(ts->goodix_wq);
1520 destroy_workqueue(ts->goodix_wq);
1521
1522 input_unregister_device(ts->input_dev);
1523 if (ts->input_dev) {
1524 input_free_device(ts->input_dev);
1525 ts->input_dev = NULL;
1526 }
1527 kfree(ts->config_data);
1528
1529 if (gpio_is_valid(ts->pdata->reset_gpio))
1530 gpio_free(ts->pdata->reset_gpio);
1531 if (gpio_is_valid(ts->pdata->irq_gpio))
1532 gpio_free(ts->pdata->irq_gpio);
1533
1534 i2c_set_clientdata(client, NULL);
1535 kfree(ts);
1536 }
1537
1538 return 0;
Andrew Huangab45aab2013-06-27 10:06:56 +00001539}
1540
1541#ifdef CONFIG_HAS_EARLYSUSPEND
1542/*******************************************************
1543Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001544 Early suspend function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001545Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001546 h: early_suspend struct.
Andrew Huangab45aab2013-06-27 10:06:56 +00001547Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001548 None.
Andrew Huangab45aab2013-06-27 10:06:56 +00001549*******************************************************/
1550static void goodix_ts_early_suspend(struct early_suspend *h)
1551{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001552 struct goodix_ts_data *ts;
1553 s8 ret = -1;
1554 ts = container_of(h, struct goodix_ts_data, early_suspend);
1555
1556 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001557
1558#if GTP_ESD_PROTECT
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001559 ts->gtp_is_suspend = 1;
1560 gtp_esd_switch(ts->client, SWITCH_OFF);
Andrew Huangab45aab2013-06-27 10:06:56 +00001561#endif
1562
1563#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001564 ret = gtp_enter_doze(ts);
Andrew Huangab45aab2013-06-27 10:06:56 +00001565#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001566 if (ts->use_irq)
1567 gtp_irq_disable(ts);
1568 else
1569 hrtimer_cancel(&ts->timer);
1570 ret = gtp_enter_sleep(ts);
1571#endif
1572 if (ret < 0)
1573 dev_err(&ts->client->dev, "GTP early suspend failed.\n");
1574 /* to avoid waking up while not sleeping,
1575 * delay 48 + 10ms to ensure reliability
1576 */
1577 msleep(58);
Andrew Huangab45aab2013-06-27 10:06:56 +00001578}
1579
1580/*******************************************************
1581Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001582 Late resume function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001583Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001584 h: early_suspend struct.
Andrew Huangab45aab2013-06-27 10:06:56 +00001585Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001586 None.
Andrew Huangab45aab2013-06-27 10:06:56 +00001587*******************************************************/
1588static void goodix_ts_late_resume(struct early_suspend *h)
1589{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001590 struct goodix_ts_data *ts;
1591 s8 ret = -1;
1592 ts = container_of(h, struct goodix_ts_data, early_suspend);
1593
1594 GTP_DEBUG_FUNC();
1595
1596 ret = gtp_wakeup_sleep(ts);
Andrew Huangab45aab2013-06-27 10:06:56 +00001597
1598#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001599 doze_status = DOZE_DISABLED;
Andrew Huangab45aab2013-06-27 10:06:56 +00001600#endif
1601
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001602 if (ret < 0)
1603 dev_err(&ts->client->dev, "GTP later resume failed.\n");
Andrew Huangab45aab2013-06-27 10:06:56 +00001604
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001605 if (ts->use_irq)
1606 gtp_irq_enable(ts);
1607 else
1608 hrtimer_start(&ts->timer,
1609 ktime_set(1, 0), HRTIMER_MODE_REL);
Andrew Huangab45aab2013-06-27 10:06:56 +00001610
1611#if GTP_ESD_PROTECT
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001612 ts->gtp_is_suspend = 0;
1613 gtp_esd_switch(ts->client, SWITCH_ON);
Andrew Huangab45aab2013-06-27 10:06:56 +00001614#endif
1615}
1616#endif
1617
1618#if GTP_ESD_PROTECT
1619/*******************************************************
1620Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001621 switch on & off esd delayed work
Andrew Huangab45aab2013-06-27 10:06:56 +00001622Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001623 client: i2c device
1624 on: SWITCH_ON / SWITCH_OFF
Andrew Huangab45aab2013-06-27 10:06:56 +00001625Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001626 void
Andrew Huangab45aab2013-06-27 10:06:56 +00001627*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001628void gtp_esd_switch(struct i2c_client *client, int on)
Andrew Huangab45aab2013-06-27 10:06:56 +00001629{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001630 struct goodix_ts_data *ts;
1631
1632 ts = i2c_get_clientdata(client);
1633 if (SWITCH_ON == on) {
1634 /* switch on esd */
1635 if (!ts->esd_running) {
1636 ts->esd_running = 1;
1637 dev_dbg(&client->dev, "Esd started\n");
1638 queue_delayed_work(gtp_esd_check_workqueue,
1639 &gtp_esd_check_work, GTP_ESD_CHECK_CIRCLE);
1640 }
1641 } else {
1642 /* switch off esd */
1643 if (ts->esd_running) {
1644 ts->esd_running = 0;
1645 dev_dbg(&client->dev, "Esd cancelled\n");
1646 cancel_delayed_work_sync(&gtp_esd_check_work);
1647 }
1648 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001649}
1650
1651/*******************************************************
1652Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001653 Initialize external watchdog for esd protect
Andrew Huangab45aab2013-06-27 10:06:56 +00001654Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001655 client: i2c device.
Andrew Huangab45aab2013-06-27 10:06:56 +00001656Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001657 result of i2c write operation.
1658 1: succeed, otherwise: failed
Andrew Huangab45aab2013-06-27 10:06:56 +00001659*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001660static int gtp_init_ext_watchdog(struct i2c_client *client)
Andrew Huangab45aab2013-06-27 10:06:56 +00001661{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001662 /* in case of recursively reset by calling gtp_i2c_write*/
1663 struct i2c_msg msg;
1664 u8 opr_buffer[4] = {0x80, 0x40, 0xAA, 0xAA};
1665 int ret;
1666 int retries = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +00001667
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001668 GTP_DEBUG("Init external watchdog...");
1669 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001670
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001671 msg.flags = !I2C_M_RD;
1672 msg.addr = client->addr;
1673 msg.len = 4;
1674 msg.buf = opr_buffer;
Andrew Huangab45aab2013-06-27 10:06:56 +00001675
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001676 while (retries < 5) {
1677 ret = i2c_transfer(client->adapter, &msg, 1);
1678 if (ret == 1)
1679 return 1;
1680 retries++;
1681 }
1682 if (retries >= 5)
1683 dev_err(&client->dev, "init external watchdog failed!");
1684 return 0;
Andrew Huangab45aab2013-06-27 10:06:56 +00001685}
1686
1687/*******************************************************
1688Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001689 Esd protect function.
1690 Added external watchdog by meta, 2013/03/07
Andrew Huangab45aab2013-06-27 10:06:56 +00001691Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001692 work: delayed work
Andrew Huangab45aab2013-06-27 10:06:56 +00001693Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001694 None.
Andrew Huangab45aab2013-06-27 10:06:56 +00001695*******************************************************/
1696static void gtp_esd_check_func(struct work_struct *work)
1697{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001698 s32 i;
1699 s32 ret = -1;
1700 struct goodix_ts_data *ts = NULL;
1701 u8 test[4] = {0x80, 0x40};
Andrew Huangab45aab2013-06-27 10:06:56 +00001702
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001703 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001704
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001705 ts = i2c_get_clientdata(i2c_connect_client);
1706
1707 if (ts->gtp_is_suspend) {
1708 dev_dbg(&ts->client->dev, "Esd terminated!\n");
1709 ts->esd_running = 0;
1710 return;
1711 }
1712#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
1713 if (ts->enter_update)
1714 return;
1715#endif
1716
1717 for (i = 0; i < 3; i++) {
1718 ret = gtp_i2c_read(ts->client, test, 4);
1719
1720 GTP_DEBUG("0x8040 = 0x%02X, 0x8041 = 0x%02X", test[2], test[3]);
1721 if ((ret < 0)) {
1722 /* IC works abnormally..*/
1723 continue;
1724 } else {
1725 if ((test[2] == 0xAA) || (test[3] != 0xAA)) {
1726 /* IC works abnormally..*/
1727 i = 3;
1728 break;
1729 } else {
1730 /* IC works normally, Write 0x8040 0xAA*/
1731 test[2] = 0xAA;
1732 gtp_i2c_write(ts->client, test, 3);
1733 break;
1734 }
1735 }
1736 }
1737 if (i >= 3) {
1738 dev_err(&ts->client->dev,
1739 "IC Working ABNORMALLY, Resetting Guitar...\n");
1740 gtp_reset_guitar(ts, 50);
1741 }
1742
1743 if (!ts->gtp_is_suspend)
1744 queue_delayed_work(gtp_esd_check_workqueue,
1745 &gtp_esd_check_work, GTP_ESD_CHECK_CIRCLE);
1746 else {
1747 dev_dbg(&ts->client->dev, "Esd terminated!\n");
1748 ts->esd_running = 0;
1749 }
1750
1751 return;
Andrew Huangab45aab2013-06-27 10:06:56 +00001752}
1753#endif
1754
1755static const struct i2c_device_id goodix_ts_id[] = {
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001756 { GTP_I2C_NAME, 0 },
1757 { }
Andrew Huangab45aab2013-06-27 10:06:56 +00001758};
1759
1760static struct i2c_driver goodix_ts_driver = {
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001761 .probe = goodix_ts_probe,
1762 .remove = goodix_ts_remove,
1763#ifdef CONFIG_HAS_EARLYSUSPEND
1764 .suspend = goodix_ts_early_suspend,
1765 .resume = goodix_ts_late_resume,
Andrew Huangab45aab2013-06-27 10:06:56 +00001766#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001767 .id_table = goodix_ts_id,
1768 .driver = {
1769 .name = GTP_I2C_NAME,
1770 .owner = THIS_MODULE,
1771 },
Andrew Huangab45aab2013-06-27 10:06:56 +00001772};
1773
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001774/*******************************************************
Andrew Huangab45aab2013-06-27 10:06:56 +00001775Function:
1776 Driver Install function.
1777Input:
1778 None.
1779Output:
1780 Executive Outcomes. 0---succeed.
1781********************************************************/
1782static int __devinit goodix_ts_init(void)
1783{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001784 int ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001785
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001786 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001787#if GTP_ESD_PROTECT
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001788 INIT_DELAYED_WORK(&gtp_esd_check_work, gtp_esd_check_func);
1789 gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");
Andrew Huangab45aab2013-06-27 10:06:56 +00001790#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001791 ret = i2c_add_driver(&goodix_ts_driver);
1792 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001793}
1794
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001795/*******************************************************
Andrew Huangab45aab2013-06-27 10:06:56 +00001796Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001797 Driver uninstall function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001798Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001799 None.
Andrew Huangab45aab2013-06-27 10:06:56 +00001800Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001801 Executive Outcomes. 0---succeed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001802********************************************************/
1803static void __exit goodix_ts_exit(void)
1804{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001805 GTP_DEBUG_FUNC();
1806 i2c_del_driver(&goodix_ts_driver);
Andrew Huangab45aab2013-06-27 10:06:56 +00001807}
1808
1809late_initcall(goodix_ts_init);
1810module_exit(goodix_ts_exit);
1811
1812MODULE_DESCRIPTION("GTP Series Driver");
1813MODULE_LICENSE("GPL");