blob: 5b594bc01da4a1779e4befb9aa68af5358c2c3d0 [file] [log] [blame]
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001/*
Iiro Valkonen7686b102011-02-02 23:21:58 -08002 * Atmel maXTouch Touchscreen driver
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003 *
4 * Copyright (C) 2010 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
Jing Lin2f863172011-10-17 10:56:58 -07006 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07007 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/firmware.h>
19#include <linux/i2c.h>
Dmitry Torokhov964de522011-02-02 23:21:58 -080020#include <linux/i2c/atmel_mxt_ts.h>
Amy Maloche2b59bab2011-10-13 16:08:16 -070021#include <linux/input.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070022#include <linux/interrupt.h>
23#include <linux/slab.h>
Amy Maloche08266db2011-11-04 11:07:16 -070024#include <linux/gpio.h>
Anirudh Ghayala498e4d2011-08-09 19:10:12 +053025#include <linux/regulator/consumer.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070026
Anirudh Ghayal253ce122011-08-09 19:32:57 +053027#if defined(CONFIG_HAS_EARLYSUSPEND)
28#include <linux/earlysuspend.h>
29/* Early-suspend level */
30#define MXT_SUSPEND_LEVEL 1
31#endif
32
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070033/* Family ID */
34#define MXT224_ID 0x80
Amy Maloche380cc0b2011-11-03 12:55:04 -070035#define MXT224E_ID 0x81
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070036#define MXT1386_ID 0xA0
37
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070038/* Version */
Iiro Valkonen7686b102011-02-02 23:21:58 -080039#define MXT_VER_20 20
40#define MXT_VER_21 21
41#define MXT_VER_22 22
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070042
43/* Slave addresses */
Iiro Valkonen7686b102011-02-02 23:21:58 -080044#define MXT_APP_LOW 0x4a
45#define MXT_APP_HIGH 0x4b
46#define MXT_BOOT_LOW 0x24
47#define MXT_BOOT_HIGH 0x25
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070048
49/* Firmware */
Iiro Valkonen7686b102011-02-02 23:21:58 -080050#define MXT_FW_NAME "maxtouch.fw"
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070051
52/* Registers */
Iiro Valkonen7686b102011-02-02 23:21:58 -080053#define MXT_FAMILY_ID 0x00
54#define MXT_VARIANT_ID 0x01
55#define MXT_VERSION 0x02
56#define MXT_BUILD 0x03
57#define MXT_MATRIX_X_SIZE 0x04
58#define MXT_MATRIX_Y_SIZE 0x05
59#define MXT_OBJECT_NUM 0x06
60#define MXT_OBJECT_START 0x07
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070061
Iiro Valkonen7686b102011-02-02 23:21:58 -080062#define MXT_OBJECT_SIZE 6
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070063
64/* Object types */
Iiro Valkonene8645592011-11-18 12:56:19 -080065#define MXT_DEBUG_DIAGNOSTIC_T37 37
66#define MXT_GEN_MESSAGE_T5 5
67#define MXT_GEN_COMMAND_T6 6
68#define MXT_GEN_POWER_T7 7
69#define MXT_GEN_ACQUIRE_T8 8
70#define MXT_GEN_DATASOURCE_T53 53
71#define MXT_TOUCH_MULTI_T9 9
72#define MXT_TOUCH_KEYARRAY_T15 15
73#define MXT_TOUCH_PROXIMITY_T23 23
74#define MXT_TOUCH_PROXKEY_T52 52
75#define MXT_PROCI_GRIPFACE_T20 20
76#define MXT_PROCG_NOISE_T22 22
77#define MXT_PROCI_ONETOUCH_T24 24
78#define MXT_PROCI_TWOTOUCH_T27 27
79#define MXT_PROCI_GRIP_T40 40
80#define MXT_PROCI_PALM_T41 41
81#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
82#define MXT_PROCI_STYLUS_T47 47
83#define MXT_PROCG_NOISESUPPRESSION_T48 48
84#define MXT_SPT_COMMSCONFIG_T18 18
85#define MXT_SPT_GPIOPWM_T19 19
86#define MXT_SPT_SELFTEST_T25 25
87#define MXT_SPT_CTECONFIG_T28 28
88#define MXT_SPT_USERDATA_T38 38
89#define MXT_SPT_DIGITIZER_T43 43
90#define MXT_SPT_MESSAGECOUNT_T44 44
91#define MXT_SPT_CTECONFIG_T46 46
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070092
Iiro Valkonene8645592011-11-18 12:56:19 -080093/* MXT_GEN_COMMAND_T6 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -080094#define MXT_COMMAND_RESET 0
95#define MXT_COMMAND_BACKUPNV 1
96#define MXT_COMMAND_CALIBRATE 2
97#define MXT_COMMAND_REPORTALL 3
98#define MXT_COMMAND_DIAGNOSTIC 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070099
Iiro Valkonene8645592011-11-18 12:56:19 -0800100/* MXT_GEN_POWER_T7 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800101#define MXT_POWER_IDLEACQINT 0
102#define MXT_POWER_ACTVACQINT 1
103#define MXT_POWER_ACTV2IDLETO 2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700104
Iiro Valkonene8645592011-11-18 12:56:19 -0800105/* MXT_GEN_ACQUIRE_T8 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800106#define MXT_ACQUIRE_CHRGTIME 0
107#define MXT_ACQUIRE_TCHDRIFT 2
108#define MXT_ACQUIRE_DRIFTST 3
109#define MXT_ACQUIRE_TCHAUTOCAL 4
110#define MXT_ACQUIRE_SYNC 5
111#define MXT_ACQUIRE_ATCHCALST 6
112#define MXT_ACQUIRE_ATCHCALSTHR 7
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700113
Iiro Valkonene8645592011-11-18 12:56:19 -0800114/* MXT_TOUCH_MULT_T9 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800115#define MXT_TOUCH_CTRL 0
116#define MXT_TOUCH_XORIGIN 1
117#define MXT_TOUCH_YORIGIN 2
118#define MXT_TOUCH_XSIZE 3
119#define MXT_TOUCH_YSIZE 4
120#define MXT_TOUCH_BLEN 6
121#define MXT_TOUCH_TCHTHR 7
122#define MXT_TOUCH_TCHDI 8
123#define MXT_TOUCH_ORIENT 9
124#define MXT_TOUCH_MOVHYSTI 11
125#define MXT_TOUCH_MOVHYSTN 12
126#define MXT_TOUCH_NUMTOUCH 14
127#define MXT_TOUCH_MRGHYST 15
128#define MXT_TOUCH_MRGTHR 16
129#define MXT_TOUCH_AMPHYST 17
130#define MXT_TOUCH_XRANGE_LSB 18
131#define MXT_TOUCH_XRANGE_MSB 19
132#define MXT_TOUCH_YRANGE_LSB 20
133#define MXT_TOUCH_YRANGE_MSB 21
134#define MXT_TOUCH_XLOCLIP 22
135#define MXT_TOUCH_XHICLIP 23
136#define MXT_TOUCH_YLOCLIP 24
137#define MXT_TOUCH_YHICLIP 25
138#define MXT_TOUCH_XEDGECTRL 26
139#define MXT_TOUCH_XEDGEDIST 27
140#define MXT_TOUCH_YEDGECTRL 28
141#define MXT_TOUCH_YEDGEDIST 29
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700142#define MXT_TOUCH_JUMPLIMIT 30
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700143
Iiro Valkonene8645592011-11-18 12:56:19 -0800144/* MXT_PROCI_GRIPFACE_T20 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800145#define MXT_GRIPFACE_CTRL 0
146#define MXT_GRIPFACE_XLOGRIP 1
147#define MXT_GRIPFACE_XHIGRIP 2
148#define MXT_GRIPFACE_YLOGRIP 3
149#define MXT_GRIPFACE_YHIGRIP 4
150#define MXT_GRIPFACE_MAXTCHS 5
151#define MXT_GRIPFACE_SZTHR1 7
152#define MXT_GRIPFACE_SZTHR2 8
153#define MXT_GRIPFACE_SHPTHR1 9
154#define MXT_GRIPFACE_SHPTHR2 10
155#define MXT_GRIPFACE_SUPEXTTO 11
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700156
Iiro Valkonen7686b102011-02-02 23:21:58 -0800157/* MXT_PROCI_NOISE field */
158#define MXT_NOISE_CTRL 0
159#define MXT_NOISE_OUTFLEN 1
160#define MXT_NOISE_GCAFUL_LSB 3
161#define MXT_NOISE_GCAFUL_MSB 4
162#define MXT_NOISE_GCAFLL_LSB 5
163#define MXT_NOISE_GCAFLL_MSB 6
164#define MXT_NOISE_ACTVGCAFVALID 7
165#define MXT_NOISE_NOISETHR 8
166#define MXT_NOISE_FREQHOPSCALE 10
167#define MXT_NOISE_FREQ0 11
168#define MXT_NOISE_FREQ1 12
169#define MXT_NOISE_FREQ2 13
170#define MXT_NOISE_FREQ3 14
171#define MXT_NOISE_FREQ4 15
172#define MXT_NOISE_IDLEGCAFVALID 16
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700173
Iiro Valkonene8645592011-11-18 12:56:19 -0800174/* MXT_SPT_COMMSCONFIG_T18 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800175#define MXT_COMMS_CTRL 0
176#define MXT_COMMS_CMD 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700177
Iiro Valkonene8645592011-11-18 12:56:19 -0800178/* MXT_SPT_CTECONFIG_T28 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800179#define MXT_CTE_CTRL 0
180#define MXT_CTE_CMD 1
181#define MXT_CTE_MODE 2
182#define MXT_CTE_IDLEGCAFDEPTH 3
183#define MXT_CTE_ACTVGCAFDEPTH 4
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700184#define MXT_CTE_VOLTAGE 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700185
Iiro Valkonen7686b102011-02-02 23:21:58 -0800186#define MXT_VOLTAGE_DEFAULT 2700000
187#define MXT_VOLTAGE_STEP 10000
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700188
Amy Maloche21115eb2011-11-02 09:04:37 -0700189/* Analog voltage @2.7 V */
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530190#define MXT_VTG_MIN_UV 2700000
191#define MXT_VTG_MAX_UV 3300000
192#define MXT_ACTIVE_LOAD_UA 15000
Jing Linbace50b2011-10-18 22:55:47 -0700193#define MXT_LPM_LOAD_UA 10
Amy Maloche21115eb2011-11-02 09:04:37 -0700194/* Digital voltage @1.8 V */
195#define MXT_VTG_DIG_MIN_UV 1800000
196#define MXT_VTG_DIG_MAX_UV 1800000
197#define MXT_ACTIVE_LOAD_DIG_UA 10000
198#define MXT_LPM_LOAD_DIG_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530199
200#define MXT_I2C_VTG_MIN_UV 1800000
201#define MXT_I2C_VTG_MAX_UV 1800000
202#define MXT_I2C_LOAD_UA 10000
Jing Linbace50b2011-10-18 22:55:47 -0700203#define MXT_I2C_LPM_LOAD_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530204
Iiro Valkonene8645592011-11-18 12:56:19 -0800205/* Define for MXT_GEN_COMMAND_T6 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800206#define MXT_BOOT_VALUE 0xa5
207#define MXT_BACKUP_VALUE 0x55
208#define MXT_BACKUP_TIME 25 /* msec */
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700209#define MXT224_RESET_TIME 65 /* msec */
Amy Maloche380cc0b2011-11-03 12:55:04 -0700210#define MXT224E_RESET_TIME 22 /* msec */
Amy Maloche7e447432011-09-14 11:36:30 -0700211#define MXT1386_RESET_TIME 250 /* msec */
212#define MXT_RESET_TIME 250 /* msec */
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700213#define MXT_RESET_NOCHGREAD 400 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700214
Iiro Valkonen7686b102011-02-02 23:21:58 -0800215#define MXT_FWRESET_TIME 175 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700216
Jing Lin36aee812011-10-17 17:17:28 -0700217#define MXT_WAKE_TIME 25
218
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700219/* Command to unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800220#define MXT_UNLOCK_CMD_MSB 0xaa
221#define MXT_UNLOCK_CMD_LSB 0xdc
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700222
223/* Bootloader mode status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800224#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
225#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
226#define MXT_FRAME_CRC_CHECK 0x02
227#define MXT_FRAME_CRC_FAIL 0x03
228#define MXT_FRAME_CRC_PASS 0x04
229#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
230#define MXT_BOOT_STATUS_MASK 0x3f
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700231
232/* Touch status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800233#define MXT_SUPPRESS (1 << 1)
234#define MXT_AMP (1 << 2)
235#define MXT_VECTOR (1 << 3)
236#define MXT_MOVE (1 << 4)
237#define MXT_RELEASE (1 << 5)
238#define MXT_PRESS (1 << 6)
239#define MXT_DETECT (1 << 7)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700240
Joonyoung Shim910d8052011-04-12 23:14:38 -0700241/* Touch orient bits */
242#define MXT_XY_SWITCH (1 << 0)
243#define MXT_X_INVERT (1 << 1)
244#define MXT_Y_INVERT (1 << 2)
245
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700246/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800247#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700248
Iiro Valkonen7686b102011-02-02 23:21:58 -0800249#define MXT_MAX_FINGER 10
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700250
Jing Lin36aee812011-10-17 17:17:28 -0700251#define T7_DATA_SIZE 3
252#define MXT_MAX_RW_TRIES 3
253#define MXT_BLOCK_SIZE 256
Mohan Pallakaab51f2b2011-09-29 18:17:35 +0530254
Iiro Valkonen7686b102011-02-02 23:21:58 -0800255struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700256 u8 family_id;
257 u8 variant_id;
258 u8 version;
259 u8 build;
260 u8 matrix_xsize;
261 u8 matrix_ysize;
262 u8 object_num;
263};
264
Iiro Valkonen7686b102011-02-02 23:21:58 -0800265struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700266 u8 type;
267 u16 start_address;
268 u8 size;
269 u8 instances;
270 u8 num_report_ids;
271
272 /* to map object and message */
273 u8 max_reportid;
274};
275
Iiro Valkonen7686b102011-02-02 23:21:58 -0800276struct mxt_message {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700277 u8 reportid;
278 u8 message[7];
279 u8 checksum;
280};
281
Iiro Valkonen7686b102011-02-02 23:21:58 -0800282struct mxt_finger {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700283 int status;
284 int x;
285 int y;
286 int area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700287 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700288};
289
290/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800291struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700292 struct i2c_client *client;
293 struct input_dev *input_dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800294 const struct mxt_platform_data *pdata;
295 struct mxt_object *object_table;
296 struct mxt_info info;
297 struct mxt_finger finger[MXT_MAX_FINGER];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700298 unsigned int irq;
Amy Maloche21115eb2011-11-02 09:04:37 -0700299 struct regulator *vcc_ana;
300 struct regulator *vcc_dig;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530301 struct regulator *vcc_i2c;
Anirudh Ghayal253ce122011-08-09 19:32:57 +0530302#if defined(CONFIG_HAS_EARLYSUSPEND)
303 struct early_suspend early_suspend;
304#endif
Jing Lin36aee812011-10-17 17:17:28 -0700305
Amy Maloche52262212011-09-15 16:46:57 -0700306 u8 t7_data[T7_DATA_SIZE];
Jing Lin36aee812011-10-17 17:17:28 -0700307 u16 t7_start_addr;
Amy Maloche52262212011-09-15 16:46:57 -0700308 u8 t9_ctrl;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700309};
310
Iiro Valkonen7686b102011-02-02 23:21:58 -0800311static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700312{
313 switch (type) {
Iiro Valkonene8645592011-11-18 12:56:19 -0800314 case MXT_GEN_MESSAGE_T5:
315 case MXT_GEN_COMMAND_T6:
316 case MXT_GEN_POWER_T7:
317 case MXT_GEN_ACQUIRE_T8:
318 case MXT_GEN_DATASOURCE_T53:
319 case MXT_TOUCH_MULTI_T9:
320 case MXT_TOUCH_KEYARRAY_T15:
321 case MXT_TOUCH_PROXIMITY_T23:
322 case MXT_TOUCH_PROXKEY_T52:
323 case MXT_PROCI_GRIPFACE_T20:
324 case MXT_PROCG_NOISE_T22:
325 case MXT_PROCI_ONETOUCH_T24:
326 case MXT_PROCI_TWOTOUCH_T27:
327 case MXT_PROCI_GRIP_T40:
328 case MXT_PROCI_PALM_T41:
329 case MXT_PROCI_TOUCHSUPPRESSION_T42:
330 case MXT_PROCI_STYLUS_T47:
331 case MXT_PROCG_NOISESUPPRESSION_T48:
332 case MXT_SPT_COMMSCONFIG_T18:
333 case MXT_SPT_GPIOPWM_T19:
334 case MXT_SPT_SELFTEST_T25:
335 case MXT_SPT_CTECONFIG_T28:
336 case MXT_SPT_USERDATA_T38:
337 case MXT_SPT_DIGITIZER_T43:
338 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700339 return true;
340 default:
341 return false;
342 }
343}
344
Iiro Valkonen7686b102011-02-02 23:21:58 -0800345static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700346{
347 switch (type) {
Iiro Valkonene8645592011-11-18 12:56:19 -0800348 case MXT_GEN_COMMAND_T6:
349 case MXT_GEN_POWER_T7:
350 case MXT_GEN_ACQUIRE_T8:
351 case MXT_TOUCH_MULTI_T9:
352 case MXT_TOUCH_KEYARRAY_T15:
353 case MXT_TOUCH_PROXIMITY_T23:
354 case MXT_TOUCH_PROXKEY_T52:
355 case MXT_PROCI_GRIPFACE_T20:
356 case MXT_PROCG_NOISE_T22:
357 case MXT_PROCI_ONETOUCH_T24:
358 case MXT_PROCI_TWOTOUCH_T27:
359 case MXT_PROCI_GRIP_T40:
360 case MXT_PROCI_PALM_T41:
361 case MXT_PROCI_TOUCHSUPPRESSION_T42:
362 case MXT_PROCI_STYLUS_T47:
363 case MXT_PROCG_NOISESUPPRESSION_T48:
364 case MXT_SPT_COMMSCONFIG_T18:
365 case MXT_SPT_GPIOPWM_T19:
366 case MXT_SPT_SELFTEST_T25:
367 case MXT_SPT_CTECONFIG_T28:
368 case MXT_SPT_USERDATA_T38:
369 case MXT_SPT_DIGITIZER_T43:
370 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700371 return true;
372 default:
373 return false;
374 }
375}
376
Iiro Valkonen7686b102011-02-02 23:21:58 -0800377static void mxt_dump_message(struct device *dev,
378 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700379{
380 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
381 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
382 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
383 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
384 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
385 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
386 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
387 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
388 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
389}
390
Iiro Valkonen7686b102011-02-02 23:21:58 -0800391static int mxt_check_bootloader(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700392 unsigned int state)
393{
394 u8 val;
395
396recheck:
397 if (i2c_master_recv(client, &val, 1) != 1) {
398 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
399 return -EIO;
400 }
401
402 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800403 case MXT_WAITING_BOOTLOAD_CMD:
404 case MXT_WAITING_FRAME_DATA:
405 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700406 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800407 case MXT_FRAME_CRC_PASS:
408 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700409 goto recheck;
410 break;
411 default:
412 return -EINVAL;
413 }
414
415 if (val != state) {
416 dev_err(&client->dev, "Unvalid bootloader mode state\n");
417 return -EINVAL;
418 }
419
420 return 0;
421}
422
Iiro Valkonen7686b102011-02-02 23:21:58 -0800423static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700424{
425 u8 buf[2];
426
Iiro Valkonen7686b102011-02-02 23:21:58 -0800427 buf[0] = MXT_UNLOCK_CMD_LSB;
428 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700429
430 if (i2c_master_send(client, buf, 2) != 2) {
431 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
432 return -EIO;
433 }
434
435 return 0;
436}
437
Iiro Valkonen7686b102011-02-02 23:21:58 -0800438static int mxt_fw_write(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700439 const u8 *data, unsigned int frame_size)
440{
441 if (i2c_master_send(client, data, frame_size) != frame_size) {
442 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
443 return -EIO;
444 }
445
446 return 0;
447}
448
Iiro Valkonen7686b102011-02-02 23:21:58 -0800449static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700450 u16 reg, u16 len, void *val)
451{
452 struct i2c_msg xfer[2];
453 u8 buf[2];
Jing Lin36aee812011-10-17 17:17:28 -0700454 int i = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700455
456 buf[0] = reg & 0xff;
457 buf[1] = (reg >> 8) & 0xff;
458
459 /* Write register */
460 xfer[0].addr = client->addr;
461 xfer[0].flags = 0;
462 xfer[0].len = 2;
463 xfer[0].buf = buf;
464
465 /* Read data */
466 xfer[1].addr = client->addr;
467 xfer[1].flags = I2C_M_RD;
468 xfer[1].len = len;
469 xfer[1].buf = val;
470
Jing Lin36aee812011-10-17 17:17:28 -0700471 do {
472 if (i2c_transfer(client->adapter, xfer, 2) == 2)
473 return 0;
474 msleep(MXT_WAKE_TIME);
475 } while (++i < MXT_MAX_RW_TRIES);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700476
Jing Lin36aee812011-10-17 17:17:28 -0700477 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
478 return -EIO;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700479}
480
Iiro Valkonen7686b102011-02-02 23:21:58 -0800481static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700482{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800483 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700484}
485
Jing Lin36aee812011-10-17 17:17:28 -0700486static int __mxt_write_reg(struct i2c_client *client,
487 u16 addr, u16 length, u8 *value)
488{
489 u8 buf[MXT_BLOCK_SIZE + 2];
490 int i, tries = 0;
491
492 if (length > MXT_BLOCK_SIZE)
493 return -EINVAL;
494
495 buf[0] = addr & 0xff;
496 buf[1] = (addr >> 8) & 0xff;
497 for (i = 0; i < length; i++)
498 buf[i + 2] = *value++;
499
500 do {
501 if (i2c_master_send(client, buf, length + 2) == (length + 2))
502 return 0;
503 msleep(MXT_WAKE_TIME);
504 } while (++tries < MXT_MAX_RW_TRIES);
505
506 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
507 return -EIO;
508}
509
Iiro Valkonen7686b102011-02-02 23:21:58 -0800510static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700511{
Jing Lin36aee812011-10-17 17:17:28 -0700512 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700513}
514
Iiro Valkonen7686b102011-02-02 23:21:58 -0800515static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700516 u16 reg, u8 *object_buf)
517{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800518 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700519 object_buf);
520}
521
Iiro Valkonen7686b102011-02-02 23:21:58 -0800522static struct mxt_object *
523mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700524{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800525 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700526 int i;
527
528 for (i = 0; i < data->info.object_num; i++) {
529 object = data->object_table + i;
530 if (object->type == type)
531 return object;
532 }
533
534 dev_err(&data->client->dev, "Invalid object type\n");
535 return NULL;
536}
537
Iiro Valkonen7686b102011-02-02 23:21:58 -0800538static int mxt_read_message(struct mxt_data *data,
539 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700540{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800541 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700542 u16 reg;
543
Iiro Valkonene8645592011-11-18 12:56:19 -0800544 object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700545 if (!object)
546 return -EINVAL;
547
548 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800549 return __mxt_read_reg(data->client, reg,
550 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700551}
552
Iiro Valkonen7686b102011-02-02 23:21:58 -0800553static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700554 u8 type, u8 offset, u8 *val)
555{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800556 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700557 u16 reg;
558
Iiro Valkonen7686b102011-02-02 23:21:58 -0800559 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700560 if (!object)
561 return -EINVAL;
562
563 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800564 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700565}
566
Iiro Valkonen7686b102011-02-02 23:21:58 -0800567static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700568 u8 type, u8 offset, u8 val)
569{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800570 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700571 u16 reg;
572
Iiro Valkonen7686b102011-02-02 23:21:58 -0800573 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700574 if (!object)
575 return -EINVAL;
576
577 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800578 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700579}
580
Iiro Valkonen7686b102011-02-02 23:21:58 -0800581static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700582{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800583 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700584 struct input_dev *input_dev = data->input_dev;
585 int status = finger[single_id].status;
586 int finger_num = 0;
587 int id;
588
Iiro Valkonen7686b102011-02-02 23:21:58 -0800589 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700590 if (!finger[id].status)
591 continue;
592
Amy Maloche2b59bab2011-10-13 16:08:16 -0700593 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
594 finger[id].status != MXT_RELEASE ?
595 finger[id].area : 0);
596 input_report_abs(input_dev, ABS_MT_POSITION_X,
597 finger[id].x);
598 input_report_abs(input_dev, ABS_MT_POSITION_Y,
599 finger[id].y);
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700600 input_report_abs(input_dev, ABS_MT_PRESSURE,
601 finger[id].pressure);
Amy Maloche2b59bab2011-10-13 16:08:16 -0700602 input_mt_sync(input_dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700603
Amy Maloche2b59bab2011-10-13 16:08:16 -0700604 if (finger[id].status == MXT_RELEASE)
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700605 finger[id].status = 0;
Amy Maloche2b59bab2011-10-13 16:08:16 -0700606 else
607 finger_num++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700608 }
609
610 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
611
Iiro Valkonen7686b102011-02-02 23:21:58 -0800612 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700613 input_report_abs(input_dev, ABS_X, finger[single_id].x);
614 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700615 input_report_abs(input_dev,
616 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700617 }
618
619 input_sync(input_dev);
620}
621
Iiro Valkonen7686b102011-02-02 23:21:58 -0800622static void mxt_input_touchevent(struct mxt_data *data,
623 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700624{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800625 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700626 struct device *dev = &data->client->dev;
627 u8 status = message->message[0];
628 int x;
629 int y;
630 int area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700631 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700632
633 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800634 if (!(status & MXT_DETECT)) {
635 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700636 dev_dbg(dev, "[%d] released\n", id);
637
Iiro Valkonen7686b102011-02-02 23:21:58 -0800638 finger[id].status = MXT_RELEASE;
639 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700640 }
641 return;
642 }
643
644 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800645 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700646 return;
647
Joonyoung Shim910d8052011-04-12 23:14:38 -0700648 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
649 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Jing Lin2f863172011-10-17 10:56:58 -0700650 if (data->pdata->x_size < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700651 x = x >> 2;
Jing Lin2f863172011-10-17 10:56:58 -0700652 if (data->pdata->y_size < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700653 y = y >> 2;
654
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700655 area = message->message[4];
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700656 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700657
658 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800659 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700660 x, y, area);
661
Iiro Valkonen7686b102011-02-02 23:21:58 -0800662 finger[id].status = status & MXT_MOVE ?
663 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700664 finger[id].x = x;
665 finger[id].y = y;
666 finger[id].area = area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700667 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700668
Iiro Valkonen7686b102011-02-02 23:21:58 -0800669 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700670}
671
Iiro Valkonen7686b102011-02-02 23:21:58 -0800672static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700673{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800674 struct mxt_data *data = dev_id;
675 struct mxt_message message;
676 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700677 struct device *dev = &data->client->dev;
678 int id;
679 u8 reportid;
680 u8 max_reportid;
681 u8 min_reportid;
682
683 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800684 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700685 dev_err(dev, "Failed to read message\n");
686 goto end;
687 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700688 reportid = message.reportid;
689
Iiro Valkonene8645592011-11-18 12:56:19 -0800690 /* whether reportid is thing of MXT_TOUCH_MULTI_T9 */
691 object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700692 if (!object)
693 goto end;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700694 max_reportid = object->max_reportid;
695 min_reportid = max_reportid - object->num_report_ids + 1;
696 id = reportid - min_reportid;
697
698 if (reportid >= min_reportid && reportid <= max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -0800699 mxt_input_touchevent(data, &message, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700700 else
Iiro Valkonen7686b102011-02-02 23:21:58 -0800701 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700702 } while (reportid != 0xff);
703
704end:
705 return IRQ_HANDLED;
706}
707
Iiro Valkonen7686b102011-02-02 23:21:58 -0800708static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700709{
Iiro Valkonen71749f52011-02-15 13:36:52 -0800710 const struct mxt_platform_data *pdata = data->pdata;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800711 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700712 struct device *dev = &data->client->dev;
713 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -0800714 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700715
Iiro Valkonen71749f52011-02-15 13:36:52 -0800716 if (!pdata->config) {
717 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
718 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700719 }
720
721 for (i = 0; i < data->info.object_num; i++) {
722 object = data->object_table + i;
723
Iiro Valkonen7686b102011-02-02 23:21:58 -0800724 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700725 continue;
726
Iiro Valkonen71749f52011-02-15 13:36:52 -0800727 for (j = 0; j < object->size + 1; j++) {
728 config_offset = index + j;
729 if (config_offset > pdata->config_length) {
730 dev_err(dev, "Not enough config data!\n");
731 return -EINVAL;
732 }
Iiro Valkonen7686b102011-02-02 23:21:58 -0800733 mxt_write_object(data, object->type, j,
Iiro Valkonen71749f52011-02-15 13:36:52 -0800734 pdata->config[config_offset]);
735 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700736 index += object->size + 1;
737 }
738
739 return 0;
740}
741
Iiro Valkonen7686b102011-02-02 23:21:58 -0800742static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700743{
744 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800745 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700746 int count = 10;
747 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700748
749 /* Read dummy message to make high CHG pin */
750 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800751 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700752 if (error)
753 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800754 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700755
756 if (!count) {
757 dev_err(dev, "CHG pin isn't cleared\n");
758 return -EBUSY;
759 }
760
761 return 0;
762}
763
Iiro Valkonen7686b102011-02-02 23:21:58 -0800764static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700765{
766 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800767 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700768 int error;
769 u8 val;
770
Iiro Valkonen7686b102011-02-02 23:21:58 -0800771 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700772 if (error)
773 return error;
774 info->family_id = val;
775
Iiro Valkonen7686b102011-02-02 23:21:58 -0800776 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700777 if (error)
778 return error;
779 info->variant_id = val;
780
Iiro Valkonen7686b102011-02-02 23:21:58 -0800781 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700782 if (error)
783 return error;
784 info->version = val;
785
Iiro Valkonen7686b102011-02-02 23:21:58 -0800786 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700787 if (error)
788 return error;
789 info->build = val;
790
Iiro Valkonen7686b102011-02-02 23:21:58 -0800791 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700792 if (error)
793 return error;
794 info->object_num = val;
795
796 return 0;
797}
798
Iiro Valkonen7686b102011-02-02 23:21:58 -0800799static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700800{
801 int error;
802 int i;
803 u16 reg;
804 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800805 u8 buf[MXT_OBJECT_SIZE];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700806
807 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800808 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700809
Iiro Valkonen7686b102011-02-02 23:21:58 -0800810 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
811 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700812 if (error)
813 return error;
814
815 object->type = buf[0];
816 object->start_address = (buf[2] << 8) | buf[1];
817 object->size = buf[3];
818 object->instances = buf[4];
819 object->num_report_ids = buf[5];
820
821 if (object->num_report_ids) {
822 reportid += object->num_report_ids *
823 (object->instances + 1);
824 object->max_reportid = reportid;
825 }
826 }
827
828 return 0;
829}
830
Amy Maloche7e447432011-09-14 11:36:30 -0700831static void mxt_reset_delay(struct mxt_data *data)
832{
833 struct mxt_info *info = &data->info;
834
835 switch (info->family_id) {
836 case MXT224_ID:
837 msleep(MXT224_RESET_TIME);
838 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -0700839 case MXT224E_ID:
840 msleep(MXT224E_RESET_TIME);
841 break;
Amy Maloche7e447432011-09-14 11:36:30 -0700842 case MXT1386_ID:
843 msleep(MXT1386_RESET_TIME);
844 break;
845 default:
846 msleep(MXT_RESET_TIME);
847 }
848}
849
Iiro Valkonen7686b102011-02-02 23:21:58 -0800850static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700851{
852 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800853 struct mxt_info *info = &data->info;
Jing Lin36aee812011-10-17 17:17:28 -0700854 int error;
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700855 int timeout_counter = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700856 u8 val;
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700857 u8 command_register;
Jing Lin36aee812011-10-17 17:17:28 -0700858 struct mxt_object *t7_object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700859
Iiro Valkonen7686b102011-02-02 23:21:58 -0800860 error = mxt_get_info(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700861 if (error)
862 return error;
863
864 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800865 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700866 GFP_KERNEL);
867 if (!data->object_table) {
868 dev_err(&client->dev, "Failed to allocate memory\n");
869 return -ENOMEM;
870 }
871
872 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800873 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700874 if (error)
Jing Lin32c72532011-11-03 12:02:33 -0700875 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700876
877 /* Check register init values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800878 error = mxt_check_reg_init(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700879 if (error)
Jing Lin32c72532011-11-03 12:02:33 -0700880 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700881
Amy Maloche52262212011-09-15 16:46:57 -0700882 /* Store T7 and T9 locally, used in suspend/resume operations */
Iiro Valkonene8645592011-11-18 12:56:19 -0800883 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
Jing Lin36aee812011-10-17 17:17:28 -0700884 if (!t7_object) {
885 dev_err(&client->dev, "Failed to get T7 object\n");
Jing Lin32c72532011-11-03 12:02:33 -0700886 error = -EINVAL;
887 goto free_object_table;
Jing Lin36aee812011-10-17 17:17:28 -0700888 }
889
890 data->t7_start_addr = t7_object->start_address;
891 error = __mxt_read_reg(client, data->t7_start_addr,
892 T7_DATA_SIZE, data->t7_data);
893 if (error < 0) {
894 dev_err(&client->dev,
Jing Lin32c72532011-11-03 12:02:33 -0700895 "Failed to save current power state\n");
896 goto free_object_table;
Amy Maloche52262212011-09-15 16:46:57 -0700897 }
Iiro Valkonene8645592011-11-18 12:56:19 -0800898 error = mxt_read_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
Amy Maloche52262212011-09-15 16:46:57 -0700899 &data->t9_ctrl);
900 if (error < 0) {
Jing Lin32c72532011-11-03 12:02:33 -0700901 dev_err(&client->dev, "Failed to save current touch object\n");
902 goto free_object_table;
Amy Maloche52262212011-09-15 16:46:57 -0700903 }
904
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700905 /* Backup to memory */
Iiro Valkonene8645592011-11-18 12:56:19 -0800906 mxt_write_object(data, MXT_GEN_COMMAND_T6,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800907 MXT_COMMAND_BACKUPNV,
908 MXT_BACKUP_VALUE);
909 msleep(MXT_BACKUP_TIME);
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700910 do {
Iiro Valkonene8645592011-11-18 12:56:19 -0800911 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700912 MXT_COMMAND_BACKUPNV,
913 &command_register);
914 if (error)
Jing Lin32c72532011-11-03 12:02:33 -0700915 goto free_object_table;
Amy Maloche7e447432011-09-14 11:36:30 -0700916 usleep_range(1000, 2000);
917 } while ((command_register != 0) && (++timeout_counter <= 100));
918 if (timeout_counter > 100) {
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700919 dev_err(&client->dev, "No response after backup!\n");
Jing Lin32c72532011-11-03 12:02:33 -0700920 error = -EIO;
921 goto free_object_table;
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700922 }
923
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700924
925 /* Soft reset */
Iiro Valkonene8645592011-11-18 12:56:19 -0800926 mxt_write_object(data, MXT_GEN_COMMAND_T6,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800927 MXT_COMMAND_RESET, 1);
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700928
Amy Maloche7e447432011-09-14 11:36:30 -0700929 mxt_reset_delay(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700930
931 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800932 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700933 if (error)
Jing Lin32c72532011-11-03 12:02:33 -0700934 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700935 info->matrix_xsize = val;
936
Iiro Valkonen7686b102011-02-02 23:21:58 -0800937 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700938 if (error)
Jing Lin32c72532011-11-03 12:02:33 -0700939 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700940 info->matrix_ysize = val;
941
942 dev_info(&client->dev,
943 "Family ID: %d Variant ID: %d Version: %d Build: %d\n",
944 info->family_id, info->variant_id, info->version,
945 info->build);
946
947 dev_info(&client->dev,
948 "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
949 info->matrix_xsize, info->matrix_ysize,
950 info->object_num);
951
952 return 0;
Jing Lin32c72532011-11-03 12:02:33 -0700953
954free_object_table:
955 kfree(data->object_table);
956 return error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700957}
958
Iiro Valkonen7686b102011-02-02 23:21:58 -0800959static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700960 struct device_attribute *attr, char *buf)
961{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800962 struct mxt_data *data = dev_get_drvdata(dev);
963 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700964 int count = 0;
965 int i, j;
966 int error;
967 u8 val;
968
969 for (i = 0; i < data->info.object_num; i++) {
970 object = data->object_table + i;
971
Daniel Kurtz4ef11a82011-11-02 10:43:08 -0700972 count += snprintf(buf + count, PAGE_SIZE - count,
973 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700974 i + 1, object->type);
Daniel Kurtz4ef11a82011-11-02 10:43:08 -0700975 if (count >= PAGE_SIZE)
976 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700977
Iiro Valkonen7686b102011-02-02 23:21:58 -0800978 if (!mxt_object_readable(object->type)) {
Daniel Kurtz4ef11a82011-11-02 10:43:08 -0700979 count += snprintf(buf + count, PAGE_SIZE - count,
980 "\n");
981 if (count >= PAGE_SIZE)
982 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700983 continue;
984 }
985
986 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800987 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700988 object->type, j, &val);
989 if (error)
990 return error;
991
Daniel Kurtz4ef11a82011-11-02 10:43:08 -0700992 count += snprintf(buf + count, PAGE_SIZE - count,
993 "\t[%2d]: %02x (%d)\n", j, val, val);
994 if (count >= PAGE_SIZE)
995 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700996 }
997
Daniel Kurtz4ef11a82011-11-02 10:43:08 -0700998 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
999 if (count >= PAGE_SIZE)
1000 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001001 }
1002
1003 return count;
1004}
1005
Iiro Valkonen7686b102011-02-02 23:21:58 -08001006static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001007{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001008 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001009 struct i2c_client *client = data->client;
1010 const struct firmware *fw = NULL;
1011 unsigned int frame_size;
1012 unsigned int pos = 0;
1013 int ret;
1014
1015 ret = request_firmware(&fw, fn, dev);
1016 if (ret) {
1017 dev_err(dev, "Unable to open firmware %s\n", fn);
1018 return ret;
1019 }
1020
1021 /* Change to the bootloader mode */
Iiro Valkonene8645592011-11-18 12:56:19 -08001022 mxt_write_object(data, MXT_GEN_COMMAND_T6,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001023 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
Amy Maloche7e447432011-09-14 11:36:30 -07001024
1025 mxt_reset_delay(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001026
1027 /* Change to slave address of bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001028 if (client->addr == MXT_APP_LOW)
1029 client->addr = MXT_BOOT_LOW;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001030 else
Iiro Valkonen7686b102011-02-02 23:21:58 -08001031 client->addr = MXT_BOOT_HIGH;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001032
Iiro Valkonen7686b102011-02-02 23:21:58 -08001033 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001034 if (ret)
1035 goto out;
1036
1037 /* Unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001038 mxt_unlock_bootloader(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001039
1040 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001041 ret = mxt_check_bootloader(client,
1042 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001043 if (ret)
1044 goto out;
1045
1046 frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
1047
1048 /* We should add 2 at frame size as the the firmware data is not
1049 * included the CRC bytes.
1050 */
1051 frame_size += 2;
1052
1053 /* Write one frame to device */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001054 mxt_fw_write(client, fw->data + pos, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001055
Iiro Valkonen7686b102011-02-02 23:21:58 -08001056 ret = mxt_check_bootloader(client,
1057 MXT_FRAME_CRC_PASS);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001058 if (ret)
1059 goto out;
1060
1061 pos += frame_size;
1062
1063 dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
1064 }
1065
1066out:
1067 release_firmware(fw);
1068
1069 /* Change to slave address of application */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001070 if (client->addr == MXT_BOOT_LOW)
1071 client->addr = MXT_APP_LOW;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001072 else
Iiro Valkonen7686b102011-02-02 23:21:58 -08001073 client->addr = MXT_APP_HIGH;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001074
1075 return ret;
1076}
1077
Iiro Valkonen7686b102011-02-02 23:21:58 -08001078static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001079 struct device_attribute *attr,
1080 const char *buf, size_t count)
1081{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001082 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001083 int error;
1084
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001085 disable_irq(data->irq);
1086
Iiro Valkonen7686b102011-02-02 23:21:58 -08001087 error = mxt_load_fw(dev, MXT_FW_NAME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001088 if (error) {
1089 dev_err(dev, "The firmware update failed(%d)\n", error);
1090 count = error;
1091 } else {
1092 dev_dbg(dev, "The firmware update succeeded\n");
1093
1094 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001095 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001096
1097 kfree(data->object_table);
1098 data->object_table = NULL;
1099
Iiro Valkonen7686b102011-02-02 23:21:58 -08001100 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001101 }
1102
1103 enable_irq(data->irq);
1104
Iiro Valkonen08960a02011-04-12 23:16:40 -07001105 error = mxt_make_highchg(data);
1106 if (error)
1107 return error;
1108
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001109 return count;
1110}
1111
Iiro Valkonen7686b102011-02-02 23:21:58 -08001112static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
1113static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001114
Iiro Valkonen7686b102011-02-02 23:21:58 -08001115static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001116 &dev_attr_object.attr,
1117 &dev_attr_update_fw.attr,
1118 NULL
1119};
1120
Iiro Valkonen7686b102011-02-02 23:21:58 -08001121static const struct attribute_group mxt_attr_group = {
1122 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001123};
1124
Amy Maloche52262212011-09-15 16:46:57 -07001125static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001126{
Jing Lin36aee812011-10-17 17:17:28 -07001127 int error;
1128
Amy Maloche52262212011-09-15 16:46:57 -07001129 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07001130 error = __mxt_write_reg(data->client, data->t7_start_addr,
1131 T7_DATA_SIZE, data->t7_data);
1132 if (error < 0) {
1133 dev_err(&data->client->dev,
1134 "failed to restore old power state\n");
1135 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001136 }
Jing Lin36aee812011-10-17 17:17:28 -07001137
Amy Maloche52262212011-09-15 16:46:57 -07001138 error = mxt_write_object(data,
Iiro Valkonene8645592011-11-18 12:56:19 -08001139 MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, data->t9_ctrl);
Amy Maloche52262212011-09-15 16:46:57 -07001140 if (error < 0) {
1141 dev_err(&data->client->dev, "failed to restore touch\n");
1142 return error;
1143 }
1144
1145 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001146}
1147
Amy Maloche52262212011-09-15 16:46:57 -07001148static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001149{
Jing Lin36aee812011-10-17 17:17:28 -07001150 int error;
1151 u8 t7_data[T7_DATA_SIZE] = {0};
1152
1153 /* disable touch and configure deep sleep mode */
Iiro Valkonene8645592011-11-18 12:56:19 -08001154 error = mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
Jing Lin36aee812011-10-17 17:17:28 -07001155 if (error < 0) {
1156 dev_err(&data->client->dev, "failed to disable touch\n");
1157 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001158 }
1159
Jing Lin36aee812011-10-17 17:17:28 -07001160 error = __mxt_write_reg(data->client, data->t7_start_addr,
1161 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07001162 if (error < 0) {
1163 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07001164 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07001165 return error;
1166 }
1167
1168 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001169}
1170
Iiro Valkonen7686b102011-02-02 23:21:58 -08001171static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001172{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001173 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001174 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001175
Amy Maloche52262212011-09-15 16:46:57 -07001176 error = mxt_start(data);
1177 if (error < 0) {
1178 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
1179 return error;
1180 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001181
1182 return 0;
1183}
1184
Iiro Valkonen7686b102011-02-02 23:21:58 -08001185static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001186{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001187 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001188 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001189
Amy Maloche52262212011-09-15 16:46:57 -07001190 error = mxt_stop(data);
1191 if (error < 0)
1192 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
1193
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001194}
1195
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301196static int mxt_power_on(struct mxt_data *data, bool on)
1197{
1198 int rc;
1199
1200 if (on == false)
1201 goto power_off;
1202
Amy Maloche21115eb2011-11-02 09:04:37 -07001203 rc = regulator_set_optimum_mode(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301204 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001205 dev_err(&data->client->dev,
1206 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301207 return rc;
1208 }
1209
Amy Maloche21115eb2011-11-02 09:04:37 -07001210 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301211 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001212 dev_err(&data->client->dev,
1213 "Regulator vcc_ana enable failed rc=%d\n", rc);
1214 goto error_reg_en_vcc_ana;
1215 }
1216
1217 if (data->pdata->digital_pwr_regulator) {
1218 rc = regulator_set_optimum_mode(data->vcc_dig,
1219 MXT_ACTIVE_LOAD_DIG_UA);
1220 if (rc < 0) {
1221 dev_err(&data->client->dev,
1222 "Regulator vcc_dig set_opt failed rc=%d\n",
1223 rc);
1224 goto error_reg_opt_vcc_dig;
1225 }
1226
1227 rc = regulator_enable(data->vcc_dig);
1228 if (rc) {
1229 dev_err(&data->client->dev,
1230 "Regulator vcc_dig enable failed rc=%d\n", rc);
1231 goto error_reg_en_vcc_dig;
1232 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301233 }
1234
1235 if (data->pdata->i2c_pull_up) {
1236 rc = regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LOAD_UA);
1237 if (rc < 0) {
1238 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001239 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301240 goto error_reg_opt_i2c;
1241 }
1242
1243 rc = regulator_enable(data->vcc_i2c);
1244 if (rc) {
1245 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001246 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301247 goto error_reg_en_vcc_i2c;
1248 }
1249 }
1250
Amy Malochef0d7b8d2011-10-17 12:10:51 -07001251 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301252
1253 return 0;
1254
1255error_reg_en_vcc_i2c:
1256 if (data->pdata->i2c_pull_up)
1257 regulator_set_optimum_mode(data->vcc_i2c, 0);
1258error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001259 if (data->pdata->digital_pwr_regulator)
1260 regulator_disable(data->vcc_dig);
1261error_reg_en_vcc_dig:
1262 if (data->pdata->digital_pwr_regulator)
1263 regulator_set_optimum_mode(data->vcc_dig, 0);
1264error_reg_opt_vcc_dig:
1265 regulator_disable(data->vcc_ana);
1266error_reg_en_vcc_ana:
1267 regulator_set_optimum_mode(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301268 return rc;
1269
1270power_off:
Amy Maloche21115eb2011-11-02 09:04:37 -07001271 regulator_set_optimum_mode(data->vcc_ana, 0);
1272 regulator_disable(data->vcc_ana);
1273 if (data->pdata->digital_pwr_regulator) {
1274 regulator_set_optimum_mode(data->vcc_dig, 0);
1275 regulator_disable(data->vcc_dig);
1276 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301277 if (data->pdata->i2c_pull_up) {
1278 regulator_set_optimum_mode(data->vcc_i2c, 0);
1279 regulator_disable(data->vcc_i2c);
1280 }
1281 msleep(50);
1282 return 0;
1283}
1284
1285static int mxt_regulator_configure(struct mxt_data *data, bool on)
1286{
1287 int rc;
1288
1289 if (on == false)
1290 goto hw_shutdown;
1291
Amy Maloche21115eb2011-11-02 09:04:37 -07001292 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
1293 if (IS_ERR(data->vcc_ana)) {
1294 rc = PTR_ERR(data->vcc_ana);
1295 dev_err(&data->client->dev,
1296 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301297 return rc;
1298 }
1299
Amy Maloche21115eb2011-11-02 09:04:37 -07001300 if (regulator_count_voltages(data->vcc_ana) > 0) {
1301 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301302 MXT_VTG_MAX_UV);
1303 if (rc) {
1304 dev_err(&data->client->dev,
1305 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07001306 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301307 }
1308 }
Amy Maloche21115eb2011-11-02 09:04:37 -07001309 if (data->pdata->digital_pwr_regulator) {
1310 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
1311 if (IS_ERR(data->vcc_dig)) {
1312 rc = PTR_ERR(data->vcc_dig);
1313 dev_err(&data->client->dev,
1314 "Regulator get dig failed rc=%d\n", rc);
1315 goto error_get_vtg_vcc_dig;
1316 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301317
Amy Maloche21115eb2011-11-02 09:04:37 -07001318 if (regulator_count_voltages(data->vcc_dig) > 0) {
1319 rc = regulator_set_voltage(data->vcc_dig,
1320 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
1321 if (rc) {
1322 dev_err(&data->client->dev,
1323 "regulator set_vtg failed rc=%d\n", rc);
1324 goto error_set_vtg_vcc_dig;
1325 }
1326 }
1327 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301328 if (data->pdata->i2c_pull_up) {
1329 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
1330 if (IS_ERR(data->vcc_i2c)) {
1331 rc = PTR_ERR(data->vcc_i2c);
1332 dev_err(&data->client->dev,
1333 "Regulator get failed rc=%d\n", rc);
1334 goto error_get_vtg_i2c;
1335 }
1336 if (regulator_count_voltages(data->vcc_i2c) > 0) {
1337 rc = regulator_set_voltage(data->vcc_i2c,
1338 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
1339 if (rc) {
1340 dev_err(&data->client->dev,
1341 "regulator set_vtg failed rc=%d\n", rc);
1342 goto error_set_vtg_i2c;
1343 }
1344 }
1345 }
1346
1347 return 0;
1348
1349error_set_vtg_i2c:
1350 regulator_put(data->vcc_i2c);
1351error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001352 if (data->pdata->digital_pwr_regulator)
1353 if (regulator_count_voltages(data->vcc_dig) > 0)
1354 regulator_set_voltage(data->vcc_dig, 0,
1355 MXT_VTG_DIG_MAX_UV);
1356error_set_vtg_vcc_dig:
1357 if (data->pdata->digital_pwr_regulator)
1358 regulator_put(data->vcc_dig);
1359error_get_vtg_vcc_dig:
1360 if (regulator_count_voltages(data->vcc_ana) > 0)
1361 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1362error_set_vtg_vcc_ana:
1363 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301364 return rc;
1365
1366hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07001367 if (regulator_count_voltages(data->vcc_ana) > 0)
1368 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1369 regulator_put(data->vcc_ana);
1370 if (data->pdata->digital_pwr_regulator) {
1371 if (regulator_count_voltages(data->vcc_dig) > 0)
1372 regulator_set_voltage(data->vcc_dig, 0,
1373 MXT_VTG_DIG_MAX_UV);
1374 regulator_put(data->vcc_dig);
1375 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301376 if (data->pdata->i2c_pull_up) {
1377 if (regulator_count_voltages(data->vcc_i2c) > 0)
1378 regulator_set_voltage(data->vcc_i2c, 0,
1379 MXT_I2C_VTG_MAX_UV);
1380 regulator_put(data->vcc_i2c);
1381 }
1382 return 0;
1383}
1384
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301385#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07001386static int mxt_regulator_lpm(struct mxt_data *data, bool on)
1387{
1388
1389 int rc;
1390
1391 if (on == false)
1392 goto regulator_hpm;
1393
Amy Maloche21115eb2011-11-02 09:04:37 -07001394 rc = regulator_set_optimum_mode(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001395 if (rc < 0) {
1396 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001397 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001398 goto fail_regulator_lpm;
1399 }
1400
Amy Maloche21115eb2011-11-02 09:04:37 -07001401 if (data->pdata->digital_pwr_regulator) {
1402 rc = regulator_set_optimum_mode(data->vcc_dig,
1403 MXT_LPM_LOAD_DIG_UA);
1404 if (rc < 0) {
1405 dev_err(&data->client->dev,
1406 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
1407 goto fail_regulator_lpm;
1408 }
1409 }
1410
Jing Linbace50b2011-10-18 22:55:47 -07001411 if (data->pdata->i2c_pull_up) {
1412 rc = regulator_set_optimum_mode(data->vcc_i2c,
1413 MXT_I2C_LPM_LOAD_UA);
1414 if (rc < 0) {
1415 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001416 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001417 goto fail_regulator_lpm;
1418 }
1419 }
1420
1421 return 0;
1422
1423regulator_hpm:
1424
Amy Maloche21115eb2011-11-02 09:04:37 -07001425 rc = regulator_set_optimum_mode(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001426 if (rc < 0) {
1427 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001428 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001429 goto fail_regulator_hpm;
1430 }
1431
Amy Maloche21115eb2011-11-02 09:04:37 -07001432 if (data->pdata->digital_pwr_regulator) {
1433 rc = regulator_set_optimum_mode(data->vcc_dig,
1434 MXT_ACTIVE_LOAD_DIG_UA);
1435 if (rc < 0) {
1436 dev_err(&data->client->dev,
1437 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
1438 goto fail_regulator_hpm;
1439 }
1440 }
1441
Jing Linbace50b2011-10-18 22:55:47 -07001442 if (data->pdata->i2c_pull_up) {
1443 rc = regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LOAD_UA);
1444 if (rc < 0) {
1445 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001446 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001447 goto fail_regulator_hpm;
1448 }
1449 }
1450
1451 return 0;
1452
1453fail_regulator_lpm:
Amy Maloche21115eb2011-11-02 09:04:37 -07001454 regulator_set_optimum_mode(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
1455 if (data->pdata->digital_pwr_regulator)
1456 regulator_set_optimum_mode(data->vcc_dig,
1457 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001458 if (data->pdata->i2c_pull_up)
1459 regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LOAD_UA);
1460
1461 return rc;
1462
1463fail_regulator_hpm:
Amy Maloche21115eb2011-11-02 09:04:37 -07001464 regulator_set_optimum_mode(data->vcc_ana, MXT_LPM_LOAD_UA);
1465 if (data->pdata->digital_pwr_regulator)
1466 regulator_set_optimum_mode(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001467 if (data->pdata->i2c_pull_up)
1468 regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
1469
1470 return rc;
1471}
1472
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301473static int mxt_suspend(struct device *dev)
1474{
1475 struct i2c_client *client = to_i2c_client(dev);
1476 struct mxt_data *data = i2c_get_clientdata(client);
1477 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07001478 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301479
1480 mutex_lock(&input_dev->mutex);
1481
Amy Maloche52262212011-09-15 16:46:57 -07001482 if (input_dev->users) {
1483 error = mxt_stop(data);
1484 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07001485 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07001486 mutex_unlock(&input_dev->mutex);
1487 return error;
1488 }
1489
1490 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301491
1492 mutex_unlock(&input_dev->mutex);
1493
Jing Linbace50b2011-10-18 22:55:47 -07001494 /* put regulators in low power mode */
1495 error = mxt_regulator_lpm(data, true);
1496 if (error < 0) {
1497 dev_err(dev, "failed to enter low power mode\n");
1498 return error;
1499 }
1500
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301501 return 0;
1502}
1503
1504static int mxt_resume(struct device *dev)
1505{
1506 struct i2c_client *client = to_i2c_client(dev);
1507 struct mxt_data *data = i2c_get_clientdata(client);
1508 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07001509 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301510
Jing Linbace50b2011-10-18 22:55:47 -07001511 /* put regulators in high power mode */
1512 error = mxt_regulator_lpm(data, false);
1513 if (error < 0) {
1514 dev_err(dev, "failed to enter high power mode\n");
1515 return error;
1516 }
1517
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301518 mutex_lock(&input_dev->mutex);
1519
Amy Maloche52262212011-09-15 16:46:57 -07001520 if (input_dev->users) {
1521 error = mxt_start(data);
1522 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07001523 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07001524 mutex_unlock(&input_dev->mutex);
1525 return error;
1526 }
1527 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301528
1529 mutex_unlock(&input_dev->mutex);
1530
1531 return 0;
1532}
1533
1534#if defined(CONFIG_HAS_EARLYSUSPEND)
1535static void mxt_early_suspend(struct early_suspend *h)
1536{
1537 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
1538
1539 mxt_suspend(&data->client->dev);
1540}
1541
1542static void mxt_late_resume(struct early_suspend *h)
1543{
1544 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
1545
1546 mxt_resume(&data->client->dev);
1547}
1548#endif
1549
1550static const struct dev_pm_ops mxt_pm_ops = {
1551#ifndef CONFIG_HAS_EARLYSUSPEND
1552 .suspend = mxt_suspend,
1553 .resume = mxt_resume,
1554#endif
1555};
1556#endif
1557
Iiro Valkonen7686b102011-02-02 23:21:58 -08001558static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001559 const struct i2c_device_id *id)
1560{
Iiro Valkonen919ed892011-02-15 13:36:52 -08001561 const struct mxt_platform_data *pdata = client->dev.platform_data;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001562 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001563 struct input_dev *input_dev;
1564 int error;
1565
Iiro Valkonen919ed892011-02-15 13:36:52 -08001566 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001567 return -EINVAL;
1568
Iiro Valkonen7686b102011-02-02 23:21:58 -08001569 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001570 input_dev = input_allocate_device();
1571 if (!data || !input_dev) {
1572 dev_err(&client->dev, "Failed to allocate memory\n");
1573 error = -ENOMEM;
1574 goto err_free_mem;
1575 }
1576
Iiro Valkonen7686b102011-02-02 23:21:58 -08001577 input_dev->name = "Atmel maXTouch Touchscreen";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001578 input_dev->id.bustype = BUS_I2C;
1579 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001580 input_dev->open = mxt_input_open;
1581 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001582
Joonyoung Shim910d8052011-04-12 23:14:38 -07001583 data->client = client;
1584 data->input_dev = input_dev;
1585 data->pdata = pdata;
1586 data->irq = client->irq;
1587
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001588 __set_bit(EV_ABS, input_dev->evbit);
1589 __set_bit(EV_KEY, input_dev->evbit);
1590 __set_bit(BTN_TOUCH, input_dev->keybit);
1591
1592 /* For single touch */
1593 input_set_abs_params(input_dev, ABS_X,
Jing Lin2f863172011-10-17 10:56:58 -07001594 0, data->pdata->x_size, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001595 input_set_abs_params(input_dev, ABS_Y,
Jing Lin2f863172011-10-17 10:56:58 -07001596 0, data->pdata->y_size, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07001597 input_set_abs_params(input_dev, ABS_PRESSURE,
1598 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001599
1600 /* For multi touch */
1601 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001602 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001603 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Jing Lin2f863172011-10-17 10:56:58 -07001604 0, data->pdata->x_size, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001605 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Jing Lin2f863172011-10-17 10:56:58 -07001606 0, data->pdata->y_size, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07001607 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
1608 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001609
1610 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001611 i2c_set_clientdata(client, data);
1612
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301613 if (pdata->init_hw)
1614 error = pdata->init_hw(true);
1615 else
1616 error = mxt_regulator_configure(data, true);
1617 if (error) {
1618 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07001619 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301620 }
1621
1622 if (pdata->power_on)
1623 error = pdata->power_on(true);
1624 else
1625 error = mxt_power_on(data, true);
1626 if (error) {
1627 dev_err(&client->dev, "Failed to power on hardware\n");
1628 goto err_regulator_on;
1629 }
1630
Amy Maloche08266db2011-11-04 11:07:16 -07001631 if (gpio_is_valid(pdata->irq_gpio)) {
1632 /* configure touchscreen irq gpio */
1633 error = gpio_request(pdata->irq_gpio,
1634 "mxt_irq_gpio");
1635 if (error) {
1636 pr_err("%s: unable to request gpio [%d]\n", __func__,
1637 pdata->irq_gpio);
1638 goto err_power_on;
1639 }
1640 error = gpio_direction_input(pdata->irq_gpio);
1641 if (error) {
1642 pr_err("%s: unable to set_direction for gpio [%d]\n",
1643 __func__, pdata->irq_gpio);
1644 goto err_irq_gpio_req;
1645 }
1646 }
1647
1648 if (gpio_is_valid(pdata->reset_gpio)) {
1649 /* configure touchscreen reset out gpio */
1650 error = gpio_request(pdata->reset_gpio,
1651 "mxt_reset_gpio");
1652 if (error) {
1653 pr_err("%s: unable to request reset gpio %d\n",
1654 __func__, pdata->reset_gpio);
1655 goto err_irq_gpio_req;
1656 }
1657
1658 error = gpio_direction_output(
1659 pdata->reset_gpio, 1);
1660 if (error) {
1661 pr_err("%s: unable to set direction for gpio %d\n",
1662 __func__, pdata->reset_gpio);
1663 goto err_reset_gpio_req;
1664 }
1665 }
1666
1667 mxt_reset_delay(data);
1668
Iiro Valkonen7686b102011-02-02 23:21:58 -08001669 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001670 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07001671 goto err_reset_gpio_req;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001672
Iiro Valkonen7686b102011-02-02 23:21:58 -08001673 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08001674 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001675 if (error) {
1676 dev_err(&client->dev, "Failed to register interrupt\n");
Jing Lin32c72532011-11-03 12:02:33 -07001677 goto err_free_object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001678 }
1679
Iiro Valkonen08960a02011-04-12 23:16:40 -07001680 error = mxt_make_highchg(data);
1681 if (error)
1682 goto err_free_irq;
1683
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001684 error = input_register_device(input_dev);
1685 if (error)
1686 goto err_free_irq;
1687
Iiro Valkonen7686b102011-02-02 23:21:58 -08001688 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001689 if (error)
1690 goto err_unregister_device;
1691
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301692#if defined(CONFIG_HAS_EARLYSUSPEND)
1693 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
1694 MXT_SUSPEND_LEVEL;
1695 data->early_suspend.suspend = mxt_early_suspend;
1696 data->early_suspend.resume = mxt_late_resume;
1697 register_early_suspend(&data->early_suspend);
1698#endif
1699
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001700 return 0;
1701
1702err_unregister_device:
1703 input_unregister_device(input_dev);
1704 input_dev = NULL;
1705err_free_irq:
1706 free_irq(client->irq, data);
Jing Lin32c72532011-11-03 12:02:33 -07001707err_free_object:
1708 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07001709err_reset_gpio_req:
1710 if (gpio_is_valid(pdata->reset_gpio))
1711 gpio_free(pdata->reset_gpio);
1712err_irq_gpio_req:
1713 if (gpio_is_valid(pdata->irq_gpio))
1714 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301715err_power_on:
1716 if (pdata->power_on)
1717 pdata->power_on(false);
1718 else
1719 mxt_power_on(data, false);
1720err_regulator_on:
1721 if (pdata->init_hw)
1722 pdata->init_hw(false);
1723 else
1724 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001725err_free_mem:
1726 input_free_device(input_dev);
1727 kfree(data);
1728 return error;
1729}
1730
Iiro Valkonen7686b102011-02-02 23:21:58 -08001731static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001732{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001733 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001734
Iiro Valkonen7686b102011-02-02 23:21:58 -08001735 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001736 free_irq(data->irq, data);
1737 input_unregister_device(data->input_dev);
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301738#if defined(CONFIG_HAS_EARLYSUSPEND)
1739 unregister_early_suspend(&data->early_suspend);
1740#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301741
1742 if (data->pdata->power_on)
1743 data->pdata->power_on(false);
1744 else
1745 mxt_power_on(data, false);
1746
1747 if (data->pdata->init_hw)
1748 data->pdata->init_hw(false);
1749 else
1750 mxt_regulator_configure(data, false);
1751
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001752 kfree(data->object_table);
1753 kfree(data);
1754
1755 return 0;
1756}
1757
Iiro Valkonen7686b102011-02-02 23:21:58 -08001758static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001759 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08001760 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08001761 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001762 { }
1763};
Iiro Valkonen7686b102011-02-02 23:21:58 -08001764MODULE_DEVICE_TABLE(i2c, mxt_id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001765
Iiro Valkonen7686b102011-02-02 23:21:58 -08001766static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001767 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001768 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001769 .owner = THIS_MODULE,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08001770#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08001771 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08001772#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001773 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08001774 .probe = mxt_probe,
1775 .remove = __devexit_p(mxt_remove),
1776 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001777};
1778
Iiro Valkonen7686b102011-02-02 23:21:58 -08001779static int __init mxt_init(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001780{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001781 return i2c_add_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001782}
1783
Iiro Valkonen7686b102011-02-02 23:21:58 -08001784static void __exit mxt_exit(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001785{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001786 i2c_del_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001787}
1788
Iiro Valkonen7686b102011-02-02 23:21:58 -08001789module_init(mxt_init);
1790module_exit(mxt_exit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001791
1792/* Module information */
1793MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08001794MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001795MODULE_LICENSE("GPL");