blob: c95426028f62adc516aa8eadf3bdd75983ea9c94 [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>
Mohan Pallaka5e7343f2012-01-02 18:30:16 +08006 * Copyright (c) 2011-2012, 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,
Mohan Pallaka5e7343f2012-01-02 18:30:16 +0800601 finger[id].status != MXT_RELEASE ?
602 finger[id].pressure : 0);
Amy Maloche2b59bab2011-10-13 16:08:16 -0700603 input_mt_sync(input_dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700604
Amy Maloche2b59bab2011-10-13 16:08:16 -0700605 if (finger[id].status == MXT_RELEASE)
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700606 finger[id].status = 0;
Amy Maloche2b59bab2011-10-13 16:08:16 -0700607 else
608 finger_num++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700609 }
610
611 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
612
Iiro Valkonen7686b102011-02-02 23:21:58 -0800613 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700614 input_report_abs(input_dev, ABS_X, finger[single_id].x);
615 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700616 input_report_abs(input_dev,
617 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700618 }
619
620 input_sync(input_dev);
621}
622
Iiro Valkonen7686b102011-02-02 23:21:58 -0800623static void mxt_input_touchevent(struct mxt_data *data,
624 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700625{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800626 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700627 struct device *dev = &data->client->dev;
628 u8 status = message->message[0];
629 int x;
630 int y;
631 int area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700632 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700633
634 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800635 if (!(status & MXT_DETECT)) {
636 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700637 dev_dbg(dev, "[%d] released\n", id);
638
Iiro Valkonen7686b102011-02-02 23:21:58 -0800639 finger[id].status = MXT_RELEASE;
640 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700641 }
642 return;
643 }
644
645 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800646 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700647 return;
648
Joonyoung Shim910d8052011-04-12 23:14:38 -0700649 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
650 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Jing Lin2f863172011-10-17 10:56:58 -0700651 if (data->pdata->x_size < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700652 x = x >> 2;
Jing Lin2f863172011-10-17 10:56:58 -0700653 if (data->pdata->y_size < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700654 y = y >> 2;
655
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700656 area = message->message[4];
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700657 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700658
659 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800660 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700661 x, y, area);
662
Iiro Valkonen7686b102011-02-02 23:21:58 -0800663 finger[id].status = status & MXT_MOVE ?
664 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700665 finger[id].x = x;
666 finger[id].y = y;
667 finger[id].area = area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700668 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700669
Iiro Valkonen7686b102011-02-02 23:21:58 -0800670 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700671}
672
Iiro Valkonen7686b102011-02-02 23:21:58 -0800673static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700674{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800675 struct mxt_data *data = dev_id;
676 struct mxt_message message;
677 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700678 struct device *dev = &data->client->dev;
679 int id;
680 u8 reportid;
681 u8 max_reportid;
682 u8 min_reportid;
683
684 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800685 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700686 dev_err(dev, "Failed to read message\n");
687 goto end;
688 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700689 reportid = message.reportid;
690
Iiro Valkonene8645592011-11-18 12:56:19 -0800691 /* whether reportid is thing of MXT_TOUCH_MULTI_T9 */
692 object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700693 if (!object)
694 goto end;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700695 max_reportid = object->max_reportid;
696 min_reportid = max_reportid - object->num_report_ids + 1;
697 id = reportid - min_reportid;
698
699 if (reportid >= min_reportid && reportid <= max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -0800700 mxt_input_touchevent(data, &message, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700701 else
Iiro Valkonen7686b102011-02-02 23:21:58 -0800702 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700703 } while (reportid != 0xff);
704
705end:
706 return IRQ_HANDLED;
707}
708
Iiro Valkonen7686b102011-02-02 23:21:58 -0800709static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700710{
Iiro Valkonen71749f52011-02-15 13:36:52 -0800711 const struct mxt_platform_data *pdata = data->pdata;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800712 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700713 struct device *dev = &data->client->dev;
714 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -0800715 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700716
Iiro Valkonen71749f52011-02-15 13:36:52 -0800717 if (!pdata->config) {
718 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
719 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700720 }
721
722 for (i = 0; i < data->info.object_num; i++) {
723 object = data->object_table + i;
724
Iiro Valkonen7686b102011-02-02 23:21:58 -0800725 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700726 continue;
727
Iiro Valkonen71749f52011-02-15 13:36:52 -0800728 for (j = 0; j < object->size + 1; j++) {
729 config_offset = index + j;
730 if (config_offset > pdata->config_length) {
731 dev_err(dev, "Not enough config data!\n");
732 return -EINVAL;
733 }
Iiro Valkonen7686b102011-02-02 23:21:58 -0800734 mxt_write_object(data, object->type, j,
Iiro Valkonen71749f52011-02-15 13:36:52 -0800735 pdata->config[config_offset]);
736 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700737 index += object->size + 1;
738 }
739
740 return 0;
741}
742
Iiro Valkonen7686b102011-02-02 23:21:58 -0800743static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700744{
745 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800746 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700747 int count = 10;
748 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700749
750 /* Read dummy message to make high CHG pin */
751 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800752 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700753 if (error)
754 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800755 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700756
757 if (!count) {
758 dev_err(dev, "CHG pin isn't cleared\n");
759 return -EBUSY;
760 }
761
762 return 0;
763}
764
Iiro Valkonen7686b102011-02-02 23:21:58 -0800765static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700766{
767 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800768 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700769 int error;
770 u8 val;
771
Iiro Valkonen7686b102011-02-02 23:21:58 -0800772 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700773 if (error)
774 return error;
775 info->family_id = val;
776
Iiro Valkonen7686b102011-02-02 23:21:58 -0800777 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700778 if (error)
779 return error;
780 info->variant_id = val;
781
Iiro Valkonen7686b102011-02-02 23:21:58 -0800782 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700783 if (error)
784 return error;
785 info->version = val;
786
Iiro Valkonen7686b102011-02-02 23:21:58 -0800787 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700788 if (error)
789 return error;
790 info->build = val;
791
Iiro Valkonen7686b102011-02-02 23:21:58 -0800792 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700793 if (error)
794 return error;
795 info->object_num = val;
796
797 return 0;
798}
799
Iiro Valkonen7686b102011-02-02 23:21:58 -0800800static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700801{
802 int error;
803 int i;
804 u16 reg;
805 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800806 u8 buf[MXT_OBJECT_SIZE];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700807
808 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800809 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700810
Iiro Valkonen7686b102011-02-02 23:21:58 -0800811 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
812 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700813 if (error)
814 return error;
815
816 object->type = buf[0];
817 object->start_address = (buf[2] << 8) | buf[1];
818 object->size = buf[3];
819 object->instances = buf[4];
820 object->num_report_ids = buf[5];
821
822 if (object->num_report_ids) {
823 reportid += object->num_report_ids *
824 (object->instances + 1);
825 object->max_reportid = reportid;
826 }
827 }
828
829 return 0;
830}
831
Amy Maloche7e447432011-09-14 11:36:30 -0700832static void mxt_reset_delay(struct mxt_data *data)
833{
834 struct mxt_info *info = &data->info;
835
836 switch (info->family_id) {
837 case MXT224_ID:
838 msleep(MXT224_RESET_TIME);
839 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -0700840 case MXT224E_ID:
841 msleep(MXT224E_RESET_TIME);
842 break;
Amy Maloche7e447432011-09-14 11:36:30 -0700843 case MXT1386_ID:
844 msleep(MXT1386_RESET_TIME);
845 break;
846 default:
847 msleep(MXT_RESET_TIME);
848 }
849}
850
Iiro Valkonen7686b102011-02-02 23:21:58 -0800851static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700852{
853 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800854 struct mxt_info *info = &data->info;
Jing Lin36aee812011-10-17 17:17:28 -0700855 int error;
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700856 int timeout_counter = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700857 u8 val;
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700858 u8 command_register;
Jing Lin36aee812011-10-17 17:17:28 -0700859 struct mxt_object *t7_object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700860
Iiro Valkonen7686b102011-02-02 23:21:58 -0800861 error = mxt_get_info(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700862 if (error)
863 return error;
864
865 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800866 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700867 GFP_KERNEL);
868 if (!data->object_table) {
869 dev_err(&client->dev, "Failed to allocate memory\n");
870 return -ENOMEM;
871 }
872
873 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800874 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700875 if (error)
Jing Lin32c72532011-11-03 12:02:33 -0700876 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700877
878 /* Check register init values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800879 error = mxt_check_reg_init(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700880 if (error)
Jing Lin32c72532011-11-03 12:02:33 -0700881 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700882
Amy Maloche52262212011-09-15 16:46:57 -0700883 /* Store T7 and T9 locally, used in suspend/resume operations */
Iiro Valkonene8645592011-11-18 12:56:19 -0800884 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
Jing Lin36aee812011-10-17 17:17:28 -0700885 if (!t7_object) {
886 dev_err(&client->dev, "Failed to get T7 object\n");
Jing Lin32c72532011-11-03 12:02:33 -0700887 error = -EINVAL;
888 goto free_object_table;
Jing Lin36aee812011-10-17 17:17:28 -0700889 }
890
891 data->t7_start_addr = t7_object->start_address;
892 error = __mxt_read_reg(client, data->t7_start_addr,
893 T7_DATA_SIZE, data->t7_data);
894 if (error < 0) {
895 dev_err(&client->dev,
Jing Lin32c72532011-11-03 12:02:33 -0700896 "Failed to save current power state\n");
897 goto free_object_table;
Amy Maloche52262212011-09-15 16:46:57 -0700898 }
Iiro Valkonene8645592011-11-18 12:56:19 -0800899 error = mxt_read_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
Amy Maloche52262212011-09-15 16:46:57 -0700900 &data->t9_ctrl);
901 if (error < 0) {
Jing Lin32c72532011-11-03 12:02:33 -0700902 dev_err(&client->dev, "Failed to save current touch object\n");
903 goto free_object_table;
Amy Maloche52262212011-09-15 16:46:57 -0700904 }
905
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700906 /* Backup to memory */
Iiro Valkonene8645592011-11-18 12:56:19 -0800907 mxt_write_object(data, MXT_GEN_COMMAND_T6,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800908 MXT_COMMAND_BACKUPNV,
909 MXT_BACKUP_VALUE);
910 msleep(MXT_BACKUP_TIME);
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700911 do {
Iiro Valkonene8645592011-11-18 12:56:19 -0800912 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700913 MXT_COMMAND_BACKUPNV,
914 &command_register);
915 if (error)
Jing Lin32c72532011-11-03 12:02:33 -0700916 goto free_object_table;
Amy Maloche7e447432011-09-14 11:36:30 -0700917 usleep_range(1000, 2000);
918 } while ((command_register != 0) && (++timeout_counter <= 100));
919 if (timeout_counter > 100) {
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700920 dev_err(&client->dev, "No response after backup!\n");
Jing Lin32c72532011-11-03 12:02:33 -0700921 error = -EIO;
922 goto free_object_table;
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700923 }
924
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700925
926 /* Soft reset */
Iiro Valkonene8645592011-11-18 12:56:19 -0800927 mxt_write_object(data, MXT_GEN_COMMAND_T6,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800928 MXT_COMMAND_RESET, 1);
Iiro Valkonen4ac053c2011-09-08 11:10:52 -0700929
Amy Maloche7e447432011-09-14 11:36:30 -0700930 mxt_reset_delay(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700931
932 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800933 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700934 if (error)
Jing Lin32c72532011-11-03 12:02:33 -0700935 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700936 info->matrix_xsize = val;
937
Iiro Valkonen7686b102011-02-02 23:21:58 -0800938 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700939 if (error)
Jing Lin32c72532011-11-03 12:02:33 -0700940 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700941 info->matrix_ysize = val;
942
943 dev_info(&client->dev,
944 "Family ID: %d Variant ID: %d Version: %d Build: %d\n",
945 info->family_id, info->variant_id, info->version,
946 info->build);
947
948 dev_info(&client->dev,
949 "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
950 info->matrix_xsize, info->matrix_ysize,
951 info->object_num);
952
953 return 0;
Jing Lin32c72532011-11-03 12:02:33 -0700954
955free_object_table:
956 kfree(data->object_table);
957 return error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700958}
959
Iiro Valkonen7686b102011-02-02 23:21:58 -0800960static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700961 struct device_attribute *attr, char *buf)
962{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800963 struct mxt_data *data = dev_get_drvdata(dev);
964 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700965 int count = 0;
966 int i, j;
967 int error;
968 u8 val;
969
970 for (i = 0; i < data->info.object_num; i++) {
971 object = data->object_table + i;
972
Daniel Kurtz4ef11a82011-11-02 10:43:08 -0700973 count += snprintf(buf + count, PAGE_SIZE - count,
974 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700975 i + 1, object->type);
Daniel Kurtz4ef11a82011-11-02 10:43:08 -0700976 if (count >= PAGE_SIZE)
977 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700978
Iiro Valkonen7686b102011-02-02 23:21:58 -0800979 if (!mxt_object_readable(object->type)) {
Daniel Kurtz4ef11a82011-11-02 10:43:08 -0700980 count += snprintf(buf + count, PAGE_SIZE - count,
981 "\n");
982 if (count >= PAGE_SIZE)
983 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700984 continue;
985 }
986
987 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800988 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700989 object->type, j, &val);
990 if (error)
991 return error;
992
Daniel Kurtz4ef11a82011-11-02 10:43:08 -0700993 count += snprintf(buf + count, PAGE_SIZE - count,
994 "\t[%2d]: %02x (%d)\n", j, val, val);
995 if (count >= PAGE_SIZE)
996 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700997 }
998
Daniel Kurtz4ef11a82011-11-02 10:43:08 -0700999 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1000 if (count >= PAGE_SIZE)
1001 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001002 }
1003
1004 return count;
1005}
1006
Iiro Valkonen7686b102011-02-02 23:21:58 -08001007static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001008{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001009 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001010 struct i2c_client *client = data->client;
1011 const struct firmware *fw = NULL;
1012 unsigned int frame_size;
1013 unsigned int pos = 0;
1014 int ret;
1015
1016 ret = request_firmware(&fw, fn, dev);
1017 if (ret) {
1018 dev_err(dev, "Unable to open firmware %s\n", fn);
1019 return ret;
1020 }
1021
1022 /* Change to the bootloader mode */
Iiro Valkonene8645592011-11-18 12:56:19 -08001023 mxt_write_object(data, MXT_GEN_COMMAND_T6,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001024 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
Amy Maloche7e447432011-09-14 11:36:30 -07001025
1026 mxt_reset_delay(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001027
1028 /* Change to slave address of bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001029 if (client->addr == MXT_APP_LOW)
1030 client->addr = MXT_BOOT_LOW;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001031 else
Iiro Valkonen7686b102011-02-02 23:21:58 -08001032 client->addr = MXT_BOOT_HIGH;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001033
Iiro Valkonen7686b102011-02-02 23:21:58 -08001034 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001035 if (ret)
1036 goto out;
1037
1038 /* Unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001039 mxt_unlock_bootloader(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001040
1041 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001042 ret = mxt_check_bootloader(client,
1043 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001044 if (ret)
1045 goto out;
1046
1047 frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
1048
1049 /* We should add 2 at frame size as the the firmware data is not
1050 * included the CRC bytes.
1051 */
1052 frame_size += 2;
1053
1054 /* Write one frame to device */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001055 mxt_fw_write(client, fw->data + pos, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001056
Iiro Valkonen7686b102011-02-02 23:21:58 -08001057 ret = mxt_check_bootloader(client,
1058 MXT_FRAME_CRC_PASS);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001059 if (ret)
1060 goto out;
1061
1062 pos += frame_size;
1063
1064 dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
1065 }
1066
1067out:
1068 release_firmware(fw);
1069
1070 /* Change to slave address of application */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001071 if (client->addr == MXT_BOOT_LOW)
1072 client->addr = MXT_APP_LOW;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001073 else
Iiro Valkonen7686b102011-02-02 23:21:58 -08001074 client->addr = MXT_APP_HIGH;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001075
1076 return ret;
1077}
1078
Iiro Valkonen7686b102011-02-02 23:21:58 -08001079static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001080 struct device_attribute *attr,
1081 const char *buf, size_t count)
1082{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001083 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001084 int error;
1085
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001086 disable_irq(data->irq);
1087
Iiro Valkonen7686b102011-02-02 23:21:58 -08001088 error = mxt_load_fw(dev, MXT_FW_NAME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001089 if (error) {
1090 dev_err(dev, "The firmware update failed(%d)\n", error);
1091 count = error;
1092 } else {
1093 dev_dbg(dev, "The firmware update succeeded\n");
1094
1095 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001096 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001097
1098 kfree(data->object_table);
1099 data->object_table = NULL;
1100
Iiro Valkonen7686b102011-02-02 23:21:58 -08001101 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001102 }
1103
1104 enable_irq(data->irq);
1105
Iiro Valkonen08960a02011-04-12 23:16:40 -07001106 error = mxt_make_highchg(data);
1107 if (error)
1108 return error;
1109
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001110 return count;
1111}
1112
Iiro Valkonen7686b102011-02-02 23:21:58 -08001113static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
1114static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001115
Iiro Valkonen7686b102011-02-02 23:21:58 -08001116static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001117 &dev_attr_object.attr,
1118 &dev_attr_update_fw.attr,
1119 NULL
1120};
1121
Iiro Valkonen7686b102011-02-02 23:21:58 -08001122static const struct attribute_group mxt_attr_group = {
1123 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001124};
1125
Amy Maloche52262212011-09-15 16:46:57 -07001126static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001127{
Jing Lin36aee812011-10-17 17:17:28 -07001128 int error;
1129
Amy Maloche52262212011-09-15 16:46:57 -07001130 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07001131 error = __mxt_write_reg(data->client, data->t7_start_addr,
1132 T7_DATA_SIZE, data->t7_data);
1133 if (error < 0) {
1134 dev_err(&data->client->dev,
1135 "failed to restore old power state\n");
1136 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001137 }
Jing Lin36aee812011-10-17 17:17:28 -07001138
Amy Maloche52262212011-09-15 16:46:57 -07001139 error = mxt_write_object(data,
Iiro Valkonene8645592011-11-18 12:56:19 -08001140 MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, data->t9_ctrl);
Amy Maloche52262212011-09-15 16:46:57 -07001141 if (error < 0) {
1142 dev_err(&data->client->dev, "failed to restore touch\n");
1143 return error;
1144 }
1145
1146 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001147}
1148
Amy Maloche52262212011-09-15 16:46:57 -07001149static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001150{
Jing Lin36aee812011-10-17 17:17:28 -07001151 int error;
1152 u8 t7_data[T7_DATA_SIZE] = {0};
1153
1154 /* disable touch and configure deep sleep mode */
Iiro Valkonene8645592011-11-18 12:56:19 -08001155 error = mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
Jing Lin36aee812011-10-17 17:17:28 -07001156 if (error < 0) {
1157 dev_err(&data->client->dev, "failed to disable touch\n");
1158 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001159 }
1160
Jing Lin36aee812011-10-17 17:17:28 -07001161 error = __mxt_write_reg(data->client, data->t7_start_addr,
1162 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07001163 if (error < 0) {
1164 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07001165 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07001166 return error;
1167 }
1168
1169 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001170}
1171
Iiro Valkonen7686b102011-02-02 23:21:58 -08001172static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001173{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001174 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001175 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001176
Amy Maloche52262212011-09-15 16:46:57 -07001177 error = mxt_start(data);
1178 if (error < 0) {
1179 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
1180 return error;
1181 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001182
1183 return 0;
1184}
1185
Iiro Valkonen7686b102011-02-02 23:21:58 -08001186static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001187{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001188 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001189 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001190
Amy Maloche52262212011-09-15 16:46:57 -07001191 error = mxt_stop(data);
1192 if (error < 0)
1193 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
1194
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001195}
1196
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301197static int mxt_power_on(struct mxt_data *data, bool on)
1198{
1199 int rc;
1200
1201 if (on == false)
1202 goto power_off;
1203
Amy Maloche21115eb2011-11-02 09:04:37 -07001204 rc = regulator_set_optimum_mode(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301205 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001206 dev_err(&data->client->dev,
1207 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301208 return rc;
1209 }
1210
Amy Maloche21115eb2011-11-02 09:04:37 -07001211 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301212 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001213 dev_err(&data->client->dev,
1214 "Regulator vcc_ana enable failed rc=%d\n", rc);
1215 goto error_reg_en_vcc_ana;
1216 }
1217
1218 if (data->pdata->digital_pwr_regulator) {
1219 rc = regulator_set_optimum_mode(data->vcc_dig,
1220 MXT_ACTIVE_LOAD_DIG_UA);
1221 if (rc < 0) {
1222 dev_err(&data->client->dev,
1223 "Regulator vcc_dig set_opt failed rc=%d\n",
1224 rc);
1225 goto error_reg_opt_vcc_dig;
1226 }
1227
1228 rc = regulator_enable(data->vcc_dig);
1229 if (rc) {
1230 dev_err(&data->client->dev,
1231 "Regulator vcc_dig enable failed rc=%d\n", rc);
1232 goto error_reg_en_vcc_dig;
1233 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301234 }
1235
1236 if (data->pdata->i2c_pull_up) {
1237 rc = regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LOAD_UA);
1238 if (rc < 0) {
1239 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001240 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301241 goto error_reg_opt_i2c;
1242 }
1243
1244 rc = regulator_enable(data->vcc_i2c);
1245 if (rc) {
1246 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001247 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301248 goto error_reg_en_vcc_i2c;
1249 }
1250 }
1251
Amy Malochef0d7b8d2011-10-17 12:10:51 -07001252 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301253
1254 return 0;
1255
1256error_reg_en_vcc_i2c:
1257 if (data->pdata->i2c_pull_up)
1258 regulator_set_optimum_mode(data->vcc_i2c, 0);
1259error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001260 if (data->pdata->digital_pwr_regulator)
1261 regulator_disable(data->vcc_dig);
1262error_reg_en_vcc_dig:
1263 if (data->pdata->digital_pwr_regulator)
1264 regulator_set_optimum_mode(data->vcc_dig, 0);
1265error_reg_opt_vcc_dig:
1266 regulator_disable(data->vcc_ana);
1267error_reg_en_vcc_ana:
1268 regulator_set_optimum_mode(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301269 return rc;
1270
1271power_off:
Amy Maloche21115eb2011-11-02 09:04:37 -07001272 regulator_set_optimum_mode(data->vcc_ana, 0);
1273 regulator_disable(data->vcc_ana);
1274 if (data->pdata->digital_pwr_regulator) {
1275 regulator_set_optimum_mode(data->vcc_dig, 0);
1276 regulator_disable(data->vcc_dig);
1277 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301278 if (data->pdata->i2c_pull_up) {
1279 regulator_set_optimum_mode(data->vcc_i2c, 0);
1280 regulator_disable(data->vcc_i2c);
1281 }
1282 msleep(50);
1283 return 0;
1284}
1285
1286static int mxt_regulator_configure(struct mxt_data *data, bool on)
1287{
1288 int rc;
1289
1290 if (on == false)
1291 goto hw_shutdown;
1292
Amy Maloche21115eb2011-11-02 09:04:37 -07001293 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
1294 if (IS_ERR(data->vcc_ana)) {
1295 rc = PTR_ERR(data->vcc_ana);
1296 dev_err(&data->client->dev,
1297 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301298 return rc;
1299 }
1300
Amy Maloche21115eb2011-11-02 09:04:37 -07001301 if (regulator_count_voltages(data->vcc_ana) > 0) {
1302 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301303 MXT_VTG_MAX_UV);
1304 if (rc) {
1305 dev_err(&data->client->dev,
1306 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07001307 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301308 }
1309 }
Amy Maloche21115eb2011-11-02 09:04:37 -07001310 if (data->pdata->digital_pwr_regulator) {
1311 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
1312 if (IS_ERR(data->vcc_dig)) {
1313 rc = PTR_ERR(data->vcc_dig);
1314 dev_err(&data->client->dev,
1315 "Regulator get dig failed rc=%d\n", rc);
1316 goto error_get_vtg_vcc_dig;
1317 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301318
Amy Maloche21115eb2011-11-02 09:04:37 -07001319 if (regulator_count_voltages(data->vcc_dig) > 0) {
1320 rc = regulator_set_voltage(data->vcc_dig,
1321 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
1322 if (rc) {
1323 dev_err(&data->client->dev,
1324 "regulator set_vtg failed rc=%d\n", rc);
1325 goto error_set_vtg_vcc_dig;
1326 }
1327 }
1328 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301329 if (data->pdata->i2c_pull_up) {
1330 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
1331 if (IS_ERR(data->vcc_i2c)) {
1332 rc = PTR_ERR(data->vcc_i2c);
1333 dev_err(&data->client->dev,
1334 "Regulator get failed rc=%d\n", rc);
1335 goto error_get_vtg_i2c;
1336 }
1337 if (regulator_count_voltages(data->vcc_i2c) > 0) {
1338 rc = regulator_set_voltage(data->vcc_i2c,
1339 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
1340 if (rc) {
1341 dev_err(&data->client->dev,
1342 "regulator set_vtg failed rc=%d\n", rc);
1343 goto error_set_vtg_i2c;
1344 }
1345 }
1346 }
1347
1348 return 0;
1349
1350error_set_vtg_i2c:
1351 regulator_put(data->vcc_i2c);
1352error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001353 if (data->pdata->digital_pwr_regulator)
1354 if (regulator_count_voltages(data->vcc_dig) > 0)
1355 regulator_set_voltage(data->vcc_dig, 0,
1356 MXT_VTG_DIG_MAX_UV);
1357error_set_vtg_vcc_dig:
1358 if (data->pdata->digital_pwr_regulator)
1359 regulator_put(data->vcc_dig);
1360error_get_vtg_vcc_dig:
1361 if (regulator_count_voltages(data->vcc_ana) > 0)
1362 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1363error_set_vtg_vcc_ana:
1364 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301365 return rc;
1366
1367hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07001368 if (regulator_count_voltages(data->vcc_ana) > 0)
1369 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1370 regulator_put(data->vcc_ana);
1371 if (data->pdata->digital_pwr_regulator) {
1372 if (regulator_count_voltages(data->vcc_dig) > 0)
1373 regulator_set_voltage(data->vcc_dig, 0,
1374 MXT_VTG_DIG_MAX_UV);
1375 regulator_put(data->vcc_dig);
1376 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301377 if (data->pdata->i2c_pull_up) {
1378 if (regulator_count_voltages(data->vcc_i2c) > 0)
1379 regulator_set_voltage(data->vcc_i2c, 0,
1380 MXT_I2C_VTG_MAX_UV);
1381 regulator_put(data->vcc_i2c);
1382 }
1383 return 0;
1384}
1385
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301386#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07001387static int mxt_regulator_lpm(struct mxt_data *data, bool on)
1388{
1389
1390 int rc;
1391
1392 if (on == false)
1393 goto regulator_hpm;
1394
Amy Maloche21115eb2011-11-02 09:04:37 -07001395 rc = regulator_set_optimum_mode(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001396 if (rc < 0) {
1397 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001398 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001399 goto fail_regulator_lpm;
1400 }
1401
Amy Maloche21115eb2011-11-02 09:04:37 -07001402 if (data->pdata->digital_pwr_regulator) {
1403 rc = regulator_set_optimum_mode(data->vcc_dig,
1404 MXT_LPM_LOAD_DIG_UA);
1405 if (rc < 0) {
1406 dev_err(&data->client->dev,
1407 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
1408 goto fail_regulator_lpm;
1409 }
1410 }
1411
Jing Linbace50b2011-10-18 22:55:47 -07001412 if (data->pdata->i2c_pull_up) {
1413 rc = regulator_set_optimum_mode(data->vcc_i2c,
1414 MXT_I2C_LPM_LOAD_UA);
1415 if (rc < 0) {
1416 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001417 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001418 goto fail_regulator_lpm;
1419 }
1420 }
1421
1422 return 0;
1423
1424regulator_hpm:
1425
Amy Maloche21115eb2011-11-02 09:04:37 -07001426 rc = regulator_set_optimum_mode(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001427 if (rc < 0) {
1428 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001429 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001430 goto fail_regulator_hpm;
1431 }
1432
Amy Maloche21115eb2011-11-02 09:04:37 -07001433 if (data->pdata->digital_pwr_regulator) {
1434 rc = regulator_set_optimum_mode(data->vcc_dig,
1435 MXT_ACTIVE_LOAD_DIG_UA);
1436 if (rc < 0) {
1437 dev_err(&data->client->dev,
1438 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
1439 goto fail_regulator_hpm;
1440 }
1441 }
1442
Jing Linbace50b2011-10-18 22:55:47 -07001443 if (data->pdata->i2c_pull_up) {
1444 rc = regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LOAD_UA);
1445 if (rc < 0) {
1446 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001447 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001448 goto fail_regulator_hpm;
1449 }
1450 }
1451
1452 return 0;
1453
1454fail_regulator_lpm:
Amy Maloche21115eb2011-11-02 09:04:37 -07001455 regulator_set_optimum_mode(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
1456 if (data->pdata->digital_pwr_regulator)
1457 regulator_set_optimum_mode(data->vcc_dig,
1458 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001459 if (data->pdata->i2c_pull_up)
1460 regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LOAD_UA);
1461
1462 return rc;
1463
1464fail_regulator_hpm:
Amy Maloche21115eb2011-11-02 09:04:37 -07001465 regulator_set_optimum_mode(data->vcc_ana, MXT_LPM_LOAD_UA);
1466 if (data->pdata->digital_pwr_regulator)
1467 regulator_set_optimum_mode(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001468 if (data->pdata->i2c_pull_up)
1469 regulator_set_optimum_mode(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
1470
1471 return rc;
1472}
1473
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301474static int mxt_suspend(struct device *dev)
1475{
1476 struct i2c_client *client = to_i2c_client(dev);
1477 struct mxt_data *data = i2c_get_clientdata(client);
1478 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07001479 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301480
1481 mutex_lock(&input_dev->mutex);
1482
Amy Maloche52262212011-09-15 16:46:57 -07001483 if (input_dev->users) {
1484 error = mxt_stop(data);
1485 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07001486 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07001487 mutex_unlock(&input_dev->mutex);
1488 return error;
1489 }
1490
1491 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301492
1493 mutex_unlock(&input_dev->mutex);
1494
Jing Linbace50b2011-10-18 22:55:47 -07001495 /* put regulators in low power mode */
1496 error = mxt_regulator_lpm(data, true);
1497 if (error < 0) {
1498 dev_err(dev, "failed to enter low power mode\n");
1499 return error;
1500 }
1501
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301502 return 0;
1503}
1504
1505static int mxt_resume(struct device *dev)
1506{
1507 struct i2c_client *client = to_i2c_client(dev);
1508 struct mxt_data *data = i2c_get_clientdata(client);
1509 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07001510 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301511
Jing Linbace50b2011-10-18 22:55:47 -07001512 /* put regulators in high power mode */
1513 error = mxt_regulator_lpm(data, false);
1514 if (error < 0) {
1515 dev_err(dev, "failed to enter high power mode\n");
1516 return error;
1517 }
1518
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301519 mutex_lock(&input_dev->mutex);
1520
Amy Maloche52262212011-09-15 16:46:57 -07001521 if (input_dev->users) {
1522 error = mxt_start(data);
1523 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07001524 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07001525 mutex_unlock(&input_dev->mutex);
1526 return error;
1527 }
1528 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301529
1530 mutex_unlock(&input_dev->mutex);
1531
1532 return 0;
1533}
1534
1535#if defined(CONFIG_HAS_EARLYSUSPEND)
1536static void mxt_early_suspend(struct early_suspend *h)
1537{
1538 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
1539
1540 mxt_suspend(&data->client->dev);
1541}
1542
1543static void mxt_late_resume(struct early_suspend *h)
1544{
1545 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
1546
1547 mxt_resume(&data->client->dev);
1548}
1549#endif
1550
1551static const struct dev_pm_ops mxt_pm_ops = {
1552#ifndef CONFIG_HAS_EARLYSUSPEND
1553 .suspend = mxt_suspend,
1554 .resume = mxt_resume,
1555#endif
1556};
1557#endif
1558
Iiro Valkonen7686b102011-02-02 23:21:58 -08001559static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001560 const struct i2c_device_id *id)
1561{
Iiro Valkonen919ed892011-02-15 13:36:52 -08001562 const struct mxt_platform_data *pdata = client->dev.platform_data;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001563 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001564 struct input_dev *input_dev;
1565 int error;
1566
Iiro Valkonen919ed892011-02-15 13:36:52 -08001567 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001568 return -EINVAL;
1569
Iiro Valkonen7686b102011-02-02 23:21:58 -08001570 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001571 input_dev = input_allocate_device();
1572 if (!data || !input_dev) {
1573 dev_err(&client->dev, "Failed to allocate memory\n");
1574 error = -ENOMEM;
1575 goto err_free_mem;
1576 }
1577
Iiro Valkonen7686b102011-02-02 23:21:58 -08001578 input_dev->name = "Atmel maXTouch Touchscreen";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001579 input_dev->id.bustype = BUS_I2C;
1580 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001581 input_dev->open = mxt_input_open;
1582 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001583
Joonyoung Shim910d8052011-04-12 23:14:38 -07001584 data->client = client;
1585 data->input_dev = input_dev;
1586 data->pdata = pdata;
1587 data->irq = client->irq;
1588
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001589 __set_bit(EV_ABS, input_dev->evbit);
1590 __set_bit(EV_KEY, input_dev->evbit);
1591 __set_bit(BTN_TOUCH, input_dev->keybit);
1592
1593 /* For single touch */
1594 input_set_abs_params(input_dev, ABS_X,
Jing Lin2f863172011-10-17 10:56:58 -07001595 0, data->pdata->x_size, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001596 input_set_abs_params(input_dev, ABS_Y,
Jing Lin2f863172011-10-17 10:56:58 -07001597 0, data->pdata->y_size, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07001598 input_set_abs_params(input_dev, ABS_PRESSURE,
1599 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001600
1601 /* For multi touch */
1602 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001603 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001604 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Jing Lin2f863172011-10-17 10:56:58 -07001605 0, data->pdata->x_size, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001606 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Jing Lin2f863172011-10-17 10:56:58 -07001607 0, data->pdata->y_size, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07001608 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
1609 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001610
1611 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001612 i2c_set_clientdata(client, data);
1613
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301614 if (pdata->init_hw)
1615 error = pdata->init_hw(true);
1616 else
1617 error = mxt_regulator_configure(data, true);
1618 if (error) {
1619 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07001620 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301621 }
1622
1623 if (pdata->power_on)
1624 error = pdata->power_on(true);
1625 else
1626 error = mxt_power_on(data, true);
1627 if (error) {
1628 dev_err(&client->dev, "Failed to power on hardware\n");
1629 goto err_regulator_on;
1630 }
1631
Amy Maloche08266db2011-11-04 11:07:16 -07001632 if (gpio_is_valid(pdata->irq_gpio)) {
1633 /* configure touchscreen irq gpio */
1634 error = gpio_request(pdata->irq_gpio,
1635 "mxt_irq_gpio");
1636 if (error) {
1637 pr_err("%s: unable to request gpio [%d]\n", __func__,
1638 pdata->irq_gpio);
1639 goto err_power_on;
1640 }
1641 error = gpio_direction_input(pdata->irq_gpio);
1642 if (error) {
1643 pr_err("%s: unable to set_direction for gpio [%d]\n",
1644 __func__, pdata->irq_gpio);
1645 goto err_irq_gpio_req;
1646 }
1647 }
1648
1649 if (gpio_is_valid(pdata->reset_gpio)) {
1650 /* configure touchscreen reset out gpio */
1651 error = gpio_request(pdata->reset_gpio,
1652 "mxt_reset_gpio");
1653 if (error) {
1654 pr_err("%s: unable to request reset gpio %d\n",
1655 __func__, pdata->reset_gpio);
1656 goto err_irq_gpio_req;
1657 }
1658
1659 error = gpio_direction_output(
1660 pdata->reset_gpio, 1);
1661 if (error) {
1662 pr_err("%s: unable to set direction for gpio %d\n",
1663 __func__, pdata->reset_gpio);
1664 goto err_reset_gpio_req;
1665 }
1666 }
1667
1668 mxt_reset_delay(data);
1669
Iiro Valkonen7686b102011-02-02 23:21:58 -08001670 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001671 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07001672 goto err_reset_gpio_req;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001673
Iiro Valkonen7686b102011-02-02 23:21:58 -08001674 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08001675 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001676 if (error) {
1677 dev_err(&client->dev, "Failed to register interrupt\n");
Jing Lin32c72532011-11-03 12:02:33 -07001678 goto err_free_object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001679 }
1680
Iiro Valkonen08960a02011-04-12 23:16:40 -07001681 error = mxt_make_highchg(data);
1682 if (error)
1683 goto err_free_irq;
1684
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001685 error = input_register_device(input_dev);
1686 if (error)
1687 goto err_free_irq;
1688
Iiro Valkonen7686b102011-02-02 23:21:58 -08001689 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001690 if (error)
1691 goto err_unregister_device;
1692
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301693#if defined(CONFIG_HAS_EARLYSUSPEND)
1694 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
1695 MXT_SUSPEND_LEVEL;
1696 data->early_suspend.suspend = mxt_early_suspend;
1697 data->early_suspend.resume = mxt_late_resume;
1698 register_early_suspend(&data->early_suspend);
1699#endif
1700
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001701 return 0;
1702
1703err_unregister_device:
1704 input_unregister_device(input_dev);
1705 input_dev = NULL;
1706err_free_irq:
1707 free_irq(client->irq, data);
Jing Lin32c72532011-11-03 12:02:33 -07001708err_free_object:
1709 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07001710err_reset_gpio_req:
1711 if (gpio_is_valid(pdata->reset_gpio))
1712 gpio_free(pdata->reset_gpio);
1713err_irq_gpio_req:
1714 if (gpio_is_valid(pdata->irq_gpio))
1715 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301716err_power_on:
1717 if (pdata->power_on)
1718 pdata->power_on(false);
1719 else
1720 mxt_power_on(data, false);
1721err_regulator_on:
1722 if (pdata->init_hw)
1723 pdata->init_hw(false);
1724 else
1725 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001726err_free_mem:
1727 input_free_device(input_dev);
1728 kfree(data);
1729 return error;
1730}
1731
Iiro Valkonen7686b102011-02-02 23:21:58 -08001732static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001733{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001734 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001735
Iiro Valkonen7686b102011-02-02 23:21:58 -08001736 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001737 free_irq(data->irq, data);
1738 input_unregister_device(data->input_dev);
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301739#if defined(CONFIG_HAS_EARLYSUSPEND)
1740 unregister_early_suspend(&data->early_suspend);
1741#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301742
1743 if (data->pdata->power_on)
1744 data->pdata->power_on(false);
1745 else
1746 mxt_power_on(data, false);
1747
1748 if (data->pdata->init_hw)
1749 data->pdata->init_hw(false);
1750 else
1751 mxt_regulator_configure(data, false);
1752
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001753 kfree(data->object_table);
1754 kfree(data);
1755
1756 return 0;
1757}
1758
Iiro Valkonen7686b102011-02-02 23:21:58 -08001759static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001760 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08001761 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08001762 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001763 { }
1764};
Iiro Valkonen7686b102011-02-02 23:21:58 -08001765MODULE_DEVICE_TABLE(i2c, mxt_id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001766
Iiro Valkonen7686b102011-02-02 23:21:58 -08001767static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001768 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001769 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001770 .owner = THIS_MODULE,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08001771#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08001772 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08001773#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001774 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08001775 .probe = mxt_probe,
1776 .remove = __devexit_p(mxt_remove),
1777 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001778};
1779
Iiro Valkonen7686b102011-02-02 23:21:58 -08001780static int __init mxt_init(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001781{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001782 return i2c_add_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001783}
1784
Iiro Valkonen7686b102011-02-02 23:21:58 -08001785static void __exit mxt_exit(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001786{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001787 i2c_del_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001788}
1789
Iiro Valkonen7686b102011-02-02 23:21:58 -08001790module_init(mxt_init);
1791module_exit(mxt_exit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001792
1793/* Module information */
1794MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08001795MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001796MODULE_LICENSE("GPL");