blob: be7c3c612092fd4a1d2ae480fd12b96fd24f1bc5 [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>
Chun Zhang7ba20f32014-01-09 15:56:53 -08006 * Copyright (c) 2011-2014, The Linux Foundation. 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 Shim8b86c1c2011-04-12 23:18:59 -070021#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>
Mohan Pallakad96f5032012-06-18 22:49:10 +053029#include <linux/of_gpio.h>
Anurag Singh49d76132013-01-29 12:07:00 -080030
31#if defined(CONFIG_FB)
32#include <linux/notifier.h>
33#include <linux/fb.h>
34
35#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +053036#include <linux/earlysuspend.h>
37/* Early-suspend level */
38#define MXT_SUSPEND_LEVEL 1
39#endif
40
Amy Maloche434b7d82013-02-15 11:11:05 +000041#if defined(CONFIG_SECURE_TOUCH)
42#include <linux/completion.h>
43#include <linux/pm_runtime.h>
44#include <linux/errno.h>
45#include <asm/system.h>
46#include <linux/atomic.h>
47#endif
48
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070049/* Family ID */
50#define MXT224_ID 0x80
Amy Maloche380cc0b2011-11-03 12:55:04 -070051#define MXT224E_ID 0x81
Amy Maloche41f1cc32012-07-12 13:02:27 -070052#define MXT336S_ID 0x82
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070053#define MXT1386_ID 0xA0
Amy Maloche41f1cc32012-07-12 13:02:27 -070054#define MXT1664S_ID 0xA2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070055
56/* Version */
Iiro Valkonen7686b102011-02-02 23:21:58 -080057#define MXT_VER_20 20
58#define MXT_VER_21 21
59#define MXT_VER_22 22
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070060
Nick Dyer0a4016c2012-01-18 15:17:59 +053061/* I2C slave address pairs */
62struct mxt_address_pair {
63 int bootloader;
64 int application;
65};
66
67static const struct mxt_address_pair mxt_slave_addresses[] = {
68 { 0x24, 0x4a },
69 { 0x25, 0x4b },
70 { 0x25, 0x4b },
71 { 0x26, 0x4c },
72 { 0x27, 0x4d },
73 { 0x34, 0x5a },
74 { 0x35, 0x5b },
75 { 0 },
76};
77
78enum mxt_device_state { INIT, APPMODE, BOOTLOADER };
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070079
80/* Firmware */
Iiro Valkonen7686b102011-02-02 23:21:58 -080081#define MXT_FW_NAME "maxtouch.fw"
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070082
Jing Lincc974cb2012-02-01 23:13:14 -080083/* Firmware frame size including frame data and CRC */
84#define MXT_SINGLE_FW_MAX_FRAME_SIZE 278
85#define MXT_CHIPSET_FW_MAX_FRAME_SIZE 534
86
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070087/* Registers */
Iiro Valkonen7686b102011-02-02 23:21:58 -080088#define MXT_FAMILY_ID 0x00
89#define MXT_VARIANT_ID 0x01
90#define MXT_VERSION 0x02
91#define MXT_BUILD 0x03
92#define MXT_MATRIX_X_SIZE 0x04
93#define MXT_MATRIX_Y_SIZE 0x05
94#define MXT_OBJECT_NUM 0x06
95#define MXT_OBJECT_START 0x07
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070096
Iiro Valkonen7686b102011-02-02 23:21:58 -080097#define MXT_OBJECT_SIZE 6
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070098
99/* Object types */
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700100#define MXT_DEBUG_DIAGNOSTIC_T37 37
101#define MXT_GEN_MESSAGE_T5 5
102#define MXT_GEN_COMMAND_T6 6
103#define MXT_GEN_POWER_T7 7
104#define MXT_GEN_ACQUIRE_T8 8
105#define MXT_GEN_DATASOURCE_T53 53
106#define MXT_TOUCH_MULTI_T9 9
107#define MXT_TOUCH_KEYARRAY_T15 15
108#define MXT_TOUCH_PROXIMITY_T23 23
109#define MXT_TOUCH_PROXKEY_T52 52
110#define MXT_PROCI_GRIPFACE_T20 20
111#define MXT_PROCG_NOISE_T22 22
Amy Maloche41f1cc32012-07-12 13:02:27 -0700112#define MXT_PROCG_NOISE_T62 62
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700113#define MXT_PROCI_ONETOUCH_T24 24
114#define MXT_PROCI_TWOTOUCH_T27 27
115#define MXT_PROCI_GRIP_T40 40
116#define MXT_PROCI_PALM_T41 41
117#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
118#define MXT_PROCI_STYLUS_T47 47
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530119#define MXT_PROCI_ADAPTIVETHRESHOLD_T55 55
Jing Linc7fc4052011-12-21 16:16:19 -0800120#define MXT_PROCI_SHIELDLESS_T56 56
Amy Maloche41f1cc32012-07-12 13:02:27 -0700121#define MXT_PROCI_EXTRATSDATA_T57 57
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700122#define MXT_PROCG_NOISESUPPRESSION_T48 48
123#define MXT_SPT_COMMSCONFIG_T18 18
124#define MXT_SPT_GPIOPWM_T19 19
125#define MXT_SPT_SELFTEST_T25 25
126#define MXT_SPT_CTECONFIG_T28 28
127#define MXT_SPT_USERDATA_T38 38
128#define MXT_SPT_DIGITIZER_T43 43
129#define MXT_SPT_MESSAGECOUNT_T44 44
130#define MXT_SPT_CTECONFIG_T46 46
Amy Malochee3146fb2013-04-12 14:59:16 -0700131#define MXT_SPT_EXTRANOISESUPCTRLS_T58 58
Amy Maloche41f1cc32012-07-12 13:02:27 -0700132#define MXT_SPT_TIMER_T61 61
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700133
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700134/* MXT_GEN_COMMAND_T6 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800135#define MXT_COMMAND_RESET 0
136#define MXT_COMMAND_BACKUPNV 1
137#define MXT_COMMAND_CALIBRATE 2
138#define MXT_COMMAND_REPORTALL 3
139#define MXT_COMMAND_DIAGNOSTIC 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700140
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700141/* MXT_GEN_POWER_T7 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800142#define MXT_POWER_IDLEACQINT 0
143#define MXT_POWER_ACTVACQINT 1
144#define MXT_POWER_ACTV2IDLETO 2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700145
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700146/* MXT_GEN_ACQUIRE_T8 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800147#define MXT_ACQUIRE_CHRGTIME 0
148#define MXT_ACQUIRE_TCHDRIFT 2
149#define MXT_ACQUIRE_DRIFTST 3
150#define MXT_ACQUIRE_TCHAUTOCAL 4
151#define MXT_ACQUIRE_SYNC 5
152#define MXT_ACQUIRE_ATCHCALST 6
153#define MXT_ACQUIRE_ATCHCALSTHR 7
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700154
Iiro Valkonene8645592011-11-18 12:56:19 -0800155/* MXT_TOUCH_MULT_T9 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800156#define MXT_TOUCH_CTRL 0
157#define MXT_TOUCH_XORIGIN 1
158#define MXT_TOUCH_YORIGIN 2
159#define MXT_TOUCH_XSIZE 3
160#define MXT_TOUCH_YSIZE 4
161#define MXT_TOUCH_BLEN 6
162#define MXT_TOUCH_TCHTHR 7
163#define MXT_TOUCH_TCHDI 8
164#define MXT_TOUCH_ORIENT 9
165#define MXT_TOUCH_MOVHYSTI 11
166#define MXT_TOUCH_MOVHYSTN 12
167#define MXT_TOUCH_NUMTOUCH 14
168#define MXT_TOUCH_MRGHYST 15
169#define MXT_TOUCH_MRGTHR 16
170#define MXT_TOUCH_AMPHYST 17
171#define MXT_TOUCH_XRANGE_LSB 18
172#define MXT_TOUCH_XRANGE_MSB 19
173#define MXT_TOUCH_YRANGE_LSB 20
174#define MXT_TOUCH_YRANGE_MSB 21
175#define MXT_TOUCH_XLOCLIP 22
176#define MXT_TOUCH_XHICLIP 23
177#define MXT_TOUCH_YLOCLIP 24
178#define MXT_TOUCH_YHICLIP 25
179#define MXT_TOUCH_XEDGECTRL 26
180#define MXT_TOUCH_XEDGEDIST 27
181#define MXT_TOUCH_YEDGECTRL 28
182#define MXT_TOUCH_YEDGEDIST 29
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700183#define MXT_TOUCH_JUMPLIMIT 30
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700184
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700185/* MXT_PROCI_GRIPFACE_T20 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800186#define MXT_GRIPFACE_CTRL 0
187#define MXT_GRIPFACE_XLOGRIP 1
188#define MXT_GRIPFACE_XHIGRIP 2
189#define MXT_GRIPFACE_YLOGRIP 3
190#define MXT_GRIPFACE_YHIGRIP 4
191#define MXT_GRIPFACE_MAXTCHS 5
192#define MXT_GRIPFACE_SZTHR1 7
193#define MXT_GRIPFACE_SZTHR2 8
194#define MXT_GRIPFACE_SHPTHR1 9
195#define MXT_GRIPFACE_SHPTHR2 10
196#define MXT_GRIPFACE_SUPEXTTO 11
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700197
Iiro Valkonen7686b102011-02-02 23:21:58 -0800198/* MXT_PROCI_NOISE field */
199#define MXT_NOISE_CTRL 0
200#define MXT_NOISE_OUTFLEN 1
201#define MXT_NOISE_GCAFUL_LSB 3
202#define MXT_NOISE_GCAFUL_MSB 4
203#define MXT_NOISE_GCAFLL_LSB 5
204#define MXT_NOISE_GCAFLL_MSB 6
205#define MXT_NOISE_ACTVGCAFVALID 7
206#define MXT_NOISE_NOISETHR 8
207#define MXT_NOISE_FREQHOPSCALE 10
208#define MXT_NOISE_FREQ0 11
209#define MXT_NOISE_FREQ1 12
210#define MXT_NOISE_FREQ2 13
211#define MXT_NOISE_FREQ3 14
212#define MXT_NOISE_FREQ4 15
213#define MXT_NOISE_IDLEGCAFVALID 16
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700214
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700215/* MXT_SPT_COMMSCONFIG_T18 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800216#define MXT_COMMS_CTRL 0
217#define MXT_COMMS_CMD 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700218
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700219/* MXT_SPT_CTECONFIG_T28 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800220#define MXT_CTE_CTRL 0
221#define MXT_CTE_CMD 1
222#define MXT_CTE_MODE 2
223#define MXT_CTE_IDLEGCAFDEPTH 3
224#define MXT_CTE_ACTVGCAFDEPTH 4
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700225#define MXT_CTE_VOLTAGE 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700226
Iiro Valkonen7686b102011-02-02 23:21:58 -0800227#define MXT_VOLTAGE_DEFAULT 2700000
228#define MXT_VOLTAGE_STEP 10000
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700229
Amy Maloche21115eb2011-11-02 09:04:37 -0700230/* Analog voltage @2.7 V */
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530231#define MXT_VTG_MIN_UV 2700000
232#define MXT_VTG_MAX_UV 3300000
233#define MXT_ACTIVE_LOAD_UA 15000
Jing Linbace50b2011-10-18 22:55:47 -0700234#define MXT_LPM_LOAD_UA 10
Amy Maloche21115eb2011-11-02 09:04:37 -0700235/* Digital voltage @1.8 V */
236#define MXT_VTG_DIG_MIN_UV 1800000
237#define MXT_VTG_DIG_MAX_UV 1800000
238#define MXT_ACTIVE_LOAD_DIG_UA 10000
239#define MXT_LPM_LOAD_DIG_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530240
241#define MXT_I2C_VTG_MIN_UV 1800000
242#define MXT_I2C_VTG_MAX_UV 1800000
243#define MXT_I2C_LOAD_UA 10000
Jing Linbace50b2011-10-18 22:55:47 -0700244#define MXT_I2C_LPM_LOAD_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530245
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700246/* Define for MXT_GEN_COMMAND_T6 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800247#define MXT_BOOT_VALUE 0xa5
248#define MXT_BACKUP_VALUE 0x55
249#define MXT_BACKUP_TIME 25 /* msec */
Jing Lin64fdd1f2012-12-20 17:08:28 -0800250
251/* Software reset delay */
252#define MXT224_RESET_TIME 64 /* msec */
253#define MXT224E_RESET_TIME 21 /* msec */
Amy Maloche41f1cc32012-07-12 13:02:27 -0700254#define MXT336S_RESET_TIME 25 /* msec */
Jing Lin64fdd1f2012-12-20 17:08:28 -0800255#define MXT1386_RESET_TIME 250 /* msec */
256#define MXT1386E_RESET_TIME 229 /* msec */
257#define MXT1664S_RESET_TIME 280 /* msec */
Amy Maloche7e447432011-09-14 11:36:30 -0700258#define MXT_RESET_TIME 250 /* msec */
Jing Linc7fc4052011-12-21 16:16:19 -0800259#define MXT_RESET_NOCHGREAD 400 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700260
Jing Lin64fdd1f2012-12-20 17:08:28 -0800261/* Power on delay */
262#define MXT224_POWER_ON_TIME 40 /* msec */
263#define MXT224E_POWER_ON_TIME 21 /* msec */
264#define MXT336S_POWER_ON_TIME 25 /* msec */
265#define MXT1386_POWER_ON_TIME 90 /* msec */
266#define MXT1386E_POWER_ON_TIME 81 /* msec */
267#define MXT1664S_POWER_ON_TIME 65 /* msec */
268#define MXT_POWER_ON_TIME 100 /* msec */
269
Nick Dyer0a4016c2012-01-18 15:17:59 +0530270#define MXT_FWRESET_TIME 1000 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700271
Jing Lin36aee812011-10-17 17:17:28 -0700272#define MXT_WAKE_TIME 25
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700273
274/* Command to unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800275#define MXT_UNLOCK_CMD_MSB 0xaa
276#define MXT_UNLOCK_CMD_LSB 0xdc
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700277
278/* Bootloader mode status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800279#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
280#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
281#define MXT_FRAME_CRC_CHECK 0x02
282#define MXT_FRAME_CRC_FAIL 0x03
283#define MXT_FRAME_CRC_PASS 0x04
284#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
285#define MXT_BOOT_STATUS_MASK 0x3f
Nick Dyer0a4016c2012-01-18 15:17:59 +0530286#define MXT_BOOT_EXTENDED_ID (1 << 5)
287#define MXT_BOOT_ID_MASK 0x1f
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700288
289/* Touch status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800290#define MXT_SUPPRESS (1 << 1)
291#define MXT_AMP (1 << 2)
292#define MXT_VECTOR (1 << 3)
293#define MXT_MOVE (1 << 4)
294#define MXT_RELEASE (1 << 5)
295#define MXT_PRESS (1 << 6)
296#define MXT_DETECT (1 << 7)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700297
Joonyoung Shim910d8052011-04-12 23:14:38 -0700298/* Touch orient bits */
299#define MXT_XY_SWITCH (1 << 0)
300#define MXT_X_INVERT (1 << 1)
301#define MXT_Y_INVERT (1 << 2)
302
Mohan Pallakab6acab42012-06-13 11:59:04 +0530303/* Touch suppression */
304#define MXT_TCHSUP_ACTIVE (1 << 0)
305
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700306/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800307#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700308
Iiro Valkonen7686b102011-02-02 23:21:58 -0800309#define MXT_MAX_FINGER 10
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700310
Jing Lin36aee812011-10-17 17:17:28 -0700311#define T7_DATA_SIZE 3
312#define MXT_MAX_RW_TRIES 3
313#define MXT_BLOCK_SIZE 256
Jing Lin8fadad72012-02-24 10:10:50 -0800314#define MXT_CFG_VERSION_LEN 3
315#define MXT_CFG_VERSION_EQUAL 0
316#define MXT_CFG_VERSION_LESS 1
317#define MXT_CFG_VERSION_GREATER 2
Mohan Pallakaab51f2b2011-09-29 18:17:35 +0530318
Mohan Pallakad96f5032012-06-18 22:49:10 +0530319#define MXT_COORDS_ARR_SIZE 4
320
Jing Lin6cfc00e2011-11-02 15:15:30 -0700321#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
322#define MXT_DEBUGFS_FILE "object"
323
Iiro Valkonen7686b102011-02-02 23:21:58 -0800324struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700325 u8 family_id;
326 u8 variant_id;
327 u8 version;
328 u8 build;
329 u8 matrix_xsize;
330 u8 matrix_ysize;
331 u8 object_num;
332};
333
Iiro Valkonen7686b102011-02-02 23:21:58 -0800334struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700335 u8 type;
336 u16 start_address;
337 u8 size;
338 u8 instances;
339 u8 num_report_ids;
340
341 /* to map object and message */
342 u8 max_reportid;
343};
344
Iiro Valkonen7686b102011-02-02 23:21:58 -0800345struct mxt_message {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700346 u8 reportid;
347 u8 message[7];
348 u8 checksum;
349};
350
Iiro Valkonen7686b102011-02-02 23:21:58 -0800351struct mxt_finger {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700352 int status;
353 int x;
354 int y;
355 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700356 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700357};
358
359/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800360struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700361 struct i2c_client *client;
362 struct input_dev *input_dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800363 const struct mxt_platform_data *pdata;
Jing Lindc4413c2012-01-16 15:22:52 -0800364 const struct mxt_config_info *config_info;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530365 enum mxt_device_state state;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800366 struct mxt_object *object_table;
367 struct mxt_info info;
368 struct mxt_finger finger[MXT_MAX_FINGER];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700369 unsigned int irq;
Amy Maloche21115eb2011-11-02 09:04:37 -0700370 struct regulator *vcc_ana;
371 struct regulator *vcc_dig;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530372 struct regulator *vcc_i2c;
Amy Maloche265fc3c2013-01-17 11:50:24 -0800373 struct mxt_address_pair addr_pair;
Anurag Singh49d76132013-01-29 12:07:00 -0800374#if defined(CONFIG_FB)
375 struct notifier_block fb_notif;
376#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +0530377 struct early_suspend early_suspend;
378#endif
Jing Lin36aee812011-10-17 17:17:28 -0700379
Amy Maloche52262212011-09-15 16:46:57 -0700380 u8 t7_data[T7_DATA_SIZE];
Jing Lin36aee812011-10-17 17:17:28 -0700381 u16 t7_start_addr;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800382 u32 keyarray_old;
383 u32 keyarray_new;
384 u8 t9_max_reportid;
385 u8 t9_min_reportid;
386 u8 t15_max_reportid;
387 u8 t15_min_reportid;
Mohan Pallakab6acab42012-06-13 11:59:04 +0530388 u8 t42_max_reportid;
389 u8 t42_min_reportid;
Jing Lin8fadad72012-02-24 10:10:50 -0800390 u8 cfg_version[MXT_CFG_VERSION_LEN];
Jing Lindc4413c2012-01-16 15:22:52 -0800391 int cfg_version_idx;
Jing Lin8a9472d2012-03-21 15:43:45 -0700392 int t38_start_addr;
Jing Lin8fadad72012-02-24 10:10:50 -0800393 bool update_cfg;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -0800394 const char *fw_name;
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +0530395 bool no_force_update;
Mohan Pallakab74e3482013-07-09 16:39:56 +0530396 bool lpm_support;
Chun Zhang53ab0202013-07-29 17:45:17 -0700397 bool dev_sleep;
Mohan Pallakab74e3482013-07-09 16:39:56 +0530398
Amy Maloche434b7d82013-02-15 11:11:05 +0000399#if defined(CONFIG_SECURE_TOUCH)
400 atomic_t st_enabled;
401 atomic_t st_pending_irqs;
Amy Maloche20f970c2013-04-10 13:04:52 +0100402 struct completion st_powerdown;
Amy Maloche434b7d82013-02-15 11:11:05 +0000403#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700404};
405
Jing Lin6cfc00e2011-11-02 15:15:30 -0700406static struct dentry *debug_base;
407
Iiro Valkonen7686b102011-02-02 23:21:58 -0800408static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700409{
410 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700411 case MXT_GEN_MESSAGE_T5:
412 case MXT_GEN_COMMAND_T6:
413 case MXT_GEN_POWER_T7:
414 case MXT_GEN_ACQUIRE_T8:
415 case MXT_GEN_DATASOURCE_T53:
416 case MXT_TOUCH_MULTI_T9:
417 case MXT_TOUCH_KEYARRAY_T15:
418 case MXT_TOUCH_PROXIMITY_T23:
419 case MXT_TOUCH_PROXKEY_T52:
420 case MXT_PROCI_GRIPFACE_T20:
421 case MXT_PROCG_NOISE_T22:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700422 case MXT_PROCG_NOISE_T62:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700423 case MXT_PROCI_ONETOUCH_T24:
424 case MXT_PROCI_TWOTOUCH_T27:
425 case MXT_PROCI_GRIP_T40:
426 case MXT_PROCI_PALM_T41:
427 case MXT_PROCI_TOUCHSUPPRESSION_T42:
428 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800429 case MXT_PROCI_SHIELDLESS_T56:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700430 case MXT_PROCI_EXTRATSDATA_T57:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700431 case MXT_PROCG_NOISESUPPRESSION_T48:
432 case MXT_SPT_COMMSCONFIG_T18:
433 case MXT_SPT_GPIOPWM_T19:
434 case MXT_SPT_SELFTEST_T25:
435 case MXT_SPT_CTECONFIG_T28:
436 case MXT_SPT_USERDATA_T38:
437 case MXT_SPT_DIGITIZER_T43:
438 case MXT_SPT_CTECONFIG_T46:
Amy Malochee3146fb2013-04-12 14:59:16 -0700439 case MXT_SPT_EXTRANOISESUPCTRLS_T58:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700440 case MXT_SPT_TIMER_T61:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530441 case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700442 return true;
443 default:
444 return false;
445 }
446}
447
Iiro Valkonen7686b102011-02-02 23:21:58 -0800448static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700449{
450 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700451 case MXT_GEN_COMMAND_T6:
452 case MXT_GEN_POWER_T7:
453 case MXT_GEN_ACQUIRE_T8:
454 case MXT_TOUCH_MULTI_T9:
455 case MXT_TOUCH_KEYARRAY_T15:
456 case MXT_TOUCH_PROXIMITY_T23:
457 case MXT_TOUCH_PROXKEY_T52:
458 case MXT_PROCI_GRIPFACE_T20:
459 case MXT_PROCG_NOISE_T22:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700460 case MXT_PROCG_NOISE_T62:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700461 case MXT_PROCI_ONETOUCH_T24:
462 case MXT_PROCI_TWOTOUCH_T27:
463 case MXT_PROCI_GRIP_T40:
464 case MXT_PROCI_PALM_T41:
465 case MXT_PROCI_TOUCHSUPPRESSION_T42:
466 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800467 case MXT_PROCI_SHIELDLESS_T56:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700468 case MXT_PROCI_EXTRATSDATA_T57:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700469 case MXT_PROCG_NOISESUPPRESSION_T48:
470 case MXT_SPT_COMMSCONFIG_T18:
471 case MXT_SPT_GPIOPWM_T19:
472 case MXT_SPT_SELFTEST_T25:
473 case MXT_SPT_CTECONFIG_T28:
Iiro Valkonene8645592011-11-18 12:56:19 -0800474 case MXT_SPT_USERDATA_T38:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700475 case MXT_SPT_DIGITIZER_T43:
476 case MXT_SPT_CTECONFIG_T46:
Amy Malochee3146fb2013-04-12 14:59:16 -0700477 case MXT_SPT_EXTRANOISESUPCTRLS_T58:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700478 case MXT_SPT_TIMER_T61:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530479 case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700480 return true;
481 default:
482 return false;
483 }
484}
485
Iiro Valkonen7686b102011-02-02 23:21:58 -0800486static void mxt_dump_message(struct device *dev,
487 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700488{
489 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
490 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
491 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
492 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
493 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
494 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
495 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
496 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
497 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
498}
499
Amy Maloche265fc3c2013-01-17 11:50:24 -0800500static int mxt_lookup_bootloader_address(struct mxt_data *data)
Amy Maloche71b8f022013-01-17 11:50:24 -0800501{
Steve Mucklee1533542013-02-13 15:03:16 -0800502 int i;
Amy Maloche265fc3c2013-01-17 11:50:24 -0800503
504 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
505 if (mxt_slave_addresses[i].application ==
506 data->client->addr) {
507 data->addr_pair.bootloader =
508 mxt_slave_addresses[i].bootloader;
509 return 0;
510 }
511 }
512
513 dev_err(&data->client->dev, "Address 0x%02x not found in address table",
514 data->client->addr);
515 return -EINVAL;
516
517};
518
519static int mxt_switch_to_bootloader_address(struct mxt_data *data)
520{
Nick Dyer0a4016c2012-01-18 15:17:59 +0530521 struct i2c_client *client = data->client;
522
523 if (data->state == BOOTLOADER) {
524 dev_err(&client->dev, "Already in BOOTLOADER state\n");
525 return -EINVAL;
526 }
527
Amy Maloche265fc3c2013-01-17 11:50:24 -0800528 dev_info(&client->dev, "Changing to bootloader address: 0x%02x -> 0x%02x",
529 client->addr, data->addr_pair.bootloader);
Nick Dyer0a4016c2012-01-18 15:17:59 +0530530
Amy Maloche265fc3c2013-01-17 11:50:24 -0800531 client->addr = data->addr_pair.bootloader;
532 data->state = BOOTLOADER;
533 return 0;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530534}
535
536static int mxt_switch_to_appmode_address(struct mxt_data *data)
537{
Nick Dyer0a4016c2012-01-18 15:17:59 +0530538 struct i2c_client *client = data->client;
539
540 if (data->state == APPMODE) {
541 dev_err(&client->dev, "Already in APPMODE state\n");
542 return -EINVAL;
543 }
544
Amy Maloche265fc3c2013-01-17 11:50:24 -0800545 dev_info(&client->dev, "Changing to application mode address: " \
546 "0x%02x -> 0x%02x", client->addr,
547 data->addr_pair.application);
Nick Dyer0a4016c2012-01-18 15:17:59 +0530548
Amy Maloche265fc3c2013-01-17 11:50:24 -0800549 client->addr = data->addr_pair.application;
550 data->state = APPMODE;
551 return 0;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530552}
553
554static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
555{
556 u8 buf[3];
557
558 if (val | MXT_BOOT_EXTENDED_ID) {
559 dev_dbg(&client->dev,
560 "Retrieving extended mode ID information");
561
562 if (i2c_master_recv(client, &buf[0], 3) != 3) {
563 dev_err(&client->dev, "%s: i2c recv failed\n",
564 __func__);
565 return -EIO;
566 }
567
568 dev_info(&client->dev, "Bootloader ID:%d Version:%d",
569 buf[1], buf[2]);
570
571 return buf[0];
572 } else {
573 dev_info(&client->dev, "Bootloader ID:%d",
574 val & MXT_BOOT_ID_MASK);
575
576 return val;
577 }
578}
579
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -0800580static int mxt_get_bootloader_id(struct i2c_client *client)
581{
582 u8 val;
583 u8 buf[3];
584
585 if (i2c_master_recv(client, &val, 1) != 1) {
586 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
587 return -EIO;
588 }
589
590 if (val | MXT_BOOT_EXTENDED_ID) {
591 if (i2c_master_recv(client, &buf[0], 3) != 3) {
592 dev_err(&client->dev, "%s: i2c recv failed\n",
593 __func__);
594 return -EIO;
595 }
596 return buf[1];
597 } else {
598 dev_info(&client->dev, "Bootloader ID:%d",
599 val & MXT_BOOT_ID_MASK);
600
601 return val & MXT_BOOT_ID_MASK;
602 }
603}
604
Iiro Valkonen7686b102011-02-02 23:21:58 -0800605static int mxt_check_bootloader(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530606 unsigned int state)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700607{
608 u8 val;
609
610recheck:
611 if (i2c_master_recv(client, &val, 1) != 1) {
612 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
613 return -EIO;
614 }
615
616 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800617 case MXT_WAITING_BOOTLOAD_CMD:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530618 val = mxt_get_bootloader_version(client, val);
619 val &= ~MXT_BOOT_STATUS_MASK;
620 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800621 case MXT_WAITING_FRAME_DATA:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530622 case MXT_APP_CRC_FAIL:
Iiro Valkonen7686b102011-02-02 23:21:58 -0800623 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700624 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800625 case MXT_FRAME_CRC_PASS:
626 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700627 goto recheck;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530628 if (val == MXT_FRAME_CRC_FAIL) {
629 dev_err(&client->dev, "Bootloader CRC fail\n");
630 return -EINVAL;
631 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700632 break;
633 default:
634 return -EINVAL;
635 }
636
637 if (val != state) {
Nick Dyer0a4016c2012-01-18 15:17:59 +0530638 dev_err(&client->dev, "Invalid bootloader mode state %X\n",
639 val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700640 return -EINVAL;
641 }
642
643 return 0;
644}
645
Iiro Valkonen7686b102011-02-02 23:21:58 -0800646static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700647{
648 u8 buf[2];
649
Iiro Valkonen7686b102011-02-02 23:21:58 -0800650 buf[0] = MXT_UNLOCK_CMD_LSB;
651 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700652
653 if (i2c_master_send(client, buf, 2) != 2) {
654 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
655 return -EIO;
656 }
657
658 return 0;
659}
660
Iiro Valkonen7686b102011-02-02 23:21:58 -0800661static int mxt_fw_write(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530662 const u8 *data, unsigned int frame_size)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700663{
664 if (i2c_master_send(client, data, frame_size) != frame_size) {
665 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
666 return -EIO;
667 }
668
669 return 0;
670}
671
Iiro Valkonen7686b102011-02-02 23:21:58 -0800672static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700673 u16 reg, u16 len, void *val)
674{
675 struct i2c_msg xfer[2];
676 u8 buf[2];
Jing Lin36aee812011-10-17 17:17:28 -0700677 int i = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700678
679 buf[0] = reg & 0xff;
680 buf[1] = (reg >> 8) & 0xff;
681
682 /* Write register */
683 xfer[0].addr = client->addr;
684 xfer[0].flags = 0;
685 xfer[0].len = 2;
686 xfer[0].buf = buf;
687
688 /* Read data */
689 xfer[1].addr = client->addr;
690 xfer[1].flags = I2C_M_RD;
691 xfer[1].len = len;
692 xfer[1].buf = val;
693
Jing Lin36aee812011-10-17 17:17:28 -0700694 do {
695 if (i2c_transfer(client->adapter, xfer, 2) == 2)
696 return 0;
697 msleep(MXT_WAKE_TIME);
698 } while (++i < MXT_MAX_RW_TRIES);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700699
Jing Lin36aee812011-10-17 17:17:28 -0700700 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
701 return -EIO;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700702}
703
Iiro Valkonen7686b102011-02-02 23:21:58 -0800704static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700705{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800706 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700707}
708
Jing Lin36aee812011-10-17 17:17:28 -0700709static int __mxt_write_reg(struct i2c_client *client,
710 u16 addr, u16 length, u8 *value)
711{
712 u8 buf[MXT_BLOCK_SIZE + 2];
713 int i, tries = 0;
714
715 if (length > MXT_BLOCK_SIZE)
716 return -EINVAL;
717
718 buf[0] = addr & 0xff;
719 buf[1] = (addr >> 8) & 0xff;
720 for (i = 0; i < length; i++)
721 buf[i + 2] = *value++;
722
723 do {
724 if (i2c_master_send(client, buf, length + 2) == (length + 2))
725 return 0;
726 msleep(MXT_WAKE_TIME);
727 } while (++tries < MXT_MAX_RW_TRIES);
728
729 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
730 return -EIO;
731}
732
Iiro Valkonen7686b102011-02-02 23:21:58 -0800733static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700734{
Jing Lin36aee812011-10-17 17:17:28 -0700735 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700736}
737
Iiro Valkonen7686b102011-02-02 23:21:58 -0800738static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700739 u16 reg, u8 *object_buf)
740{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800741 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700742 object_buf);
743}
744
Iiro Valkonen7686b102011-02-02 23:21:58 -0800745static struct mxt_object *
746mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700747{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800748 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700749 int i;
750
751 for (i = 0; i < data->info.object_num; i++) {
752 object = data->object_table + i;
753 if (object->type == type)
754 return object;
755 }
756
757 dev_err(&data->client->dev, "Invalid object type\n");
758 return NULL;
759}
760
Iiro Valkonen7686b102011-02-02 23:21:58 -0800761static int mxt_read_message(struct mxt_data *data,
762 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700763{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800764 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700765 u16 reg;
766
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700767 object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700768 if (!object)
769 return -EINVAL;
770
771 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800772 return __mxt_read_reg(data->client, reg,
773 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700774}
775
Iiro Valkonen7686b102011-02-02 23:21:58 -0800776static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700777 u8 type, u8 offset, u8 *val)
778{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800779 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700780 u16 reg;
781
Iiro Valkonen7686b102011-02-02 23:21:58 -0800782 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700783 if (!object)
784 return -EINVAL;
785
786 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800787 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700788}
789
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530790static int mxt_get_object_address(struct device *dev, u8 type)
791{
792 struct mxt_data *data = dev_get_drvdata(dev);
793 u8 obj_num, obj_buf[MXT_OBJECT_SIZE];
794 u16 reg;
795 int i, error;
796
797 error = mxt_read_reg(data->client, MXT_OBJECT_NUM, &obj_num);
798
799 if (error) {
800 dev_err(dev, "reading number of objects failed\n");
801 return -EINVAL;
802 }
803
804 for (i = 0; i < obj_num; i++) {
805 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
806 error = mxt_read_object_table(data->client,
807 reg, obj_buf);
808 if (error)
809 return error;
810
811 if (obj_buf[0] == type)
812 return obj_buf[2] << 8 | obj_buf[1];
813 }
814 /* If control reaches here, i = obj_num and object not found */
815 dev_err(dev, "Requested object %d not found.\n", type);
816 return -EINVAL;
817
818}
819
Iiro Valkonen7686b102011-02-02 23:21:58 -0800820static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700821 u8 type, u8 offset, u8 val)
822{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800823 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700824 u16 reg;
825
Iiro Valkonen7686b102011-02-02 23:21:58 -0800826 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700827 if (!object)
828 return -EINVAL;
829
830 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800831 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700832}
833
Iiro Valkonen7686b102011-02-02 23:21:58 -0800834static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700835{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800836 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700837 struct input_dev *input_dev = data->input_dev;
838 int status = finger[single_id].status;
839 int finger_num = 0;
840 int id;
841
Iiro Valkonen7686b102011-02-02 23:21:58 -0800842 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700843 if (!finger[id].status)
844 continue;
845
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700846 input_mt_slot(input_dev, id);
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800847 /* Firmware reports min/max values when the touch is
848 * outside screen area. Send a release event in
849 * such cases to avoid unwanted touches.
850 */
851 if (finger[id].x <= data->pdata->panel_minx ||
852 finger[id].x >= data->pdata->panel_maxx ||
853 finger[id].y <= data->pdata->panel_miny ||
854 finger[id].y >= data->pdata->panel_maxy) {
855 finger[id].status = MXT_RELEASE;
856 }
857
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700858 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
859 finger[id].status != MXT_RELEASE);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700860
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700861 if (finger[id].status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700862 finger_num++;
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700863 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
864 finger[id].area);
865 input_report_abs(input_dev, ABS_MT_POSITION_X,
866 finger[id].x);
867 input_report_abs(input_dev, ABS_MT_POSITION_Y,
868 finger[id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700869 input_report_abs(input_dev, ABS_MT_PRESSURE,
Anirudh Ghayal279a2ae52012-05-18 18:07:46 +0530870 finger[id].pressure);
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700871 } else {
872 finger[id].status = 0;
873 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700874 }
875
876 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
877
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800878 if (finger[single_id].x <= data->pdata->panel_minx ||
879 finger[single_id].x >= data->pdata->panel_maxx ||
880 finger[single_id].y <= data->pdata->panel_miny ||
881 finger[single_id].y >= data->pdata->panel_maxy) {
882 status = MXT_RELEASE;
883 }
884
Chun Zhang7ba20f32014-01-09 15:56:53 -0800885 if ((status != MXT_RELEASE) && status) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700886 input_report_abs(input_dev, ABS_X, finger[single_id].x);
887 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700888 input_report_abs(input_dev,
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700889 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700890 }
891
892 input_sync(input_dev);
893}
894
Amy Maloche1b7ac702013-02-21 19:47:53 -0800895static void mxt_release_all(struct mxt_data *data)
896{
897 int id;
898
899 for (id = 0; id < MXT_MAX_FINGER; id++)
900 if (data->finger[id].status)
901 data->finger[id].status = MXT_RELEASE;
902
903 mxt_input_report(data, 0);
904}
905
Iiro Valkonen7686b102011-02-02 23:21:58 -0800906static void mxt_input_touchevent(struct mxt_data *data,
907 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700908{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800909 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700910 struct device *dev = &data->client->dev;
911 u8 status = message->message[0];
912 int x;
913 int y;
914 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700915 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700916
Amy Maloche1b7ac702013-02-21 19:47:53 -0800917 if (status & MXT_SUPPRESS) {
918 mxt_release_all(data);
919 return;
920 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700921 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800922 if (!(status & MXT_DETECT)) {
923 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700924 dev_dbg(dev, "[%d] released\n", id);
925
Iiro Valkonen7686b102011-02-02 23:21:58 -0800926 finger[id].status = MXT_RELEASE;
927 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700928 }
929 return;
930 }
931
932 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800933 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700934 return;
935
Joonyoung Shim910d8052011-04-12 23:14:38 -0700936 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
937 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800938 if (data->pdata->panel_maxx < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700939 x = x >> 2;
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800940 if (data->pdata->panel_maxy < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700941 y = y >> 2;
942
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700943 area = message->message[4];
Yufeng Shen28ac2932011-08-16 00:40:54 -0700944 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700945
946 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800947 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700948 x, y, area);
949
Iiro Valkonen7686b102011-02-02 23:21:58 -0800950 finger[id].status = status & MXT_MOVE ?
951 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700952 finger[id].x = x;
953 finger[id].y = y;
954 finger[id].area = area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700955 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700956
Iiro Valkonen7686b102011-02-02 23:21:58 -0800957 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700958}
959
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800960static void mxt_handle_key_array(struct mxt_data *data,
961 struct mxt_message *message)
962{
963 u32 keys_changed;
964 int i;
965
966 if (!data->pdata->key_codes) {
967 dev_err(&data->client->dev, "keyarray is not supported\n");
968 return;
969 }
970
971 data->keyarray_new = message->message[1] |
972 (message->message[2] << 8) |
973 (message->message[3] << 16) |
974 (message->message[4] << 24);
975
976 keys_changed = data->keyarray_old ^ data->keyarray_new;
977
978 if (!keys_changed) {
979 dev_dbg(&data->client->dev, "no keys changed\n");
980 return;
981 }
982
983 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
984 if (!(keys_changed & (1 << i)))
985 continue;
986
987 input_report_key(data->input_dev, data->pdata->key_codes[i],
988 (data->keyarray_new & (1 << i)));
989 input_sync(data->input_dev);
990 }
991
992 data->keyarray_old = data->keyarray_new;
993}
994
Amy Maloche1b7ac702013-02-21 19:47:53 -0800995static void mxt_handle_touch_suppression(struct mxt_data *data, u8 status)
Mohan Pallakab6acab42012-06-13 11:59:04 +0530996{
997 dev_dbg(&data->client->dev, "touch suppression\n");
998 /* release all touches */
999 if (status & MXT_TCHSUP_ACTIVE)
1000 mxt_release_all(data);
1001}
1002
Amy Maloche434b7d82013-02-15 11:11:05 +00001003#if defined(CONFIG_SECURE_TOUCH)
Amy Maloche1e0c66a2013-09-24 18:26:26 +01001004static void mxt_secure_touch_notify(struct mxt_data *data)
1005{
1006 sysfs_notify(&data->client->dev.kobj, NULL, "secure_touch");
1007}
1008
Amy Maloche434b7d82013-02-15 11:11:05 +00001009static irqreturn_t mxt_filter_interrupt(struct mxt_data *data)
1010{
1011 if (atomic_read(&data->st_enabled)) {
Amy Maloche20f970c2013-04-10 13:04:52 +01001012 if (atomic_cmpxchg(&data->st_pending_irqs, 0, 1) == 0)
Amy Maloche1e0c66a2013-09-24 18:26:26 +01001013 mxt_secure_touch_notify(data);
Amy Maloche434b7d82013-02-15 11:11:05 +00001014 return IRQ_HANDLED;
1015 }
1016 return IRQ_NONE;
1017}
1018#else
1019static irqreturn_t mxt_filter_interrupt(struct mxt_data *data)
1020{
1021 return IRQ_NONE;
1022}
1023#endif
1024
Iiro Valkonen7686b102011-02-02 23:21:58 -08001025static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001026{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001027 struct mxt_data *data = dev_id;
1028 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001029 struct device *dev = &data->client->dev;
1030 int id;
1031 u8 reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001032
Nick Dyer0a4016c2012-01-18 15:17:59 +05301033 if (data->state != APPMODE) {
1034 dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
1035 return IRQ_HANDLED;
1036 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001037
Amy Maloche434b7d82013-02-15 11:11:05 +00001038 if (IRQ_HANDLED == mxt_filter_interrupt(data))
1039 goto end;
1040
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001041 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001042 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001043 dev_err(dev, "Failed to read message\n");
1044 goto end;
1045 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001046 reportid = message.reportid;
1047
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001048 if (!reportid) {
1049 dev_dbg(dev, "Report id 0 is reserved\n");
1050 continue;
1051 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001052
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001053 id = reportid - data->t9_min_reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001054
Amy Maloche1b7ac702013-02-21 19:47:53 -08001055 /* check whether report id is part of T9, T15 or T42 */
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001056 if (reportid >= data->t9_min_reportid &&
1057 reportid <= data->t9_max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -08001058 mxt_input_touchevent(data, &message, id);
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001059 else if (reportid >= data->t15_min_reportid &&
1060 reportid <= data->t15_max_reportid)
1061 mxt_handle_key_array(data, &message);
Mohan Pallakab6acab42012-06-13 11:59:04 +05301062 else if (reportid >= data->t42_min_reportid &&
Amy Maloche1b7ac702013-02-21 19:47:53 -08001063 reportid <= data->t42_max_reportid)
1064 mxt_handle_touch_suppression(data,
1065 message.message[0]);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001066 else
Iiro Valkonen7686b102011-02-02 23:21:58 -08001067 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001068 } while (reportid != 0xff);
1069
1070end:
1071 return IRQ_HANDLED;
1072}
1073
Iiro Valkonen7686b102011-02-02 23:21:58 -08001074static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001075{
Jing Lindc4413c2012-01-16 15:22:52 -08001076 const struct mxt_config_info *config_info = data->config_info;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001077 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001078 struct device *dev = &data->client->dev;
1079 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -08001080 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001081
Jing Lindc4413c2012-01-16 15:22:52 -08001082 if (!config_info) {
Iiro Valkonen71749f52011-02-15 13:36:52 -08001083 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
1084 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001085 }
1086
1087 for (i = 0; i < data->info.object_num; i++) {
1088 object = data->object_table + i;
1089
Iiro Valkonen7686b102011-02-02 23:21:58 -08001090 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001091 continue;
1092
Iiro Valkonen71749f52011-02-15 13:36:52 -08001093 for (j = 0; j < object->size + 1; j++) {
1094 config_offset = index + j;
Jing Lindc4413c2012-01-16 15:22:52 -08001095 if (config_offset > config_info->config_length) {
Iiro Valkonen71749f52011-02-15 13:36:52 -08001096 dev_err(dev, "Not enough config data!\n");
1097 return -EINVAL;
1098 }
Iiro Valkonen7686b102011-02-02 23:21:58 -08001099 mxt_write_object(data, object->type, j,
Jing Lindc4413c2012-01-16 15:22:52 -08001100 config_info->config[config_offset]);
Iiro Valkonen71749f52011-02-15 13:36:52 -08001101 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001102 index += object->size + 1;
1103 }
1104
1105 return 0;
1106}
1107
Iiro Valkonen7686b102011-02-02 23:21:58 -08001108static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001109{
1110 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001111 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001112 int count = 10;
1113 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001114
1115 /* Read dummy message to make high CHG pin */
1116 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001117 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001118 if (error)
1119 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001120 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001121
1122 if (!count) {
1123 dev_err(dev, "CHG pin isn't cleared\n");
1124 return -EBUSY;
1125 }
1126
1127 return 0;
1128}
1129
Iiro Valkonen7686b102011-02-02 23:21:58 -08001130static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001131{
1132 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001133 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001134 int error;
1135 u8 val;
1136
Iiro Valkonen7686b102011-02-02 23:21:58 -08001137 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001138 if (error)
1139 return error;
1140 info->family_id = val;
1141
Iiro Valkonen7686b102011-02-02 23:21:58 -08001142 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001143 if (error)
1144 return error;
1145 info->variant_id = val;
1146
Iiro Valkonen7686b102011-02-02 23:21:58 -08001147 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001148 if (error)
1149 return error;
1150 info->version = val;
1151
Iiro Valkonen7686b102011-02-02 23:21:58 -08001152 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001153 if (error)
1154 return error;
1155 info->build = val;
1156
Iiro Valkonen7686b102011-02-02 23:21:58 -08001157 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001158 if (error)
1159 return error;
1160 info->object_num = val;
1161
1162 return 0;
1163}
1164
Iiro Valkonen7686b102011-02-02 23:21:58 -08001165static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001166{
1167 int error;
1168 int i;
1169 u16 reg;
1170 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001171 u8 buf[MXT_OBJECT_SIZE];
Jing Lindc4413c2012-01-16 15:22:52 -08001172 bool found_t38 = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001173
1174 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001175 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001176
Iiro Valkonen7686b102011-02-02 23:21:58 -08001177 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
1178 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001179 if (error)
1180 return error;
1181
1182 object->type = buf[0];
1183 object->start_address = (buf[2] << 8) | buf[1];
1184 object->size = buf[3];
1185 object->instances = buf[4];
1186 object->num_report_ids = buf[5];
1187
1188 if (object->num_report_ids) {
1189 reportid += object->num_report_ids *
1190 (object->instances + 1);
1191 object->max_reportid = reportid;
1192 }
Jing Lindc4413c2012-01-16 15:22:52 -08001193
1194 /* Calculate index for config major version in config array.
1195 * Major version is the first byte in object T38.
1196 */
Jing Lin8a9472d2012-03-21 15:43:45 -07001197 if (object->type == MXT_SPT_USERDATA_T38) {
1198 data->t38_start_addr = object->start_address;
Jing Lindc4413c2012-01-16 15:22:52 -08001199 found_t38 = true;
Jing Lin8a9472d2012-03-21 15:43:45 -07001200 }
Jing Lindc4413c2012-01-16 15:22:52 -08001201 if (!found_t38 && mxt_object_writable(object->type))
1202 data->cfg_version_idx += object->size + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001203 }
1204
1205 return 0;
1206}
1207
Jing Lin8fadad72012-02-24 10:10:50 -08001208static int compare_versions(const u8 *v1, const u8 *v2)
1209{
1210 int i;
1211
1212 if (!v1 || !v2)
1213 return -EINVAL;
1214
1215 /* The major version number stays the same across different versions for
1216 * a particular controller on a target. The minor and sub-minor version
1217 * numbers indicate which version is newer.
1218 */
1219 if (v1[0] != v2[0])
1220 return -EINVAL;
1221
1222 for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
1223 if (v1[i] > v2[i])
1224 return MXT_CFG_VERSION_LESS; /* v2 is older */
1225
1226 if (v1[i] < v2[i])
1227 return MXT_CFG_VERSION_GREATER; /* v2 is newer */
1228 }
1229
1230 return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
1231}
1232
1233static void mxt_check_config_version(struct mxt_data *data,
1234 const struct mxt_config_info *cfg_info,
1235 bool match_major,
1236 const u8 **cfg_version_found,
1237 bool *found_cfg_major_match)
1238{
1239 const u8 *cfg_version;
1240 int result = -EINVAL;
1241
1242 cfg_version = cfg_info->config + data->cfg_version_idx;
1243
1244 if (*cfg_version_found)
1245 result = compare_versions(*cfg_version_found, cfg_version);
1246
1247 if (match_major) {
1248 if (result >= MXT_CFG_VERSION_EQUAL)
1249 *found_cfg_major_match = true;
1250
1251 if (result == MXT_CFG_VERSION_EQUAL ||
1252 result == MXT_CFG_VERSION_GREATER) {
1253 data->config_info = cfg_info;
1254 data->fw_name = cfg_info->fw_name;
1255 *cfg_version_found = cfg_version;
1256 }
1257
1258 if (result == MXT_CFG_VERSION_GREATER)
1259 data->update_cfg = true;
1260 } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
1261 data->config_info = cfg_info;
1262 data->fw_name = cfg_info->fw_name;
1263 data->update_cfg = true;
1264 *cfg_version_found = cfg_version;
1265 }
1266}
1267
1268/* If the controller's config version has a non-zero major number, call this
1269 * function with match_major = true to look for the latest config present in
1270 * the pdata based on matching family id, variant id, f/w version, build, and
1271 * config major number. If the controller is programmed with wrong config data
1272 * previously, call this function with match_major = false to look for latest
1273 * config based on based on matching family id, variant id, f/w version and
1274 * build only.
1275 */
1276static int mxt_search_config_array(struct mxt_data *data, bool match_major)
Jing Lindc4413c2012-01-16 15:22:52 -08001277{
1278
1279 const struct mxt_platform_data *pdata = data->pdata;
1280 const struct mxt_config_info *cfg_info;
Jing Lin8fadad72012-02-24 10:10:50 -08001281 const struct mxt_info *info = &data->info;
1282 const u8 *cfg_version_found;
1283 bool found_cfg_major_match = false;
Jing Lindc4413c2012-01-16 15:22:52 -08001284 int i;
Jing Lin8fadad72012-02-24 10:10:50 -08001285
1286 cfg_version_found = match_major ? data->cfg_version : NULL;
Jing Lindc4413c2012-01-16 15:22:52 -08001287
1288 for (i = 0; i < pdata->config_array_size; i++) {
1289
1290 cfg_info = &pdata->config_array[i];
1291
1292 if (!cfg_info->config || !cfg_info->config_length)
1293 continue;
1294
1295 if (info->family_id == cfg_info->family_id &&
1296 info->variant_id == cfg_info->variant_id &&
1297 info->version == cfg_info->version &&
1298 info->build == cfg_info->build) {
1299
Jing Lin8fadad72012-02-24 10:10:50 -08001300 mxt_check_config_version(data, cfg_info, match_major,
1301 &cfg_version_found, &found_cfg_major_match);
Jing Lindc4413c2012-01-16 15:22:52 -08001302 }
1303 }
1304
Jing Lin8fadad72012-02-24 10:10:50 -08001305 if (data->config_info || found_cfg_major_match)
1306 return 0;
1307
1308 data->config_info = NULL;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001309 data->fw_name = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001310
Jing Lindc4413c2012-01-16 15:22:52 -08001311 return -EINVAL;
1312}
1313
1314static int mxt_get_config(struct mxt_data *data)
1315{
1316 const struct mxt_platform_data *pdata = data->pdata;
1317 struct device *dev = &data->client->dev;
1318 struct mxt_object *object;
1319 int error;
1320
1321 if (!pdata->config_array || !pdata->config_array_size) {
1322 dev_dbg(dev, "No cfg data provided by platform data\n");
1323 return 0;
1324 }
1325
1326 /* Get current config version */
1327 object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
1328 if (!object) {
1329 dev_err(dev, "Unable to obtain USERDATA object\n");
1330 return -EINVAL;
1331 }
1332
Jing Lin8fadad72012-02-24 10:10:50 -08001333 error = __mxt_read_reg(data->client, object->start_address,
1334 sizeof(data->cfg_version), data->cfg_version);
Jing Lindc4413c2012-01-16 15:22:52 -08001335 if (error) {
1336 dev_err(dev, "Unable to read config version\n");
1337 return error;
1338 }
Jing Lin8fadad72012-02-24 10:10:50 -08001339 dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
1340 data->cfg_version[0], data->cfg_version[1],
1341 data->cfg_version[2]);
Jing Lindc4413c2012-01-16 15:22:52 -08001342
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301343 /* configuration update requires major match */
1344 error = mxt_search_config_array(data, true);
1345
1346 /* if no_force_update is false , try again with false
1347 as the second parameter to mxt_search_config_array */
1348 if (error && (data->no_force_update == false))
1349 error = mxt_search_config_array(data, false);
1350
Jing Lin8fadad72012-02-24 10:10:50 -08001351 if (error) {
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301352 dev_err(dev,
1353 "Unable to find matching config in pdata\n");
1354 return error;
Jing Lin8fadad72012-02-24 10:10:50 -08001355 }
Jing Lindc4413c2012-01-16 15:22:52 -08001356
1357 return 0;
1358}
Jing Lin8fadad72012-02-24 10:10:50 -08001359
Jing Lin64fdd1f2012-12-20 17:08:28 -08001360static void mxt_power_on_delay(struct mxt_data *data)
1361{
1362 const struct mxt_platform_data *pdata = data->pdata;
1363 const struct mxt_config_info *cfg_info;
1364 u32 delay = 0;
1365 int i;
1366
1367 for (i = 0; i < pdata->config_array_size; i++) {
1368 cfg_info = &pdata->config_array[i];
1369
1370 switch (cfg_info->family_id) {
1371 case MXT224_ID:
1372 delay = max_t(u32, delay, MXT224_POWER_ON_TIME);
1373 break;
1374 case MXT224E_ID:
1375 delay = max_t(u32, delay, MXT224E_POWER_ON_TIME);
1376 break;
1377 case MXT336S_ID:
1378 delay = max_t(u32, delay, MXT336S_POWER_ON_TIME);
1379 break;
1380 case MXT1386_ID:
1381 delay = max_t(u32, delay,
1382 max_t(u32, MXT1386_POWER_ON_TIME,
1383 MXT1386E_POWER_ON_TIME));
1384 break;
1385 case MXT1664S_ID:
1386 delay = max_t(u32, delay, MXT1664S_POWER_ON_TIME);
1387 break;
1388 default:
1389 delay = max_t(u32, delay, MXT_POWER_ON_TIME);
1390 }
1391 }
1392
1393 msleep(delay);
1394}
1395
Amy Maloche7e447432011-09-14 11:36:30 -07001396static void mxt_reset_delay(struct mxt_data *data)
1397{
1398 struct mxt_info *info = &data->info;
1399
1400 switch (info->family_id) {
1401 case MXT224_ID:
1402 msleep(MXT224_RESET_TIME);
1403 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -07001404 case MXT224E_ID:
1405 msleep(MXT224E_RESET_TIME);
1406 break;
Amy Maloche41f1cc32012-07-12 13:02:27 -07001407 case MXT336S_ID:
1408 msleep(MXT336S_RESET_TIME);
Jing Lin64fdd1f2012-12-20 17:08:28 -08001409 break;
Amy Maloche7e447432011-09-14 11:36:30 -07001410 case MXT1386_ID:
Jing Lin64fdd1f2012-12-20 17:08:28 -08001411 msleep(max_t(u32, MXT1386_RESET_TIME, MXT1386E_RESET_TIME));
1412 break;
Amy Maloche41f1cc32012-07-12 13:02:27 -07001413 case MXT1664S_ID:
1414 msleep(MXT1664S_RESET_TIME);
Amy Maloche7e447432011-09-14 11:36:30 -07001415 break;
1416 default:
1417 msleep(MXT_RESET_TIME);
1418 }
1419}
1420
Jing Lin8fadad72012-02-24 10:10:50 -08001421static int mxt_backup_nv(struct mxt_data *data)
1422{
1423 int error;
1424 u8 command_register;
1425 int timeout_counter = 0;
1426
1427 /* Backup to memory */
1428 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1429 MXT_COMMAND_BACKUPNV,
1430 MXT_BACKUP_VALUE);
1431 msleep(MXT_BACKUP_TIME);
1432
1433 do {
1434 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
1435 MXT_COMMAND_BACKUPNV,
1436 &command_register);
1437 if (error)
1438 return error;
1439
1440 usleep_range(1000, 2000);
1441
1442 } while ((command_register != 0) && (++timeout_counter <= 100));
1443
1444 if (timeout_counter > 100) {
1445 dev_err(&data->client->dev, "No response after backup!\n");
1446 return -EIO;
1447 }
1448
1449 /* Soft reset */
1450 mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
1451
1452 mxt_reset_delay(data);
1453
1454 return 0;
1455}
1456
Jing Lin412aedc2012-02-28 13:57:19 -08001457static int mxt_save_objects(struct mxt_data *data)
1458{
1459 struct i2c_client *client = data->client;
1460 struct mxt_object *t7_object;
1461 struct mxt_object *t9_object;
1462 struct mxt_object *t15_object;
Mohan Pallakab6acab42012-06-13 11:59:04 +05301463 struct mxt_object *t42_object;
Jing Lin412aedc2012-02-28 13:57:19 -08001464 int error;
1465
1466 /* Store T7 and T9 locally, used in suspend/resume operations */
1467 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
1468 if (!t7_object) {
1469 dev_err(&client->dev, "Failed to get T7 object\n");
1470 return -EINVAL;
1471 }
1472
1473 data->t7_start_addr = t7_object->start_address;
1474 error = __mxt_read_reg(client, data->t7_start_addr,
1475 T7_DATA_SIZE, data->t7_data);
1476 if (error < 0) {
1477 dev_err(&client->dev,
1478 "Failed to save current power state\n");
1479 return error;
1480 }
1481
Jing Lin412aedc2012-02-28 13:57:19 -08001482 /* Store T9, T15's min and max report ids */
1483 t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1484 if (!t9_object) {
1485 dev_err(&client->dev, "Failed to get T9 object\n");
1486 return -EINVAL;
1487 }
1488 data->t9_max_reportid = t9_object->max_reportid;
1489 data->t9_min_reportid = t9_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001490 (t9_object->num_report_ids *
1491 (t9_object->instances + 1)) + 1;
Jing Lin412aedc2012-02-28 13:57:19 -08001492
1493 if (data->pdata->key_codes) {
1494 t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
1495 if (!t15_object)
1496 dev_dbg(&client->dev, "T15 object is not available\n");
1497 else {
1498 data->t15_max_reportid = t15_object->max_reportid;
1499 data->t15_min_reportid = t15_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001500 (t15_object->num_report_ids *
1501 (t15_object->instances + 1)) + 1;
Jing Lin412aedc2012-02-28 13:57:19 -08001502 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001503 }
1504
Mohan Pallakab6acab42012-06-13 11:59:04 +05301505 /* Store T42 min and max report ids */
1506 t42_object = mxt_get_object(data, MXT_PROCI_TOUCHSUPPRESSION_T42);
1507 if (!t42_object)
1508 dev_dbg(&client->dev, "T42 object is not available\n");
1509 else {
1510 data->t42_max_reportid = t42_object->max_reportid;
1511 data->t42_min_reportid = t42_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001512 (t42_object->num_report_ids *
1513 (t42_object->instances + 1)) + 1;
Mohan Pallakab6acab42012-06-13 11:59:04 +05301514 }
1515
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001516 return 0;
1517}
1518
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301519static int mxt_update_cfg(struct mxt_data *data)
1520{
1521 int error;
1522 const u8 *cfg_ver;
1523
1524 /* Get config data from platform data */
1525 error = mxt_get_config(data);
1526 if (error)
1527 dev_dbg(&data->client->dev, "Config info not found.\n");
1528
1529 /* Check register init values */
1530 if (data->config_info && data->config_info->config) {
1531 if (data->update_cfg) {
1532 error = mxt_check_reg_init(data);
1533 if (error) {
1534 dev_err(&data->client->dev,
1535 "Failed to check reg init value\n");
1536 return error;
1537 }
1538
1539 error = mxt_backup_nv(data);
1540 if (error) {
1541 dev_err(&data->client->dev, "Failed to back up NV\n");
1542 return error;
1543 }
1544
1545 cfg_ver = data->config_info->config +
1546 data->cfg_version_idx;
1547 dev_info(&data->client->dev,
1548 "Config updated from %d.%d.%d to %d.%d.%d\n",
1549 data->cfg_version[0], data->cfg_version[1],
1550 data->cfg_version[2],
1551 cfg_ver[0], cfg_ver[1], cfg_ver[2]);
1552
1553 memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
1554 }
1555 } else {
1556 dev_info(&data->client->dev,
1557 "No cfg data defined, skipping check reg init\n");
1558 }
1559
1560 error = mxt_save_objects(data);
1561 if (error)
1562 return error;
1563
1564 return 0;
1565}
1566
1567
1568
Iiro Valkonen7686b102011-02-02 23:21:58 -08001569static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001570{
1571 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001572 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001573 int error;
1574 u8 val;
1575
Iiro Valkonen7686b102011-02-02 23:21:58 -08001576 error = mxt_get_info(data);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301577 if (error) {
1578 /* Try bootloader mode */
1579 error = mxt_switch_to_bootloader_address(data);
1580 if (error)
1581 return error;
1582
1583 error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
1584 if (error)
1585 return error;
1586
1587 dev_err(&client->dev, "Application CRC failure\n");
1588 data->state = BOOTLOADER;
1589
1590 return 0;
1591 }
1592
1593 dev_info(&client->dev,
1594 "Family ID: %d Variant ID: %d Version: %d.%d "
1595 "Build: 0x%02X Object Num: %d\n",
1596 info->family_id, info->variant_id,
1597 info->version >> 4, info->version & 0xf,
1598 info->build, info->object_num);
1599
1600 data->state = APPMODE;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001601
1602 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001603 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001604 GFP_KERNEL);
1605 if (!data->object_table) {
1606 dev_err(&client->dev, "Failed to allocate memory\n");
1607 return -ENOMEM;
1608 }
1609
1610 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001611 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001612 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001613 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001614
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301615 error = mxt_update_cfg(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001616 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001617 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001618 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001619 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001620 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001621 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001622 info->matrix_xsize = val;
1623
Iiro Valkonen7686b102011-02-02 23:21:58 -08001624 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001625 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001626 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001627 info->matrix_ysize = val;
1628
1629 dev_info(&client->dev,
Nick Dyer0a4016c2012-01-18 15:17:59 +05301630 "Matrix X Size: %d Matrix Y Size: %d\n",
1631 info->matrix_xsize, info->matrix_ysize);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001632
1633 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001634
Jing Lin32c72532011-11-03 12:02:33 -07001635free_object_table:
1636 kfree(data->object_table);
1637 return error;
Joonyoung Shim910d8052011-04-12 23:14:38 -07001638}
1639
Iiro Valkonen7686b102011-02-02 23:21:58 -08001640static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001641 struct device_attribute *attr, char *buf)
1642{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001643 struct mxt_data *data = dev_get_drvdata(dev);
1644 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001645 int count = 0;
1646 int i, j;
1647 int error;
1648 u8 val;
1649
1650 for (i = 0; i < data->info.object_num; i++) {
1651 object = data->object_table + i;
1652
Daniel Kurtz626af862011-10-06 15:43:20 -07001653 count += snprintf(buf + count, PAGE_SIZE - count,
1654 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001655 i + 1, object->type);
Daniel Kurtz626af862011-10-06 15:43:20 -07001656 if (count >= PAGE_SIZE)
1657 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001658
Iiro Valkonen7686b102011-02-02 23:21:58 -08001659 if (!mxt_object_readable(object->type)) {
Daniel Kurtz626af862011-10-06 15:43:20 -07001660 count += snprintf(buf + count, PAGE_SIZE - count,
1661 "\n");
1662 if (count >= PAGE_SIZE)
1663 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001664 continue;
1665 }
1666
1667 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001668 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001669 object->type, j, &val);
1670 if (error)
1671 return error;
1672
Daniel Kurtz626af862011-10-06 15:43:20 -07001673 count += snprintf(buf + count, PAGE_SIZE - count,
1674 "\t[%2d]: %02x (%d)\n", j, val, val);
1675 if (count >= PAGE_SIZE)
1676 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001677 }
1678
Daniel Kurtz626af862011-10-06 15:43:20 -07001679 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1680 if (count >= PAGE_SIZE)
1681 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001682 }
1683
1684 return count;
1685}
1686
Jing Lincc974cb2012-02-01 23:13:14 -08001687static int strtobyte(const char *data, u8 *value)
1688{
1689 char str[3];
1690
1691 str[0] = data[0];
1692 str[1] = data[1];
1693 str[2] = '\0';
1694
1695 return kstrtou8(str, 16, value);
1696}
1697
Iiro Valkonen7686b102011-02-02 23:21:58 -08001698static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001699{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001700 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001701 struct i2c_client *client = data->client;
1702 const struct firmware *fw = NULL;
1703 unsigned int frame_size;
Nick Dyer0a4016c2012-01-18 15:17:59 +05301704 unsigned int retry = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001705 unsigned int pos = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001706 int ret, i, max_frame_size;
1707 u8 *frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001708
Jing Lincc974cb2012-02-01 23:13:14 -08001709 switch (data->info.family_id) {
1710 case MXT224_ID:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301711 case MXT224E_ID:
Amy Maloche265fc3c2013-01-17 11:50:24 -08001712 case MXT336S_ID:
Jing Lincc974cb2012-02-01 23:13:14 -08001713 max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
1714 break;
1715 case MXT1386_ID:
Amy Maloche265fc3c2013-01-17 11:50:24 -08001716 case MXT1664S_ID:
Jing Lincc974cb2012-02-01 23:13:14 -08001717 max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
1718 break;
1719 default:
1720 return -EINVAL;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001721 }
1722
Jing Lincc974cb2012-02-01 23:13:14 -08001723 frame = kmalloc(max_frame_size, GFP_KERNEL);
1724 if (!frame) {
1725 dev_err(dev, "Unable to allocate memory for frame data\n");
1726 return -ENOMEM;
1727 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001728
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001729 ret = request_firmware(&fw, fn, dev);
Himanshu Aggarwalb0966ac2013-08-13 13:46:03 +05301730 if (ret < 0 || !fw) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001731 dev_err(dev, "Unable to open firmware %s\n", fn);
Jing Lincc974cb2012-02-01 23:13:14 -08001732 goto free_frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001733 }
1734
Nick Dyer0a4016c2012-01-18 15:17:59 +05301735 if (data->state != BOOTLOADER) {
1736 /* Change to the bootloader mode */
1737 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1738 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1739 mxt_reset_delay(data);
Amy Maloche7e447432011-09-14 11:36:30 -07001740
Nick Dyer0a4016c2012-01-18 15:17:59 +05301741 ret = mxt_switch_to_bootloader_address(data);
1742 if (ret)
1743 goto release_firmware;
1744 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001745
Iiro Valkonen7686b102011-02-02 23:21:58 -08001746 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301747 if (ret) {
1748 /* Bootloader may still be unlocked from previous update
1749 * attempt */
1750 ret = mxt_check_bootloader(client,
1751 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001752
Nick Dyer0a4016c2012-01-18 15:17:59 +05301753 if (ret)
1754 goto return_to_app_mode;
1755 } else {
1756 dev_info(dev, "Unlocking bootloader\n");
1757 /* Unlock bootloader */
1758 mxt_unlock_bootloader(client);
1759 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001760
1761 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001762 ret = mxt_check_bootloader(client,
1763 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001764 if (ret)
Nick Dyer0a4016c2012-01-18 15:17:59 +05301765 goto release_firmware;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001766
Jing Lincc974cb2012-02-01 23:13:14 -08001767 /* Get frame length MSB */
1768 ret = strtobyte(fw->data + pos, frame);
1769 if (ret)
1770 goto release_firmware;
1771
1772 /* Get frame length LSB */
1773 ret = strtobyte(fw->data + pos + 2, frame + 1);
1774 if (ret)
1775 goto release_firmware;
1776
1777 frame_size = ((*frame << 8) | *(frame + 1));
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001778
1779 /* We should add 2 at frame size as the the firmware data is not
1780 * included the CRC bytes.
1781 */
1782 frame_size += 2;
1783
Jing Lincc974cb2012-02-01 23:13:14 -08001784 if (frame_size > max_frame_size) {
1785 dev_err(dev, "Invalid frame size - %d\n", frame_size);
1786 ret = -EINVAL;
1787 goto release_firmware;
1788 }
1789
1790 /* Convert frame data and CRC from hex to binary */
1791 for (i = 2; i < frame_size; i++) {
1792 ret = strtobyte(fw->data + pos + i * 2, frame + i);
1793 if (ret)
1794 goto release_firmware;
1795 }
1796
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001797 /* Write one frame to device */
Jing Lincc974cb2012-02-01 23:13:14 -08001798 mxt_fw_write(client, frame, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001799
Iiro Valkonen7686b102011-02-02 23:21:58 -08001800 ret = mxt_check_bootloader(client,
1801 MXT_FRAME_CRC_PASS);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301802 if (ret) {
1803 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001804
Nick Dyer0a4016c2012-01-18 15:17:59 +05301805 /* Back off by 20ms per retry */
1806 msleep(retry * 20);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001807
Nick Dyer0a4016c2012-01-18 15:17:59 +05301808 if (retry > 20)
1809 goto release_firmware;
1810 } else {
1811 retry = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001812 pos += frame_size * 2;
1813 dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301814 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001815 }
1816
Nick Dyer0a4016c2012-01-18 15:17:59 +05301817return_to_app_mode:
1818 mxt_switch_to_appmode_address(data);
1819release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001820 release_firmware(fw);
Jing Lincc974cb2012-02-01 23:13:14 -08001821free_frame:
1822 kfree(frame);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001823
1824 return ret;
1825}
1826
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001827static const char *
1828mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
1829{
1830 const struct mxt_platform_data *pdata = data->pdata;
1831 const struct mxt_config_info *cfg_info;
1832 const char *fw_name = NULL;
1833 int i;
1834
1835 for (i = 0; i < pdata->config_array_size; i++) {
1836 cfg_info = &pdata->config_array[i];
1837 if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
1838 data->config_info = cfg_info;
1839 data->info.family_id = cfg_info->family_id;
1840 fw_name = cfg_info->fw_name;
1841 }
1842 }
1843
1844 return fw_name;
1845}
1846
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301847static ssize_t mxt_force_cfg_update_store(struct device *dev,
1848 struct device_attribute *attr,
1849 const char *buf, size_t count)
1850{
1851 struct mxt_data *data = dev_get_drvdata(dev);
1852 int flag = buf[0]-'0';
1853 int error;
1854 data->no_force_update = !flag;
1855
1856 if (data->state == APPMODE) {
1857 disable_irq(data->irq);
1858 error = mxt_update_cfg(data);
1859 enable_irq(data->irq);
1860 if (error)
1861 return error;
1862 } else {
1863 dev_err(dev,
1864 "Not in APPMODE, Unable to force cfg update\n");
1865 return -EINVAL;
1866 }
1867
1868 return count;
1869}
1870
Iiro Valkonen7686b102011-02-02 23:21:58 -08001871static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001872 struct device_attribute *attr,
1873 const char *buf, size_t count)
1874{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001875 struct mxt_data *data = dev_get_drvdata(dev);
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301876 int error, address;
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001877 const char *fw_name;
1878 u8 bootldr_id;
Jing Lin8a9472d2012-03-21 15:43:45 -07001879 u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001880
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301881 data->no_force_update = false;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001882 /* If fw_name is set, then the existing firmware has an upgrade */
1883 if (!data->fw_name) {
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001884 /*
1885 * If the device boots up in the bootloader mode, check if
1886 * there is a firmware to upgrade.
1887 */
1888 if (data->state == BOOTLOADER) {
1889 bootldr_id = mxt_get_bootloader_id(data->client);
1890 if (bootldr_id <= 0) {
1891 dev_err(dev,
1892 "Unable to retrieve bootloader id\n");
1893 return -EINVAL;
1894 }
1895 fw_name = mxt_search_fw_name(data, bootldr_id);
1896 if (fw_name == NULL) {
1897 dev_err(dev,
1898 "Unable to find fw from bootloader id\n");
1899 return -EINVAL;
1900 }
1901 } else {
1902 /* In APPMODE, if the f/w name does not exist, quit */
1903 dev_err(dev,
1904 "Firmware name not specified in platform data\n");
1905 return -EINVAL;
1906 }
1907 } else {
1908 fw_name = data->fw_name;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001909 }
1910
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001911 dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001912
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001913 disable_irq(data->irq);
1914
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001915 error = mxt_load_fw(dev, fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001916 if (error) {
1917 dev_err(dev, "The firmware update failed(%d)\n", error);
1918 count = error;
1919 } else {
Nick Dyer0a4016c2012-01-18 15:17:59 +05301920 dev_info(dev, "The firmware update succeeded\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001921
1922 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001923 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001924
Nick Dyer0a4016c2012-01-18 15:17:59 +05301925 data->state = INIT;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001926 kfree(data->object_table);
1927 data->object_table = NULL;
Jing Lincc974cb2012-02-01 23:13:14 -08001928 data->cfg_version_idx = 0;
Jing Lina962ba32012-12-03 09:46:33 -08001929 data->config_info = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001930 data->update_cfg = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001931
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301932 /* T38 object address might have changed, read it from
1933 touch controller */
1934 address = mxt_get_object_address(dev, MXT_SPT_USERDATA_T38);
1935 if (address < 0) {
1936 dev_err(dev, "T38 required for touch operation\n");
1937 return -EINVAL;
1938 }
1939
1940 data->t38_start_addr = address;
1941
Jing Lin8a9472d2012-03-21 15:43:45 -07001942 error = __mxt_write_reg(data->client, data->t38_start_addr,
1943 sizeof(cfg_version), cfg_version);
1944 if (error)
1945 dev_err(dev,
1946 "Unable to zero out config version after fw upgrade\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001947
Iiro Valkonen7686b102011-02-02 23:21:58 -08001948 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001949 }
1950
Nick Dyer0a4016c2012-01-18 15:17:59 +05301951 if (data->state == APPMODE) {
1952 enable_irq(data->irq);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001953
Nick Dyer0a4016c2012-01-18 15:17:59 +05301954 error = mxt_make_highchg(data);
1955 if (error)
1956 return error;
1957 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07001958
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001959 return count;
1960}
1961
Amy Maloche434b7d82013-02-15 11:11:05 +00001962#if defined(CONFIG_SECURE_TOUCH)
1963
1964static ssize_t mxt_secure_touch_enable_show(struct device *dev,
1965 struct device_attribute *attr, char *buf)
1966{
1967 struct mxt_data *data = dev_get_drvdata(dev);
1968 return scnprintf(buf, PAGE_SIZE, "%d", atomic_read(&data->st_enabled));
1969}
1970/*
1971 * Accept only "0" and "1" valid values.
1972 * "0" will reset the st_enabled flag, then wake up the reading process.
1973 * The bus driver is notified via pm_runtime that it is not required to stay
1974 * awake anymore.
1975 * It will also make sure the queue of events is emptied in the controller,
1976 * in case a touch happened in between the secure touch being disabled and
1977 * the local ISR being ungated.
1978 * "1" will set the st_enabled flag and clear the st_pending_irqs flag.
1979 * The bus driver is requested via pm_runtime to stay awake.
1980 */
1981static ssize_t mxt_secure_touch_enable_store(struct device *dev,
1982 struct device_attribute *attr,
1983 const char *buf, size_t count)
1984{
1985 struct mxt_data *data = dev_get_drvdata(dev);
Keith Fallowsf0655aa2014-03-13 10:08:09 +00001986 struct device *adapter = data->client->adapter->dev.parent;
Amy Maloche434b7d82013-02-15 11:11:05 +00001987 unsigned long value;
1988 int err = 0;
1989
1990 if (count > 2)
1991 return -EINVAL;
1992
1993 err = kstrtoul(buf, 10, &value);
1994 if (err != 0)
1995 return err;
1996
1997 err = count;
1998
1999 switch (value) {
2000 case 0:
2001 if (atomic_read(&data->st_enabled) == 0)
2002 break;
2003
Keith Fallowsf0655aa2014-03-13 10:08:09 +00002004 pm_runtime_put(adapter);
Amy Maloche434b7d82013-02-15 11:11:05 +00002005 atomic_set(&data->st_enabled, 0);
Amy Maloche1e0c66a2013-09-24 18:26:26 +01002006 mxt_secure_touch_notify(data);
Amy Maloche434b7d82013-02-15 11:11:05 +00002007 mxt_interrupt(data->client->irq, data);
Amy Maloche20f970c2013-04-10 13:04:52 +01002008 complete(&data->st_powerdown);
Amy Maloche434b7d82013-02-15 11:11:05 +00002009 break;
2010 case 1:
2011 if (atomic_read(&data->st_enabled)) {
2012 err = -EBUSY;
2013 break;
2014 }
2015
Keith Fallowsf0655aa2014-03-13 10:08:09 +00002016 if (pm_runtime_get_sync(adapter) < 0) {
Amy Maloche434b7d82013-02-15 11:11:05 +00002017 dev_err(&data->client->dev, "pm_runtime_get failed\n");
2018 err = -EIO;
2019 break;
2020 }
Amy Maloche20f970c2013-04-10 13:04:52 +01002021 INIT_COMPLETION(data->st_powerdown);
Amy Maloche434b7d82013-02-15 11:11:05 +00002022 atomic_set(&data->st_enabled, 1);
Amy Maloche2f646c82013-07-17 11:57:11 +01002023 synchronize_irq(data->client->irq);
2024 atomic_set(&data->st_pending_irqs, 0);
Amy Maloche434b7d82013-02-15 11:11:05 +00002025 break;
2026 default:
2027 dev_err(&data->client->dev, "unsupported value: %lu\n", value);
2028 err = -EINVAL;
2029 break;
2030 }
2031
2032 return err;
2033}
2034
2035static ssize_t mxt_secure_touch_show(struct device *dev,
2036 struct device_attribute *attr, char *buf)
2037{
2038 struct mxt_data *data = dev_get_drvdata(dev);
Amy Maloche1e0c66a2013-09-24 18:26:26 +01002039 int val = 0;
Amy Maloche434b7d82013-02-15 11:11:05 +00002040
2041 if (atomic_read(&data->st_enabled) == 0)
2042 return -EBADF;
2043
Amy Maloche1e0c66a2013-09-24 18:26:26 +01002044 if (atomic_cmpxchg(&data->st_pending_irqs, -1, 0) == -1)
Amy Maloche20f970c2013-04-10 13:04:52 +01002045 return -EINVAL;
Amy Maloche434b7d82013-02-15 11:11:05 +00002046
Amy Maloche1e0c66a2013-09-24 18:26:26 +01002047 if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) == 1)
2048 val = 1;
2049
2050 return scnprintf(buf, PAGE_SIZE, "%u", val);
Amy Maloche434b7d82013-02-15 11:11:05 +00002051}
2052
Himanshu Aggarwala4fa6732013-12-27 12:47:31 +05302053static DEVICE_ATTR(secure_touch_enable, S_IRUGO | S_IWUSR | S_IWGRP ,
2054 mxt_secure_touch_enable_show,
2055 mxt_secure_touch_enable_store);
2056static DEVICE_ATTR(secure_touch, S_IRUGO, mxt_secure_touch_show, NULL);
Amy Maloche434b7d82013-02-15 11:11:05 +00002057#endif
2058
Himanshu Aggarwala4fa6732013-12-27 12:47:31 +05302059static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
2060static DEVICE_ATTR(update_fw, S_IWUSR | S_IWGRP , NULL, mxt_update_fw_store);
2061static DEVICE_ATTR(force_cfg_update, S_IWUSR | S_IWGRP ,
2062 NULL,
2063 mxt_force_cfg_update_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002064
Iiro Valkonen7686b102011-02-02 23:21:58 -08002065static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002066 &dev_attr_object.attr,
2067 &dev_attr_update_fw.attr,
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302068 &dev_attr_force_cfg_update.attr,
Amy Maloche434b7d82013-02-15 11:11:05 +00002069#if defined(CONFIG_SECURE_TOUCH)
2070 &dev_attr_secure_touch_enable.attr,
2071 &dev_attr_secure_touch.attr,
2072#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002073 NULL
2074};
2075
Iiro Valkonen7686b102011-02-02 23:21:58 -08002076static const struct attribute_group mxt_attr_group = {
2077 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002078};
2079
Amy Maloche20f970c2013-04-10 13:04:52 +01002080
2081#if defined(CONFIG_SECURE_TOUCH)
Amy Maloche1e0c66a2013-09-24 18:26:26 +01002082static void mxt_secure_touch_stop(struct mxt_data *data, int blocking)
Amy Maloche20f970c2013-04-10 13:04:52 +01002083{
2084 if (atomic_read(&data->st_enabled)) {
Amy Maloche1e0c66a2013-09-24 18:26:26 +01002085 atomic_set(&data->st_pending_irqs, -1);
2086 mxt_secure_touch_notify(data);
2087 if (blocking)
2088 wait_for_completion_interruptible(&data->st_powerdown);
Amy Maloche20f970c2013-04-10 13:04:52 +01002089 }
2090}
2091#else
Amy Maloche1e0c66a2013-09-24 18:26:26 +01002092static void mxt_secure_touch_stop(struct mxt_data *data, int blocking)
Amy Maloche20f970c2013-04-10 13:04:52 +01002093{
2094}
2095#endif
2096
Amy Maloche52262212011-09-15 16:46:57 -07002097static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002098{
Jing Lin36aee812011-10-17 17:17:28 -07002099 int error;
Amy Maloche1e0c66a2013-09-24 18:26:26 +01002100 mxt_secure_touch_stop(data, 1);
Jing Lin36aee812011-10-17 17:17:28 -07002101
Amy Maloche52262212011-09-15 16:46:57 -07002102 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07002103 error = __mxt_write_reg(data->client, data->t7_start_addr,
2104 T7_DATA_SIZE, data->t7_data);
2105 if (error < 0) {
2106 dev_err(&data->client->dev,
2107 "failed to restore old power state\n");
2108 return error;
Amy Maloche52262212011-09-15 16:46:57 -07002109 }
Jing Lin36aee812011-10-17 17:17:28 -07002110
Amy Maloche52262212011-09-15 16:46:57 -07002111 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002112}
2113
Amy Maloche52262212011-09-15 16:46:57 -07002114static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002115{
Jing Lin36aee812011-10-17 17:17:28 -07002116 int error;
2117 u8 t7_data[T7_DATA_SIZE] = {0};
Amy Maloche1e0c66a2013-09-24 18:26:26 +01002118 mxt_secure_touch_stop(data, 1);
Jing Lin36aee812011-10-17 17:17:28 -07002119
Jing Lin36aee812011-10-17 17:17:28 -07002120 error = __mxt_write_reg(data->client, data->t7_start_addr,
2121 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07002122 if (error < 0) {
2123 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07002124 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07002125 return error;
2126 }
2127
2128 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002129}
2130
Iiro Valkonen7686b102011-02-02 23:21:58 -08002131static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002132{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002133 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07002134 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002135
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08002136 if (data->state == APPMODE) {
2137 error = mxt_start(data);
2138 if (error < 0) {
2139 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
2140 return error;
2141 }
Amy Maloche52262212011-09-15 16:46:57 -07002142 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002143
2144 return 0;
2145}
2146
Iiro Valkonen7686b102011-02-02 23:21:58 -08002147static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002148{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002149 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07002150 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002151
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08002152 if (data->state == APPMODE) {
2153 error = mxt_stop(data);
2154 if (error < 0)
2155 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
2156 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002157}
2158
Amy Malochec331f842012-01-24 10:33:47 -08002159static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
2160{
2161 return (regulator_count_voltages(reg) > 0) ?
2162 regulator_set_optimum_mode(reg, load_uA) : 0;
2163}
2164
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302165static int mxt_power_on(struct mxt_data *data, bool on)
2166{
2167 int rc;
2168
2169 if (on == false)
2170 goto power_off;
2171
Amy Malochec331f842012-01-24 10:33:47 -08002172 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302173 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07002174 dev_err(&data->client->dev,
2175 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302176 return rc;
2177 }
2178
Amy Maloche21115eb2011-11-02 09:04:37 -07002179 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302180 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07002181 dev_err(&data->client->dev,
2182 "Regulator vcc_ana enable failed rc=%d\n", rc);
2183 goto error_reg_en_vcc_ana;
2184 }
2185
2186 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002187 rc = reg_set_optimum_mode_check(data->vcc_dig,
2188 MXT_ACTIVE_LOAD_DIG_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002189 if (rc < 0) {
2190 dev_err(&data->client->dev,
2191 "Regulator vcc_dig set_opt failed rc=%d\n",
2192 rc);
2193 goto error_reg_opt_vcc_dig;
2194 }
2195
2196 rc = regulator_enable(data->vcc_dig);
2197 if (rc) {
2198 dev_err(&data->client->dev,
2199 "Regulator vcc_dig enable failed rc=%d\n", rc);
2200 goto error_reg_en_vcc_dig;
2201 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302202 }
2203
2204 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002205 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302206 if (rc < 0) {
2207 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002208 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302209 goto error_reg_opt_i2c;
2210 }
2211
2212 rc = regulator_enable(data->vcc_i2c);
2213 if (rc) {
2214 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002215 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302216 goto error_reg_en_vcc_i2c;
2217 }
2218 }
2219
Amy Malochef0d7b8d2011-10-17 12:10:51 -07002220 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302221
2222 return 0;
2223
2224error_reg_en_vcc_i2c:
2225 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002226 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302227error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07002228 if (data->pdata->digital_pwr_regulator)
2229 regulator_disable(data->vcc_dig);
2230error_reg_en_vcc_dig:
2231 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002232 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002233error_reg_opt_vcc_dig:
2234 regulator_disable(data->vcc_ana);
2235error_reg_en_vcc_ana:
Amy Malochec331f842012-01-24 10:33:47 -08002236 reg_set_optimum_mode_check(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302237 return rc;
2238
2239power_off:
Amy Malochec331f842012-01-24 10:33:47 -08002240 reg_set_optimum_mode_check(data->vcc_ana, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002241 regulator_disable(data->vcc_ana);
2242 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002243 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002244 regulator_disable(data->vcc_dig);
2245 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302246 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002247 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302248 regulator_disable(data->vcc_i2c);
2249 }
Mohan Pallakab74e3482013-07-09 16:39:56 +05302250
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302251 msleep(50);
2252 return 0;
2253}
2254
2255static int mxt_regulator_configure(struct mxt_data *data, bool on)
2256{
2257 int rc;
2258
2259 if (on == false)
2260 goto hw_shutdown;
2261
Amy Maloche21115eb2011-11-02 09:04:37 -07002262 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
2263 if (IS_ERR(data->vcc_ana)) {
2264 rc = PTR_ERR(data->vcc_ana);
2265 dev_err(&data->client->dev,
2266 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302267 return rc;
2268 }
2269
Amy Maloche21115eb2011-11-02 09:04:37 -07002270 if (regulator_count_voltages(data->vcc_ana) > 0) {
2271 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302272 MXT_VTG_MAX_UV);
2273 if (rc) {
2274 dev_err(&data->client->dev,
2275 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07002276 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302277 }
2278 }
Amy Maloche21115eb2011-11-02 09:04:37 -07002279 if (data->pdata->digital_pwr_regulator) {
2280 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
2281 if (IS_ERR(data->vcc_dig)) {
2282 rc = PTR_ERR(data->vcc_dig);
2283 dev_err(&data->client->dev,
2284 "Regulator get dig failed rc=%d\n", rc);
2285 goto error_get_vtg_vcc_dig;
2286 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302287
Amy Maloche21115eb2011-11-02 09:04:37 -07002288 if (regulator_count_voltages(data->vcc_dig) > 0) {
2289 rc = regulator_set_voltage(data->vcc_dig,
2290 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
2291 if (rc) {
2292 dev_err(&data->client->dev,
2293 "regulator set_vtg failed rc=%d\n", rc);
2294 goto error_set_vtg_vcc_dig;
2295 }
2296 }
2297 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302298 if (data->pdata->i2c_pull_up) {
2299 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
2300 if (IS_ERR(data->vcc_i2c)) {
2301 rc = PTR_ERR(data->vcc_i2c);
2302 dev_err(&data->client->dev,
2303 "Regulator get failed rc=%d\n", rc);
2304 goto error_get_vtg_i2c;
2305 }
2306 if (regulator_count_voltages(data->vcc_i2c) > 0) {
2307 rc = regulator_set_voltage(data->vcc_i2c,
2308 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
2309 if (rc) {
2310 dev_err(&data->client->dev,
2311 "regulator set_vtg failed rc=%d\n", rc);
2312 goto error_set_vtg_i2c;
2313 }
2314 }
2315 }
2316
2317 return 0;
2318
2319error_set_vtg_i2c:
2320 regulator_put(data->vcc_i2c);
2321error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07002322 if (data->pdata->digital_pwr_regulator)
2323 if (regulator_count_voltages(data->vcc_dig) > 0)
2324 regulator_set_voltage(data->vcc_dig, 0,
2325 MXT_VTG_DIG_MAX_UV);
2326error_set_vtg_vcc_dig:
2327 if (data->pdata->digital_pwr_regulator)
2328 regulator_put(data->vcc_dig);
2329error_get_vtg_vcc_dig:
2330 if (regulator_count_voltages(data->vcc_ana) > 0)
2331 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2332error_set_vtg_vcc_ana:
2333 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302334 return rc;
2335
2336hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07002337 if (regulator_count_voltages(data->vcc_ana) > 0)
2338 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2339 regulator_put(data->vcc_ana);
2340 if (data->pdata->digital_pwr_regulator) {
2341 if (regulator_count_voltages(data->vcc_dig) > 0)
2342 regulator_set_voltage(data->vcc_dig, 0,
2343 MXT_VTG_DIG_MAX_UV);
2344 regulator_put(data->vcc_dig);
2345 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302346 if (data->pdata->i2c_pull_up) {
2347 if (regulator_count_voltages(data->vcc_i2c) > 0)
2348 regulator_set_voltage(data->vcc_i2c, 0,
2349 MXT_I2C_VTG_MAX_UV);
2350 regulator_put(data->vcc_i2c);
2351 }
2352 return 0;
2353}
2354
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302355#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07002356static int mxt_regulator_lpm(struct mxt_data *data, bool on)
2357{
2358
2359 int rc;
2360
2361 if (on == false)
2362 goto regulator_hpm;
2363
Amy Malochec331f842012-01-24 10:33:47 -08002364 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002365 if (rc < 0) {
2366 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002367 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002368 goto fail_regulator_lpm;
2369 }
2370
Amy Maloche21115eb2011-11-02 09:04:37 -07002371 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002372 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002373 MXT_LPM_LOAD_DIG_UA);
2374 if (rc < 0) {
2375 dev_err(&data->client->dev,
2376 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2377 goto fail_regulator_lpm;
2378 }
2379 }
2380
Jing Linbace50b2011-10-18 22:55:47 -07002381 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002382 rc = reg_set_optimum_mode_check(data->vcc_i2c,
Jing Linbace50b2011-10-18 22:55:47 -07002383 MXT_I2C_LPM_LOAD_UA);
2384 if (rc < 0) {
2385 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002386 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002387 goto fail_regulator_lpm;
2388 }
2389 }
2390
2391 return 0;
2392
2393regulator_hpm:
2394
Amy Malochec331f842012-01-24 10:33:47 -08002395 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002396 if (rc < 0) {
2397 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002398 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002399 goto fail_regulator_hpm;
2400 }
2401
Amy Maloche21115eb2011-11-02 09:04:37 -07002402 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002403 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002404 MXT_ACTIVE_LOAD_DIG_UA);
2405 if (rc < 0) {
2406 dev_err(&data->client->dev,
2407 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2408 goto fail_regulator_hpm;
2409 }
2410 }
2411
Jing Linbace50b2011-10-18 22:55:47 -07002412 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002413 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002414 if (rc < 0) {
2415 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002416 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002417 goto fail_regulator_hpm;
2418 }
2419 }
2420
2421 return 0;
2422
2423fail_regulator_lpm:
Amy Malochec331f842012-01-24 10:33:47 -08002424 reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002425 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002426 reg_set_optimum_mode_check(data->vcc_dig,
2427 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002428 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002429 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002430
2431 return rc;
2432
2433fail_regulator_hpm:
Amy Malochec331f842012-01-24 10:33:47 -08002434 reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002435 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002436 reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002437 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002438 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002439
2440 return rc;
2441}
2442
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302443static int mxt_suspend(struct device *dev)
2444{
2445 struct i2c_client *client = to_i2c_client(dev);
2446 struct mxt_data *data = i2c_get_clientdata(client);
2447 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002448 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302449
Chun Zhang53ab0202013-07-29 17:45:17 -07002450 if (data->dev_sleep) {
2451 dev_dbg(dev, "Device already in sleep\n");
2452 return 0;
2453 }
2454
Mohan Pallakab74e3482013-07-09 16:39:56 +05302455 disable_irq(data->irq);
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302456
Mohan Pallakab74e3482013-07-09 16:39:56 +05302457 mutex_lock(&input_dev->mutex);
Amy Maloche52262212011-09-15 16:46:57 -07002458 if (input_dev->users) {
2459 error = mxt_stop(data);
2460 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002461 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07002462 mutex_unlock(&input_dev->mutex);
2463 return error;
2464 }
Amy Maloche52262212011-09-15 16:46:57 -07002465 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302466
2467 mutex_unlock(&input_dev->mutex);
Mohan Pallakab74e3482013-07-09 16:39:56 +05302468 mxt_release_all(data);
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302469
Jing Linbace50b2011-10-18 22:55:47 -07002470 /* put regulators in low power mode */
Mohan Pallakab74e3482013-07-09 16:39:56 +05302471 if (data->lpm_support) {
2472 error = mxt_regulator_lpm(data, true);
2473 if (error < 0) {
2474 dev_err(dev, "failed to enter low power mode\n");
2475 return error;
2476 }
2477 } else {
2478 error = mxt_power_on(data, false);
2479 if (error < 0) {
2480 dev_err(dev, "failed to disable regulators\n");
2481 return error;
2482 }
Jing Linbace50b2011-10-18 22:55:47 -07002483 }
2484
Chun Zhang53ab0202013-07-29 17:45:17 -07002485 data->dev_sleep = true;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302486 return 0;
2487}
2488
2489static int mxt_resume(struct device *dev)
2490{
2491 struct i2c_client *client = to_i2c_client(dev);
2492 struct mxt_data *data = i2c_get_clientdata(client);
2493 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002494 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302495
Chun Zhang53ab0202013-07-29 17:45:17 -07002496 if (!data->dev_sleep) {
2497 dev_dbg(dev, "Device already in resume\n");
2498 return 0;
2499 }
2500
Mohan Pallakab74e3482013-07-09 16:39:56 +05302501 /* put regulators back in active power mode */
2502 if (data->lpm_support) {
2503 error = mxt_regulator_lpm(data, false);
2504 if (error < 0) {
2505 dev_err(dev, "failed to enter high power mode\n");
2506 return error;
2507 }
2508 } else {
2509 error = mxt_power_on(data, true);
2510 if (error < 0) {
2511 dev_err(dev, "failed to enable regulators\n");
2512 return error;
2513 }
2514 mxt_power_on_delay(data);
Jing Linbace50b2011-10-18 22:55:47 -07002515 }
2516
Mohan Pallakab74e3482013-07-09 16:39:56 +05302517 mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
2518 mxt_reset_delay(data);
2519
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302520 mutex_lock(&input_dev->mutex);
2521
Amy Maloche52262212011-09-15 16:46:57 -07002522 if (input_dev->users) {
2523 error = mxt_start(data);
2524 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002525 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07002526 mutex_unlock(&input_dev->mutex);
2527 return error;
2528 }
2529 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302530
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302531 /* calibrate */
2532 if (data->pdata->need_calibration) {
Amy Maloche1e0c66a2013-09-24 18:26:26 +01002533 mxt_secure_touch_stop(data, 1);
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302534 error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
2535 MXT_COMMAND_CALIBRATE, 1);
2536 if (error < 0)
2537 dev_dbg(dev, "sending calibration command failed\n");
2538 }
2539
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302540 mutex_unlock(&input_dev->mutex);
2541
Mohan Pallakab74e3482013-07-09 16:39:56 +05302542 enable_irq(data->irq);
2543
Chun Zhang53ab0202013-07-29 17:45:17 -07002544 data->dev_sleep = false;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302545 return 0;
2546}
2547
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302548static const struct dev_pm_ops mxt_pm_ops = {
Anurag Singh49d76132013-01-29 12:07:00 -08002549#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302550 .suspend = mxt_suspend,
2551 .resume = mxt_resume,
2552#endif
2553};
Amy Maloche0e854fb2013-12-04 13:43:32 -08002554#else
2555static int mxt_suspend(struct device *dev)
2556{
2557 return 0;
2558};
2559static int mxt_resume(struct device *dev)
2560{
2561 return 0;
2562};
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302563#endif
2564
Jing Lin6cfc00e2011-11-02 15:15:30 -07002565static int mxt_debugfs_object_show(struct seq_file *m, void *v)
2566{
2567 struct mxt_data *data = m->private;
2568 struct mxt_object *object;
2569 struct device *dev = &data->client->dev;
2570 int i, j, k;
2571 int error;
2572 int obj_size;
2573 u8 val;
2574
2575 for (i = 0; i < data->info.object_num; i++) {
2576 object = data->object_table + i;
2577 obj_size = object->size + 1;
2578
2579 seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
2580
2581 for (j = 0; j < object->instances + 1; j++) {
2582 seq_printf(m, "[Instance %d]\n", j);
2583
2584 for (k = 0; k < obj_size; k++) {
2585 error = mxt_read_object(data, object->type,
2586 j * obj_size + k, &val);
2587 if (error) {
2588 dev_err(dev,
2589 "Failed to read object %d "
2590 "instance %d at offset %d\n",
2591 object->type, j, k);
2592 return error;
2593 }
2594
2595 seq_printf(m, "Byte %d: 0x%02x (%d)\n",
2596 k, val, val);
2597 }
2598 }
2599 }
2600
2601 return 0;
2602}
2603
2604static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
2605{
2606 return single_open(file, mxt_debugfs_object_show, inode->i_private);
2607}
2608
2609static const struct file_operations mxt_object_fops = {
2610 .owner = THIS_MODULE,
2611 .open = mxt_debugfs_object_open,
2612 .read = seq_read,
2613 .release = single_release,
2614};
2615
Stephen Boyd0d578692012-04-25 11:49:18 -07002616static void __devinit mxt_debugfs_init(struct mxt_data *data)
Jing Lin6cfc00e2011-11-02 15:15:30 -07002617{
2618 debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
2619 if (IS_ERR_OR_NULL(debug_base))
2620 pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
2621 if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
2622 0444,
2623 debug_base,
2624 data,
2625 &mxt_object_fops))) {
2626 pr_err("atmel_mxt_ts: Failed to create object file\n");
2627 debugfs_remove_recursive(debug_base);
2628 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002629}
2630
Mohan Pallakad96f5032012-06-18 22:49:10 +05302631#ifdef CONFIG_OF
2632static int mxt_get_dt_coords(struct device *dev, char *name,
2633 struct mxt_platform_data *pdata)
2634{
2635 u32 coords[MXT_COORDS_ARR_SIZE];
2636 struct property *prop;
2637 struct device_node *np = dev->of_node;
2638 int coords_size, rc;
2639
2640 prop = of_find_property(np, name, NULL);
2641 if (!prop)
2642 return -EINVAL;
2643 if (!prop->value)
2644 return -ENODATA;
2645
2646 coords_size = prop->length / sizeof(u32);
2647 if (coords_size != MXT_COORDS_ARR_SIZE) {
2648 dev_err(dev, "invalid %s\n", name);
2649 return -EINVAL;
2650 }
2651
2652 rc = of_property_read_u32_array(np, name, coords, coords_size);
2653 if (rc && (rc != -EINVAL)) {
2654 dev_err(dev, "Unable to read %s\n", name);
2655 return rc;
2656 }
2657
2658 if (strncmp(name, "atmel,panel-coords",
2659 sizeof("atmel,panel-coords")) == 0) {
2660 pdata->panel_minx = coords[0];
2661 pdata->panel_miny = coords[1];
2662 pdata->panel_maxx = coords[2];
2663 pdata->panel_maxy = coords[3];
2664 } else if (strncmp(name, "atmel,display-coords",
2665 sizeof("atmel,display-coords")) == 0) {
2666 pdata->disp_minx = coords[0];
2667 pdata->disp_miny = coords[1];
2668 pdata->disp_maxx = coords[2];
2669 pdata->disp_maxy = coords[3];
2670 } else {
2671 dev_err(dev, "unsupported property %s\n", name);
2672 return -EINVAL;
2673 }
2674
2675 return 0;
2676}
2677
2678static int mxt_parse_config(struct device *dev, struct device_node *np,
2679 struct mxt_config_info *info)
2680{
2681 struct property *prop;
2682 u8 *temp_cfg;
2683
2684 prop = of_find_property(np, "atmel,config", &info->config_length);
2685 if (!prop) {
2686 dev_err(dev, "Looking up %s property in node %s failed",
2687 "atmel,config", np->full_name);
2688 return -ENODEV;
2689 } else if (!info->config_length) {
2690 dev_err(dev, "Invalid length of configuration data\n");
2691 return -EINVAL;
2692 }
2693
2694 temp_cfg = devm_kzalloc(dev,
2695 info->config_length * sizeof(u8), GFP_KERNEL);
2696 if (!temp_cfg) {
2697 dev_err(dev, "Unable to allocate memory to store cfg\n");
2698 return -ENOMEM;
2699 }
2700
2701 memcpy(temp_cfg, prop->value, info->config_length);
2702 info->config = temp_cfg;
2703
2704 return 0;
2705}
2706
2707static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
2708{
2709 int rc;
2710 struct mxt_config_info *info;
2711 struct device_node *temp, *np = dev->of_node;
2712 struct property *prop;
2713 u32 temp_val;
2714
2715 rc = mxt_get_dt_coords(dev, "atmel,panel-coords", pdata);
2716 if (rc)
2717 return rc;
2718
2719 rc = mxt_get_dt_coords(dev, "atmel,display-coords", pdata);
2720 if (rc)
2721 return rc;
2722
2723 /* regulator info */
2724 pdata->i2c_pull_up = of_property_read_bool(np, "atmel,i2c-pull-up");
2725 pdata->digital_pwr_regulator = of_property_read_bool(np,
2726 "atmel,dig-reg-support");
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302727
2728 pdata->no_force_update = of_property_read_bool(np,
2729 "atmel,no-force-update");
2730
Mohan Pallakab74e3482013-07-09 16:39:56 +05302731 pdata->no_lpm_support = of_property_read_bool(np,
2732 "atmel,no-lpm-support");
2733
Mohan Pallakad96f5032012-06-18 22:49:10 +05302734 /* reset, irq gpio info */
2735 pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
2736 0, &pdata->reset_gpio_flags);
2737 pdata->irq_gpio = of_get_named_gpio_flags(np, "atmel,irq-gpio",
2738 0, &pdata->irq_gpio_flags);
2739
2740 /* keycodes for keyarray object*/
2741 prop = of_find_property(np, "atmel,key-codes", NULL);
2742 if (prop) {
2743 pdata->key_codes = devm_kzalloc(dev,
2744 sizeof(int) * MXT_KEYARRAY_MAX_KEYS,
2745 GFP_KERNEL);
2746 if (!pdata->key_codes)
2747 return -ENOMEM;
2748 if ((prop->length/sizeof(u32)) == MXT_KEYARRAY_MAX_KEYS) {
2749 rc = of_property_read_u32_array(np, "atmel,key-codes",
2750 pdata->key_codes, MXT_KEYARRAY_MAX_KEYS);
2751 if (rc) {
2752 dev_err(dev, "Unable to read key codes\n");
2753 return rc;
2754 }
2755 } else
2756 return -EINVAL;
2757 }
2758
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302759 /* need calibration during wakeup? */
2760 pdata->need_calibration = of_property_read_bool(np,
2761 "atmel,need-calibration");
Mohan Pallakad96f5032012-06-18 22:49:10 +05302762 /* config array size */
2763 pdata->config_array_size = 0;
2764 temp = NULL;
2765 while ((temp = of_get_next_child(np, temp)))
2766 pdata->config_array_size++;
2767
2768 if (!pdata->config_array_size)
2769 return 0;
2770
2771 info = devm_kzalloc(dev, pdata->config_array_size *
2772 sizeof(struct mxt_config_info), GFP_KERNEL);
2773 if (!info) {
2774 dev_err(dev, "Unable to allocate memory\n");
2775 return -ENOMEM;
2776 }
2777
Amy Maloche265fc3c2013-01-17 11:50:24 -08002778 rc = of_property_read_u32(np, "atmel,bl-addr", &temp_val);
2779 if (rc && (rc != -EINVAL))
2780 dev_err(dev, "Unable to read bootloader address\n");
2781 else if (rc != -EINVAL)
2782 pdata->bl_addr = (u8) temp_val;
2783
Mohan Pallakad96f5032012-06-18 22:49:10 +05302784 pdata->config_array = info;
2785
2786 for_each_child_of_node(np, temp) {
2787 rc = of_property_read_string(temp, "atmel,fw-name",
2788 &info->fw_name);
2789 if (rc && (rc != -EINVAL)) {
2790 dev_err(dev, "Unable to read fw name\n");
2791 return rc;
2792 }
2793
2794 rc = of_property_read_u32(temp, "atmel,family-id", &temp_val);
2795 if (rc) {
2796 dev_err(dev, "Unable to read family id\n");
2797 return rc;
2798 } else
2799 info->family_id = (u8) temp_val;
2800
2801 rc = of_property_read_u32(temp, "atmel,variant-id", &temp_val);
2802 if (rc) {
2803 dev_err(dev, "Unable to read variant id\n");
2804 return rc;
2805 } else
2806 info->variant_id = (u8) temp_val;
2807
2808 rc = of_property_read_u32(temp, "atmel,version", &temp_val);
2809 if (rc) {
2810 dev_err(dev, "Unable to read controller version\n");
2811 return rc;
2812 } else
2813 info->version = (u8) temp_val;
2814
2815 rc = of_property_read_u32(temp, "atmel,build", &temp_val);
2816 if (rc) {
2817 dev_err(dev, "Unable to read build id\n");
2818 return rc;
2819 } else
2820 info->build = (u8) temp_val;
2821
Amy Maloche265fc3c2013-01-17 11:50:24 -08002822 rc = of_property_read_u32(temp,
Mohan Pallakad96f5032012-06-18 22:49:10 +05302823 "atmel,bootldr-id", &temp_val);
Amy Maloche265fc3c2013-01-17 11:50:24 -08002824 if (rc && (rc != -EINVAL))
Mohan Pallakad96f5032012-06-18 22:49:10 +05302825 dev_err(dev, "Unable to read bootldr-id\n");
Amy Maloche265fc3c2013-01-17 11:50:24 -08002826 else if (rc != -EINVAL)
Mohan Pallakad96f5032012-06-18 22:49:10 +05302827 info->bootldr_id = (u8) temp_val;
2828
2829 rc = mxt_parse_config(dev, temp, info);
2830 if (rc) {
2831 dev_err(dev, "Unable to parse config data\n");
2832 return rc;
2833 }
2834 info++;
2835 }
2836
2837 return 0;
2838}
2839#else
2840static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
2841{
2842 return -ENODEV;
2843}
2844#endif
2845
Anurag Singh49d76132013-01-29 12:07:00 -08002846#if defined(CONFIG_FB)
2847static int fb_notifier_callback(struct notifier_block *self,
2848 unsigned long event, void *data)
2849{
2850 struct fb_event *evdata = data;
2851 int *blank;
2852 struct mxt_data *mxt_dev_data =
2853 container_of(self, struct mxt_data, fb_notif);
2854
Amy Maloche1e0c66a2013-09-24 18:26:26 +01002855 if (evdata && evdata->data && mxt_dev_data && mxt_dev_data->client) {
2856 if (event == FB_EVENT_BLANK) {
2857 blank = evdata->data;
2858 if (*blank == FB_BLANK_UNBLANK)
2859 mxt_resume(&mxt_dev_data->client->dev);
2860 else if (*blank == FB_BLANK_POWERDOWN)
2861 mxt_suspend(&mxt_dev_data->client->dev);
2862 }
Anurag Singh49d76132013-01-29 12:07:00 -08002863 }
2864
2865 return 0;
2866}
2867#elif defined(CONFIG_HAS_EARLYSUSPEND)
2868static void mxt_early_suspend(struct early_suspend *h)
2869{
2870 struct mxt_data *data = container_of(h, struct mxt_data,
2871 early_suspend);
2872 mxt_suspend(&data->client->dev);
2873}
2874
2875static void mxt_late_resume(struct early_suspend *h)
2876{
2877 struct mxt_data *data = container_of(h, struct mxt_data,
2878 early_suspend);
2879 mxt_resume(&data->client->dev);
2880}
2881
2882#endif
2883
Amy Maloche434b7d82013-02-15 11:11:05 +00002884#if defined(CONFIG_SECURE_TOUCH)
Amy Maloche20f970c2013-04-10 13:04:52 +01002885static void __devinit mxt_secure_touch_init(struct mxt_data *data)
Amy Maloche434b7d82013-02-15 11:11:05 +00002886{
Amy Maloche20f970c2013-04-10 13:04:52 +01002887 init_completion(&data->st_powerdown);
Amy Maloche434b7d82013-02-15 11:11:05 +00002888}
2889#else
Amy Maloche20f970c2013-04-10 13:04:52 +01002890static void __devinit mxt_secure_touch_init(struct mxt_data *data)
Amy Maloche434b7d82013-02-15 11:11:05 +00002891{
2892}
2893#endif
2894
Iiro Valkonen7686b102011-02-02 23:21:58 -08002895static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002896 const struct i2c_device_id *id)
2897{
Mohan Pallakad96f5032012-06-18 22:49:10 +05302898 struct mxt_platform_data *pdata;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002899 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002900 struct input_dev *input_dev;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002901 int error, i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002902
Mohan Pallakad96f5032012-06-18 22:49:10 +05302903 if (client->dev.of_node) {
2904 pdata = devm_kzalloc(&client->dev,
2905 sizeof(struct mxt_platform_data), GFP_KERNEL);
2906 if (!pdata) {
2907 dev_err(&client->dev, "Failed to allocate memory\n");
2908 return -ENOMEM;
2909 }
2910
2911 error = mxt_parse_dt(&client->dev, pdata);
2912 if (error)
2913 return error;
2914 } else
2915 pdata = client->dev.platform_data;
2916
Iiro Valkonen919ed892011-02-15 13:36:52 -08002917 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002918 return -EINVAL;
2919
Iiro Valkonen7686b102011-02-02 23:21:58 -08002920 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002921 input_dev = input_allocate_device();
2922 if (!data || !input_dev) {
2923 dev_err(&client->dev, "Failed to allocate memory\n");
2924 error = -ENOMEM;
2925 goto err_free_mem;
2926 }
2927
Nick Dyer0a4016c2012-01-18 15:17:59 +05302928 data->state = INIT;
Amy Maloche83c385a2012-02-01 10:32:03 +05302929 input_dev->name = "atmel_mxt_ts";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002930 input_dev->id.bustype = BUS_I2C;
2931 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002932 input_dev->open = mxt_input_open;
2933 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002934
Joonyoung Shim910d8052011-04-12 23:14:38 -07002935 data->client = client;
2936 data->input_dev = input_dev;
2937 data->pdata = pdata;
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302938 data->no_force_update = pdata->no_force_update;
Mohan Pallakab74e3482013-07-09 16:39:56 +05302939 data->lpm_support = !pdata->no_lpm_support;
Chun Zhang53ab0202013-07-29 17:45:17 -07002940 data->dev_sleep = false;
Joonyoung Shim910d8052011-04-12 23:14:38 -07002941
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002942 __set_bit(EV_ABS, input_dev->evbit);
2943 __set_bit(EV_KEY, input_dev->evbit);
2944 __set_bit(BTN_TOUCH, input_dev->keybit);
Amy Maloche9d0faa02012-06-19 12:37:39 -07002945 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002946
2947 /* For single touch */
2948 input_set_abs_params(input_dev, ABS_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002949 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002950 input_set_abs_params(input_dev, ABS_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002951 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002952 input_set_abs_params(input_dev, ABS_PRESSURE,
2953 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002954
2955 /* For multi touch */
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -07002956 input_mt_init_slots(input_dev, MXT_MAX_FINGER);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002957 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08002958 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002959 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002960 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002961 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002962 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002963 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2964 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002965
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002966 /* set key array supported keys */
2967 if (pdata->key_codes) {
2968 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
2969 if (pdata->key_codes[i])
2970 input_set_capability(input_dev, EV_KEY,
2971 pdata->key_codes[i]);
2972 }
2973 }
2974
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002975 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002976 i2c_set_clientdata(client, data);
2977
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302978 if (pdata->init_hw)
2979 error = pdata->init_hw(true);
2980 else
2981 error = mxt_regulator_configure(data, true);
2982 if (error) {
2983 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07002984 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302985 }
2986
Eugene Yasmanc18bc1f2013-06-11 12:29:24 +03002987 if (gpio_is_valid(pdata->reset_gpio)) {
2988 /* configure touchscreen reset out gpio */
2989 error = gpio_request(pdata->reset_gpio, "mxt_reset_gpio");
2990 if (error) {
2991 dev_err(&client->dev, "unable to request gpio [%d]\n",
2992 pdata->reset_gpio);
2993 goto err_regulator_on;
2994 }
2995
2996 error = gpio_direction_output(pdata->reset_gpio, 0);
2997 if (error) {
2998 dev_err(&client->dev,
2999 "unable to set direction for gpio [%d]\n",
3000 pdata->reset_gpio);
3001 goto err_reset_gpio_req;
3002 }
3003 mxt_reset_delay(data);
3004 }
3005
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05303006 if (pdata->power_on)
3007 error = pdata->power_on(true);
3008 else
3009 error = mxt_power_on(data, true);
3010 if (error) {
3011 dev_err(&client->dev, "Failed to power on hardware\n");
Eugene Yasmanc18bc1f2013-06-11 12:29:24 +03003012 goto err_reset_gpio_req;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05303013 }
3014
Amy Maloche08266db2011-11-04 11:07:16 -07003015 if (gpio_is_valid(pdata->irq_gpio)) {
3016 /* configure touchscreen irq gpio */
Mohan Pallakad96f5032012-06-18 22:49:10 +05303017 error = gpio_request(pdata->irq_gpio, "mxt_irq_gpio");
Amy Maloche08266db2011-11-04 11:07:16 -07003018 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05303019 dev_err(&client->dev, "unable to request gpio [%d]\n",
Amy Maloche08266db2011-11-04 11:07:16 -07003020 pdata->irq_gpio);
3021 goto err_power_on;
3022 }
3023 error = gpio_direction_input(pdata->irq_gpio);
3024 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05303025 dev_err(&client->dev,
3026 "unable to set direction for gpio [%d]\n",
3027 pdata->irq_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07003028 goto err_irq_gpio_req;
3029 }
Mohan Pallakad96f5032012-06-18 22:49:10 +05303030 data->irq = client->irq = gpio_to_irq(pdata->irq_gpio);
3031 } else {
3032 dev_err(&client->dev, "irq gpio not provided\n");
3033 goto err_power_on;
Amy Maloche08266db2011-11-04 11:07:16 -07003034 }
3035
3036 if (gpio_is_valid(pdata->reset_gpio)) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05303037 error = gpio_direction_output(pdata->reset_gpio, 1);
Amy Maloche08266db2011-11-04 11:07:16 -07003038 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05303039 dev_err(&client->dev,
3040 "unable to set direction for gpio [%d]\n",
3041 pdata->reset_gpio);
Eugene Yasmanc18bc1f2013-06-11 12:29:24 +03003042 goto err_irq_gpio_req;
Amy Maloche08266db2011-11-04 11:07:16 -07003043 }
3044 }
3045
Jing Lin64fdd1f2012-12-20 17:08:28 -08003046 mxt_power_on_delay(data);
3047
Amy Maloche265fc3c2013-01-17 11:50:24 -08003048 data->addr_pair.application = data->client->addr;
3049
3050 if (pdata->bl_addr)
3051 data->addr_pair.bootloader = pdata->bl_addr;
3052 else
3053 mxt_lookup_bootloader_address(data);
3054
Iiro Valkonen7686b102011-02-02 23:21:58 -08003055 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003056 if (error)
Eugene Yasmanc18bc1f2013-06-11 12:29:24 +03003057 goto err_irq_gpio_req;
Jing Lin64fdd1f2012-12-20 17:08:28 -08003058
Iiro Valkonen7686b102011-02-02 23:21:58 -08003059 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08003060 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003061 if (error) {
3062 dev_err(&client->dev, "Failed to register interrupt\n");
3063 goto err_free_object;
3064 }
3065
Nick Dyer0a4016c2012-01-18 15:17:59 +05303066 if (data->state == APPMODE) {
3067 error = mxt_make_highchg(data);
3068 if (error) {
3069 dev_err(&client->dev, "Failed to make high CHG\n");
3070 goto err_free_irq;
3071 }
3072 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07003073
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003074 error = input_register_device(input_dev);
3075 if (error)
3076 goto err_free_irq;
3077
Iiro Valkonen7686b102011-02-02 23:21:58 -08003078 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003079 if (error)
3080 goto err_unregister_device;
3081
Anurag Singh49d76132013-01-29 12:07:00 -08003082#if defined(CONFIG_FB)
3083 data->fb_notif.notifier_call = fb_notifier_callback;
3084
3085 error = fb_register_client(&data->fb_notif);
3086
3087 if (error)
3088 dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
3089 error);
3090#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +05303091 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
3092 MXT_SUSPEND_LEVEL;
3093 data->early_suspend.suspend = mxt_early_suspend;
3094 data->early_suspend.resume = mxt_late_resume;
3095 register_early_suspend(&data->early_suspend);
3096#endif
3097
Jing Lin6cfc00e2011-11-02 15:15:30 -07003098 mxt_debugfs_init(data);
3099
Amy Maloche20f970c2013-04-10 13:04:52 +01003100 mxt_secure_touch_init(data);
Amy Maloche434b7d82013-02-15 11:11:05 +00003101
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003102 return 0;
3103
3104err_unregister_device:
3105 input_unregister_device(input_dev);
3106 input_dev = NULL;
3107err_free_irq:
3108 free_irq(client->irq, data);
3109err_free_object:
3110 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07003111err_irq_gpio_req:
3112 if (gpio_is_valid(pdata->irq_gpio))
3113 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05303114err_power_on:
3115 if (pdata->power_on)
3116 pdata->power_on(false);
3117 else
3118 mxt_power_on(data, false);
Eugene Yasmanc18bc1f2013-06-11 12:29:24 +03003119err_reset_gpio_req:
3120 if (gpio_is_valid(pdata->reset_gpio))
3121 gpio_free(pdata->reset_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05303122err_regulator_on:
3123 if (pdata->init_hw)
3124 pdata->init_hw(false);
3125 else
3126 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003127err_free_mem:
3128 input_free_device(input_dev);
3129 kfree(data);
3130 return error;
3131}
3132
Iiro Valkonen7686b102011-02-02 23:21:58 -08003133static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003134{
Iiro Valkonen7686b102011-02-02 23:21:58 -08003135 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003136
Iiro Valkonen7686b102011-02-02 23:21:58 -08003137 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003138 free_irq(data->irq, data);
3139 input_unregister_device(data->input_dev);
Anurag Singh49d76132013-01-29 12:07:00 -08003140#if defined(CONFIG_FB)
3141 if (fb_unregister_client(&data->fb_notif))
3142 dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
3143#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +05303144 unregister_early_suspend(&data->early_suspend);
3145#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05303146
3147 if (data->pdata->power_on)
3148 data->pdata->power_on(false);
3149 else
3150 mxt_power_on(data, false);
3151
3152 if (data->pdata->init_hw)
3153 data->pdata->init_hw(false);
3154 else
3155 mxt_regulator_configure(data, false);
3156
Mohan Pallakabfe8f302012-01-02 18:32:08 +08003157 if (gpio_is_valid(data->pdata->reset_gpio))
3158 gpio_free(data->pdata->reset_gpio);
3159
3160 if (gpio_is_valid(data->pdata->irq_gpio))
3161 gpio_free(data->pdata->irq_gpio);
3162
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003163 kfree(data->object_table);
3164 kfree(data);
3165
Jing Lin6cfc00e2011-11-02 15:15:30 -07003166 debugfs_remove_recursive(debug_base);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003167
3168 return 0;
3169}
3170
Iiro Valkonen7686b102011-02-02 23:21:58 -08003171static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003172 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08003173 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08003174 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003175 { }
3176};
Iiro Valkonen7686b102011-02-02 23:21:58 -08003177MODULE_DEVICE_TABLE(i2c, mxt_id);
Amy Maloche56cb58c2012-08-23 13:21:03 -07003178#ifdef CONFIG_OF
Mohan Pallakad96f5032012-06-18 22:49:10 +05303179static struct of_device_id mxt_match_table[] = {
3180 { .compatible = "atmel,mxt-ts",},
3181 { },
3182};
3183#else
3184#define mxt_match_table NULL
3185#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003186
Iiro Valkonen7686b102011-02-02 23:21:58 -08003187static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003188 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08003189 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003190 .owner = THIS_MODULE,
Mohan Pallakad96f5032012-06-18 22:49:10 +05303191 .of_match_table = mxt_match_table,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08003192#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08003193 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08003194#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003195 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08003196 .probe = mxt_probe,
3197 .remove = __devexit_p(mxt_remove),
3198 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003199};
3200
Axel Lin1b92c1c2012-03-16 23:05:41 -07003201module_i2c_driver(mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003202
3203/* Module information */
3204MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08003205MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003206MODULE_LICENSE("GPL");