blob: 403fe2cbe7e179901322faba0c11ebb1e9aedd8c [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
Bingzhe Caid0361172013-07-18 19:22:11 +080048#include <linux/of_gpio.h>
49
Andrew Huangab45aab2013-06-27 10:06:56 +000050#if GTP_ICS_SLOT_REPORT
Bingzhe Cai83caeea2013-07-16 17:57:37 +080051#include <linux/input/mt.h>
Andrew Huangab45aab2013-06-27 10:06:56 +000052#endif
53
Bingzhe Cai83caeea2013-07-16 17:57:37 +080054#define GOODIX_DEV_NAME "Goodix Capacitive TouchScreen"
55#define CFG_MAX_TOUCH_POINTS 5
56#define GOODIX_COORDS_ARR_SIZE 4
57#define MAX_BUTTONS 4
58
59/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
60#define GTP_I2C_ADDRESS_HIGH 0x14
61#define GTP_I2C_ADDRESS_LOW 0x5D
62#define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0]))
63
64#define RESET_DELAY_T3_US 200 /* T3: > 100us */
65#define RESET_DELAY_T4 20 /* T4: > 5ms */
66
67#define PHY_BUF_SIZE 32
68
69#define GTP_MAX_TOUCH 5
70#define GTP_ESD_CHECK_CIRCLE_MS 2000
Andrew Huangab45aab2013-06-27 10:06:56 +000071
72#if GTP_HAVE_TOUCH_KEY
Bingzhe Cai83caeea2013-07-16 17:57:37 +080073static const u16 touch_key_array[] = {KEY_MENU, KEY_HOMEPAGE, KEY_BACK};
74#define GTP_MAX_KEY_NUM (sizeof(touch_key_array)/sizeof(touch_key_array[0]))
75
Andrew Huangab45aab2013-06-27 10:06:56 +000076#if GTP_DEBUG_ON
Bingzhe Cai83caeea2013-07-16 17:57:37 +080077static const int key_codes[] = {
78 KEY_HOME, KEY_BACK, KEY_MENU, KEY_SEARCH
79};
80static const char *const key_names[] = {
81 "Key_Home", "Key_Back", "Key_Menu", "Key_Search"
82};
Andrew Huangab45aab2013-06-27 10:06:56 +000083#endif
Andrew Huangab45aab2013-06-27 10:06:56 +000084#endif
85
Bingzhe Cai83caeea2013-07-16 17:57:37 +080086static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms);
87static void gtp_int_sync(struct goodix_ts_data *ts, int ms);
88static int gtp_i2c_test(struct i2c_client *client);
Andrew Huangab45aab2013-06-27 10:06:56 +000089
90#ifdef CONFIG_HAS_EARLYSUSPEND
91static void goodix_ts_early_suspend(struct early_suspend *h);
92static void goodix_ts_late_resume(struct early_suspend *h);
93#endif
Andrew Huangab45aab2013-06-27 10:06:56 +000094
95#if GTP_ESD_PROTECT
96static struct delayed_work gtp_esd_check_work;
Bingzhe Cai83caeea2013-07-16 17:57:37 +080097static struct workqueue_struct *gtp_esd_check_workqueue;
98static void gtp_esd_check_func(struct work_struct *work);
99static int gtp_init_ext_watchdog(struct i2c_client *client);
100struct i2c_client *i2c_connect_client;
Andrew Huangab45aab2013-06-27 10:06:56 +0000101#endif
102
Andrew Huangab45aab2013-06-27 10:06:56 +0000103#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800104enum doze_status {
105 DOZE_DISABLED = 0,
106 DOZE_ENABLED = 1,
107 DOZE_WAKEUP = 2,
108};
109static enum doze_status = DOZE_DISABLED;
Andrew Huangab45aab2013-06-27 10:06:56 +0000110static s8 gtp_enter_doze(struct goodix_ts_data *ts);
111#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800112bool init_done;
113static u8 chip_gt9xxs; /* true if ic is gt9xxs, like gt915s */
114u8 grp_cfg_version;
Andrew Huangab45aab2013-06-27 10:06:56 +0000115
116/*******************************************************
117Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800118 Read data from the i2c slave device.
Andrew Huangab45aab2013-06-27 10:06:56 +0000119Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800120 client: i2c device.
121 buf[0~1]: read start address.
122 buf[2~len-1]: read data buffer.
123 len: GTP_ADDR_LENGTH + read bytes count
Andrew Huangab45aab2013-06-27 10:06:56 +0000124Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800125 numbers of i2c_msgs to transfer:
126 2: succeed, otherwise: failed
Andrew Huangab45aab2013-06-27 10:06:56 +0000127*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800128int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len)
Andrew Huangab45aab2013-06-27 10:06:56 +0000129{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800130 struct goodix_ts_data *ts = i2c_get_clientdata(client);
131 struct i2c_msg msgs[2];
132 int ret = -EIO;
133 int retries = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +0000134
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800135 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000136
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800137 msgs[0].flags = !I2C_M_RD;
138 msgs[0].addr = client->addr;
139 msgs[0].len = GTP_ADDR_LENGTH;
140 msgs[0].buf = &buf[0];
Andrew Huangab45aab2013-06-27 10:06:56 +0000141
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800142 msgs[1].flags = I2C_M_RD;
143 msgs[1].addr = client->addr;
144 msgs[1].len = len - GTP_ADDR_LENGTH;
145 msgs[1].buf = &buf[GTP_ADDR_LENGTH];
146
147 while (retries < 5) {
148 ret = i2c_transfer(client->adapter, msgs, 2);
149 if (ret == 2)
150 break;
151 retries++;
152 }
153 if (retries >= 5) {
154#if GTP_SLIDE_WAKEUP
155 /* reset chip would quit doze mode */
156 if (DOZE_ENABLED == doze_status)
157 return ret;
158#endif
159 GTP_DEBUG("I2C communication timeout, resetting chip...");
160 if (init_done)
161 gtp_reset_guitar(ts, 10);
162 else
163 dev_warn(&client->dev,
164 "<GTP> gtp_reset_guitar exit init_done=%d:\n",
165 init_done);
166 }
167 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000168}
169
170/*******************************************************
171Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800172 Write data to the i2c slave device.
Andrew Huangab45aab2013-06-27 10:06:56 +0000173Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800174 client: i2c device.
175 buf[0~1]: write start address.
176 buf[2~len-1]: data buffer
177 len: GTP_ADDR_LENGTH + write bytes count
Andrew Huangab45aab2013-06-27 10:06:56 +0000178Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800179 numbers of i2c_msgs to transfer:
180 1: succeed, otherwise: failed
Andrew Huangab45aab2013-06-27 10:06:56 +0000181*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800182int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len)
Andrew Huangab45aab2013-06-27 10:06:56 +0000183{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800184 struct goodix_ts_data *ts = i2c_get_clientdata(client);
185 struct i2c_msg msg;
186 int ret = -EIO;
187 int retries = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +0000188
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800189 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000190
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800191 msg.flags = !I2C_M_RD;
192 msg.addr = client->addr;
193 msg.len = len;
194 msg.buf = buf;
Andrew Huangab45aab2013-06-27 10:06:56 +0000195
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800196 while (retries < 5) {
197 ret = i2c_transfer(client->adapter, &msg, 1);
198 if (ret == 1)
199 break;
200 retries++;
201 }
202 if ((retries >= 5)) {
203#if GTP_SLIDE_WAKEUP
204 if (DOZE_ENABLED == doze_status)
205 return ret;
206#endif
207 GTP_DEBUG("I2C communication timeout, resetting chip...");
208 if (init_done)
209 gtp_reset_guitar(ts, 10);
210 else
211 dev_warn(&client->dev,
212 "<GTP> gtp_reset_guitar exit init_done=%d:\n",
213 init_done);
214 }
215 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000216}
217/*******************************************************
218Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800219 i2c read twice, compare the results
Andrew Huangab45aab2013-06-27 10:06:56 +0000220Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800221 client: i2c device
222 addr: operate address
223 rxbuf: read data to store, if compare successful
224 len: bytes to read
Andrew Huangab45aab2013-06-27 10:06:56 +0000225Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800226 FAIL: read failed
227 SUCCESS: read successful
Andrew Huangab45aab2013-06-27 10:06:56 +0000228*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800229int gtp_i2c_read_dbl_check(struct i2c_client *client,
230 u16 addr, u8 *rxbuf, int len)
Andrew Huangab45aab2013-06-27 10:06:56 +0000231{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800232 u8 buf[16] = {0};
233 u8 confirm_buf[16] = {0};
234 u8 retry = 0;
235
236 while (retry++ < 3) {
237 memset(buf, 0xAA, 16);
238 buf[0] = (u8)(addr >> 8);
239 buf[1] = (u8)(addr & 0xFF);
240 gtp_i2c_read(client, buf, len + 2);
241
242 memset(confirm_buf, 0xAB, 16);
243 confirm_buf[0] = (u8)(addr >> 8);
244 confirm_buf[1] = (u8)(addr & 0xFF);
245 gtp_i2c_read(client, confirm_buf, len + 2);
246
247 if (!memcmp(buf, confirm_buf, len + 2))
248 break;
249 }
250 if (retry < 3) {
251 memcpy(rxbuf, confirm_buf + 2, len);
252 return SUCCESS;
253 } else {
254 dev_err(&client->dev,
255 "i2c read 0x%04X, %d bytes, double check failed!",
256 addr, len);
257 return FAIL;
258 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000259}
260
261/*******************************************************
262Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800263 Send config data.
Andrew Huangab45aab2013-06-27 10:06:56 +0000264Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800265 client: i2c device.
Andrew Huangab45aab2013-06-27 10:06:56 +0000266Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800267 result of i2c write operation.
268 > 0: succeed, otherwise: failed
Andrew Huangab45aab2013-06-27 10:06:56 +0000269*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800270static int gtp_send_cfg(struct goodix_ts_data *ts)
Andrew Huangab45aab2013-06-27 10:06:56 +0000271{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800272 int ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000273#if GTP_DRIVER_SEND_CFG
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800274 int retry = 0;
275
276 if (ts->fixed_cfg) {
277 dev_dbg(&ts->client->dev,
278 "Ic fixed config, no config sent!");
279 ret = 2;
280 } else {
281 for (retry = 0; retry < 5; retry++) {
282 ret = gtp_i2c_write(ts->client,
283 ts->config_data,
284 GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);
285 if (ret > 0)
286 break;
287 }
288 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000289#endif
290
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800291 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000292}
293
294/*******************************************************
295Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800296 Disable irq function
Andrew Huangab45aab2013-06-27 10:06:56 +0000297Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800298 ts: goodix i2c_client private data
Andrew Huangab45aab2013-06-27 10:06:56 +0000299Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800300 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000301*********************************************************/
302void gtp_irq_disable(struct goodix_ts_data *ts)
303{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800304 unsigned long irqflags;
Andrew Huangab45aab2013-06-27 10:06:56 +0000305
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800306 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000307
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800308 spin_lock_irqsave(&ts->irq_lock, irqflags);
309 if (!ts->irq_is_disabled) {
310 ts->irq_is_disabled = true;
311 disable_irq_nosync(ts->client->irq);
312 }
313 spin_unlock_irqrestore(&ts->irq_lock, irqflags);
Andrew Huangab45aab2013-06-27 10:06:56 +0000314}
315
316/*******************************************************
317Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800318 Enable irq function
Andrew Huangab45aab2013-06-27 10:06:56 +0000319Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800320 ts: goodix i2c_client private data
Andrew Huangab45aab2013-06-27 10:06:56 +0000321Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800322 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000323*********************************************************/
324void gtp_irq_enable(struct goodix_ts_data *ts)
325{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800326 unsigned long irqflags = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +0000327
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800328 GTP_DEBUG_FUNC();
329
330 spin_lock_irqsave(&ts->irq_lock, irqflags);
331 if (ts->irq_is_disabled) {
332 enable_irq(ts->client->irq);
333 ts->irq_is_disabled = false;
334 }
335 spin_unlock_irqrestore(&ts->irq_lock, irqflags);
Andrew Huangab45aab2013-06-27 10:06:56 +0000336}
337
Andrew Huangab45aab2013-06-27 10:06:56 +0000338/*******************************************************
339Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800340 Report touch point event
Andrew Huangab45aab2013-06-27 10:06:56 +0000341Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800342 ts: goodix i2c_client private data
343 id: trackId
344 x: input x coordinate
345 y: input y coordinate
346 w: input pressure
Andrew Huangab45aab2013-06-27 10:06:56 +0000347Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800348 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000349*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800350static void gtp_touch_down(struct goodix_ts_data *ts, int id, int x, int y,
351 int w)
Andrew Huangab45aab2013-06-27 10:06:56 +0000352{
353#if GTP_CHANGE_X2Y
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800354 GTP_SWAP(x, y);
Andrew Huangab45aab2013-06-27 10:06:56 +0000355#endif
356
357#if GTP_ICS_SLOT_REPORT
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800358 input_mt_slot(ts->input_dev, id);
359 input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
360 input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
361 input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
362 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
363 input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
Andrew Huangab45aab2013-06-27 10:06:56 +0000364#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800365 input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
366 input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
367 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
368 input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
369 input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, id);
370 input_mt_sync(ts->input_dev);
Andrew Huangab45aab2013-06-27 10:06:56 +0000371#endif
372
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800373 GTP_DEBUG("ID:%d, X:%d, Y:%d, W:%d", id, x, y, w);
Andrew Huangab45aab2013-06-27 10:06:56 +0000374}
375
376/*******************************************************
377Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800378 Report touch release event
Andrew Huangab45aab2013-06-27 10:06:56 +0000379Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800380 ts: goodix i2c_client private data
Andrew Huangab45aab2013-06-27 10:06:56 +0000381Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800382 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000383*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800384static void gtp_touch_up(struct goodix_ts_data *ts, int id)
Andrew Huangab45aab2013-06-27 10:06:56 +0000385{
386#if GTP_ICS_SLOT_REPORT
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800387 input_mt_slot(ts->input_dev, id);
388 input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
389 GTP_DEBUG("Touch id[%2d] release!", id);
Andrew Huangab45aab2013-06-27 10:06:56 +0000390#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800391 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
392 input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0);
393 input_mt_sync(ts->input_dev);
Andrew Huangab45aab2013-06-27 10:06:56 +0000394#endif
395}
396
397
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800398
Andrew Huangab45aab2013-06-27 10:06:56 +0000399/*******************************************************
400Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800401 Goodix touchscreen work function
Andrew Huangab45aab2013-06-27 10:06:56 +0000402Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800403 work: work struct of goodix_workqueue
Andrew Huangab45aab2013-06-27 10:06:56 +0000404Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800405 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000406*********************************************************/
407static void goodix_ts_work_func(struct work_struct *work)
408{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800409 u8 end_cmd[3] = { GTP_READ_COOR_ADDR >> 8,
410 GTP_READ_COOR_ADDR & 0xFF, 0};
411 u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH + 1] = {
412 GTP_READ_COOR_ADDR >> 8,
413 GTP_READ_COOR_ADDR & 0xFF};
414 u8 touch_num = 0;
415 u8 finger = 0;
416 static u16 pre_touch;
417 static u8 pre_key;
Andrew Huangab45aab2013-06-27 10:06:56 +0000418#if GTP_WITH_PEN
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800419 static u8 pre_pen;
Andrew Huangab45aab2013-06-27 10:06:56 +0000420#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800421 u8 key_value = 0;
422 u8 *coor_data = NULL;
423 s32 input_x = 0;
424 s32 input_y = 0;
425 s32 input_w = 0;
426 s32 id = 0;
427 s32 i = 0;
428 int ret = -1;
429 struct goodix_ts_data *ts = NULL;
Andrew Huangab45aab2013-06-27 10:06:56 +0000430
431#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800432 u8 doze_buf[3] = {0x81, 0x4B};
Andrew Huangab45aab2013-06-27 10:06:56 +0000433#endif
434
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800435 GTP_DEBUG_FUNC();
436
437 ts = container_of(work, struct goodix_ts_data, work);
438#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
439 if (ts->enter_update)
440 return;
441#endif
442
Andrew Huangab45aab2013-06-27 10:06:56 +0000443#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800444 if (DOZE_ENABLED == doze_status) {
445 ret = gtp_i2c_read(ts->client, doze_buf, 3);
446 GTP_DEBUG("0x814B = 0x%02X", doze_buf[2]);
447 if (ret > 0) {
448 if (doze_buf[2] == 0xAA) {
449 dev_dbg(&ts->client->dev,
450 "Slide(0xAA) To Light up the screen!");
451 doze_status = DOZE_WAKEUP;
452 input_report_key(
453 ts->input_dev, KEY_POWER, 1);
454 input_sync(ts->input_dev);
455 input_report_key(
456 ts->input_dev, KEY_POWER, 0);
457 input_sync(ts->input_dev);
458 /* clear 0x814B */
459 doze_buf[2] = 0x00;
460 gtp_i2c_write(ts->client, doze_buf, 3);
461 } else if (doze_buf[2] == 0xBB) {
462 dev_dbg(&ts->client->dev,
463 "Slide(0xBB) To Light up the screen!");
464 doze_status = DOZE_WAKEUP;
465 input_report_key(ts->input_dev, KEY_POWER, 1);
466 input_sync(ts->input_dev);
467 input_report_key(ts->input_dev, KEY_POWER, 0);
468 input_sync(ts->input_dev);
469 /* clear 0x814B*/
470 doze_buf[2] = 0x00;
471 gtp_i2c_write(ts->client, doze_buf, 3);
472 } else if (0xC0 == (doze_buf[2] & 0xC0)) {
473 dev_dbg(&ts->client->dev,
474 "double click to light up the screen!");
475 doze_status = DOZE_WAKEUP;
476 input_report_key(ts->input_dev, KEY_POWER, 1);
477 input_sync(ts->input_dev);
478 input_report_key(ts->input_dev, KEY_POWER, 0);
479 input_sync(ts->input_dev);
480 /* clear 0x814B */
481 doze_buf[2] = 0x00;
482 gtp_i2c_write(ts->client, doze_buf, 3);
483 } else {
484 gtp_enter_doze(ts);
485 }
486 }
487 if (ts->use_irq)
488 gtp_irq_enable(ts);
489
490 return;
491 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000492#endif
493
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800494 ret = gtp_i2c_read(ts->client, point_data, 12);
495 if (ret < 0) {
496 dev_err(&ts->client->dev,
497 "I2C transfer error. errno:%d\n ", ret);
498 goto exit_work_func;
499 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000500
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800501 finger = point_data[GTP_ADDR_LENGTH];
502 if ((finger & 0x80) == 0)
503 goto exit_work_func;
Andrew Huangab45aab2013-06-27 10:06:56 +0000504
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800505 touch_num = finger & 0x0f;
506 if (touch_num > GTP_MAX_TOUCH)
507 goto exit_work_func;
Andrew Huangab45aab2013-06-27 10:06:56 +0000508
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800509 if (touch_num > 1) {
510 u8 buf[8 * GTP_MAX_TOUCH] = { (GTP_READ_COOR_ADDR + 10) >> 8,
511 (GTP_READ_COOR_ADDR + 10) & 0xff };
Andrew Huangab45aab2013-06-27 10:06:56 +0000512
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800513 ret = gtp_i2c_read(ts->client, buf,
514 2 + 8 * (touch_num - 1));
515 memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));
516 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000517
518#if GTP_HAVE_TOUCH_KEY
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800519 key_value = point_data[3 + 8 * touch_num];
Andrew Huangab45aab2013-06-27 10:06:56 +0000520
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800521 if (key_value || pre_key) {
522 for (i = 0; i < GTP_MAX_KEY_NUM; i++) {
523#if GTP_DEBUG_ON
524 for (ret = 0; ret < 4; ++ret) {
525 if (key_codes[ret] == touch_key_array[i]) {
526 GTP_DEBUG("Key: %s %s",
527 key_names[ret],
528 (key_value & (0x01 << i))
529 ? "Down" : "Up");
530 break;
531 }
532 }
533#endif
534
535 input_report_key(ts->input_dev,
536 touch_key_array[i], key_value & (0x01<<i));
537 }
538 touch_num = 0;
539 pre_touch = 0;
540 }
541#endif
542 pre_key = key_value;
543
544 GTP_DEBUG("pre_touch:%02x, finger:%02x.", pre_touch, finger);
Andrew Huangab45aab2013-06-27 10:06:56 +0000545
546#if GTP_ICS_SLOT_REPORT
Andrew Huangab45aab2013-06-27 10:06:56 +0000547#if GTP_WITH_PEN
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800548 if (pre_pen && (touch_num == 0)) {
549 GTP_DEBUG("Pen touch UP(Slot)!");
550 input_report_key(ts->input_dev, BTN_TOOL_PEN, 0);
551 input_mt_slot(ts->input_dev, 5);
552 input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
553 pre_pen = 0;
554 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000555#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800556 if (pre_touch || touch_num) {
557 s32 pos = 0;
558 u16 touch_index = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +0000559
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800560 coor_data = &point_data[3];
561 if (touch_num) {
562 id = coor_data[pos] & 0x0F;
563#if GTP_WITH_PEN
564 id = coor_data[pos];
565 if (id == 128) {
566 GTP_DEBUG("Pen touch DOWN(Slot)!");
567 input_x = coor_data[pos + 1]
568 | (coor_data[pos + 2] << 8);
569 input_y = coor_data[pos + 3]
570 | (coor_data[pos + 4] << 8);
571 input_w = coor_data[pos + 5]
572 | (coor_data[pos + 6] << 8);
Andrew Huangab45aab2013-06-27 10:06:56 +0000573
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800574 input_report_key(ts->input_dev,
575 BTN_TOOL_PEN, 1);
576 input_mt_slot(ts->input_dev, 5);
577 input_report_abs(ts->input_dev,
578 ABS_MT_TRACKING_ID, 5);
579 input_report_abs(ts->input_dev,
580 ABS_MT_POSITION_X, input_x);
581 input_report_abs(ts->input_dev,
582 ABS_MT_POSITION_Y, input_y);
583 input_report_abs(ts->input_dev,
584 ABS_MT_TOUCH_MAJOR, input_w);
585 GTP_DEBUG("Pen/Stylus: (%d, %d)[%d]",
586 input_x, input_y, input_w);
587 pre_pen = 1;
588 pre_touch = 0;
589 }
590#endif
591
592 touch_index |= (0x01<<id);
593 }
594
595 GTP_DEBUG("id = %d,touch_index = 0x%x, pre_touch = 0x%x\n",
596 id, touch_index, pre_touch);
597 for (i = 0; i < GTP_MAX_TOUCH; i++) {
598#if GTP_WITH_PEN
599 if (pre_pen == 1)
600 break;
601#endif
602 if (touch_index & (0x01<<i)) {
603 input_x = coor_data[pos + 1] |
604 coor_data[pos + 2] << 8;
605 input_y = coor_data[pos + 3] |
606 coor_data[pos + 4] << 8;
607 input_w = coor_data[pos + 5] |
608 coor_data[pos + 6] << 8;
609
610 gtp_touch_down(ts, id,
611 input_x, input_y, input_w);
612 pre_touch |= 0x01 << i;
613
614 pos += 8;
615 id = coor_data[pos] & 0x0F;
616 touch_index |= (0x01<<id);
617 } else {
618 gtp_touch_up(ts, i);
619 pre_touch &= ~(0x01 << i);
620 }
621 }
622 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000623#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800624 input_report_key(ts->input_dev, BTN_TOUCH, (touch_num || key_value));
625 if (touch_num) {
626 for (i = 0; i < touch_num; i++) {
627 coor_data = &point_data[i * 8 + 3];
Andrew Huangab45aab2013-06-27 10:06:56 +0000628
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800629 id = coor_data[0];
630 input_x = coor_data[1] | coor_data[2] << 8;
631 input_y = coor_data[3] | coor_data[4] << 8;
632 input_w = coor_data[5] | coor_data[6] << 8;
633#if GTP_WITH_PEN
634 if (id == 128) {
635 GTP_DEBUG("Pen touch DOWN!");
636 input_report_key(ts->input_dev,
637 BTN_TOOL_PEN, 1);
638 pre_pen = 1;
639 id = 0;
640 }
641#endif
642 gtp_touch_down(ts, id, input_x, input_y, input_w);
643 }
644 } else if (pre_touch) {
645#if GTP_WITH_PEN
646 if (pre_pen == 1) {
647 GTP_DEBUG("Pen touch UP!");
648 input_report_key(ts->input_dev, BTN_TOOL_PEN, 0);
649 pre_pen = 0;
650 }
651#endif
652 GTP_DEBUG("Touch Released!");
653 gtp_touch_up(ts, 0);
654 }
Andrew Huangab45aab2013-06-27 10:06:56 +0000655
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800656 pre_touch = touch_num;
Andrew Huangab45aab2013-06-27 10:06:56 +0000657#endif
658
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800659 input_sync(ts->input_dev);
Andrew Huangab45aab2013-06-27 10:06:56 +0000660
661exit_work_func:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800662 if (!ts->gtp_rawdiff_mode) {
663 ret = gtp_i2c_write(ts->client, end_cmd, 3);
664 if (ret < 0)
665 dev_warn(&ts->client->dev, "I2C write end_cmd error!\n");
666
667 }
668 if (ts->use_irq)
669 gtp_irq_enable(ts);
670
671 return;
Andrew Huangab45aab2013-06-27 10:06:56 +0000672}
673
674/*******************************************************
675Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800676 Timer interrupt service routine for polling mode.
Andrew Huangab45aab2013-06-27 10:06:56 +0000677Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800678 timer: timer struct pointer
Andrew Huangab45aab2013-06-27 10:06:56 +0000679Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800680 Timer work mode.
681 HRTIMER_NORESTART: no restart mode
Andrew Huangab45aab2013-06-27 10:06:56 +0000682*********************************************************/
683static enum hrtimer_restart goodix_ts_timer_handler(struct hrtimer *timer)
684{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800685 struct goodix_ts_data
686 *ts = container_of(timer, struct goodix_ts_data, timer);
Andrew Huangab45aab2013-06-27 10:06:56 +0000687
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800688 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000689
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800690 queue_work(ts->goodix_wq, &ts->work);
691 hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME + 6) * 1000000),
692 HRTIMER_MODE_REL);
693 return HRTIMER_NORESTART;
Andrew Huangab45aab2013-06-27 10:06:56 +0000694}
695
696/*******************************************************
697Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800698 External interrupt service routine for interrupt mode.
Andrew Huangab45aab2013-06-27 10:06:56 +0000699Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800700 irq: interrupt number.
701 dev_id: private data pointer
Andrew Huangab45aab2013-06-27 10:06:56 +0000702Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800703 Handle Result.
704 IRQ_HANDLED: interrupt handled successfully
Andrew Huangab45aab2013-06-27 10:06:56 +0000705*********************************************************/
706static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
707{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800708 struct goodix_ts_data *ts = dev_id;
Andrew Huangab45aab2013-06-27 10:06:56 +0000709
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800710 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000711
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800712 gtp_irq_disable(ts);
713
714 queue_work(ts->goodix_wq, &ts->work);
715
716 return IRQ_HANDLED;
Andrew Huangab45aab2013-06-27 10:06:56 +0000717}
718/*******************************************************
719Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800720 Synchronization.
Andrew Huangab45aab2013-06-27 10:06:56 +0000721Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800722 ms: synchronization time in millisecond.
Andrew Huangab45aab2013-06-27 10:06:56 +0000723Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800724 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000725*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800726void gtp_int_sync(struct goodix_ts_data *ts, int ms)
Andrew Huangab45aab2013-06-27 10:06:56 +0000727{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800728 gpio_direction_output(ts->pdata->irq_gpio, 0);
729 msleep(ms);
730 gpio_direction_input(ts->pdata->irq_gpio);
Andrew Huangab45aab2013-06-27 10:06:56 +0000731}
732
733/*******************************************************
734Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800735 Reset chip.
Andrew Huangab45aab2013-06-27 10:06:56 +0000736Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800737 ms: reset time in millisecond, must >10ms
Andrew Huangab45aab2013-06-27 10:06:56 +0000738Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800739 None.
Andrew Huangab45aab2013-06-27 10:06:56 +0000740*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800741static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms)
Andrew Huangab45aab2013-06-27 10:06:56 +0000742{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800743 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000744
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800745 /* This reset sequence will selcet I2C slave address */
746 gpio_direction_output(ts->pdata->reset_gpio, 0);
747 msleep(ms);
Andrew Huangab45aab2013-06-27 10:06:56 +0000748
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800749 if (ts->client->addr == GTP_I2C_ADDRESS_HIGH)
750 gpio_direction_output(ts->pdata->irq_gpio, 1);
751 else
752 gpio_direction_output(ts->pdata->irq_gpio, 0);
Andrew Huangab45aab2013-06-27 10:06:56 +0000753
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800754 usleep(RESET_DELAY_T3_US);
755 gpio_direction_output(ts->pdata->reset_gpio, 1);
756 msleep(RESET_DELAY_T4);
Andrew Huangab45aab2013-06-27 10:06:56 +0000757
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800758 gpio_direction_input(ts->pdata->reset_gpio);
759
760 gtp_int_sync(ts, 50);
761
Andrew Huangab45aab2013-06-27 10:06:56 +0000762#if GTP_ESD_PROTECT
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800763 gtp_init_ext_watchdog(ts->client);
Andrew Huangab45aab2013-06-27 10:06:56 +0000764#endif
765}
766
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800767#ifdef CONFIG_HAS_EARLYSUSPEND
Andrew Huangab45aab2013-06-27 10:06:56 +0000768#if GTP_SLIDE_WAKEUP
769/*******************************************************
770Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800771 Enter doze mode for sliding wakeup.
Andrew Huangab45aab2013-06-27 10:06:56 +0000772Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800773 ts: goodix tp private data
Andrew Huangab45aab2013-06-27 10:06:56 +0000774Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800775 1: succeed, otherwise failed
Andrew Huangab45aab2013-06-27 10:06:56 +0000776*******************************************************/
777static s8 gtp_enter_doze(struct goodix_ts_data *ts)
778{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800779 int ret = -1;
780 s8 retry = 0;
781 u8 i2c_control_buf[3] = {
782 (u8)(GTP_REG_SLEEP >> 8),
783 (u8)GTP_REG_SLEEP, 8};
Andrew Huangab45aab2013-06-27 10:06:56 +0000784
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800785 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +0000786
787#if GTP_DBL_CLK_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800788 i2c_control_buf[2] = 0x09;
Andrew Huangab45aab2013-06-27 10:06:56 +0000789#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800790 gtp_irq_disable(ts);
Andrew Huangab45aab2013-06-27 10:06:56 +0000791
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800792 GTP_DEBUG("entering doze mode...");
793 while (retry++ < 5) {
794 i2c_control_buf[0] = 0x80;
795 i2c_control_buf[1] = 0x46;
796 ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
797 if (ret < 0) {
798 GTP_DEBUG(
799 "failed to set doze flag into 0x8046, %d",
800 retry);
801 continue;
802 }
803 i2c_control_buf[0] = 0x80;
804 i2c_control_buf[1] = 0x40;
805 ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
806 if (ret > 0) {
807 doze_status = DOZE_ENABLED;
808 dev_dbg(&ts->client->dev,
809 "GTP has been working in doze mode!");
810 gtp_irq_enable(ts);
811 return ret;
812 }
813 msleep(20);
814 }
815 dev_err(&ts->client->dev, "GTP send doze cmd failed.\n");
816 gtp_irq_enable(ts);
817 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000818}
Andrew Huangab45aab2013-06-27 10:06:56 +0000819#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800820/*******************************************************
821Function:
822 Enter sleep mode.
823Input:
824 ts: private data.
825Output:
826 Executive outcomes.
827 1: succeed, otherwise failed.
828*******************************************************/
829static s8 gtp_enter_sleep(struct goodix_ts_data *ts)
830{
831 int ret = -1;
832 s8 retry = 0;
833 u8 i2c_control_buf[3] = {
834 (u8)(GTP_REG_SLEEP >> 8),
835 (u8)GTP_REG_SLEEP, 5};
Andrew Huangab45aab2013-06-27 10:06:56 +0000836
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800837 GTP_DEBUG_FUNC();
838
839 ret = gpio_direction_output(ts->pdata->irq_gpio, 0);
840 usleep(5000);
841 while (retry++ < 5) {
842 ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
843 if (ret > 0) {
844 dev_dbg(&ts->client->dev,
845 "GTP enter sleep!");
846 return ret;
847 }
848 msleep(20);
849 }
850 dev_err(&ts->client->dev, "GTP send sleep cmd failed.\n");
851 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +0000852}
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800853#endif
Andrew Huangab45aab2013-06-27 10:06:56 +0000854
855/*******************************************************
856Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800857 Wakeup from sleep.
Andrew Huangab45aab2013-06-27 10:06:56 +0000858Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800859 ts: private data.
Andrew Huangab45aab2013-06-27 10:06:56 +0000860Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800861 Executive outcomes.
862 >0: succeed, otherwise: failed.
Andrew Huangab45aab2013-06-27 10:06:56 +0000863*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800864static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts)
Andrew Huangab45aab2013-06-27 10:06:56 +0000865{
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800866 u8 retry = 0;
867 s8 ret = -1;
868
869 GTP_DEBUG_FUNC();
870
871#if GTP_POWER_CTRL_SLEEP
872 while (retry++ < 5) {
873 gtp_reset_guitar(ts, 20);
874
875 ret = gtp_send_cfg(ts);
876 if (ret > 0) {
877 dev_dbg(&ts->client->dev,
878 "Wakeup sleep send config success.");
879 continue;
880 }
881 dev_dbg(&ts->client->dev, "GTP Wakeup!");
882 return 1;
883 }
884#else
885 while (retry++ < 10) {
886#if GTP_SLIDE_WAKEUP
887 /* wakeup not by slide */
888 if (DOZE_WAKEUP != doze_status)
889 gtp_reset_guitar(ts, 10);
890 else
891 /* wakeup by slide */
892 doze_status = DOZE_DISABLED;
893#else
894 if (chip_gt9xxs == 1) {
895 gtp_reset_guitar(ts, 10);
896 } else {
897 ret = gpio_direction_output(ts->pdata->irq_gpio, 1);
898 usleep(5000);
899 }
900#endif
901 ret = gtp_i2c_test(ts->client);
902 if (ret > 0) {
903 dev_dbg(&ts->client->dev, "GTP wakeup sleep.");
904#if (!GTP_SLIDE_WAKEUP)
905 if (chip_gt9xxs == 0) {
906 gtp_int_sync(ts, 25);
907 msleep(20);
908#if GTP_ESD_PROTECT
909 gtp_init_ext_watchdog(ts->client);
910#endif
911 }
912#endif
913 return ret;
914 }
915 gtp_reset_guitar(ts, 20);
916 }
917#endif
918
919 dev_err(&ts->client->dev, "GTP wakeup sleep failed.\n");
920 return ret;
921}
922#endif /* !CONFIG_HAS_EARLYSUSPEND */
923
924/*******************************************************
925Function:
926 Initialize gtp.
927Input:
928 ts: goodix private data
929Output:
930 Executive outcomes.
931 > =0: succeed, otherwise: failed
932*******************************************************/
933static int gtp_init_panel(struct goodix_ts_data *ts)
934{
935 struct i2c_client *client = ts->client;
936 unsigned char *config_data;
937 int ret = -EIO;
Andrew Huangab45aab2013-06-27 10:06:56 +0000938
939#if GTP_DRIVER_SEND_CFG
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800940 int i;
941 u8 check_sum = 0;
942 u8 opr_buf[16];
943 u8 sensor_id = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +0000944
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800945 u8 cfg_info_group1[] = CTP_CFG_GROUP1;
946 u8 cfg_info_group2[] = CTP_CFG_GROUP2;
947 u8 cfg_info_group3[] = CTP_CFG_GROUP3;
948 u8 cfg_info_group4[] = CTP_CFG_GROUP4;
949 u8 cfg_info_group5[] = CTP_CFG_GROUP5;
950 u8 cfg_info_group6[] = CTP_CFG_GROUP6;
951 u8 *send_cfg_buf[] = {cfg_info_group1, cfg_info_group2,
952 cfg_info_group3, cfg_info_group4,
953 cfg_info_group5, cfg_info_group6};
Andrew Huangab45aab2013-06-27 10:06:56 +0000954
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800955 u8 cfg_info_len[] = {CFG_GROUP_LEN(cfg_info_group1),
956 CFG_GROUP_LEN(cfg_info_group2),
957 CFG_GROUP_LEN(cfg_info_group3),
958 CFG_GROUP_LEN(cfg_info_group4),
959 CFG_GROUP_LEN(cfg_info_group5),
960 CFG_GROUP_LEN(cfg_info_group6)};
Andrew Huangab45aab2013-06-27 10:06:56 +0000961
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800962 GTP_DEBUG("Config Groups\' Lengths: %d, %d, %d, %d, %d, %d",
963 cfg_info_len[0], cfg_info_len[1], cfg_info_len[2],
964 cfg_info_len[3], cfg_info_len[4], cfg_info_len[5]);
Andrew Huangab45aab2013-06-27 10:06:56 +0000965
Bingzhe Cai83caeea2013-07-16 17:57:37 +0800966 ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);
967 if (SUCCESS == ret) {
968 if (opr_buf[0] != 0xBE) {
969 ts->fw_error = 1;
970 dev_err(&client->dev,
971 "Firmware error, no config sent!");
972 return -EINVAL;
973 }
974 }
975 if ((!cfg_info_len[1]) && (!cfg_info_len[2]) && (!cfg_info_len[3])
976 && (!cfg_info_len[4]) && (!cfg_info_len[5])) {
977 sensor_id = 0;
978 } else {
979 ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID,
980 &sensor_id, 1);
981 if (SUCCESS == ret) {
982 if (sensor_id >= 0x06) {
983 dev_err(&client->dev,
984 "Invalid sensor_id(0x%02X), No Config Sent!",
985 sensor_id);
986 return -EINVAL;
987 }
988 } else {
989 dev_err(&client->dev,
990 "Failed to get sensor_id, No config sent!");
991 return -EINVAL;
992 }
993 }
994 GTP_DEBUG("Sensor_ID: %d", sensor_id);
995
996 ts->gtp_cfg_len = cfg_info_len[sensor_id];
997
998 if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH) {
999 dev_err(&client->dev,
1000 "Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!\n",
1001 sensor_id);
1002 return -EINVAL;
1003 }
1004 ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
1005 &opr_buf[0], 1);
1006
1007 if (ret == SUCCESS) {
1008 if (opr_buf[0] < 90) {
1009 /* backup group config version */
1010 grp_cfg_version = send_cfg_buf[sensor_id][0];
1011 send_cfg_buf[sensor_id][0] = 0x00;
1012 ts->fixed_cfg = 0;
1013 } else {
1014 /* treated as fixed config, not send config */
1015 dev_warn(&client->dev,
1016 "Ic fixed config with config version(%d, 0x%02X)",
1017 opr_buf[0], opr_buf[0]);
1018 ts->fixed_cfg = 1;
1019 }
1020 } else {
1021 dev_err(&client->dev,
1022 "Failed to get ic config version!No config sent!");
1023 return -EINVAL;
1024 }
1025
Bingzhe Caid0361172013-07-18 19:22:11 +08001026 if (ts->pdata->gtp_cfg_len) {
1027 config_data = ts->pdata->config_data;
1028 ts->config_data = ts->pdata->config_data;
1029 ts->gtp_cfg_len = ts->pdata->gtp_cfg_len;
1030 } else {
1031 config_data = devm_kzalloc(&client->dev,
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001032 GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
Bingzhe Caid0361172013-07-18 19:22:11 +08001033 GFP_KERNEL);
1034 if (!config_data) {
1035 dev_err(&client->dev,
1036 "Not enough memory for panel config data\n");
1037 return -ENOMEM;
1038 }
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001039
Bingzhe Caid0361172013-07-18 19:22:11 +08001040 ts->config_data = config_data;
1041 config_data[0] = GTP_REG_CONFIG_DATA >> 8;
1042 config_data[1] = GTP_REG_CONFIG_DATA & 0xff;
1043 memset(&config_data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
1044 memcpy(&config_data[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id],
1045 ts->gtp_cfg_len);
1046 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001047
1048#if GTP_CUSTOM_CFG
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001049 config_data[RESOLUTION_LOC] =
1050 (unsigned char)(GTP_MAX_WIDTH && 0xFF);
1051 config_data[RESOLUTION_LOC + 1] =
1052 (unsigned char)(GTP_MAX_WIDTH >> 8);
1053 config_data[RESOLUTION_LOC + 2] =
1054 (unsigned char)(GTP_MAX_HEIGHT && 0xFF);
1055 config_data[RESOLUTION_LOC + 3] =
1056 (unsigned char)(GTP_MAX_HEIGHT >> 8);
Andrew Huangab45aab2013-06-27 10:06:56 +00001057
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001058 if (GTP_INT_TRIGGER == 0)
1059 config_data[TRIGGER_LOC] &= 0xfe;
1060 else if (GTP_INT_TRIGGER == 1)
1061 config_data[TRIGGER_LOC] |= 0x01;
1062#endif /* !GTP_CUSTOM_CFG */
Andrew Huangab45aab2013-06-27 10:06:56 +00001063
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001064 check_sum = 0;
1065 for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
1066 check_sum += config_data[i];
1067
1068 config_data[ts->gtp_cfg_len] = (~check_sum) + 1;
1069
1070#else /* DRIVER NOT SEND CONFIG */
1071 ts->gtp_cfg_len = GTP_CONFIG_MAX_LENGTH;
1072 ret = gtp_i2c_read(ts->client, config_data,
1073 ts->gtp_cfg_len + GTP_ADDR_LENGTH);
1074 if (ret < 0) {
1075 dev_err(&client->dev,
1076 "Read Config Failed, Using DEFAULT Resolution & INT Trigger!\n");
1077 ts->abs_x_max = GTP_MAX_WIDTH;
1078 ts->abs_y_max = GTP_MAX_HEIGHT;
1079 ts->int_trigger_type = GTP_INT_TRIGGER;
1080 }
1081#endif /* !DRIVER NOT SEND CONFIG */
1082
1083 GTP_DEBUG_FUNC();
1084 if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0)) {
1085 ts->abs_x_max = (config_data[RESOLUTION_LOC + 1] << 8)
1086 + config_data[RESOLUTION_LOC];
1087 ts->abs_y_max = (config_data[RESOLUTION_LOC + 3] << 8)
1088 + config_data[RESOLUTION_LOC + 2];
1089 ts->int_trigger_type = (config_data[TRIGGER_LOC]) & 0x03;
1090 }
1091 ret = gtp_send_cfg(ts);
1092 if (ret < 0)
1093 dev_err(&client->dev, "%s: Send config error.\n", __func__);
1094
1095 GTP_DEBUG("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",
1096 ts->abs_x_max, ts->abs_y_max,
1097 ts->int_trigger_type);
1098
1099 msleep(20);
1100 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001101}
1102
1103/*******************************************************
1104Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001105 Read chip version.
Andrew Huangab45aab2013-06-27 10:06:56 +00001106Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001107 client: i2c device
1108 version: buffer to keep ic firmware version
Andrew Huangab45aab2013-06-27 10:06:56 +00001109Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001110 read operation return.
1111 2: succeed, otherwise: failed
Andrew Huangab45aab2013-06-27 10:06:56 +00001112*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001113int gtp_read_version(struct i2c_client *client, u16 *version)
Andrew Huangab45aab2013-06-27 10:06:56 +00001114{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001115 int ret = -EIO;
1116 u8 buf[8] = { GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff };
Andrew Huangab45aab2013-06-27 10:06:56 +00001117
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001118 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001119
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001120 ret = gtp_i2c_read(client, buf, sizeof(buf));
1121 if (ret < 0) {
1122 dev_err(&client->dev, "GTP read version failed.\n");
1123 return ret;
1124 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001125
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001126 if (version)
1127 *version = (buf[7] << 8) | buf[6];
1128
1129 if (buf[5] == 0x00) {
1130 dev_dbg(&client->dev, "IC Version: %c%c%c_%02x%02x\n", buf[2],
1131 buf[3], buf[4], buf[7], buf[6]);
1132 } else {
1133 if (buf[5] == 'S' || buf[5] == 's')
1134 chip_gt9xxs = 1;
1135 dev_dbg(&client->dev, "IC Version: %c%c%c%c_%02x%02x\n", buf[2],
1136 buf[3], buf[4], buf[5], buf[7], buf[6]);
1137 }
1138 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001139}
1140
1141/*******************************************************
1142Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001143 I2c test Function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001144Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001145 client:i2c client.
Andrew Huangab45aab2013-06-27 10:06:56 +00001146Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001147 Executive outcomes.
1148 2: succeed, otherwise failed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001149*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001150static int gtp_i2c_test(struct i2c_client *client)
Andrew Huangab45aab2013-06-27 10:06:56 +00001151{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001152 u8 buf[3] = { GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff };
1153 int retry = 5;
1154 int ret = -EIO;
1155
1156 GTP_DEBUG_FUNC();
1157
1158 while (retry--) {
1159 ret = gtp_i2c_read(client, buf, 3);
1160 if (ret > 0)
1161 return ret;
1162 dev_err(&client->dev, "GTP i2c test failed time %d.\n", retry);
1163 msleep(20);
1164 }
1165 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001166}
1167
1168/*******************************************************
1169Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001170 Request gpio(INT & RST) ports.
Andrew Huangab45aab2013-06-27 10:06:56 +00001171Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001172 ts: private data.
Andrew Huangab45aab2013-06-27 10:06:56 +00001173Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001174 Executive outcomes.
1175 = 0: succeed, != 0: failed
Andrew Huangab45aab2013-06-27 10:06:56 +00001176*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001177static int gtp_request_io_port(struct goodix_ts_data *ts)
Andrew Huangab45aab2013-06-27 10:06:56 +00001178{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001179 struct i2c_client *client = ts->client;
1180 struct goodix_ts_platform_data *pdata = ts->pdata;
1181 int ret;
1182 if (gpio_is_valid(pdata->irq_gpio)) {
1183 ret = gpio_request(pdata->irq_gpio, "goodix_ts_irq_gpio");
1184 if (ret) {
1185 dev_err(&client->dev, "irq gpio request failed\n");
1186 goto pwr_off;
1187 }
1188 ret = gpio_direction_input(pdata->irq_gpio);
1189 if (ret) {
1190 dev_err(&client->dev,
1191 "set_direction for irq gpio failed\n");
1192 goto free_irq_gpio;
1193 }
1194 } else {
1195 dev_err(&client->dev, "irq gpio is invalid!\n");
1196 ret = -EINVAL;
1197 goto free_irq_gpio;
1198 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001199
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001200 if (gpio_is_valid(pdata->reset_gpio)) {
1201 ret = gpio_request(pdata->reset_gpio, "goodix_ts__reset_gpio");
1202 if (ret) {
1203 dev_err(&client->dev, "reset gpio request failed\n");
1204 goto free_irq_gpio;
1205 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001206
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001207 ret = gpio_direction_output(pdata->reset_gpio, 0);
1208 if (ret) {
1209 dev_err(&client->dev,
1210 "set_direction for reset gpio failed\n");
1211 goto free_reset_gpio;
1212 }
1213 } else {
1214 dev_err(&client->dev, "reset gpio is invalid!\n");
1215 ret = -EINVAL;
1216 goto free_reset_gpio;
1217 }
1218 gpio_direction_input(pdata->reset_gpio);
Andrew Huangab45aab2013-06-27 10:06:56 +00001219
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001220 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001221
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001222free_reset_gpio:
1223 if (gpio_is_valid(pdata->reset_gpio))
1224 gpio_free(pdata->reset_gpio);
1225free_irq_gpio:
1226 if (gpio_is_valid(pdata->irq_gpio))
1227 gpio_free(pdata->irq_gpio);
1228pwr_off:
1229 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001230}
1231
1232/*******************************************************
1233Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001234 Request interrupt.
Andrew Huangab45aab2013-06-27 10:06:56 +00001235Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001236 ts: private data.
Andrew Huangab45aab2013-06-27 10:06:56 +00001237Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001238 Executive outcomes.
1239 0: succeed, -1: failed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001240*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001241static int gtp_request_irq(struct goodix_ts_data *ts)
Andrew Huangab45aab2013-06-27 10:06:56 +00001242{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001243 int ret;
1244 const u8 irq_table[] = GTP_IRQ_TAB;
Andrew Huangab45aab2013-06-27 10:06:56 +00001245
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001246 GTP_DEBUG("INT trigger type:%x, irq=%d", ts->int_trigger_type,
1247 ts->client->irq);
Andrew Huangab45aab2013-06-27 10:06:56 +00001248
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001249 ret = request_irq(ts->client->irq, goodix_ts_irq_handler,
1250 irq_table[ts->int_trigger_type],
1251 ts->client->name, ts);
1252 if (ret) {
1253 dev_err(&ts->client->dev, "Request IRQ failed!ERRNO:%d.\n",
1254 ret);
1255 gpio_direction_input(ts->pdata->irq_gpio);
Andrew Huangab45aab2013-06-27 10:06:56 +00001256
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001257 hrtimer_init(&ts->timer, CLOCK_MONOTONIC,
1258 HRTIMER_MODE_REL);
1259 ts->timer.function = goodix_ts_timer_handler;
1260 hrtimer_start(&ts->timer, ktime_set(1, 0),
1261 HRTIMER_MODE_REL);
1262 ts->use_irq = false;
1263 return ret;
1264 } else {
1265 gtp_irq_disable(ts);
1266 ts->use_irq = true;
1267 return 0;
1268 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001269}
1270
1271/*******************************************************
1272Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001273 Request input device Function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001274Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001275 ts:private data.
Andrew Huangab45aab2013-06-27 10:06:56 +00001276Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001277 Executive outcomes.
1278 0: succeed, otherwise: failed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001279*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001280static int gtp_request_input_dev(struct goodix_ts_data *ts)
Andrew Huangab45aab2013-06-27 10:06:56 +00001281{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001282 int ret;
1283 char phys[PHY_BUF_SIZE];
Andrew Huangab45aab2013-06-27 10:06:56 +00001284#if GTP_HAVE_TOUCH_KEY
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001285 int index = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +00001286#endif
Andrew Huangab45aab2013-06-27 10:06:56 +00001287
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001288 GTP_DEBUG_FUNC();
1289
1290 ts->input_dev = input_allocate_device();
1291 if (ts->input_dev == NULL) {
1292 dev_err(&ts->client->dev,
1293 "Failed to allocate input device.\n");
1294 return -ENOMEM;
1295 }
1296
1297 ts->input_dev->evbit[0] =
1298 BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
Andrew Huangab45aab2013-06-27 10:06:56 +00001299#if GTP_ICS_SLOT_REPORT
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001300 __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
1301 input_mt_init_slots(ts->input_dev, 10);/* in case of "out of memory" */
Andrew Huangab45aab2013-06-27 10:06:56 +00001302#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001303 ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
Andrew Huangab45aab2013-06-27 10:06:56 +00001304#endif
1305
1306#if GTP_HAVE_TOUCH_KEY
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001307 for (index = 0; index < GTP_MAX_KEY_NUM; index++) {
1308 input_set_capability(ts->input_dev,
1309 EV_KEY, touch_key_array[index]);
1310 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001311#endif
1312
1313#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001314 input_set_capability(ts->input_dev, EV_KEY, KEY_POWER);
1315#endif
Andrew Huangab45aab2013-06-27 10:06:56 +00001316
1317#if GTP_WITH_PEN
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001318 /* pen support */
1319 __set_bit(BTN_TOOL_PEN, ts->input_dev->keybit);
1320 __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
1321 __set_bit(INPUT_PROP_POINTER, ts->input_dev->propbit);
Andrew Huangab45aab2013-06-27 10:06:56 +00001322#endif
1323
1324#if GTP_CHANGE_X2Y
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001325 GTP_SWAP(ts->abs_x_max, ts->abs_y_max);
Andrew Huangab45aab2013-06-27 10:06:56 +00001326#endif
1327
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001328 input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
1329 0, ts->abs_x_max, 0, 0);
1330 input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
1331 0, ts->abs_y_max, 0, 0);
1332 input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,
1333 0, 255, 0, 0);
1334 input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,
1335 0, 255, 0, 0);
1336 input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID,
1337 0, 255, 0, 0);
Andrew Huangab45aab2013-06-27 10:06:56 +00001338
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001339 snprintf(phys, PHY_BUF_SIZE, "input/ts");
1340 ts->input_dev->name = GOODIX_DEV_NAME;
1341 ts->input_dev->phys = phys;
1342 ts->input_dev->id.bustype = BUS_I2C;
1343 ts->input_dev->id.vendor = 0xDEAD;
1344 ts->input_dev->id.product = 0xBEEF;
1345 ts->input_dev->id.version = 10427;
Andrew Huangab45aab2013-06-27 10:06:56 +00001346
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001347 ret = input_register_device(ts->input_dev);
1348 if (ret) {
1349 dev_err(&ts->client->dev,
1350 "Register %s input device failed.\n",
1351 ts->input_dev->name);
1352 goto exit_free_inputdev;
1353 }
1354
1355 return 0;
1356
1357exit_free_inputdev:
1358 input_free_device(ts->input_dev);
1359 ts->input_dev = NULL;
1360 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001361}
1362
Bingzhe Caid0361172013-07-18 19:22:11 +08001363static int goodix_ts_get_dt_coords(struct device *dev, char *name,
1364 struct goodix_ts_platform_data *pdata)
1365{
1366 struct property *prop;
1367 struct device_node *np = dev->of_node;
1368 int rc;
1369 u32 coords[GOODIX_COORDS_ARR_SIZE];
1370
1371 prop = of_find_property(np, name, NULL);
1372 if (!prop)
1373 return -EINVAL;
1374 if (!prop->value)
1375 return -ENODATA;
1376
1377 rc = of_property_read_u32_array(np, name, coords,
1378 GOODIX_COORDS_ARR_SIZE);
1379 if (rc && (rc != -EINVAL)) {
1380 dev_err(dev, "Unable to read %s\n", name);
1381 return rc;
1382 }
1383
1384 if (!strcmp(name, "goodix,panel-coords")) {
1385 pdata->panel_minx = coords[0];
1386 pdata->panel_miny = coords[1];
1387 pdata->panel_maxx = coords[2];
1388 pdata->panel_maxy = coords[3];
1389 } else if (!strcmp(name, "goodix,display-coords")) {
1390 pdata->x_min = coords[0];
1391 pdata->y_min = coords[1];
1392 pdata->x_max = coords[2];
1393 pdata->y_max = coords[3];
1394 } else {
1395 dev_err(dev, "unsupported property %s\n", name);
1396 return -EINVAL;
1397 }
1398
1399 return 0;
1400}
1401
1402static int goodix_parse_dt(struct device *dev,
1403 struct goodix_ts_platform_data *pdata)
1404{
1405 int rc;
1406 struct device_node *np = dev->of_node;
1407 struct property *prop;
1408 u32 temp_val, num_buttons;
1409 u32 button_map[MAX_BUTTONS];
1410
1411 rc = goodix_ts_get_dt_coords(dev, "goodix,panel-coords", pdata);
1412 if (rc && (rc != -EINVAL))
1413 return rc;
1414
1415 rc = goodix_ts_get_dt_coords(dev, "goodix,display-coords", pdata);
1416 if (rc)
1417 return rc;
1418
1419 pdata->i2c_pull_up = of_property_read_bool(np,
1420 "goodix,i2c-pull-up");
1421
1422 pdata->no_force_update = of_property_read_bool(np,
1423 "goodix,no-force-update");
1424 /* reset, irq gpio info */
1425 pdata->reset_gpio = of_get_named_gpio_flags(np, "reset-gpios",
1426 0, &pdata->reset_gpio_flags);
1427 if (pdata->reset_gpio < 0)
1428 return pdata->reset_gpio;
1429
1430 pdata->irq_gpio = of_get_named_gpio_flags(np, "interrupt-gpios",
1431 0, &pdata->irq_gpio_flags);
1432 if (pdata->irq_gpio < 0)
1433 return pdata->irq_gpio;
1434
1435 rc = of_property_read_u32(np, "goodix,family-id", &temp_val);
1436 if (!rc)
1437 pdata->family_id = temp_val;
1438 else
1439 return rc;
1440
1441 prop = of_find_property(np, "goodix,button-map", NULL);
1442 if (prop) {
1443 num_buttons = prop->length / sizeof(temp_val);
1444 if (num_buttons > MAX_BUTTONS)
1445 return -EINVAL;
1446
1447 rc = of_property_read_u32_array(np,
1448 "goodix,button-map", button_map,
1449 num_buttons);
1450 if (rc) {
1451 dev_err(dev, "Unable to read key codes\n");
1452 return rc;
1453 }
1454 }
1455
1456 prop = of_find_property(np, "goodix,cfg-data", &pdata->gtp_cfg_len);
1457 if (prop && prop->value) {
1458 pdata->config_data = devm_kzalloc(dev,
1459 GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, GFP_KERNEL);
1460 if (!pdata->config_data) {
1461 dev_err(dev, "Not enough memory for panel config data\n");
1462 return -ENOMEM;
1463 }
1464
1465 pdata->config_data[0] = GTP_REG_CONFIG_DATA >> 8;
1466 pdata->config_data[1] = GTP_REG_CONFIG_DATA & 0xff;
1467 memset(&pdata->config_data[GTP_ADDR_LENGTH], 0,
1468 GTP_CONFIG_MAX_LENGTH);
1469 memcpy(&pdata->config_data[GTP_ADDR_LENGTH],
1470 prop->value, pdata->gtp_cfg_len);
1471 } else {
1472 dev_err(dev,
1473 "Unable to get configure data, default will be used.\n");
1474 pdata->gtp_cfg_len = 0;
1475 }
1476
1477 return 0;
1478}
Andrew Huangab45aab2013-06-27 10:06:56 +00001479/*******************************************************
1480Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001481 I2c probe.
Andrew Huangab45aab2013-06-27 10:06:56 +00001482Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001483 client: i2c device struct.
1484 id: device id.
Andrew Huangab45aab2013-06-27 10:06:56 +00001485Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001486 Executive outcomes.
1487 0: succeed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001488*******************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001489
1490static int goodix_ts_probe(struct i2c_client *client,
1491 const struct i2c_device_id *id)
Andrew Huangab45aab2013-06-27 10:06:56 +00001492{
Bingzhe Caid0361172013-07-18 19:22:11 +08001493 struct goodix_ts_platform_data *pdata;
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001494 struct goodix_ts_data *ts;
1495 u16 version_info;
1496 int ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001497
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001498 dev_dbg(&client->dev, "GTP I2C Address: 0x%02x\n", client->addr);
Bingzhe Caid0361172013-07-18 19:22:11 +08001499 if (client->dev.of_node) {
1500 pdata = devm_kzalloc(&client->dev,
1501 sizeof(struct goodix_ts_platform_data), GFP_KERNEL);
1502 if (!pdata) {
1503 dev_err(&client->dev,
1504 "GTP Failed to allocate memory for pdata\n");
1505 return -ENOMEM;
1506 }
1507
1508 ret = goodix_parse_dt(&client->dev, pdata);
1509 if (ret)
1510 return ret;
1511 } else {
1512 pdata = client->dev.platform_data;
1513 }
1514
1515 if (!pdata) {
1516 dev_err(&client->dev, "GTP invalid pdata\n");
1517 return -EINVAL;
1518 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001519
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001520#if GTP_ESD_PROTECT
1521 i2c_connect_client = client;
1522#endif
Bingzhe Caid0361172013-07-18 19:22:11 +08001523
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001524 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1525 dev_err(&client->dev, "GTP I2C not supported\n");
1526 return -ENODEV;
1527 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001528
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001529 ts = kzalloc(sizeof(*ts), GFP_KERNEL);
1530 if (!ts) {
1531 dev_err(&client->dev, "GTP not enough memory for ts\n");
1532 return -ENOMEM;
1533 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001534
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001535 memset(ts, 0, sizeof(*ts));
1536 ts->client = client;
Bingzhe Caid0361172013-07-18 19:22:11 +08001537 ts->pdata = pdata;
1538 /* For 2.6.39 & later use spin_lock_init(&ts->irq_lock)
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001539 * For 2.6.39 & before, use ts->irq_lock = SPIN_LOCK_UNLOCKED
1540 */
1541 spin_lock_init(&ts->irq_lock);
1542 i2c_set_clientdata(client, ts);
1543
1544 ts->gtp_rawdiff_mode = 0;
1545
1546 ret = gtp_request_io_port(ts);
1547 if (ret) {
1548 dev_err(&client->dev, "GTP request IO port failed.\n");
1549 goto exit_power_off;
1550 }
1551
1552 gtp_reset_guitar(ts, 20);
1553
1554 ret = gtp_i2c_test(client);
1555 if (ret != 2) {
1556 dev_err(&client->dev, "I2C communication ERROR!\n");
1557 goto exit_free_io_port;
1558 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001559
1560#if GTP_AUTO_UPDATE
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001561 ret = gup_init_update_proc(ts);
1562 if (ret < 0) {
1563 dev_err(&client->dev,
1564 "GTP Create firmware update thread error.\n");
1565 goto exit_free_io_port;
1566 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001567#endif
Andrew Huangab45aab2013-06-27 10:06:56 +00001568
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001569 ret = gtp_init_panel(ts);
1570 if (ret < 0) {
1571 dev_err(&client->dev, "GTP init panel failed.\n");
1572 ts->abs_x_max = GTP_MAX_WIDTH;
1573 ts->abs_y_max = GTP_MAX_HEIGHT;
1574 ts->int_trigger_type = GTP_INT_TRIGGER;
1575 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001576
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001577 ret = gtp_request_input_dev(ts);
1578 if (ret) {
1579 dev_err(&client->dev, "GTP request input dev failed.\n");
1580 goto exit_free_inputdev;
1581 }
1582
1583 ts->goodix_wq = create_singlethread_workqueue("goodix_wq");
1584 INIT_WORK(&ts->work, goodix_ts_work_func);
1585
1586 ret = gtp_request_irq(ts);
1587 if (ret < 0)
1588 dev_info(&client->dev, "GTP works in polling mode.\n");
1589 else
1590 dev_info(&client->dev, "GTP works in interrupt mode.\n");
1591
1592 ret = gtp_read_version(client, &version_info);
1593 if (ret != 2) {
1594 dev_err(&client->dev, "Read version failed.\n");
1595 goto exit_free_irq;
1596 }
1597 if (ts->use_irq)
1598 gtp_irq_enable(ts);
1599
Andrew Huangab45aab2013-06-27 10:06:56 +00001600#if GTP_CREATE_WR_NODE
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001601 init_wr_node(client);
Andrew Huangab45aab2013-06-27 10:06:56 +00001602#endif
Andrew Huangab45aab2013-06-27 10:06:56 +00001603
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001604#if GTP_ESD_PROTECT
1605 gtp_esd_switch(client, SWITCH_ON);
1606#endif
1607 init_done = true;
1608 return 0;
1609exit_free_irq:
1610 if (ts->use_irq)
1611 free_irq(client->irq, ts);
1612 else
1613 hrtimer_cancel(&ts->timer);
1614 cancel_work_sync(&ts->work);
1615 flush_workqueue(ts->goodix_wq);
1616 destroy_workqueue(ts->goodix_wq);
1617
1618 input_unregister_device(ts->input_dev);
1619 if (ts->input_dev) {
1620 input_free_device(ts->input_dev);
1621 ts->input_dev = NULL;
1622 }
1623exit_free_inputdev:
1624 kfree(ts->config_data);
1625exit_free_io_port:
Bingzhe Caid0361172013-07-18 19:22:11 +08001626 if (gpio_is_valid(pdata->reset_gpio))
1627 gpio_free(pdata->reset_gpio);
1628 if (gpio_is_valid(pdata->irq_gpio))
1629 gpio_free(pdata->irq_gpio);
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001630exit_power_off:
1631 i2c_set_clientdata(client, NULL);
1632 kfree(ts);
1633 return ret;
1634}
Andrew Huangab45aab2013-06-27 10:06:56 +00001635
1636/*******************************************************
1637Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001638 Goodix touchscreen driver release function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001639Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001640 client: i2c device struct.
Andrew Huangab45aab2013-06-27 10:06:56 +00001641Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001642 Executive outcomes. 0---succeed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001643*******************************************************/
1644static int goodix_ts_remove(struct i2c_client *client)
1645{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001646 struct goodix_ts_data *ts = i2c_get_clientdata(client);
1647
1648 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001649#ifdef CONFIG_HAS_EARLYSUSPEND
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001650 unregister_early_suspend(&ts->early_suspend);
Andrew Huangab45aab2013-06-27 10:06:56 +00001651#endif
1652
1653#if GTP_CREATE_WR_NODE
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001654 uninit_wr_node();
Andrew Huangab45aab2013-06-27 10:06:56 +00001655#endif
1656
1657#if GTP_ESD_PROTECT
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001658 cancel_work_sync(gtp_esd_check_workqueue);
1659 flush_workqueue(gtp_esd_check_workqueue);
1660 destroy_workqueue(gtp_esd_check_workqueue);
Andrew Huangab45aab2013-06-27 10:06:56 +00001661#endif
1662
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001663 if (ts) {
1664 if (ts->use_irq)
1665 free_irq(client->irq, ts);
1666 else
1667 hrtimer_cancel(&ts->timer);
Andrew Huangab45aab2013-06-27 10:06:56 +00001668
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001669 cancel_work_sync(&ts->work);
1670 flush_workqueue(ts->goodix_wq);
1671 destroy_workqueue(ts->goodix_wq);
1672
1673 input_unregister_device(ts->input_dev);
1674 if (ts->input_dev) {
1675 input_free_device(ts->input_dev);
1676 ts->input_dev = NULL;
1677 }
1678 kfree(ts->config_data);
1679
1680 if (gpio_is_valid(ts->pdata->reset_gpio))
1681 gpio_free(ts->pdata->reset_gpio);
1682 if (gpio_is_valid(ts->pdata->irq_gpio))
1683 gpio_free(ts->pdata->irq_gpio);
1684
1685 i2c_set_clientdata(client, NULL);
1686 kfree(ts);
1687 }
1688
1689 return 0;
Andrew Huangab45aab2013-06-27 10:06:56 +00001690}
1691
1692#ifdef CONFIG_HAS_EARLYSUSPEND
1693/*******************************************************
1694Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001695 Early suspend function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001696Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001697 h: early_suspend struct.
Andrew Huangab45aab2013-06-27 10:06:56 +00001698Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001699 None.
Andrew Huangab45aab2013-06-27 10:06:56 +00001700*******************************************************/
1701static void goodix_ts_early_suspend(struct early_suspend *h)
1702{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001703 struct goodix_ts_data *ts;
1704 s8 ret = -1;
1705 ts = container_of(h, struct goodix_ts_data, early_suspend);
1706
1707 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001708
1709#if GTP_ESD_PROTECT
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001710 ts->gtp_is_suspend = 1;
1711 gtp_esd_switch(ts->client, SWITCH_OFF);
Andrew Huangab45aab2013-06-27 10:06:56 +00001712#endif
1713
1714#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001715 ret = gtp_enter_doze(ts);
Andrew Huangab45aab2013-06-27 10:06:56 +00001716#else
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001717 if (ts->use_irq)
1718 gtp_irq_disable(ts);
1719 else
1720 hrtimer_cancel(&ts->timer);
1721 ret = gtp_enter_sleep(ts);
1722#endif
1723 if (ret < 0)
1724 dev_err(&ts->client->dev, "GTP early suspend failed.\n");
1725 /* to avoid waking up while not sleeping,
1726 * delay 48 + 10ms to ensure reliability
1727 */
1728 msleep(58);
Andrew Huangab45aab2013-06-27 10:06:56 +00001729}
1730
1731/*******************************************************
1732Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001733 Late resume function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001734Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001735 h: early_suspend struct.
Andrew Huangab45aab2013-06-27 10:06:56 +00001736Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001737 None.
Andrew Huangab45aab2013-06-27 10:06:56 +00001738*******************************************************/
1739static void goodix_ts_late_resume(struct early_suspend *h)
1740{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001741 struct goodix_ts_data *ts;
1742 s8 ret = -1;
1743 ts = container_of(h, struct goodix_ts_data, early_suspend);
1744
1745 GTP_DEBUG_FUNC();
1746
1747 ret = gtp_wakeup_sleep(ts);
Andrew Huangab45aab2013-06-27 10:06:56 +00001748
1749#if GTP_SLIDE_WAKEUP
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001750 doze_status = DOZE_DISABLED;
Andrew Huangab45aab2013-06-27 10:06:56 +00001751#endif
1752
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001753 if (ret < 0)
1754 dev_err(&ts->client->dev, "GTP later resume failed.\n");
Andrew Huangab45aab2013-06-27 10:06:56 +00001755
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001756 if (ts->use_irq)
1757 gtp_irq_enable(ts);
1758 else
1759 hrtimer_start(&ts->timer,
1760 ktime_set(1, 0), HRTIMER_MODE_REL);
Andrew Huangab45aab2013-06-27 10:06:56 +00001761
1762#if GTP_ESD_PROTECT
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001763 ts->gtp_is_suspend = 0;
1764 gtp_esd_switch(ts->client, SWITCH_ON);
Andrew Huangab45aab2013-06-27 10:06:56 +00001765#endif
1766}
1767#endif
1768
1769#if GTP_ESD_PROTECT
1770/*******************************************************
1771Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001772 switch on & off esd delayed work
Andrew Huangab45aab2013-06-27 10:06:56 +00001773Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001774 client: i2c device
1775 on: SWITCH_ON / SWITCH_OFF
Andrew Huangab45aab2013-06-27 10:06:56 +00001776Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001777 void
Andrew Huangab45aab2013-06-27 10:06:56 +00001778*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001779void gtp_esd_switch(struct i2c_client *client, int on)
Andrew Huangab45aab2013-06-27 10:06:56 +00001780{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001781 struct goodix_ts_data *ts;
1782
1783 ts = i2c_get_clientdata(client);
1784 if (SWITCH_ON == on) {
1785 /* switch on esd */
1786 if (!ts->esd_running) {
1787 ts->esd_running = 1;
1788 dev_dbg(&client->dev, "Esd started\n");
1789 queue_delayed_work(gtp_esd_check_workqueue,
1790 &gtp_esd_check_work, GTP_ESD_CHECK_CIRCLE);
1791 }
1792 } else {
1793 /* switch off esd */
1794 if (ts->esd_running) {
1795 ts->esd_running = 0;
1796 dev_dbg(&client->dev, "Esd cancelled\n");
1797 cancel_delayed_work_sync(&gtp_esd_check_work);
1798 }
1799 }
Andrew Huangab45aab2013-06-27 10:06:56 +00001800}
1801
1802/*******************************************************
1803Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001804 Initialize external watchdog for esd protect
Andrew Huangab45aab2013-06-27 10:06:56 +00001805Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001806 client: i2c device.
Andrew Huangab45aab2013-06-27 10:06:56 +00001807Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001808 result of i2c write operation.
1809 1: succeed, otherwise: failed
Andrew Huangab45aab2013-06-27 10:06:56 +00001810*********************************************************/
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001811static int gtp_init_ext_watchdog(struct i2c_client *client)
Andrew Huangab45aab2013-06-27 10:06:56 +00001812{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001813 /* in case of recursively reset by calling gtp_i2c_write*/
1814 struct i2c_msg msg;
1815 u8 opr_buffer[4] = {0x80, 0x40, 0xAA, 0xAA};
1816 int ret;
1817 int retries = 0;
Andrew Huangab45aab2013-06-27 10:06:56 +00001818
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001819 GTP_DEBUG("Init external watchdog...");
1820 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001821
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001822 msg.flags = !I2C_M_RD;
1823 msg.addr = client->addr;
1824 msg.len = 4;
1825 msg.buf = opr_buffer;
Andrew Huangab45aab2013-06-27 10:06:56 +00001826
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001827 while (retries < 5) {
1828 ret = i2c_transfer(client->adapter, &msg, 1);
1829 if (ret == 1)
1830 return 1;
1831 retries++;
1832 }
1833 if (retries >= 5)
1834 dev_err(&client->dev, "init external watchdog failed!");
1835 return 0;
Andrew Huangab45aab2013-06-27 10:06:56 +00001836}
1837
1838/*******************************************************
1839Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001840 Esd protect function.
1841 Added external watchdog by meta, 2013/03/07
Andrew Huangab45aab2013-06-27 10:06:56 +00001842Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001843 work: delayed work
Andrew Huangab45aab2013-06-27 10:06:56 +00001844Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001845 None.
Andrew Huangab45aab2013-06-27 10:06:56 +00001846*******************************************************/
1847static void gtp_esd_check_func(struct work_struct *work)
1848{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001849 s32 i;
1850 s32 ret = -1;
1851 struct goodix_ts_data *ts = NULL;
1852 u8 test[4] = {0x80, 0x40};
Andrew Huangab45aab2013-06-27 10:06:56 +00001853
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001854 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001855
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001856 ts = i2c_get_clientdata(i2c_connect_client);
1857
1858 if (ts->gtp_is_suspend) {
1859 dev_dbg(&ts->client->dev, "Esd terminated!\n");
1860 ts->esd_running = 0;
1861 return;
1862 }
1863#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
1864 if (ts->enter_update)
1865 return;
1866#endif
1867
1868 for (i = 0; i < 3; i++) {
1869 ret = gtp_i2c_read(ts->client, test, 4);
1870
1871 GTP_DEBUG("0x8040 = 0x%02X, 0x8041 = 0x%02X", test[2], test[3]);
1872 if ((ret < 0)) {
1873 /* IC works abnormally..*/
1874 continue;
1875 } else {
1876 if ((test[2] == 0xAA) || (test[3] != 0xAA)) {
1877 /* IC works abnormally..*/
1878 i = 3;
1879 break;
1880 } else {
1881 /* IC works normally, Write 0x8040 0xAA*/
1882 test[2] = 0xAA;
1883 gtp_i2c_write(ts->client, test, 3);
1884 break;
1885 }
1886 }
1887 }
1888 if (i >= 3) {
1889 dev_err(&ts->client->dev,
1890 "IC Working ABNORMALLY, Resetting Guitar...\n");
1891 gtp_reset_guitar(ts, 50);
1892 }
1893
1894 if (!ts->gtp_is_suspend)
1895 queue_delayed_work(gtp_esd_check_workqueue,
1896 &gtp_esd_check_work, GTP_ESD_CHECK_CIRCLE);
1897 else {
1898 dev_dbg(&ts->client->dev, "Esd terminated!\n");
1899 ts->esd_running = 0;
1900 }
1901
1902 return;
Andrew Huangab45aab2013-06-27 10:06:56 +00001903}
1904#endif
1905
1906static const struct i2c_device_id goodix_ts_id[] = {
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001907 { GTP_I2C_NAME, 0 },
1908 { }
Andrew Huangab45aab2013-06-27 10:06:56 +00001909};
1910
Bingzhe Caid0361172013-07-18 19:22:11 +08001911static struct of_device_id goodix_match_table[] = {
1912 { .compatible = "goodix,gt9xx", },
1913 { },
1914};
1915
Andrew Huangab45aab2013-06-27 10:06:56 +00001916static struct i2c_driver goodix_ts_driver = {
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001917 .probe = goodix_ts_probe,
1918 .remove = goodix_ts_remove,
1919#ifdef CONFIG_HAS_EARLYSUSPEND
1920 .suspend = goodix_ts_early_suspend,
1921 .resume = goodix_ts_late_resume,
Andrew Huangab45aab2013-06-27 10:06:56 +00001922#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001923 .id_table = goodix_ts_id,
1924 .driver = {
1925 .name = GTP_I2C_NAME,
1926 .owner = THIS_MODULE,
Bingzhe Caid0361172013-07-18 19:22:11 +08001927 .of_match_table = goodix_match_table,
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001928 },
Andrew Huangab45aab2013-06-27 10:06:56 +00001929};
1930
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001931/*******************************************************
Andrew Huangab45aab2013-06-27 10:06:56 +00001932Function:
1933 Driver Install function.
1934Input:
1935 None.
1936Output:
1937 Executive Outcomes. 0---succeed.
1938********************************************************/
1939static int __devinit goodix_ts_init(void)
1940{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001941 int ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001942
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001943 GTP_DEBUG_FUNC();
Andrew Huangab45aab2013-06-27 10:06:56 +00001944#if GTP_ESD_PROTECT
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001945 INIT_DELAYED_WORK(&gtp_esd_check_work, gtp_esd_check_func);
1946 gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");
Andrew Huangab45aab2013-06-27 10:06:56 +00001947#endif
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001948 ret = i2c_add_driver(&goodix_ts_driver);
1949 return ret;
Andrew Huangab45aab2013-06-27 10:06:56 +00001950}
1951
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001952/*******************************************************
Andrew Huangab45aab2013-06-27 10:06:56 +00001953Function:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001954 Driver uninstall function.
Andrew Huangab45aab2013-06-27 10:06:56 +00001955Input:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001956 None.
Andrew Huangab45aab2013-06-27 10:06:56 +00001957Output:
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001958 Executive Outcomes. 0---succeed.
Andrew Huangab45aab2013-06-27 10:06:56 +00001959********************************************************/
1960static void __exit goodix_ts_exit(void)
1961{
Bingzhe Cai83caeea2013-07-16 17:57:37 +08001962 GTP_DEBUG_FUNC();
1963 i2c_del_driver(&goodix_ts_driver);
Andrew Huangab45aab2013-06-27 10:06:56 +00001964}
1965
1966late_initcall(goodix_ts_init);
1967module_exit(goodix_ts_exit);
1968
1969MODULE_DESCRIPTION("GTP Series Driver");
1970MODULE_LICENSE("GPL");