blob: 39c158d657bab039c5e1a4ee6052465daad4e791 [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>
Joonyoung Shimcd473222012-02-14 18:32:48 -080021#include <linux/input/mt.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>
Jing Lin6cfc00e2011-11-02 15:15:30 -070025#include <linux/debugfs.h>
26#include <linux/seq_file.h>
Anirudh Ghayala498e4d2011-08-09 19:10:12 +053027#include <linux/regulator/consumer.h>
Jing Lincc974cb2012-02-01 23:13:14 -080028#include <linux/string.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070029
Anirudh Ghayal253ce122011-08-09 19:32:57 +053030#if defined(CONFIG_HAS_EARLYSUSPEND)
31#include <linux/earlysuspend.h>
32/* Early-suspend level */
33#define MXT_SUSPEND_LEVEL 1
34#endif
35
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070036/* Family ID */
37#define MXT224_ID 0x80
Amy Maloche380cc0b2011-11-03 12:55:04 -070038#define MXT224E_ID 0x81
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070039#define MXT1386_ID 0xA0
40
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070041/* Version */
Iiro Valkonen7686b102011-02-02 23:21:58 -080042#define MXT_VER_20 20
43#define MXT_VER_21 21
44#define MXT_VER_22 22
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070045
Nick Dyer0a4016c2012-01-18 15:17:59 +053046/* I2C slave address pairs */
47struct mxt_address_pair {
48 int bootloader;
49 int application;
50};
51
52static const struct mxt_address_pair mxt_slave_addresses[] = {
53 { 0x24, 0x4a },
54 { 0x25, 0x4b },
55 { 0x25, 0x4b },
56 { 0x26, 0x4c },
57 { 0x27, 0x4d },
58 { 0x34, 0x5a },
59 { 0x35, 0x5b },
60 { 0 },
61};
62
63enum mxt_device_state { INIT, APPMODE, BOOTLOADER };
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070064
65/* Firmware */
Iiro Valkonen7686b102011-02-02 23:21:58 -080066#define MXT_FW_NAME "maxtouch.fw"
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070067
Jing Lincc974cb2012-02-01 23:13:14 -080068/* Firmware frame size including frame data and CRC */
69#define MXT_SINGLE_FW_MAX_FRAME_SIZE 278
70#define MXT_CHIPSET_FW_MAX_FRAME_SIZE 534
71
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070072/* Registers */
Iiro Valkonen7686b102011-02-02 23:21:58 -080073#define MXT_FAMILY_ID 0x00
74#define MXT_VARIANT_ID 0x01
75#define MXT_VERSION 0x02
76#define MXT_BUILD 0x03
77#define MXT_MATRIX_X_SIZE 0x04
78#define MXT_MATRIX_Y_SIZE 0x05
79#define MXT_OBJECT_NUM 0x06
80#define MXT_OBJECT_START 0x07
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070081
Iiro Valkonen7686b102011-02-02 23:21:58 -080082#define MXT_OBJECT_SIZE 6
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070083
84/* Object types */
Iiro Valkonene8645592011-11-18 12:56:19 -080085#define MXT_DEBUG_DIAGNOSTIC_T37 37
86#define MXT_GEN_MESSAGE_T5 5
87#define MXT_GEN_COMMAND_T6 6
88#define MXT_GEN_POWER_T7 7
89#define MXT_GEN_ACQUIRE_T8 8
90#define MXT_GEN_DATASOURCE_T53 53
91#define MXT_TOUCH_MULTI_T9 9
92#define MXT_TOUCH_KEYARRAY_T15 15
93#define MXT_TOUCH_PROXIMITY_T23 23
94#define MXT_TOUCH_PROXKEY_T52 52
95#define MXT_PROCI_GRIPFACE_T20 20
96#define MXT_PROCG_NOISE_T22 22
97#define MXT_PROCI_ONETOUCH_T24 24
98#define MXT_PROCI_TWOTOUCH_T27 27
99#define MXT_PROCI_GRIP_T40 40
100#define MXT_PROCI_PALM_T41 41
101#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
102#define MXT_PROCI_STYLUS_T47 47
Jing Linc7fc4052011-12-21 16:16:19 -0800103#define MXT_PROCI_SHIELDLESS_T56 56
Iiro Valkonene8645592011-11-18 12:56:19 -0800104#define MXT_PROCG_NOISESUPPRESSION_T48 48
105#define MXT_SPT_COMMSCONFIG_T18 18
106#define MXT_SPT_GPIOPWM_T19 19
107#define MXT_SPT_SELFTEST_T25 25
108#define MXT_SPT_CTECONFIG_T28 28
109#define MXT_SPT_USERDATA_T38 38
110#define MXT_SPT_DIGITIZER_T43 43
111#define MXT_SPT_MESSAGECOUNT_T44 44
112#define MXT_SPT_CTECONFIG_T46 46
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700113
Iiro Valkonene8645592011-11-18 12:56:19 -0800114/* MXT_GEN_COMMAND_T6 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800115#define MXT_COMMAND_RESET 0
116#define MXT_COMMAND_BACKUPNV 1
117#define MXT_COMMAND_CALIBRATE 2
118#define MXT_COMMAND_REPORTALL 3
119#define MXT_COMMAND_DIAGNOSTIC 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700120
Iiro Valkonene8645592011-11-18 12:56:19 -0800121/* MXT_GEN_POWER_T7 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800122#define MXT_POWER_IDLEACQINT 0
123#define MXT_POWER_ACTVACQINT 1
124#define MXT_POWER_ACTV2IDLETO 2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700125
Iiro Valkonene8645592011-11-18 12:56:19 -0800126/* MXT_GEN_ACQUIRE_T8 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800127#define MXT_ACQUIRE_CHRGTIME 0
128#define MXT_ACQUIRE_TCHDRIFT 2
129#define MXT_ACQUIRE_DRIFTST 3
130#define MXT_ACQUIRE_TCHAUTOCAL 4
131#define MXT_ACQUIRE_SYNC 5
132#define MXT_ACQUIRE_ATCHCALST 6
133#define MXT_ACQUIRE_ATCHCALSTHR 7
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700134
Iiro Valkonene8645592011-11-18 12:56:19 -0800135/* MXT_TOUCH_MULT_T9 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800136#define MXT_TOUCH_CTRL 0
137#define MXT_TOUCH_XORIGIN 1
138#define MXT_TOUCH_YORIGIN 2
139#define MXT_TOUCH_XSIZE 3
140#define MXT_TOUCH_YSIZE 4
141#define MXT_TOUCH_BLEN 6
142#define MXT_TOUCH_TCHTHR 7
143#define MXT_TOUCH_TCHDI 8
144#define MXT_TOUCH_ORIENT 9
145#define MXT_TOUCH_MOVHYSTI 11
146#define MXT_TOUCH_MOVHYSTN 12
147#define MXT_TOUCH_NUMTOUCH 14
148#define MXT_TOUCH_MRGHYST 15
149#define MXT_TOUCH_MRGTHR 16
150#define MXT_TOUCH_AMPHYST 17
151#define MXT_TOUCH_XRANGE_LSB 18
152#define MXT_TOUCH_XRANGE_MSB 19
153#define MXT_TOUCH_YRANGE_LSB 20
154#define MXT_TOUCH_YRANGE_MSB 21
155#define MXT_TOUCH_XLOCLIP 22
156#define MXT_TOUCH_XHICLIP 23
157#define MXT_TOUCH_YLOCLIP 24
158#define MXT_TOUCH_YHICLIP 25
159#define MXT_TOUCH_XEDGECTRL 26
160#define MXT_TOUCH_XEDGEDIST 27
161#define MXT_TOUCH_YEDGECTRL 28
162#define MXT_TOUCH_YEDGEDIST 29
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700163#define MXT_TOUCH_JUMPLIMIT 30
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700164
Iiro Valkonene8645592011-11-18 12:56:19 -0800165/* MXT_PROCI_GRIPFACE_T20 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800166#define MXT_GRIPFACE_CTRL 0
167#define MXT_GRIPFACE_XLOGRIP 1
168#define MXT_GRIPFACE_XHIGRIP 2
169#define MXT_GRIPFACE_YLOGRIP 3
170#define MXT_GRIPFACE_YHIGRIP 4
171#define MXT_GRIPFACE_MAXTCHS 5
172#define MXT_GRIPFACE_SZTHR1 7
173#define MXT_GRIPFACE_SZTHR2 8
174#define MXT_GRIPFACE_SHPTHR1 9
175#define MXT_GRIPFACE_SHPTHR2 10
176#define MXT_GRIPFACE_SUPEXTTO 11
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700177
Iiro Valkonen7686b102011-02-02 23:21:58 -0800178/* MXT_PROCI_NOISE field */
179#define MXT_NOISE_CTRL 0
180#define MXT_NOISE_OUTFLEN 1
181#define MXT_NOISE_GCAFUL_LSB 3
182#define MXT_NOISE_GCAFUL_MSB 4
183#define MXT_NOISE_GCAFLL_LSB 5
184#define MXT_NOISE_GCAFLL_MSB 6
185#define MXT_NOISE_ACTVGCAFVALID 7
186#define MXT_NOISE_NOISETHR 8
187#define MXT_NOISE_FREQHOPSCALE 10
188#define MXT_NOISE_FREQ0 11
189#define MXT_NOISE_FREQ1 12
190#define MXT_NOISE_FREQ2 13
191#define MXT_NOISE_FREQ3 14
192#define MXT_NOISE_FREQ4 15
193#define MXT_NOISE_IDLEGCAFVALID 16
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700194
Iiro Valkonene8645592011-11-18 12:56:19 -0800195/* MXT_SPT_COMMSCONFIG_T18 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800196#define MXT_COMMS_CTRL 0
197#define MXT_COMMS_CMD 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700198
Iiro Valkonene8645592011-11-18 12:56:19 -0800199/* MXT_SPT_CTECONFIG_T28 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800200#define MXT_CTE_CTRL 0
201#define MXT_CTE_CMD 1
202#define MXT_CTE_MODE 2
203#define MXT_CTE_IDLEGCAFDEPTH 3
204#define MXT_CTE_ACTVGCAFDEPTH 4
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700205#define MXT_CTE_VOLTAGE 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700206
Iiro Valkonen7686b102011-02-02 23:21:58 -0800207#define MXT_VOLTAGE_DEFAULT 2700000
208#define MXT_VOLTAGE_STEP 10000
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700209
Amy Maloche21115eb2011-11-02 09:04:37 -0700210/* Analog voltage @2.7 V */
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530211#define MXT_VTG_MIN_UV 2700000
212#define MXT_VTG_MAX_UV 3300000
213#define MXT_ACTIVE_LOAD_UA 15000
Jing Linbace50b2011-10-18 22:55:47 -0700214#define MXT_LPM_LOAD_UA 10
Amy Maloche21115eb2011-11-02 09:04:37 -0700215/* Digital voltage @1.8 V */
216#define MXT_VTG_DIG_MIN_UV 1800000
217#define MXT_VTG_DIG_MAX_UV 1800000
218#define MXT_ACTIVE_LOAD_DIG_UA 10000
219#define MXT_LPM_LOAD_DIG_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530220
221#define MXT_I2C_VTG_MIN_UV 1800000
222#define MXT_I2C_VTG_MAX_UV 1800000
223#define MXT_I2C_LOAD_UA 10000
Jing Linbace50b2011-10-18 22:55:47 -0700224#define MXT_I2C_LPM_LOAD_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530225
Iiro Valkonene8645592011-11-18 12:56:19 -0800226/* Define for MXT_GEN_COMMAND_T6 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800227#define MXT_BOOT_VALUE 0xa5
228#define MXT_BACKUP_VALUE 0x55
229#define MXT_BACKUP_TIME 25 /* msec */
Jing Linc7fc4052011-12-21 16:16:19 -0800230#define MXT224_RESET_TIME 65 /* msec */
231#define MXT224E_RESET_TIME 22 /* msec */
232#define MXT1386_RESET_TIME 250 /* msec */
Amy Maloche7e447432011-09-14 11:36:30 -0700233#define MXT_RESET_TIME 250 /* msec */
Jing Linc7fc4052011-12-21 16:16:19 -0800234#define MXT_RESET_NOCHGREAD 400 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700235
Nick Dyer0a4016c2012-01-18 15:17:59 +0530236#define MXT_FWRESET_TIME 1000 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700237
Jing Lin36aee812011-10-17 17:17:28 -0700238#define MXT_WAKE_TIME 25
239
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700240/* Command to unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800241#define MXT_UNLOCK_CMD_MSB 0xaa
242#define MXT_UNLOCK_CMD_LSB 0xdc
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700243
244/* Bootloader mode status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800245#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
246#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
247#define MXT_FRAME_CRC_CHECK 0x02
248#define MXT_FRAME_CRC_FAIL 0x03
249#define MXT_FRAME_CRC_PASS 0x04
250#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
251#define MXT_BOOT_STATUS_MASK 0x3f
Nick Dyer0a4016c2012-01-18 15:17:59 +0530252#define MXT_BOOT_EXTENDED_ID (1 << 5)
253#define MXT_BOOT_ID_MASK 0x1f
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700254
255/* Touch status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800256#define MXT_SUPPRESS (1 << 1)
257#define MXT_AMP (1 << 2)
258#define MXT_VECTOR (1 << 3)
259#define MXT_MOVE (1 << 4)
260#define MXT_RELEASE (1 << 5)
261#define MXT_PRESS (1 << 6)
262#define MXT_DETECT (1 << 7)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700263
Joonyoung Shim910d8052011-04-12 23:14:38 -0700264/* Touch orient bits */
265#define MXT_XY_SWITCH (1 << 0)
266#define MXT_X_INVERT (1 << 1)
267#define MXT_Y_INVERT (1 << 2)
268
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700269/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800270#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700271
Iiro Valkonen7686b102011-02-02 23:21:58 -0800272#define MXT_MAX_FINGER 10
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700273
Jing Lin36aee812011-10-17 17:17:28 -0700274#define T7_DATA_SIZE 3
275#define MXT_MAX_RW_TRIES 3
276#define MXT_BLOCK_SIZE 256
Mohan Pallakaab51f2b2011-09-29 18:17:35 +0530277
Jing Lin6cfc00e2011-11-02 15:15:30 -0700278#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
279#define MXT_DEBUGFS_FILE "object"
280
Iiro Valkonen7686b102011-02-02 23:21:58 -0800281struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700282 u8 family_id;
283 u8 variant_id;
284 u8 version;
285 u8 build;
286 u8 matrix_xsize;
287 u8 matrix_ysize;
288 u8 object_num;
289};
290
Iiro Valkonen7686b102011-02-02 23:21:58 -0800291struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700292 u8 type;
293 u16 start_address;
294 u8 size;
295 u8 instances;
296 u8 num_report_ids;
297
298 /* to map object and message */
299 u8 max_reportid;
300};
301
Iiro Valkonen7686b102011-02-02 23:21:58 -0800302struct mxt_message {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700303 u8 reportid;
304 u8 message[7];
305 u8 checksum;
306};
307
Iiro Valkonen7686b102011-02-02 23:21:58 -0800308struct mxt_finger {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700309 int status;
310 int x;
311 int y;
312 int area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700313 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700314};
315
316/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800317struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700318 struct i2c_client *client;
319 struct input_dev *input_dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800320 const struct mxt_platform_data *pdata;
Jing Lindc4413c2012-01-16 15:22:52 -0800321 const struct mxt_config_info *config_info;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530322 enum mxt_device_state state;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800323 struct mxt_object *object_table;
324 struct mxt_info info;
325 struct mxt_finger finger[MXT_MAX_FINGER];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700326 unsigned int irq;
Amy Maloche21115eb2011-11-02 09:04:37 -0700327 struct regulator *vcc_ana;
328 struct regulator *vcc_dig;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530329 struct regulator *vcc_i2c;
Anirudh Ghayal253ce122011-08-09 19:32:57 +0530330#if defined(CONFIG_HAS_EARLYSUSPEND)
331 struct early_suspend early_suspend;
332#endif
Jing Lin36aee812011-10-17 17:17:28 -0700333
Amy Maloche52262212011-09-15 16:46:57 -0700334 u8 t7_data[T7_DATA_SIZE];
Jing Lin36aee812011-10-17 17:17:28 -0700335 u16 t7_start_addr;
Amy Maloche52262212011-09-15 16:46:57 -0700336 u8 t9_ctrl;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800337 u32 keyarray_old;
338 u32 keyarray_new;
339 u8 t9_max_reportid;
340 u8 t9_min_reportid;
341 u8 t15_max_reportid;
342 u8 t15_min_reportid;
Jing Lindc4413c2012-01-16 15:22:52 -0800343 u8 curr_cfg_version;
344 int cfg_version_idx;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -0800345 const char *fw_name;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700346};
347
Jing Lin6cfc00e2011-11-02 15:15:30 -0700348static struct dentry *debug_base;
349
Iiro Valkonen7686b102011-02-02 23:21:58 -0800350static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700351{
352 switch (type) {
Iiro Valkonene8645592011-11-18 12:56:19 -0800353 case MXT_GEN_MESSAGE_T5:
354 case MXT_GEN_COMMAND_T6:
355 case MXT_GEN_POWER_T7:
356 case MXT_GEN_ACQUIRE_T8:
357 case MXT_GEN_DATASOURCE_T53:
358 case MXT_TOUCH_MULTI_T9:
359 case MXT_TOUCH_KEYARRAY_T15:
360 case MXT_TOUCH_PROXIMITY_T23:
361 case MXT_TOUCH_PROXKEY_T52:
362 case MXT_PROCI_GRIPFACE_T20:
363 case MXT_PROCG_NOISE_T22:
364 case MXT_PROCI_ONETOUCH_T24:
365 case MXT_PROCI_TWOTOUCH_T27:
366 case MXT_PROCI_GRIP_T40:
367 case MXT_PROCI_PALM_T41:
368 case MXT_PROCI_TOUCHSUPPRESSION_T42:
369 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800370 case MXT_PROCI_SHIELDLESS_T56:
Iiro Valkonene8645592011-11-18 12:56:19 -0800371 case MXT_PROCG_NOISESUPPRESSION_T48:
372 case MXT_SPT_COMMSCONFIG_T18:
373 case MXT_SPT_GPIOPWM_T19:
374 case MXT_SPT_SELFTEST_T25:
375 case MXT_SPT_CTECONFIG_T28:
376 case MXT_SPT_USERDATA_T38:
377 case MXT_SPT_DIGITIZER_T43:
378 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700379 return true;
380 default:
381 return false;
382 }
383}
384
Iiro Valkonen7686b102011-02-02 23:21:58 -0800385static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700386{
387 switch (type) {
Iiro Valkonene8645592011-11-18 12:56:19 -0800388 case MXT_GEN_COMMAND_T6:
389 case MXT_GEN_POWER_T7:
390 case MXT_GEN_ACQUIRE_T8:
391 case MXT_TOUCH_MULTI_T9:
392 case MXT_TOUCH_KEYARRAY_T15:
393 case MXT_TOUCH_PROXIMITY_T23:
394 case MXT_TOUCH_PROXKEY_T52:
395 case MXT_PROCI_GRIPFACE_T20:
396 case MXT_PROCG_NOISE_T22:
397 case MXT_PROCI_ONETOUCH_T24:
398 case MXT_PROCI_TWOTOUCH_T27:
399 case MXT_PROCI_GRIP_T40:
400 case MXT_PROCI_PALM_T41:
401 case MXT_PROCI_TOUCHSUPPRESSION_T42:
402 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800403 case MXT_PROCI_SHIELDLESS_T56:
Iiro Valkonene8645592011-11-18 12:56:19 -0800404 case MXT_PROCG_NOISESUPPRESSION_T48:
405 case MXT_SPT_COMMSCONFIG_T18:
406 case MXT_SPT_GPIOPWM_T19:
407 case MXT_SPT_SELFTEST_T25:
408 case MXT_SPT_CTECONFIG_T28:
409 case MXT_SPT_USERDATA_T38:
410 case MXT_SPT_DIGITIZER_T43:
411 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700412 return true;
413 default:
414 return false;
415 }
416}
417
Iiro Valkonen7686b102011-02-02 23:21:58 -0800418static void mxt_dump_message(struct device *dev,
419 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700420{
421 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
422 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
423 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
424 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
425 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
426 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
427 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
428 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
429 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
430}
431
Nick Dyer0a4016c2012-01-18 15:17:59 +0530432static int mxt_switch_to_bootloader_address(struct mxt_data *data)
433{
434 int i;
435 struct i2c_client *client = data->client;
436
437 if (data->state == BOOTLOADER) {
438 dev_err(&client->dev, "Already in BOOTLOADER state\n");
439 return -EINVAL;
440 }
441
442 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
443 if (mxt_slave_addresses[i].application == client->addr) {
444 dev_info(&client->dev, "Changing to bootloader address: "
445 "%02x -> %02x",
446 client->addr,
447 mxt_slave_addresses[i].bootloader);
448
449 client->addr = mxt_slave_addresses[i].bootloader;
450 data->state = BOOTLOADER;
451 return 0;
452 }
453 }
454
455 dev_err(&client->dev, "Address 0x%02x not found in address table",
456 client->addr);
457 return -EINVAL;
458}
459
460static int mxt_switch_to_appmode_address(struct mxt_data *data)
461{
462 int i;
463 struct i2c_client *client = data->client;
464
465 if (data->state == APPMODE) {
466 dev_err(&client->dev, "Already in APPMODE state\n");
467 return -EINVAL;
468 }
469
470 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
471 if (mxt_slave_addresses[i].bootloader == client->addr) {
472 dev_info(&client->dev,
473 "Changing to application mode address: "
474 "0x%02x -> 0x%02x",
475 client->addr,
476 mxt_slave_addresses[i].application);
477
478 client->addr = mxt_slave_addresses[i].application;
479 data->state = APPMODE;
480 return 0;
481 }
482 }
483
484 dev_err(&client->dev, "Address 0x%02x not found in address table",
485 client->addr);
486 return -EINVAL;
487}
488
489static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
490{
491 u8 buf[3];
492
493 if (val | MXT_BOOT_EXTENDED_ID) {
494 dev_dbg(&client->dev,
495 "Retrieving extended mode ID information");
496
497 if (i2c_master_recv(client, &buf[0], 3) != 3) {
498 dev_err(&client->dev, "%s: i2c recv failed\n",
499 __func__);
500 return -EIO;
501 }
502
503 dev_info(&client->dev, "Bootloader ID:%d Version:%d",
504 buf[1], buf[2]);
505
506 return buf[0];
507 } else {
508 dev_info(&client->dev, "Bootloader ID:%d",
509 val & MXT_BOOT_ID_MASK);
510
511 return val;
512 }
513}
514
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -0800515static int mxt_get_bootloader_id(struct i2c_client *client)
516{
517 u8 val;
518 u8 buf[3];
519
520 if (i2c_master_recv(client, &val, 1) != 1) {
521 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
522 return -EIO;
523 }
524
525 if (val | MXT_BOOT_EXTENDED_ID) {
526 if (i2c_master_recv(client, &buf[0], 3) != 3) {
527 dev_err(&client->dev, "%s: i2c recv failed\n",
528 __func__);
529 return -EIO;
530 }
531 return buf[1];
532 } else {
533 dev_info(&client->dev, "Bootloader ID:%d",
534 val & MXT_BOOT_ID_MASK);
535
536 return val & MXT_BOOT_ID_MASK;
537 }
538}
539
Iiro Valkonen7686b102011-02-02 23:21:58 -0800540static int mxt_check_bootloader(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530541 unsigned int state)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700542{
543 u8 val;
544
545recheck:
546 if (i2c_master_recv(client, &val, 1) != 1) {
547 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
548 return -EIO;
549 }
550
551 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800552 case MXT_WAITING_BOOTLOAD_CMD:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530553 val = mxt_get_bootloader_version(client, val);
554 val &= ~MXT_BOOT_STATUS_MASK;
555 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800556 case MXT_WAITING_FRAME_DATA:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530557 case MXT_APP_CRC_FAIL:
Iiro Valkonen7686b102011-02-02 23:21:58 -0800558 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700559 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800560 case MXT_FRAME_CRC_PASS:
561 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700562 goto recheck;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530563 if (val == MXT_FRAME_CRC_FAIL) {
564 dev_err(&client->dev, "Bootloader CRC fail\n");
565 return -EINVAL;
566 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700567 break;
568 default:
569 return -EINVAL;
570 }
571
572 if (val != state) {
Nick Dyer0a4016c2012-01-18 15:17:59 +0530573 dev_err(&client->dev, "Invalid bootloader mode state %X\n",
574 val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700575 return -EINVAL;
576 }
577
578 return 0;
579}
580
Iiro Valkonen7686b102011-02-02 23:21:58 -0800581static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700582{
583 u8 buf[2];
584
Iiro Valkonen7686b102011-02-02 23:21:58 -0800585 buf[0] = MXT_UNLOCK_CMD_LSB;
586 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700587
588 if (i2c_master_send(client, buf, 2) != 2) {
589 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
590 return -EIO;
591 }
592
593 return 0;
594}
595
Iiro Valkonen7686b102011-02-02 23:21:58 -0800596static int mxt_fw_write(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530597 const u8 *data, unsigned int frame_size)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700598{
599 if (i2c_master_send(client, data, frame_size) != frame_size) {
600 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
601 return -EIO;
602 }
603
604 return 0;
605}
606
Iiro Valkonen7686b102011-02-02 23:21:58 -0800607static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700608 u16 reg, u16 len, void *val)
609{
610 struct i2c_msg xfer[2];
611 u8 buf[2];
Jing Lin36aee812011-10-17 17:17:28 -0700612 int i = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700613
614 buf[0] = reg & 0xff;
615 buf[1] = (reg >> 8) & 0xff;
616
617 /* Write register */
618 xfer[0].addr = client->addr;
619 xfer[0].flags = 0;
620 xfer[0].len = 2;
621 xfer[0].buf = buf;
622
623 /* Read data */
624 xfer[1].addr = client->addr;
625 xfer[1].flags = I2C_M_RD;
626 xfer[1].len = len;
627 xfer[1].buf = val;
628
Jing Lin36aee812011-10-17 17:17:28 -0700629 do {
630 if (i2c_transfer(client->adapter, xfer, 2) == 2)
631 return 0;
632 msleep(MXT_WAKE_TIME);
633 } while (++i < MXT_MAX_RW_TRIES);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700634
Jing Lin36aee812011-10-17 17:17:28 -0700635 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
636 return -EIO;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700637}
638
Iiro Valkonen7686b102011-02-02 23:21:58 -0800639static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700640{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800641 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700642}
643
Jing Lin36aee812011-10-17 17:17:28 -0700644static int __mxt_write_reg(struct i2c_client *client,
645 u16 addr, u16 length, u8 *value)
646{
647 u8 buf[MXT_BLOCK_SIZE + 2];
648 int i, tries = 0;
649
650 if (length > MXT_BLOCK_SIZE)
651 return -EINVAL;
652
653 buf[0] = addr & 0xff;
654 buf[1] = (addr >> 8) & 0xff;
655 for (i = 0; i < length; i++)
656 buf[i + 2] = *value++;
657
658 do {
659 if (i2c_master_send(client, buf, length + 2) == (length + 2))
660 return 0;
661 msleep(MXT_WAKE_TIME);
662 } while (++tries < MXT_MAX_RW_TRIES);
663
664 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
665 return -EIO;
666}
667
Iiro Valkonen7686b102011-02-02 23:21:58 -0800668static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700669{
Jing Lin36aee812011-10-17 17:17:28 -0700670 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700671}
672
Iiro Valkonen7686b102011-02-02 23:21:58 -0800673static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700674 u16 reg, u8 *object_buf)
675{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800676 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700677 object_buf);
678}
679
Iiro Valkonen7686b102011-02-02 23:21:58 -0800680static struct mxt_object *
681mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700682{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800683 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700684 int i;
685
686 for (i = 0; i < data->info.object_num; i++) {
687 object = data->object_table + i;
688 if (object->type == type)
689 return object;
690 }
691
692 dev_err(&data->client->dev, "Invalid object type\n");
693 return NULL;
694}
695
Iiro Valkonen7686b102011-02-02 23:21:58 -0800696static int mxt_read_message(struct mxt_data *data,
697 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700698{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800699 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700700 u16 reg;
701
Iiro Valkonene8645592011-11-18 12:56:19 -0800702 object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700703 if (!object)
704 return -EINVAL;
705
706 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800707 return __mxt_read_reg(data->client, reg,
708 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700709}
710
Iiro Valkonen7686b102011-02-02 23:21:58 -0800711static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700712 u8 type, u8 offset, u8 *val)
713{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800714 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700715 u16 reg;
716
Iiro Valkonen7686b102011-02-02 23:21:58 -0800717 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700718 if (!object)
719 return -EINVAL;
720
721 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800722 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700723}
724
Iiro Valkonen7686b102011-02-02 23:21:58 -0800725static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700726 u8 type, u8 offset, u8 val)
727{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800728 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700729 u16 reg;
730
Iiro Valkonen7686b102011-02-02 23:21:58 -0800731 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700732 if (!object)
733 return -EINVAL;
734
735 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800736 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700737}
738
Iiro Valkonen7686b102011-02-02 23:21:58 -0800739static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700740{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800741 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700742 struct input_dev *input_dev = data->input_dev;
743 int status = finger[single_id].status;
744 int finger_num = 0;
745 int id;
746
Iiro Valkonen7686b102011-02-02 23:21:58 -0800747 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700748 if (!finger[id].status)
749 continue;
750
Joonyoung Shimcd473222012-02-14 18:32:48 -0800751 input_mt_slot(input_dev, id);
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800752 /* Firmware reports min/max values when the touch is
753 * outside screen area. Send a release event in
754 * such cases to avoid unwanted touches.
755 */
756 if (finger[id].x <= data->pdata->panel_minx ||
757 finger[id].x >= data->pdata->panel_maxx ||
758 finger[id].y <= data->pdata->panel_miny ||
759 finger[id].y >= data->pdata->panel_maxy) {
760 finger[id].status = MXT_RELEASE;
761 }
762
Joonyoung Shimcd473222012-02-14 18:32:48 -0800763 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
764 finger[id].status != MXT_RELEASE);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700765
Joonyoung Shimcd473222012-02-14 18:32:48 -0800766 if (finger[id].status != MXT_RELEASE) {
Amy Maloche2b59bab2011-10-13 16:08:16 -0700767 finger_num++;
Joonyoung Shimcd473222012-02-14 18:32:48 -0800768 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
769 finger[id].area);
770 input_report_abs(input_dev, ABS_MT_POSITION_X,
771 finger[id].x);
772 input_report_abs(input_dev, ABS_MT_POSITION_Y,
773 finger[id].y);
774 input_report_abs(input_dev, ABS_MT_PRESSURE,
775 finger[id].area);
776 } else {
777 finger[id].status = 0;
778 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700779 }
780
781 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
782
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800783 if (finger[single_id].x <= data->pdata->panel_minx ||
784 finger[single_id].x >= data->pdata->panel_maxx ||
785 finger[single_id].y <= data->pdata->panel_miny ||
786 finger[single_id].y >= data->pdata->panel_maxy) {
787 status = MXT_RELEASE;
788 }
789
Iiro Valkonen7686b102011-02-02 23:21:58 -0800790 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700791 input_report_abs(input_dev, ABS_X, finger[single_id].x);
792 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700793 input_report_abs(input_dev,
794 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700795 }
796
797 input_sync(input_dev);
798}
799
Iiro Valkonen7686b102011-02-02 23:21:58 -0800800static void mxt_input_touchevent(struct mxt_data *data,
801 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700802{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800803 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700804 struct device *dev = &data->client->dev;
805 u8 status = message->message[0];
806 int x;
807 int y;
808 int area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700809 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700810
811 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800812 if (!(status & MXT_DETECT)) {
813 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700814 dev_dbg(dev, "[%d] released\n", id);
815
Iiro Valkonen7686b102011-02-02 23:21:58 -0800816 finger[id].status = MXT_RELEASE;
817 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700818 }
819 return;
820 }
821
822 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800823 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700824 return;
825
Joonyoung Shim910d8052011-04-12 23:14:38 -0700826 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
827 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800828 if (data->pdata->panel_maxx < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700829 x = x >> 2;
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800830 if (data->pdata->panel_maxy < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700831 y = y >> 2;
832
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700833 area = message->message[4];
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700834 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700835
836 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800837 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700838 x, y, area);
839
Iiro Valkonen7686b102011-02-02 23:21:58 -0800840 finger[id].status = status & MXT_MOVE ?
841 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700842 finger[id].x = x;
843 finger[id].y = y;
844 finger[id].area = area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700845 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700846
Iiro Valkonen7686b102011-02-02 23:21:58 -0800847 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700848}
849
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800850static void mxt_handle_key_array(struct mxt_data *data,
851 struct mxt_message *message)
852{
853 u32 keys_changed;
854 int i;
855
856 if (!data->pdata->key_codes) {
857 dev_err(&data->client->dev, "keyarray is not supported\n");
858 return;
859 }
860
861 data->keyarray_new = message->message[1] |
862 (message->message[2] << 8) |
863 (message->message[3] << 16) |
864 (message->message[4] << 24);
865
866 keys_changed = data->keyarray_old ^ data->keyarray_new;
867
868 if (!keys_changed) {
869 dev_dbg(&data->client->dev, "no keys changed\n");
870 return;
871 }
872
873 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
874 if (!(keys_changed & (1 << i)))
875 continue;
876
877 input_report_key(data->input_dev, data->pdata->key_codes[i],
878 (data->keyarray_new & (1 << i)));
879 input_sync(data->input_dev);
880 }
881
882 data->keyarray_old = data->keyarray_new;
883}
884
Iiro Valkonen7686b102011-02-02 23:21:58 -0800885static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700886{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800887 struct mxt_data *data = dev_id;
888 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700889 struct device *dev = &data->client->dev;
890 int id;
891 u8 reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700892
Nick Dyer0a4016c2012-01-18 15:17:59 +0530893 if (data->state != APPMODE) {
894 dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
895 return IRQ_HANDLED;
896 }
897
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700898 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800899 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700900 dev_err(dev, "Failed to read message\n");
901 goto end;
902 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700903 reportid = message.reportid;
904
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800905 if (!reportid) {
906 dev_dbg(dev, "Report id 0 is reserved\n");
907 continue;
908 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700909
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800910 /* check whether report id is part of T9 or T15 */
911 id = reportid - data->t9_min_reportid;
912
913 if (reportid >= data->t9_min_reportid &&
914 reportid <= data->t9_max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -0800915 mxt_input_touchevent(data, &message, id);
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800916 else if (reportid >= data->t15_min_reportid &&
917 reportid <= data->t15_max_reportid)
918 mxt_handle_key_array(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700919 else
Iiro Valkonen7686b102011-02-02 23:21:58 -0800920 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700921 } while (reportid != 0xff);
922
923end:
924 return IRQ_HANDLED;
925}
926
Iiro Valkonen7686b102011-02-02 23:21:58 -0800927static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700928{
Jing Lindc4413c2012-01-16 15:22:52 -0800929 const struct mxt_config_info *config_info = data->config_info;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800930 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700931 struct device *dev = &data->client->dev;
932 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -0800933 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700934
Jing Lindc4413c2012-01-16 15:22:52 -0800935 if (!config_info) {
Iiro Valkonen71749f52011-02-15 13:36:52 -0800936 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
937 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700938 }
939
940 for (i = 0; i < data->info.object_num; i++) {
941 object = data->object_table + i;
942
Iiro Valkonen7686b102011-02-02 23:21:58 -0800943 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700944 continue;
945
Iiro Valkonen71749f52011-02-15 13:36:52 -0800946 for (j = 0; j < object->size + 1; j++) {
947 config_offset = index + j;
Jing Lindc4413c2012-01-16 15:22:52 -0800948 if (config_offset > config_info->config_length) {
Iiro Valkonen71749f52011-02-15 13:36:52 -0800949 dev_err(dev, "Not enough config data!\n");
950 return -EINVAL;
951 }
Iiro Valkonen7686b102011-02-02 23:21:58 -0800952 mxt_write_object(data, object->type, j,
Jing Lindc4413c2012-01-16 15:22:52 -0800953 config_info->config[config_offset]);
Iiro Valkonen71749f52011-02-15 13:36:52 -0800954 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700955 index += object->size + 1;
956 }
957
958 return 0;
959}
960
Iiro Valkonen7686b102011-02-02 23:21:58 -0800961static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700962{
963 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800964 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700965 int count = 10;
966 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700967
968 /* Read dummy message to make high CHG pin */
969 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800970 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700971 if (error)
972 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800973 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700974
975 if (!count) {
976 dev_err(dev, "CHG pin isn't cleared\n");
977 return -EBUSY;
978 }
979
980 return 0;
981}
982
Iiro Valkonen7686b102011-02-02 23:21:58 -0800983static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700984{
985 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800986 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700987 int error;
988 u8 val;
989
Iiro Valkonen7686b102011-02-02 23:21:58 -0800990 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700991 if (error)
992 return error;
993 info->family_id = val;
994
Iiro Valkonen7686b102011-02-02 23:21:58 -0800995 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700996 if (error)
997 return error;
998 info->variant_id = val;
999
Iiro Valkonen7686b102011-02-02 23:21:58 -08001000 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001001 if (error)
1002 return error;
1003 info->version = val;
1004
Iiro Valkonen7686b102011-02-02 23:21:58 -08001005 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001006 if (error)
1007 return error;
1008 info->build = val;
1009
Iiro Valkonen7686b102011-02-02 23:21:58 -08001010 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001011 if (error)
1012 return error;
1013 info->object_num = val;
1014
1015 return 0;
1016}
1017
Iiro Valkonen7686b102011-02-02 23:21:58 -08001018static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001019{
1020 int error;
1021 int i;
1022 u16 reg;
1023 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001024 u8 buf[MXT_OBJECT_SIZE];
Jing Lindc4413c2012-01-16 15:22:52 -08001025 bool found_t38 = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001026
1027 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001028 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001029
Iiro Valkonen7686b102011-02-02 23:21:58 -08001030 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
1031 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001032 if (error)
1033 return error;
1034
1035 object->type = buf[0];
1036 object->start_address = (buf[2] << 8) | buf[1];
1037 object->size = buf[3];
1038 object->instances = buf[4];
1039 object->num_report_ids = buf[5];
1040
1041 if (object->num_report_ids) {
1042 reportid += object->num_report_ids *
1043 (object->instances + 1);
1044 object->max_reportid = reportid;
1045 }
Jing Lindc4413c2012-01-16 15:22:52 -08001046
1047 /* Calculate index for config major version in config array.
1048 * Major version is the first byte in object T38.
1049 */
1050 if (object->type == MXT_SPT_USERDATA_T38)
1051 found_t38 = true;
1052 if (!found_t38 && mxt_object_writable(object->type))
1053 data->cfg_version_idx += object->size + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001054 }
1055
1056 return 0;
1057}
1058
Jing Lindc4413c2012-01-16 15:22:52 -08001059static int mxt_search_config_array(struct mxt_data *data, bool version_match)
1060{
1061
1062 const struct mxt_platform_data *pdata = data->pdata;
1063 const struct mxt_config_info *cfg_info;
1064 struct mxt_info *info = &data->info;
1065 int i;
1066 u8 cfg_version;
1067
1068 for (i = 0; i < pdata->config_array_size; i++) {
1069
1070 cfg_info = &pdata->config_array[i];
1071
1072 if (!cfg_info->config || !cfg_info->config_length)
1073 continue;
1074
1075 if (info->family_id == cfg_info->family_id &&
1076 info->variant_id == cfg_info->variant_id &&
1077 info->version == cfg_info->version &&
1078 info->build == cfg_info->build) {
1079
1080 cfg_version = cfg_info->config[data->cfg_version_idx];
1081 if (data->curr_cfg_version == cfg_version ||
1082 !version_match) {
1083 data->config_info = cfg_info;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001084 data->fw_name = pdata->config_array[i].fw_name;
Jing Lindc4413c2012-01-16 15:22:52 -08001085 return 0;
1086 }
1087 }
1088 }
1089
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001090 data->fw_name = NULL;
Jing Lindc4413c2012-01-16 15:22:52 -08001091 dev_info(&data->client->dev,
1092 "Config not found: F: %d, V: %d, FW: %d.%d.%d, CFG: %d\n",
1093 info->family_id, info->variant_id,
1094 info->version >> 4, info->version & 0xF, info->build,
1095 data->curr_cfg_version);
1096 return -EINVAL;
1097}
1098
1099static int mxt_get_config(struct mxt_data *data)
1100{
1101 const struct mxt_platform_data *pdata = data->pdata;
1102 struct device *dev = &data->client->dev;
1103 struct mxt_object *object;
1104 int error;
1105
1106 if (!pdata->config_array || !pdata->config_array_size) {
1107 dev_dbg(dev, "No cfg data provided by platform data\n");
1108 return 0;
1109 }
1110
1111 /* Get current config version */
1112 object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
1113 if (!object) {
1114 dev_err(dev, "Unable to obtain USERDATA object\n");
1115 return -EINVAL;
1116 }
1117
1118 error = mxt_read_reg(data->client, object->start_address,
1119 &data->curr_cfg_version);
1120 if (error) {
1121 dev_err(dev, "Unable to read config version\n");
1122 return error;
1123 }
1124
1125 /* It is possible that the config data on the controller is not
1126 * versioned and the version number returns 0. In this case,
1127 * find a match without the config version checking.
1128 */
1129 error = mxt_search_config_array(data,
1130 data->curr_cfg_version != 0 ? true : false);
1131 if (error)
1132 return error;
1133
1134 return 0;
1135}
Amy Maloche7e447432011-09-14 11:36:30 -07001136static void mxt_reset_delay(struct mxt_data *data)
1137{
1138 struct mxt_info *info = &data->info;
1139
1140 switch (info->family_id) {
1141 case MXT224_ID:
1142 msleep(MXT224_RESET_TIME);
1143 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -07001144 case MXT224E_ID:
1145 msleep(MXT224E_RESET_TIME);
1146 break;
Amy Maloche7e447432011-09-14 11:36:30 -07001147 case MXT1386_ID:
1148 msleep(MXT1386_RESET_TIME);
1149 break;
1150 default:
1151 msleep(MXT_RESET_TIME);
1152 }
1153}
1154
Iiro Valkonen7686b102011-02-02 23:21:58 -08001155static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001156{
1157 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001158 struct mxt_info *info = &data->info;
Jing Lin36aee812011-10-17 17:17:28 -07001159 int error;
Iiro Valkonen4ac053c2011-09-08 11:10:52 -07001160 int timeout_counter = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001161 u8 val;
Iiro Valkonen4ac053c2011-09-08 11:10:52 -07001162 u8 command_register;
Jing Lin36aee812011-10-17 17:17:28 -07001163 struct mxt_object *t7_object;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001164 struct mxt_object *t9_object;
1165 struct mxt_object *t15_object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001166
Iiro Valkonen7686b102011-02-02 23:21:58 -08001167 error = mxt_get_info(data);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301168 if (error) {
1169 /* Try bootloader mode */
1170 error = mxt_switch_to_bootloader_address(data);
1171 if (error)
1172 return error;
1173
1174 error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
1175 if (error)
1176 return error;
1177
1178 dev_err(&client->dev, "Application CRC failure\n");
1179 data->state = BOOTLOADER;
1180
1181 return 0;
1182 }
1183
1184 dev_info(&client->dev,
1185 "Family ID: %d Variant ID: %d Version: %d.%d "
1186 "Build: 0x%02X Object Num: %d\n",
1187 info->family_id, info->variant_id,
1188 info->version >> 4, info->version & 0xf,
1189 info->build, info->object_num);
1190
1191 data->state = APPMODE;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001192
1193 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001194 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001195 GFP_KERNEL);
1196 if (!data->object_table) {
1197 dev_err(&client->dev, "Failed to allocate memory\n");
1198 return -ENOMEM;
1199 }
1200
1201 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001202 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001203 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001204 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001205
Jing Lindc4413c2012-01-16 15:22:52 -08001206 /* Get config data from platform data */
1207 error = mxt_get_config(data);
1208 if (error)
1209 dev_dbg(&client->dev, "Config info not found.\n");
1210
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001211 /* Check register init values */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001212 error = mxt_check_reg_init(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001213 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001214 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001215
Amy Maloche52262212011-09-15 16:46:57 -07001216 /* Store T7 and T9 locally, used in suspend/resume operations */
Iiro Valkonene8645592011-11-18 12:56:19 -08001217 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
Jing Lin36aee812011-10-17 17:17:28 -07001218 if (!t7_object) {
1219 dev_err(&client->dev, "Failed to get T7 object\n");
Jing Lin32c72532011-11-03 12:02:33 -07001220 error = -EINVAL;
1221 goto free_object_table;
Jing Lin36aee812011-10-17 17:17:28 -07001222 }
1223
1224 data->t7_start_addr = t7_object->start_address;
1225 error = __mxt_read_reg(client, data->t7_start_addr,
1226 T7_DATA_SIZE, data->t7_data);
1227 if (error < 0) {
1228 dev_err(&client->dev,
Jing Lin32c72532011-11-03 12:02:33 -07001229 "Failed to save current power state\n");
1230 goto free_object_table;
Amy Maloche52262212011-09-15 16:46:57 -07001231 }
Iiro Valkonene8645592011-11-18 12:56:19 -08001232 error = mxt_read_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
Amy Maloche52262212011-09-15 16:46:57 -07001233 &data->t9_ctrl);
1234 if (error < 0) {
Jing Lin32c72532011-11-03 12:02:33 -07001235 dev_err(&client->dev, "Failed to save current touch object\n");
1236 goto free_object_table;
Amy Maloche52262212011-09-15 16:46:57 -07001237 }
1238
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001239 /* Store T9, T15's min and max report ids */
1240 t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1241 if (!t9_object) {
1242 dev_err(&client->dev, "Failed to get T9 object\n");
1243 error = -EINVAL;
1244 goto free_object_table;
1245 }
1246 data->t9_max_reportid = t9_object->max_reportid;
1247 data->t9_min_reportid = t9_object->max_reportid -
1248 t9_object->num_report_ids + 1;
1249
1250 if (data->pdata->key_codes) {
1251 t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
1252 if (!t15_object)
1253 dev_dbg(&client->dev, "T15 object is not available\n");
1254 else {
1255 data->t15_max_reportid = t15_object->max_reportid;
1256 data->t15_min_reportid = t15_object->max_reportid -
1257 t15_object->num_report_ids + 1;
1258 }
1259 }
1260
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001261 /* Backup to memory */
Iiro Valkonene8645592011-11-18 12:56:19 -08001262 mxt_write_object(data, MXT_GEN_COMMAND_T6,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001263 MXT_COMMAND_BACKUPNV,
1264 MXT_BACKUP_VALUE);
1265 msleep(MXT_BACKUP_TIME);
Iiro Valkonen4ac053c2011-09-08 11:10:52 -07001266 do {
Iiro Valkonene8645592011-11-18 12:56:19 -08001267 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
Iiro Valkonen4ac053c2011-09-08 11:10:52 -07001268 MXT_COMMAND_BACKUPNV,
1269 &command_register);
1270 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001271 goto free_object_table;
Amy Maloche7e447432011-09-14 11:36:30 -07001272 usleep_range(1000, 2000);
1273 } while ((command_register != 0) && (++timeout_counter <= 100));
1274 if (timeout_counter > 100) {
Iiro Valkonen4ac053c2011-09-08 11:10:52 -07001275 dev_err(&client->dev, "No response after backup!\n");
Jing Lin32c72532011-11-03 12:02:33 -07001276 error = -EIO;
1277 goto free_object_table;
Iiro Valkonen4ac053c2011-09-08 11:10:52 -07001278 }
1279
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001280
1281 /* Soft reset */
Iiro Valkonene8645592011-11-18 12:56:19 -08001282 mxt_write_object(data, MXT_GEN_COMMAND_T6,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001283 MXT_COMMAND_RESET, 1);
Iiro Valkonen4ac053c2011-09-08 11:10:52 -07001284
Amy Maloche7e447432011-09-14 11:36:30 -07001285 mxt_reset_delay(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001286
1287 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001288 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001289 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001290 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001291 info->matrix_xsize = val;
1292
Iiro Valkonen7686b102011-02-02 23:21:58 -08001293 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001294 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001295 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001296 info->matrix_ysize = val;
1297
1298 dev_info(&client->dev,
Nick Dyer0a4016c2012-01-18 15:17:59 +05301299 "Matrix X Size: %d Matrix Y Size: %d\n",
1300 info->matrix_xsize, info->matrix_ysize);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001301
1302 return 0;
Jing Lin32c72532011-11-03 12:02:33 -07001303
1304free_object_table:
1305 kfree(data->object_table);
1306 return error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001307}
1308
Iiro Valkonen7686b102011-02-02 23:21:58 -08001309static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001310 struct device_attribute *attr, char *buf)
1311{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001312 struct mxt_data *data = dev_get_drvdata(dev);
1313 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001314 int count = 0;
1315 int i, j;
1316 int error;
1317 u8 val;
1318
1319 for (i = 0; i < data->info.object_num; i++) {
1320 object = data->object_table + i;
1321
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001322 count += snprintf(buf + count, PAGE_SIZE - count,
1323 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001324 i + 1, object->type);
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001325 if (count >= PAGE_SIZE)
1326 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001327
Iiro Valkonen7686b102011-02-02 23:21:58 -08001328 if (!mxt_object_readable(object->type)) {
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001329 count += snprintf(buf + count, PAGE_SIZE - count,
1330 "\n");
1331 if (count >= PAGE_SIZE)
1332 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001333 continue;
1334 }
1335
1336 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001337 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001338 object->type, j, &val);
1339 if (error)
1340 return error;
1341
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001342 count += snprintf(buf + count, PAGE_SIZE - count,
1343 "\t[%2d]: %02x (%d)\n", j, val, val);
1344 if (count >= PAGE_SIZE)
1345 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001346 }
1347
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001348 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1349 if (count >= PAGE_SIZE)
1350 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001351 }
1352
1353 return count;
1354}
1355
Jing Lincc974cb2012-02-01 23:13:14 -08001356static int strtobyte(const char *data, u8 *value)
1357{
1358 char str[3];
1359
1360 str[0] = data[0];
1361 str[1] = data[1];
1362 str[2] = '\0';
1363
1364 return kstrtou8(str, 16, value);
1365}
1366
Iiro Valkonen7686b102011-02-02 23:21:58 -08001367static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001368{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001369 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001370 struct i2c_client *client = data->client;
1371 const struct firmware *fw = NULL;
1372 unsigned int frame_size;
Nick Dyer0a4016c2012-01-18 15:17:59 +05301373 unsigned int retry = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001374 unsigned int pos = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001375 int ret, i, max_frame_size;
1376 u8 *frame;
1377
1378 switch (data->info.family_id) {
1379 case MXT224_ID:
1380 max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
1381 break;
1382 case MXT1386_ID:
1383 max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
1384 break;
1385 default:
1386 return -EINVAL;
1387 }
1388
1389 frame = kmalloc(max_frame_size, GFP_KERNEL);
1390 if (!frame) {
1391 dev_err(dev, "Unable to allocate memory for frame data\n");
1392 return -ENOMEM;
1393 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001394
1395 ret = request_firmware(&fw, fn, dev);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301396 if (ret < 0) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001397 dev_err(dev, "Unable to open firmware %s\n", fn);
Jing Lincc974cb2012-02-01 23:13:14 -08001398 goto free_frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001399 }
1400
Nick Dyer0a4016c2012-01-18 15:17:59 +05301401 if (data->state != BOOTLOADER) {
1402 /* Change to the bootloader mode */
1403 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1404 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1405 mxt_reset_delay(data);
Amy Maloche7e447432011-09-14 11:36:30 -07001406
Nick Dyer0a4016c2012-01-18 15:17:59 +05301407 ret = mxt_switch_to_bootloader_address(data);
1408 if (ret)
1409 goto release_firmware;
1410 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001411
Iiro Valkonen7686b102011-02-02 23:21:58 -08001412 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301413 if (ret) {
1414 /* Bootloader may still be unlocked from previous update
1415 * attempt */
1416 ret = mxt_check_bootloader(client,
1417 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001418
Nick Dyer0a4016c2012-01-18 15:17:59 +05301419 if (ret)
1420 goto return_to_app_mode;
1421 } else {
1422 dev_info(dev, "Unlocking bootloader\n");
1423 /* Unlock bootloader */
1424 mxt_unlock_bootloader(client);
1425 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001426
1427 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001428 ret = mxt_check_bootloader(client,
1429 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001430 if (ret)
Nick Dyer0a4016c2012-01-18 15:17:59 +05301431 goto release_firmware;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001432
Jing Lincc974cb2012-02-01 23:13:14 -08001433 /* Get frame length MSB */
1434 ret = strtobyte(fw->data + pos, frame);
1435 if (ret)
1436 goto release_firmware;
1437
1438 /* Get frame length LSB */
1439 ret = strtobyte(fw->data + pos + 2, frame + 1);
1440 if (ret)
1441 goto release_firmware;
1442
1443 frame_size = ((*frame << 8) | *(frame + 1));
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001444
1445 /* We should add 2 at frame size as the the firmware data is not
1446 * included the CRC bytes.
1447 */
1448 frame_size += 2;
1449
Jing Lincc974cb2012-02-01 23:13:14 -08001450 if (frame_size > max_frame_size) {
1451 dev_err(dev, "Invalid frame size - %d\n", frame_size);
1452 ret = -EINVAL;
1453 goto release_firmware;
1454 }
1455
1456 /* Convert frame data and CRC from hex to binary */
1457 for (i = 2; i < frame_size; i++) {
1458 ret = strtobyte(fw->data + pos + i * 2, frame + i);
1459 if (ret)
1460 goto release_firmware;
1461 }
1462
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001463 /* Write one frame to device */
Jing Lincc974cb2012-02-01 23:13:14 -08001464 mxt_fw_write(client, frame, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001465
Iiro Valkonen7686b102011-02-02 23:21:58 -08001466 ret = mxt_check_bootloader(client,
1467 MXT_FRAME_CRC_PASS);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301468 if (ret) {
1469 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001470
Nick Dyer0a4016c2012-01-18 15:17:59 +05301471 /* Back off by 20ms per retry */
1472 msleep(retry * 20);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001473
Nick Dyer0a4016c2012-01-18 15:17:59 +05301474 if (retry > 20)
1475 goto release_firmware;
1476 } else {
1477 retry = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001478 pos += frame_size * 2;
1479 dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301480 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001481 }
1482
Nick Dyer0a4016c2012-01-18 15:17:59 +05301483return_to_app_mode:
1484 mxt_switch_to_appmode_address(data);
1485release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001486 release_firmware(fw);
Jing Lincc974cb2012-02-01 23:13:14 -08001487free_frame:
1488 kfree(frame);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001489
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001490 return ret;
1491}
1492
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001493static const char *
1494mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
1495{
1496 const struct mxt_platform_data *pdata = data->pdata;
1497 const struct mxt_config_info *cfg_info;
1498 const char *fw_name = NULL;
1499 int i;
1500
1501 for (i = 0; i < pdata->config_array_size; i++) {
1502 cfg_info = &pdata->config_array[i];
1503 if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
1504 data->config_info = cfg_info;
1505 data->info.family_id = cfg_info->family_id;
1506 fw_name = cfg_info->fw_name;
1507 }
1508 }
1509
1510 return fw_name;
1511}
1512
Iiro Valkonen7686b102011-02-02 23:21:58 -08001513static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001514 struct device_attribute *attr,
1515 const char *buf, size_t count)
1516{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001517 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001518 int error;
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001519 const char *fw_name;
1520 u8 bootldr_id;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001521
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001522 /* If fw_name is set, then the existing firmware has an upgrade */
1523 if (!data->fw_name) {
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001524 /*
1525 * If the device boots up in the bootloader mode, check if
1526 * there is a firmware to upgrade.
1527 */
1528 if (data->state == BOOTLOADER) {
1529 bootldr_id = mxt_get_bootloader_id(data->client);
1530 if (bootldr_id <= 0) {
1531 dev_err(dev,
1532 "Unable to retrieve bootloader id\n");
1533 return -EINVAL;
1534 }
1535 fw_name = mxt_search_fw_name(data, bootldr_id);
1536 if (fw_name == NULL) {
1537 dev_err(dev,
1538 "Unable to find fw from bootloader id\n");
1539 return -EINVAL;
1540 }
1541 } else {
1542 /* In APPMODE, if the f/w name does not exist, quit */
1543 dev_err(dev,
1544 "Firmware name not specified in platform data\n");
1545 return -EINVAL;
1546 }
1547 } else {
1548 fw_name = data->fw_name;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001549 }
1550
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001551 dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001552
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001553 disable_irq(data->irq);
1554
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001555 error = mxt_load_fw(dev, fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001556 if (error) {
1557 dev_err(dev, "The firmware update failed(%d)\n", error);
1558 count = error;
1559 } else {
Nick Dyer0a4016c2012-01-18 15:17:59 +05301560 dev_info(dev, "The firmware update succeeded\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001561
1562 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001563 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001564
Nick Dyer0a4016c2012-01-18 15:17:59 +05301565 data->state = INIT;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001566 kfree(data->object_table);
1567 data->object_table = NULL;
Jing Lincc974cb2012-02-01 23:13:14 -08001568 data->cfg_version_idx = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001569
Iiro Valkonen7686b102011-02-02 23:21:58 -08001570 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001571 }
1572
Nick Dyer0a4016c2012-01-18 15:17:59 +05301573 if (data->state == APPMODE) {
1574 enable_irq(data->irq);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001575
Nick Dyer0a4016c2012-01-18 15:17:59 +05301576 error = mxt_make_highchg(data);
1577 if (error)
1578 return error;
1579 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07001580
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001581 return count;
1582}
1583
Iiro Valkonen7686b102011-02-02 23:21:58 -08001584static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
1585static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001586
Iiro Valkonen7686b102011-02-02 23:21:58 -08001587static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001588 &dev_attr_object.attr,
1589 &dev_attr_update_fw.attr,
1590 NULL
1591};
1592
Iiro Valkonen7686b102011-02-02 23:21:58 -08001593static const struct attribute_group mxt_attr_group = {
1594 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001595};
1596
Amy Maloche52262212011-09-15 16:46:57 -07001597static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001598{
Jing Lin36aee812011-10-17 17:17:28 -07001599 int error;
1600
Amy Maloche52262212011-09-15 16:46:57 -07001601 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07001602 error = __mxt_write_reg(data->client, data->t7_start_addr,
1603 T7_DATA_SIZE, data->t7_data);
1604 if (error < 0) {
1605 dev_err(&data->client->dev,
1606 "failed to restore old power state\n");
1607 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001608 }
Jing Lin36aee812011-10-17 17:17:28 -07001609
Amy Maloche52262212011-09-15 16:46:57 -07001610 error = mxt_write_object(data,
Iiro Valkonene8645592011-11-18 12:56:19 -08001611 MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, data->t9_ctrl);
Amy Maloche52262212011-09-15 16:46:57 -07001612 if (error < 0) {
1613 dev_err(&data->client->dev, "failed to restore touch\n");
1614 return error;
1615 }
1616
1617 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001618}
1619
Amy Maloche52262212011-09-15 16:46:57 -07001620static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001621{
Jing Lin36aee812011-10-17 17:17:28 -07001622 int error;
1623 u8 t7_data[T7_DATA_SIZE] = {0};
1624
1625 /* disable touch and configure deep sleep mode */
Iiro Valkonene8645592011-11-18 12:56:19 -08001626 error = mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
Jing Lin36aee812011-10-17 17:17:28 -07001627 if (error < 0) {
1628 dev_err(&data->client->dev, "failed to disable touch\n");
1629 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001630 }
1631
Jing Lin36aee812011-10-17 17:17:28 -07001632 error = __mxt_write_reg(data->client, data->t7_start_addr,
1633 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07001634 if (error < 0) {
1635 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07001636 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07001637 return error;
1638 }
1639
1640 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001641}
1642
Iiro Valkonen7686b102011-02-02 23:21:58 -08001643static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001644{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001645 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001646 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001647
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001648 if (data->state == APPMODE) {
1649 error = mxt_start(data);
1650 if (error < 0) {
1651 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
1652 return error;
1653 }
Amy Maloche52262212011-09-15 16:46:57 -07001654 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001655
1656 return 0;
1657}
1658
Iiro Valkonen7686b102011-02-02 23:21:58 -08001659static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001660{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001661 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001662 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001663
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001664 if (data->state == APPMODE) {
1665 error = mxt_stop(data);
1666 if (error < 0)
1667 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
1668 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001669}
1670
Amy Malochec331f842012-01-24 10:33:47 -08001671static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
1672{
1673 return (regulator_count_voltages(reg) > 0) ?
1674 regulator_set_optimum_mode(reg, load_uA) : 0;
1675}
1676
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301677static int mxt_power_on(struct mxt_data *data, bool on)
1678{
1679 int rc;
1680
1681 if (on == false)
1682 goto power_off;
1683
Amy Malochec331f842012-01-24 10:33:47 -08001684 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301685 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001686 dev_err(&data->client->dev,
1687 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301688 return rc;
1689 }
1690
Amy Maloche21115eb2011-11-02 09:04:37 -07001691 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301692 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001693 dev_err(&data->client->dev,
1694 "Regulator vcc_ana enable failed rc=%d\n", rc);
1695 goto error_reg_en_vcc_ana;
1696 }
1697
1698 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001699 rc = reg_set_optimum_mode_check(data->vcc_dig,
1700 MXT_ACTIVE_LOAD_DIG_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07001701 if (rc < 0) {
1702 dev_err(&data->client->dev,
1703 "Regulator vcc_dig set_opt failed rc=%d\n",
1704 rc);
1705 goto error_reg_opt_vcc_dig;
1706 }
1707
1708 rc = regulator_enable(data->vcc_dig);
1709 if (rc) {
1710 dev_err(&data->client->dev,
1711 "Regulator vcc_dig enable failed rc=%d\n", rc);
1712 goto error_reg_en_vcc_dig;
1713 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301714 }
1715
1716 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001717 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301718 if (rc < 0) {
1719 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001720 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301721 goto error_reg_opt_i2c;
1722 }
1723
1724 rc = regulator_enable(data->vcc_i2c);
1725 if (rc) {
1726 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001727 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301728 goto error_reg_en_vcc_i2c;
1729 }
1730 }
1731
Amy Malochef0d7b8d2011-10-17 12:10:51 -07001732 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301733
1734 return 0;
1735
1736error_reg_en_vcc_i2c:
1737 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08001738 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301739error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001740 if (data->pdata->digital_pwr_regulator)
1741 regulator_disable(data->vcc_dig);
1742error_reg_en_vcc_dig:
1743 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08001744 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001745error_reg_opt_vcc_dig:
1746 regulator_disable(data->vcc_ana);
1747error_reg_en_vcc_ana:
Amy Malochec331f842012-01-24 10:33:47 -08001748 reg_set_optimum_mode_check(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301749 return rc;
1750
1751power_off:
Amy Malochec331f842012-01-24 10:33:47 -08001752 reg_set_optimum_mode_check(data->vcc_ana, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001753 regulator_disable(data->vcc_ana);
1754 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001755 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001756 regulator_disable(data->vcc_dig);
1757 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301758 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001759 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301760 regulator_disable(data->vcc_i2c);
1761 }
1762 msleep(50);
1763 return 0;
1764}
1765
1766static int mxt_regulator_configure(struct mxt_data *data, bool on)
1767{
1768 int rc;
1769
1770 if (on == false)
1771 goto hw_shutdown;
1772
Amy Maloche21115eb2011-11-02 09:04:37 -07001773 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
1774 if (IS_ERR(data->vcc_ana)) {
1775 rc = PTR_ERR(data->vcc_ana);
1776 dev_err(&data->client->dev,
1777 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301778 return rc;
1779 }
1780
Amy Maloche21115eb2011-11-02 09:04:37 -07001781 if (regulator_count_voltages(data->vcc_ana) > 0) {
1782 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301783 MXT_VTG_MAX_UV);
1784 if (rc) {
1785 dev_err(&data->client->dev,
1786 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07001787 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301788 }
1789 }
Amy Maloche21115eb2011-11-02 09:04:37 -07001790 if (data->pdata->digital_pwr_regulator) {
1791 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
1792 if (IS_ERR(data->vcc_dig)) {
1793 rc = PTR_ERR(data->vcc_dig);
1794 dev_err(&data->client->dev,
1795 "Regulator get dig failed rc=%d\n", rc);
1796 goto error_get_vtg_vcc_dig;
1797 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301798
Amy Maloche21115eb2011-11-02 09:04:37 -07001799 if (regulator_count_voltages(data->vcc_dig) > 0) {
1800 rc = regulator_set_voltage(data->vcc_dig,
1801 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
1802 if (rc) {
1803 dev_err(&data->client->dev,
1804 "regulator set_vtg failed rc=%d\n", rc);
1805 goto error_set_vtg_vcc_dig;
1806 }
1807 }
1808 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301809 if (data->pdata->i2c_pull_up) {
1810 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
1811 if (IS_ERR(data->vcc_i2c)) {
1812 rc = PTR_ERR(data->vcc_i2c);
1813 dev_err(&data->client->dev,
1814 "Regulator get failed rc=%d\n", rc);
1815 goto error_get_vtg_i2c;
1816 }
1817 if (regulator_count_voltages(data->vcc_i2c) > 0) {
1818 rc = regulator_set_voltage(data->vcc_i2c,
1819 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
1820 if (rc) {
1821 dev_err(&data->client->dev,
1822 "regulator set_vtg failed rc=%d\n", rc);
1823 goto error_set_vtg_i2c;
1824 }
1825 }
1826 }
1827
1828 return 0;
1829
1830error_set_vtg_i2c:
1831 regulator_put(data->vcc_i2c);
1832error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001833 if (data->pdata->digital_pwr_regulator)
1834 if (regulator_count_voltages(data->vcc_dig) > 0)
1835 regulator_set_voltage(data->vcc_dig, 0,
1836 MXT_VTG_DIG_MAX_UV);
1837error_set_vtg_vcc_dig:
1838 if (data->pdata->digital_pwr_regulator)
1839 regulator_put(data->vcc_dig);
1840error_get_vtg_vcc_dig:
1841 if (regulator_count_voltages(data->vcc_ana) > 0)
1842 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1843error_set_vtg_vcc_ana:
1844 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301845 return rc;
1846
1847hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07001848 if (regulator_count_voltages(data->vcc_ana) > 0)
1849 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1850 regulator_put(data->vcc_ana);
1851 if (data->pdata->digital_pwr_regulator) {
1852 if (regulator_count_voltages(data->vcc_dig) > 0)
1853 regulator_set_voltage(data->vcc_dig, 0,
1854 MXT_VTG_DIG_MAX_UV);
1855 regulator_put(data->vcc_dig);
1856 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301857 if (data->pdata->i2c_pull_up) {
1858 if (regulator_count_voltages(data->vcc_i2c) > 0)
1859 regulator_set_voltage(data->vcc_i2c, 0,
1860 MXT_I2C_VTG_MAX_UV);
1861 regulator_put(data->vcc_i2c);
1862 }
1863 return 0;
1864}
1865
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301866#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07001867static int mxt_regulator_lpm(struct mxt_data *data, bool on)
1868{
1869
1870 int rc;
1871
1872 if (on == false)
1873 goto regulator_hpm;
1874
Amy Malochec331f842012-01-24 10:33:47 -08001875 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001876 if (rc < 0) {
1877 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001878 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001879 goto fail_regulator_lpm;
1880 }
1881
Amy Maloche21115eb2011-11-02 09:04:37 -07001882 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001883 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07001884 MXT_LPM_LOAD_DIG_UA);
1885 if (rc < 0) {
1886 dev_err(&data->client->dev,
1887 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
1888 goto fail_regulator_lpm;
1889 }
1890 }
1891
Jing Linbace50b2011-10-18 22:55:47 -07001892 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001893 rc = reg_set_optimum_mode_check(data->vcc_i2c,
Jing Linbace50b2011-10-18 22:55:47 -07001894 MXT_I2C_LPM_LOAD_UA);
1895 if (rc < 0) {
1896 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001897 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001898 goto fail_regulator_lpm;
1899 }
1900 }
1901
1902 return 0;
1903
1904regulator_hpm:
1905
Amy Malochec331f842012-01-24 10:33:47 -08001906 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001907 if (rc < 0) {
1908 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001909 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001910 goto fail_regulator_hpm;
1911 }
1912
Amy Maloche21115eb2011-11-02 09:04:37 -07001913 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001914 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07001915 MXT_ACTIVE_LOAD_DIG_UA);
1916 if (rc < 0) {
1917 dev_err(&data->client->dev,
1918 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
1919 goto fail_regulator_hpm;
1920 }
1921 }
1922
Jing Linbace50b2011-10-18 22:55:47 -07001923 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001924 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001925 if (rc < 0) {
1926 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001927 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07001928 goto fail_regulator_hpm;
1929 }
1930 }
1931
1932 return 0;
1933
1934fail_regulator_lpm:
Amy Malochec331f842012-01-24 10:33:47 -08001935 reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07001936 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08001937 reg_set_optimum_mode_check(data->vcc_dig,
1938 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001939 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08001940 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001941
1942 return rc;
1943
1944fail_regulator_hpm:
Amy Malochec331f842012-01-24 10:33:47 -08001945 reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07001946 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08001947 reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001948 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08001949 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001950
1951 return rc;
1952}
1953
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301954static int mxt_suspend(struct device *dev)
1955{
1956 struct i2c_client *client = to_i2c_client(dev);
1957 struct mxt_data *data = i2c_get_clientdata(client);
1958 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07001959 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301960
1961 mutex_lock(&input_dev->mutex);
1962
Amy Maloche52262212011-09-15 16:46:57 -07001963 if (input_dev->users) {
1964 error = mxt_stop(data);
1965 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07001966 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07001967 mutex_unlock(&input_dev->mutex);
1968 return error;
1969 }
1970
1971 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301972
1973 mutex_unlock(&input_dev->mutex);
1974
Jing Linbace50b2011-10-18 22:55:47 -07001975 /* put regulators in low power mode */
1976 error = mxt_regulator_lpm(data, true);
1977 if (error < 0) {
1978 dev_err(dev, "failed to enter low power mode\n");
1979 return error;
1980 }
1981
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301982 return 0;
1983}
1984
1985static int mxt_resume(struct device *dev)
1986{
1987 struct i2c_client *client = to_i2c_client(dev);
1988 struct mxt_data *data = i2c_get_clientdata(client);
1989 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07001990 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301991
Jing Linbace50b2011-10-18 22:55:47 -07001992 /* put regulators in high power mode */
1993 error = mxt_regulator_lpm(data, false);
1994 if (error < 0) {
1995 dev_err(dev, "failed to enter high power mode\n");
1996 return error;
1997 }
1998
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301999 mutex_lock(&input_dev->mutex);
2000
Amy Maloche52262212011-09-15 16:46:57 -07002001 if (input_dev->users) {
2002 error = mxt_start(data);
2003 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002004 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07002005 mutex_unlock(&input_dev->mutex);
2006 return error;
2007 }
2008 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302009
2010 mutex_unlock(&input_dev->mutex);
2011
2012 return 0;
2013}
2014
2015#if defined(CONFIG_HAS_EARLYSUSPEND)
2016static void mxt_early_suspend(struct early_suspend *h)
2017{
2018 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2019
2020 mxt_suspend(&data->client->dev);
2021}
2022
2023static void mxt_late_resume(struct early_suspend *h)
2024{
2025 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2026
2027 mxt_resume(&data->client->dev);
2028}
2029#endif
2030
2031static const struct dev_pm_ops mxt_pm_ops = {
2032#ifndef CONFIG_HAS_EARLYSUSPEND
2033 .suspend = mxt_suspend,
2034 .resume = mxt_resume,
2035#endif
2036};
2037#endif
2038
Jing Lin6cfc00e2011-11-02 15:15:30 -07002039static int mxt_debugfs_object_show(struct seq_file *m, void *v)
2040{
2041 struct mxt_data *data = m->private;
2042 struct mxt_object *object;
2043 struct device *dev = &data->client->dev;
2044 int i, j, k;
2045 int error;
2046 int obj_size;
2047 u8 val;
2048
2049 for (i = 0; i < data->info.object_num; i++) {
2050 object = data->object_table + i;
2051 obj_size = object->size + 1;
2052
2053 seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
2054
2055 for (j = 0; j < object->instances + 1; j++) {
2056 seq_printf(m, "[Instance %d]\n", j);
2057
2058 for (k = 0; k < obj_size; k++) {
2059 error = mxt_read_object(data, object->type,
2060 j * obj_size + k, &val);
2061 if (error) {
2062 dev_err(dev,
2063 "Failed to read object %d "
2064 "instance %d at offset %d\n",
2065 object->type, j, k);
2066 return error;
2067 }
2068
2069 seq_printf(m, "Byte %d: 0x%02x (%d)\n",
2070 k, val, val);
2071 }
2072 }
2073 }
2074
2075 return 0;
2076}
2077
2078static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
2079{
2080 return single_open(file, mxt_debugfs_object_show, inode->i_private);
2081}
2082
2083static const struct file_operations mxt_object_fops = {
2084 .owner = THIS_MODULE,
2085 .open = mxt_debugfs_object_open,
2086 .read = seq_read,
2087 .release = single_release,
2088};
2089
2090static void __init mxt_debugfs_init(struct mxt_data *data)
2091{
2092 debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
2093 if (IS_ERR_OR_NULL(debug_base))
2094 pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
2095 if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
2096 0444,
2097 debug_base,
2098 data,
2099 &mxt_object_fops))) {
2100 pr_err("atmel_mxt_ts: Failed to create object file\n");
2101 debugfs_remove_recursive(debug_base);
2102 }
2103}
2104
Iiro Valkonen7686b102011-02-02 23:21:58 -08002105static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002106 const struct i2c_device_id *id)
2107{
Iiro Valkonen919ed892011-02-15 13:36:52 -08002108 const struct mxt_platform_data *pdata = client->dev.platform_data;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002109 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002110 struct input_dev *input_dev;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002111 int error, i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002112
Iiro Valkonen919ed892011-02-15 13:36:52 -08002113 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002114 return -EINVAL;
2115
Iiro Valkonen7686b102011-02-02 23:21:58 -08002116 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002117 input_dev = input_allocate_device();
2118 if (!data || !input_dev) {
2119 dev_err(&client->dev, "Failed to allocate memory\n");
2120 error = -ENOMEM;
2121 goto err_free_mem;
2122 }
2123
Nick Dyer0a4016c2012-01-18 15:17:59 +05302124 data->state = INIT;
Amy Maloche83c385a2012-02-01 10:32:03 +05302125 input_dev->name = "atmel_mxt_ts";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002126 input_dev->id.bustype = BUS_I2C;
2127 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002128 input_dev->open = mxt_input_open;
2129 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002130
Joonyoung Shim910d8052011-04-12 23:14:38 -07002131 data->client = client;
2132 data->input_dev = input_dev;
2133 data->pdata = pdata;
2134 data->irq = client->irq;
2135
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002136 __set_bit(EV_ABS, input_dev->evbit);
2137 __set_bit(EV_KEY, input_dev->evbit);
2138 __set_bit(BTN_TOUCH, input_dev->keybit);
2139
2140 /* For single touch */
2141 input_set_abs_params(input_dev, ABS_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002142 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002143 input_set_abs_params(input_dev, ABS_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002144 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07002145 input_set_abs_params(input_dev, ABS_PRESSURE,
2146 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002147
2148 /* For multi touch */
Joonyoung Shimcd473222012-02-14 18:32:48 -08002149 input_mt_init_slots(input_dev, MXT_MAX_FINGER);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002150 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08002151 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002152 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002153 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002154 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002155 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07002156 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2157 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002158
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002159 /* set key array supported keys */
2160 if (pdata->key_codes) {
2161 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
2162 if (pdata->key_codes[i])
2163 input_set_capability(input_dev, EV_KEY,
2164 pdata->key_codes[i]);
2165 }
2166 }
2167
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002168 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002169 i2c_set_clientdata(client, data);
2170
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302171 if (pdata->init_hw)
2172 error = pdata->init_hw(true);
2173 else
2174 error = mxt_regulator_configure(data, true);
2175 if (error) {
2176 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07002177 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302178 }
2179
2180 if (pdata->power_on)
2181 error = pdata->power_on(true);
2182 else
2183 error = mxt_power_on(data, true);
2184 if (error) {
2185 dev_err(&client->dev, "Failed to power on hardware\n");
2186 goto err_regulator_on;
2187 }
2188
Amy Maloche08266db2011-11-04 11:07:16 -07002189 if (gpio_is_valid(pdata->irq_gpio)) {
2190 /* configure touchscreen irq gpio */
2191 error = gpio_request(pdata->irq_gpio,
2192 "mxt_irq_gpio");
2193 if (error) {
2194 pr_err("%s: unable to request gpio [%d]\n", __func__,
2195 pdata->irq_gpio);
2196 goto err_power_on;
2197 }
2198 error = gpio_direction_input(pdata->irq_gpio);
2199 if (error) {
2200 pr_err("%s: unable to set_direction for gpio [%d]\n",
2201 __func__, pdata->irq_gpio);
2202 goto err_irq_gpio_req;
2203 }
2204 }
2205
2206 if (gpio_is_valid(pdata->reset_gpio)) {
2207 /* configure touchscreen reset out gpio */
2208 error = gpio_request(pdata->reset_gpio,
2209 "mxt_reset_gpio");
2210 if (error) {
2211 pr_err("%s: unable to request reset gpio %d\n",
2212 __func__, pdata->reset_gpio);
2213 goto err_irq_gpio_req;
2214 }
2215
2216 error = gpio_direction_output(
2217 pdata->reset_gpio, 1);
2218 if (error) {
2219 pr_err("%s: unable to set direction for gpio %d\n",
2220 __func__, pdata->reset_gpio);
2221 goto err_reset_gpio_req;
2222 }
2223 }
2224
2225 mxt_reset_delay(data);
2226
Iiro Valkonen7686b102011-02-02 23:21:58 -08002227 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002228 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07002229 goto err_reset_gpio_req;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002230
Iiro Valkonen7686b102011-02-02 23:21:58 -08002231 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08002232 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002233 if (error) {
2234 dev_err(&client->dev, "Failed to register interrupt\n");
Jing Lin32c72532011-11-03 12:02:33 -07002235 goto err_free_object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002236 }
2237
Nick Dyer0a4016c2012-01-18 15:17:59 +05302238 if (data->state == APPMODE) {
2239 error = mxt_make_highchg(data);
2240 if (error) {
2241 dev_err(&client->dev, "Failed to make high CHG\n");
2242 goto err_free_irq;
2243 }
2244 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07002245
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002246 error = input_register_device(input_dev);
2247 if (error)
2248 goto err_free_irq;
2249
Iiro Valkonen7686b102011-02-02 23:21:58 -08002250 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002251 if (error)
2252 goto err_unregister_device;
2253
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302254#if defined(CONFIG_HAS_EARLYSUSPEND)
2255 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
2256 MXT_SUSPEND_LEVEL;
2257 data->early_suspend.suspend = mxt_early_suspend;
2258 data->early_suspend.resume = mxt_late_resume;
2259 register_early_suspend(&data->early_suspend);
2260#endif
2261
Jing Lin6cfc00e2011-11-02 15:15:30 -07002262 mxt_debugfs_init(data);
2263
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002264 return 0;
2265
2266err_unregister_device:
2267 input_unregister_device(input_dev);
2268 input_dev = NULL;
2269err_free_irq:
2270 free_irq(client->irq, data);
Jing Lin32c72532011-11-03 12:02:33 -07002271err_free_object:
2272 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07002273err_reset_gpio_req:
2274 if (gpio_is_valid(pdata->reset_gpio))
2275 gpio_free(pdata->reset_gpio);
2276err_irq_gpio_req:
2277 if (gpio_is_valid(pdata->irq_gpio))
2278 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302279err_power_on:
2280 if (pdata->power_on)
2281 pdata->power_on(false);
2282 else
2283 mxt_power_on(data, false);
2284err_regulator_on:
2285 if (pdata->init_hw)
2286 pdata->init_hw(false);
2287 else
2288 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002289err_free_mem:
2290 input_free_device(input_dev);
2291 kfree(data);
2292 return error;
2293}
2294
Iiro Valkonen7686b102011-02-02 23:21:58 -08002295static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002296{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002297 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002298
Iiro Valkonen7686b102011-02-02 23:21:58 -08002299 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002300 free_irq(data->irq, data);
2301 input_unregister_device(data->input_dev);
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302302#if defined(CONFIG_HAS_EARLYSUSPEND)
2303 unregister_early_suspend(&data->early_suspend);
2304#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302305
2306 if (data->pdata->power_on)
2307 data->pdata->power_on(false);
2308 else
2309 mxt_power_on(data, false);
2310
2311 if (data->pdata->init_hw)
2312 data->pdata->init_hw(false);
2313 else
2314 mxt_regulator_configure(data, false);
2315
Mohan Pallakabfe8f302012-01-02 18:32:08 +08002316 if (gpio_is_valid(data->pdata->reset_gpio))
2317 gpio_free(data->pdata->reset_gpio);
2318
2319 if (gpio_is_valid(data->pdata->irq_gpio))
2320 gpio_free(data->pdata->irq_gpio);
2321
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002322 kfree(data->object_table);
2323 kfree(data);
2324
Jing Lin6cfc00e2011-11-02 15:15:30 -07002325 debugfs_remove_recursive(debug_base);
2326
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002327 return 0;
2328}
2329
Iiro Valkonen7686b102011-02-02 23:21:58 -08002330static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002331 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002332 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08002333 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002334 { }
2335};
Iiro Valkonen7686b102011-02-02 23:21:58 -08002336MODULE_DEVICE_TABLE(i2c, mxt_id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002337
Iiro Valkonen7686b102011-02-02 23:21:58 -08002338static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002339 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08002340 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002341 .owner = THIS_MODULE,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002342#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08002343 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002344#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002345 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002346 .probe = mxt_probe,
2347 .remove = __devexit_p(mxt_remove),
2348 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002349};
2350
Iiro Valkonen7686b102011-02-02 23:21:58 -08002351static int __init mxt_init(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002352{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002353 return i2c_add_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002354}
2355
Iiro Valkonen7686b102011-02-02 23:21:58 -08002356static void __exit mxt_exit(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002357{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002358 i2c_del_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002359}
2360
Iiro Valkonen7686b102011-02-02 23:21:58 -08002361module_init(mxt_init);
2362module_exit(mxt_exit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002363
2364/* Module information */
2365MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08002366MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002367MODULE_LICENSE("GPL");