blob: 0c208155ac4178351a9ab1d2a2b0385770251256 [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>
Anurag Singh49d76132013-01-29 12:07:00 -08006 * Copyright (c) 2011-2013, 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 Maloche41f1cc32012-07-12 13:02:27 -0700131#define MXT_SPT_TIMER_T61 61
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700132
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700133/* MXT_GEN_COMMAND_T6 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800134#define MXT_COMMAND_RESET 0
135#define MXT_COMMAND_BACKUPNV 1
136#define MXT_COMMAND_CALIBRATE 2
137#define MXT_COMMAND_REPORTALL 3
138#define MXT_COMMAND_DIAGNOSTIC 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700139
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700140/* MXT_GEN_POWER_T7 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800141#define MXT_POWER_IDLEACQINT 0
142#define MXT_POWER_ACTVACQINT 1
143#define MXT_POWER_ACTV2IDLETO 2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700144
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700145/* MXT_GEN_ACQUIRE_T8 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800146#define MXT_ACQUIRE_CHRGTIME 0
147#define MXT_ACQUIRE_TCHDRIFT 2
148#define MXT_ACQUIRE_DRIFTST 3
149#define MXT_ACQUIRE_TCHAUTOCAL 4
150#define MXT_ACQUIRE_SYNC 5
151#define MXT_ACQUIRE_ATCHCALST 6
152#define MXT_ACQUIRE_ATCHCALSTHR 7
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700153
Iiro Valkonene8645592011-11-18 12:56:19 -0800154/* MXT_TOUCH_MULT_T9 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800155#define MXT_TOUCH_CTRL 0
156#define MXT_TOUCH_XORIGIN 1
157#define MXT_TOUCH_YORIGIN 2
158#define MXT_TOUCH_XSIZE 3
159#define MXT_TOUCH_YSIZE 4
160#define MXT_TOUCH_BLEN 6
161#define MXT_TOUCH_TCHTHR 7
162#define MXT_TOUCH_TCHDI 8
163#define MXT_TOUCH_ORIENT 9
164#define MXT_TOUCH_MOVHYSTI 11
165#define MXT_TOUCH_MOVHYSTN 12
166#define MXT_TOUCH_NUMTOUCH 14
167#define MXT_TOUCH_MRGHYST 15
168#define MXT_TOUCH_MRGTHR 16
169#define MXT_TOUCH_AMPHYST 17
170#define MXT_TOUCH_XRANGE_LSB 18
171#define MXT_TOUCH_XRANGE_MSB 19
172#define MXT_TOUCH_YRANGE_LSB 20
173#define MXT_TOUCH_YRANGE_MSB 21
174#define MXT_TOUCH_XLOCLIP 22
175#define MXT_TOUCH_XHICLIP 23
176#define MXT_TOUCH_YLOCLIP 24
177#define MXT_TOUCH_YHICLIP 25
178#define MXT_TOUCH_XEDGECTRL 26
179#define MXT_TOUCH_XEDGEDIST 27
180#define MXT_TOUCH_YEDGECTRL 28
181#define MXT_TOUCH_YEDGEDIST 29
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700182#define MXT_TOUCH_JUMPLIMIT 30
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700183
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700184/* MXT_PROCI_GRIPFACE_T20 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800185#define MXT_GRIPFACE_CTRL 0
186#define MXT_GRIPFACE_XLOGRIP 1
187#define MXT_GRIPFACE_XHIGRIP 2
188#define MXT_GRIPFACE_YLOGRIP 3
189#define MXT_GRIPFACE_YHIGRIP 4
190#define MXT_GRIPFACE_MAXTCHS 5
191#define MXT_GRIPFACE_SZTHR1 7
192#define MXT_GRIPFACE_SZTHR2 8
193#define MXT_GRIPFACE_SHPTHR1 9
194#define MXT_GRIPFACE_SHPTHR2 10
195#define MXT_GRIPFACE_SUPEXTTO 11
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700196
Iiro Valkonen7686b102011-02-02 23:21:58 -0800197/* MXT_PROCI_NOISE field */
198#define MXT_NOISE_CTRL 0
199#define MXT_NOISE_OUTFLEN 1
200#define MXT_NOISE_GCAFUL_LSB 3
201#define MXT_NOISE_GCAFUL_MSB 4
202#define MXT_NOISE_GCAFLL_LSB 5
203#define MXT_NOISE_GCAFLL_MSB 6
204#define MXT_NOISE_ACTVGCAFVALID 7
205#define MXT_NOISE_NOISETHR 8
206#define MXT_NOISE_FREQHOPSCALE 10
207#define MXT_NOISE_FREQ0 11
208#define MXT_NOISE_FREQ1 12
209#define MXT_NOISE_FREQ2 13
210#define MXT_NOISE_FREQ3 14
211#define MXT_NOISE_FREQ4 15
212#define MXT_NOISE_IDLEGCAFVALID 16
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700213
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700214/* MXT_SPT_COMMSCONFIG_T18 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800215#define MXT_COMMS_CTRL 0
216#define MXT_COMMS_CMD 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700217
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700218/* MXT_SPT_CTECONFIG_T28 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800219#define MXT_CTE_CTRL 0
220#define MXT_CTE_CMD 1
221#define MXT_CTE_MODE 2
222#define MXT_CTE_IDLEGCAFDEPTH 3
223#define MXT_CTE_ACTVGCAFDEPTH 4
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700224#define MXT_CTE_VOLTAGE 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700225
Iiro Valkonen7686b102011-02-02 23:21:58 -0800226#define MXT_VOLTAGE_DEFAULT 2700000
227#define MXT_VOLTAGE_STEP 10000
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700228
Amy Maloche21115eb2011-11-02 09:04:37 -0700229/* Analog voltage @2.7 V */
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530230#define MXT_VTG_MIN_UV 2700000
231#define MXT_VTG_MAX_UV 3300000
232#define MXT_ACTIVE_LOAD_UA 15000
Jing Linbace50b2011-10-18 22:55:47 -0700233#define MXT_LPM_LOAD_UA 10
Amy Maloche21115eb2011-11-02 09:04:37 -0700234/* Digital voltage @1.8 V */
235#define MXT_VTG_DIG_MIN_UV 1800000
236#define MXT_VTG_DIG_MAX_UV 1800000
237#define MXT_ACTIVE_LOAD_DIG_UA 10000
238#define MXT_LPM_LOAD_DIG_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530239
240#define MXT_I2C_VTG_MIN_UV 1800000
241#define MXT_I2C_VTG_MAX_UV 1800000
242#define MXT_I2C_LOAD_UA 10000
Jing Linbace50b2011-10-18 22:55:47 -0700243#define MXT_I2C_LPM_LOAD_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530244
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700245/* Define for MXT_GEN_COMMAND_T6 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800246#define MXT_BOOT_VALUE 0xa5
247#define MXT_BACKUP_VALUE 0x55
248#define MXT_BACKUP_TIME 25 /* msec */
Jing Lin64fdd1f2012-12-20 17:08:28 -0800249
250/* Software reset delay */
251#define MXT224_RESET_TIME 64 /* msec */
252#define MXT224E_RESET_TIME 21 /* msec */
Amy Maloche41f1cc32012-07-12 13:02:27 -0700253#define MXT336S_RESET_TIME 25 /* msec */
Jing Lin64fdd1f2012-12-20 17:08:28 -0800254#define MXT1386_RESET_TIME 250 /* msec */
255#define MXT1386E_RESET_TIME 229 /* msec */
256#define MXT1664S_RESET_TIME 280 /* msec */
Amy Maloche7e447432011-09-14 11:36:30 -0700257#define MXT_RESET_TIME 250 /* msec */
Jing Linc7fc4052011-12-21 16:16:19 -0800258#define MXT_RESET_NOCHGREAD 400 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700259
Jing Lin64fdd1f2012-12-20 17:08:28 -0800260/* Power on delay */
261#define MXT224_POWER_ON_TIME 40 /* msec */
262#define MXT224E_POWER_ON_TIME 21 /* msec */
263#define MXT336S_POWER_ON_TIME 25 /* msec */
264#define MXT1386_POWER_ON_TIME 90 /* msec */
265#define MXT1386E_POWER_ON_TIME 81 /* msec */
266#define MXT1664S_POWER_ON_TIME 65 /* msec */
267#define MXT_POWER_ON_TIME 100 /* msec */
268
Nick Dyer0a4016c2012-01-18 15:17:59 +0530269#define MXT_FWRESET_TIME 1000 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700270
Jing Lin36aee812011-10-17 17:17:28 -0700271#define MXT_WAKE_TIME 25
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700272
273/* Command to unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800274#define MXT_UNLOCK_CMD_MSB 0xaa
275#define MXT_UNLOCK_CMD_LSB 0xdc
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700276
277/* Bootloader mode status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800278#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
279#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
280#define MXT_FRAME_CRC_CHECK 0x02
281#define MXT_FRAME_CRC_FAIL 0x03
282#define MXT_FRAME_CRC_PASS 0x04
283#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
284#define MXT_BOOT_STATUS_MASK 0x3f
Nick Dyer0a4016c2012-01-18 15:17:59 +0530285#define MXT_BOOT_EXTENDED_ID (1 << 5)
286#define MXT_BOOT_ID_MASK 0x1f
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700287
288/* Touch status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800289#define MXT_SUPPRESS (1 << 1)
290#define MXT_AMP (1 << 2)
291#define MXT_VECTOR (1 << 3)
292#define MXT_MOVE (1 << 4)
293#define MXT_RELEASE (1 << 5)
294#define MXT_PRESS (1 << 6)
295#define MXT_DETECT (1 << 7)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700296
Joonyoung Shim910d8052011-04-12 23:14:38 -0700297/* Touch orient bits */
298#define MXT_XY_SWITCH (1 << 0)
299#define MXT_X_INVERT (1 << 1)
300#define MXT_Y_INVERT (1 << 2)
301
Mohan Pallakab6acab42012-06-13 11:59:04 +0530302/* Touch suppression */
303#define MXT_TCHSUP_ACTIVE (1 << 0)
304
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700305/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800306#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700307
Iiro Valkonen7686b102011-02-02 23:21:58 -0800308#define MXT_MAX_FINGER 10
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700309
Jing Lin36aee812011-10-17 17:17:28 -0700310#define T7_DATA_SIZE 3
311#define MXT_MAX_RW_TRIES 3
312#define MXT_BLOCK_SIZE 256
Jing Lin8fadad72012-02-24 10:10:50 -0800313#define MXT_CFG_VERSION_LEN 3
314#define MXT_CFG_VERSION_EQUAL 0
315#define MXT_CFG_VERSION_LESS 1
316#define MXT_CFG_VERSION_GREATER 2
Mohan Pallakaab51f2b2011-09-29 18:17:35 +0530317
Mohan Pallakad96f5032012-06-18 22:49:10 +0530318#define MXT_COORDS_ARR_SIZE 4
319
Jing Lin6cfc00e2011-11-02 15:15:30 -0700320#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
321#define MXT_DEBUGFS_FILE "object"
322
Iiro Valkonen7686b102011-02-02 23:21:58 -0800323struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700324 u8 family_id;
325 u8 variant_id;
326 u8 version;
327 u8 build;
328 u8 matrix_xsize;
329 u8 matrix_ysize;
330 u8 object_num;
331};
332
Iiro Valkonen7686b102011-02-02 23:21:58 -0800333struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700334 u8 type;
335 u16 start_address;
336 u8 size;
337 u8 instances;
338 u8 num_report_ids;
339
340 /* to map object and message */
341 u8 max_reportid;
342};
343
Iiro Valkonen7686b102011-02-02 23:21:58 -0800344struct mxt_message {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700345 u8 reportid;
346 u8 message[7];
347 u8 checksum;
348};
349
Iiro Valkonen7686b102011-02-02 23:21:58 -0800350struct mxt_finger {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700351 int status;
352 int x;
353 int y;
354 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700355 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700356};
357
358/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800359struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700360 struct i2c_client *client;
361 struct input_dev *input_dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800362 const struct mxt_platform_data *pdata;
Jing Lindc4413c2012-01-16 15:22:52 -0800363 const struct mxt_config_info *config_info;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530364 enum mxt_device_state state;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800365 struct mxt_object *object_table;
366 struct mxt_info info;
367 struct mxt_finger finger[MXT_MAX_FINGER];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700368 unsigned int irq;
Amy Maloche21115eb2011-11-02 09:04:37 -0700369 struct regulator *vcc_ana;
370 struct regulator *vcc_dig;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530371 struct regulator *vcc_i2c;
Anurag Singh49d76132013-01-29 12:07:00 -0800372#if defined(CONFIG_FB)
373 struct notifier_block fb_notif;
374#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +0530375 struct early_suspend early_suspend;
376#endif
Jing Lin36aee812011-10-17 17:17:28 -0700377
Amy Maloche52262212011-09-15 16:46:57 -0700378 u8 t7_data[T7_DATA_SIZE];
Jing Lin36aee812011-10-17 17:17:28 -0700379 u16 t7_start_addr;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800380 u32 keyarray_old;
381 u32 keyarray_new;
382 u8 t9_max_reportid;
383 u8 t9_min_reportid;
384 u8 t15_max_reportid;
385 u8 t15_min_reportid;
Mohan Pallakab6acab42012-06-13 11:59:04 +0530386 u8 t42_max_reportid;
387 u8 t42_min_reportid;
Jing Lin8fadad72012-02-24 10:10:50 -0800388 u8 cfg_version[MXT_CFG_VERSION_LEN];
Jing Lindc4413c2012-01-16 15:22:52 -0800389 int cfg_version_idx;
Jing Lin8a9472d2012-03-21 15:43:45 -0700390 int t38_start_addr;
Jing Lin8fadad72012-02-24 10:10:50 -0800391 bool update_cfg;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -0800392 const char *fw_name;
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +0530393 bool no_force_update;
Amy Maloche434b7d82013-02-15 11:11:05 +0000394#if defined(CONFIG_SECURE_TOUCH)
395 atomic_t st_enabled;
396 atomic_t st_pending_irqs;
397 struct completion st_completion;
398#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700399};
400
Jing Lin6cfc00e2011-11-02 15:15:30 -0700401static struct dentry *debug_base;
402
Iiro Valkonen7686b102011-02-02 23:21:58 -0800403static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700404{
405 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700406 case MXT_GEN_MESSAGE_T5:
407 case MXT_GEN_COMMAND_T6:
408 case MXT_GEN_POWER_T7:
409 case MXT_GEN_ACQUIRE_T8:
410 case MXT_GEN_DATASOURCE_T53:
411 case MXT_TOUCH_MULTI_T9:
412 case MXT_TOUCH_KEYARRAY_T15:
413 case MXT_TOUCH_PROXIMITY_T23:
414 case MXT_TOUCH_PROXKEY_T52:
415 case MXT_PROCI_GRIPFACE_T20:
416 case MXT_PROCG_NOISE_T22:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700417 case MXT_PROCG_NOISE_T62:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700418 case MXT_PROCI_ONETOUCH_T24:
419 case MXT_PROCI_TWOTOUCH_T27:
420 case MXT_PROCI_GRIP_T40:
421 case MXT_PROCI_PALM_T41:
422 case MXT_PROCI_TOUCHSUPPRESSION_T42:
423 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800424 case MXT_PROCI_SHIELDLESS_T56:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700425 case MXT_PROCI_EXTRATSDATA_T57:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700426 case MXT_PROCG_NOISESUPPRESSION_T48:
427 case MXT_SPT_COMMSCONFIG_T18:
428 case MXT_SPT_GPIOPWM_T19:
429 case MXT_SPT_SELFTEST_T25:
430 case MXT_SPT_CTECONFIG_T28:
431 case MXT_SPT_USERDATA_T38:
432 case MXT_SPT_DIGITIZER_T43:
433 case MXT_SPT_CTECONFIG_T46:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700434 case MXT_SPT_TIMER_T61:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530435 case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700436 return true;
437 default:
438 return false;
439 }
440}
441
Iiro Valkonen7686b102011-02-02 23:21:58 -0800442static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700443{
444 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700445 case MXT_GEN_COMMAND_T6:
446 case MXT_GEN_POWER_T7:
447 case MXT_GEN_ACQUIRE_T8:
448 case MXT_TOUCH_MULTI_T9:
449 case MXT_TOUCH_KEYARRAY_T15:
450 case MXT_TOUCH_PROXIMITY_T23:
451 case MXT_TOUCH_PROXKEY_T52:
452 case MXT_PROCI_GRIPFACE_T20:
453 case MXT_PROCG_NOISE_T22:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700454 case MXT_PROCG_NOISE_T62:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700455 case MXT_PROCI_ONETOUCH_T24:
456 case MXT_PROCI_TWOTOUCH_T27:
457 case MXT_PROCI_GRIP_T40:
458 case MXT_PROCI_PALM_T41:
459 case MXT_PROCI_TOUCHSUPPRESSION_T42:
460 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800461 case MXT_PROCI_SHIELDLESS_T56:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700462 case MXT_PROCI_EXTRATSDATA_T57:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700463 case MXT_PROCG_NOISESUPPRESSION_T48:
464 case MXT_SPT_COMMSCONFIG_T18:
465 case MXT_SPT_GPIOPWM_T19:
466 case MXT_SPT_SELFTEST_T25:
467 case MXT_SPT_CTECONFIG_T28:
Iiro Valkonene8645592011-11-18 12:56:19 -0800468 case MXT_SPT_USERDATA_T38:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700469 case MXT_SPT_DIGITIZER_T43:
470 case MXT_SPT_CTECONFIG_T46:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700471 case MXT_SPT_TIMER_T61:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530472 case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700473 return true;
474 default:
475 return false;
476 }
477}
478
Iiro Valkonen7686b102011-02-02 23:21:58 -0800479static void mxt_dump_message(struct device *dev,
480 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700481{
482 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
483 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
484 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
485 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
486 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
487 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
488 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
489 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
490 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
491}
492
Amy Maloche71b8f022013-01-17 11:50:24 -0800493static int mxt_switch_to_bootloader_address(struct mxt_data *data)
494{
Steve Mucklee1533542013-02-13 15:03:16 -0800495 int i;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530496 struct i2c_client *client = data->client;
497
498 if (data->state == BOOTLOADER) {
499 dev_err(&client->dev, "Already in BOOTLOADER state\n");
500 return -EINVAL;
501 }
502
Steve Mucklee1533542013-02-13 15:03:16 -0800503 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
504 if (mxt_slave_addresses[i].application == client->addr) {
505 dev_info(&client->dev, "Changing to bootloader address: "
506 "%02x -> %02x",
507 client->addr,
508 mxt_slave_addresses[i].bootloader);
Nick Dyer0a4016c2012-01-18 15:17:59 +0530509
Steve Mucklee1533542013-02-13 15:03:16 -0800510 client->addr = mxt_slave_addresses[i].bootloader;
511 data->state = BOOTLOADER;
512 return 0;
513 }
514 }
515
516 dev_err(&client->dev, "Address 0x%02x not found in address table",
517 client->addr);
518 return -EINVAL;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530519}
520
521static int mxt_switch_to_appmode_address(struct mxt_data *data)
522{
Steve Mucklee1533542013-02-13 15:03:16 -0800523 int i;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530524 struct i2c_client *client = data->client;
525
526 if (data->state == APPMODE) {
527 dev_err(&client->dev, "Already in APPMODE state\n");
528 return -EINVAL;
529 }
530
Steve Mucklee1533542013-02-13 15:03:16 -0800531 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
532 if (mxt_slave_addresses[i].bootloader == client->addr) {
533 dev_info(&client->dev,
534 "Changing to application mode address: "
535 "0x%02x -> 0x%02x",
536 client->addr,
537 mxt_slave_addresses[i].application);
Nick Dyer0a4016c2012-01-18 15:17:59 +0530538
Steve Mucklee1533542013-02-13 15:03:16 -0800539 client->addr = mxt_slave_addresses[i].application;
540 data->state = APPMODE;
541 return 0;
542 }
543 }
544
545 dev_err(&client->dev, "Address 0x%02x not found in address table",
546 client->addr);
547 return -EINVAL;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530548}
549
550static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
551{
552 u8 buf[3];
553
554 if (val | MXT_BOOT_EXTENDED_ID) {
555 dev_dbg(&client->dev,
556 "Retrieving extended mode ID information");
557
558 if (i2c_master_recv(client, &buf[0], 3) != 3) {
559 dev_err(&client->dev, "%s: i2c recv failed\n",
560 __func__);
561 return -EIO;
562 }
563
564 dev_info(&client->dev, "Bootloader ID:%d Version:%d",
565 buf[1], buf[2]);
566
567 return buf[0];
568 } else {
569 dev_info(&client->dev, "Bootloader ID:%d",
570 val & MXT_BOOT_ID_MASK);
571
572 return val;
573 }
574}
575
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -0800576static int mxt_get_bootloader_id(struct i2c_client *client)
577{
578 u8 val;
579 u8 buf[3];
580
581 if (i2c_master_recv(client, &val, 1) != 1) {
582 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
583 return -EIO;
584 }
585
586 if (val | MXT_BOOT_EXTENDED_ID) {
587 if (i2c_master_recv(client, &buf[0], 3) != 3) {
588 dev_err(&client->dev, "%s: i2c recv failed\n",
589 __func__);
590 return -EIO;
591 }
592 return buf[1];
593 } else {
594 dev_info(&client->dev, "Bootloader ID:%d",
595 val & MXT_BOOT_ID_MASK);
596
597 return val & MXT_BOOT_ID_MASK;
598 }
599}
600
Iiro Valkonen7686b102011-02-02 23:21:58 -0800601static int mxt_check_bootloader(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530602 unsigned int state)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700603{
604 u8 val;
605
606recheck:
607 if (i2c_master_recv(client, &val, 1) != 1) {
608 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
609 return -EIO;
610 }
611
612 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800613 case MXT_WAITING_BOOTLOAD_CMD:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530614 val = mxt_get_bootloader_version(client, val);
615 val &= ~MXT_BOOT_STATUS_MASK;
616 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800617 case MXT_WAITING_FRAME_DATA:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530618 case MXT_APP_CRC_FAIL:
Iiro Valkonen7686b102011-02-02 23:21:58 -0800619 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700620 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800621 case MXT_FRAME_CRC_PASS:
622 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700623 goto recheck;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530624 if (val == MXT_FRAME_CRC_FAIL) {
625 dev_err(&client->dev, "Bootloader CRC fail\n");
626 return -EINVAL;
627 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700628 break;
629 default:
630 return -EINVAL;
631 }
632
633 if (val != state) {
Nick Dyer0a4016c2012-01-18 15:17:59 +0530634 dev_err(&client->dev, "Invalid bootloader mode state %X\n",
635 val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700636 return -EINVAL;
637 }
638
639 return 0;
640}
641
Iiro Valkonen7686b102011-02-02 23:21:58 -0800642static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700643{
644 u8 buf[2];
645
Iiro Valkonen7686b102011-02-02 23:21:58 -0800646 buf[0] = MXT_UNLOCK_CMD_LSB;
647 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700648
649 if (i2c_master_send(client, buf, 2) != 2) {
650 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
651 return -EIO;
652 }
653
654 return 0;
655}
656
Iiro Valkonen7686b102011-02-02 23:21:58 -0800657static int mxt_fw_write(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530658 const u8 *data, unsigned int frame_size)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700659{
660 if (i2c_master_send(client, data, frame_size) != frame_size) {
661 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
662 return -EIO;
663 }
664
665 return 0;
666}
667
Iiro Valkonen7686b102011-02-02 23:21:58 -0800668static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700669 u16 reg, u16 len, void *val)
670{
671 struct i2c_msg xfer[2];
672 u8 buf[2];
Jing Lin36aee812011-10-17 17:17:28 -0700673 int i = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700674
675 buf[0] = reg & 0xff;
676 buf[1] = (reg >> 8) & 0xff;
677
678 /* Write register */
679 xfer[0].addr = client->addr;
680 xfer[0].flags = 0;
681 xfer[0].len = 2;
682 xfer[0].buf = buf;
683
684 /* Read data */
685 xfer[1].addr = client->addr;
686 xfer[1].flags = I2C_M_RD;
687 xfer[1].len = len;
688 xfer[1].buf = val;
689
Jing Lin36aee812011-10-17 17:17:28 -0700690 do {
691 if (i2c_transfer(client->adapter, xfer, 2) == 2)
692 return 0;
693 msleep(MXT_WAKE_TIME);
694 } while (++i < MXT_MAX_RW_TRIES);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700695
Jing Lin36aee812011-10-17 17:17:28 -0700696 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
697 return -EIO;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700698}
699
Iiro Valkonen7686b102011-02-02 23:21:58 -0800700static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700701{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800702 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700703}
704
Jing Lin36aee812011-10-17 17:17:28 -0700705static int __mxt_write_reg(struct i2c_client *client,
706 u16 addr, u16 length, u8 *value)
707{
708 u8 buf[MXT_BLOCK_SIZE + 2];
709 int i, tries = 0;
710
711 if (length > MXT_BLOCK_SIZE)
712 return -EINVAL;
713
714 buf[0] = addr & 0xff;
715 buf[1] = (addr >> 8) & 0xff;
716 for (i = 0; i < length; i++)
717 buf[i + 2] = *value++;
718
719 do {
720 if (i2c_master_send(client, buf, length + 2) == (length + 2))
721 return 0;
722 msleep(MXT_WAKE_TIME);
723 } while (++tries < MXT_MAX_RW_TRIES);
724
725 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
726 return -EIO;
727}
728
Iiro Valkonen7686b102011-02-02 23:21:58 -0800729static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700730{
Jing Lin36aee812011-10-17 17:17:28 -0700731 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700732}
733
Iiro Valkonen7686b102011-02-02 23:21:58 -0800734static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700735 u16 reg, u8 *object_buf)
736{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800737 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700738 object_buf);
739}
740
Iiro Valkonen7686b102011-02-02 23:21:58 -0800741static struct mxt_object *
742mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700743{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800744 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700745 int i;
746
747 for (i = 0; i < data->info.object_num; i++) {
748 object = data->object_table + i;
749 if (object->type == type)
750 return object;
751 }
752
753 dev_err(&data->client->dev, "Invalid object type\n");
754 return NULL;
755}
756
Iiro Valkonen7686b102011-02-02 23:21:58 -0800757static int mxt_read_message(struct mxt_data *data,
758 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700759{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800760 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700761 u16 reg;
762
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700763 object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700764 if (!object)
765 return -EINVAL;
766
767 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800768 return __mxt_read_reg(data->client, reg,
769 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700770}
771
Iiro Valkonen7686b102011-02-02 23:21:58 -0800772static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700773 u8 type, u8 offset, u8 *val)
774{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800775 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700776 u16 reg;
777
Iiro Valkonen7686b102011-02-02 23:21:58 -0800778 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700779 if (!object)
780 return -EINVAL;
781
782 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800783 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700784}
785
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530786static int mxt_get_object_address(struct device *dev, u8 type)
787{
788 struct mxt_data *data = dev_get_drvdata(dev);
789 u8 obj_num, obj_buf[MXT_OBJECT_SIZE];
790 u16 reg;
791 int i, error;
792
793 error = mxt_read_reg(data->client, MXT_OBJECT_NUM, &obj_num);
794
795 if (error) {
796 dev_err(dev, "reading number of objects failed\n");
797 return -EINVAL;
798 }
799
800 for (i = 0; i < obj_num; i++) {
801 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
802 error = mxt_read_object_table(data->client,
803 reg, obj_buf);
804 if (error)
805 return error;
806
807 if (obj_buf[0] == type)
808 return obj_buf[2] << 8 | obj_buf[1];
809 }
810 /* If control reaches here, i = obj_num and object not found */
811 dev_err(dev, "Requested object %d not found.\n", type);
812 return -EINVAL;
813
814}
815
Iiro Valkonen7686b102011-02-02 23:21:58 -0800816static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700817 u8 type, u8 offset, u8 val)
818{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800819 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700820 u16 reg;
821
Iiro Valkonen7686b102011-02-02 23:21:58 -0800822 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700823 if (!object)
824 return -EINVAL;
825
826 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800827 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700828}
829
Iiro Valkonen7686b102011-02-02 23:21:58 -0800830static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700831{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800832 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700833 struct input_dev *input_dev = data->input_dev;
834 int status = finger[single_id].status;
835 int finger_num = 0;
836 int id;
837
Iiro Valkonen7686b102011-02-02 23:21:58 -0800838 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700839 if (!finger[id].status)
840 continue;
841
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700842 input_mt_slot(input_dev, id);
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800843 /* Firmware reports min/max values when the touch is
844 * outside screen area. Send a release event in
845 * such cases to avoid unwanted touches.
846 */
847 if (finger[id].x <= data->pdata->panel_minx ||
848 finger[id].x >= data->pdata->panel_maxx ||
849 finger[id].y <= data->pdata->panel_miny ||
850 finger[id].y >= data->pdata->panel_maxy) {
851 finger[id].status = MXT_RELEASE;
852 }
853
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700854 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
855 finger[id].status != MXT_RELEASE);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700856
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700857 if (finger[id].status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700858 finger_num++;
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700859 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
860 finger[id].area);
861 input_report_abs(input_dev, ABS_MT_POSITION_X,
862 finger[id].x);
863 input_report_abs(input_dev, ABS_MT_POSITION_Y,
864 finger[id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700865 input_report_abs(input_dev, ABS_MT_PRESSURE,
Anirudh Ghayal279a2ae52012-05-18 18:07:46 +0530866 finger[id].pressure);
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700867 } else {
868 finger[id].status = 0;
869 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700870 }
871
872 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
873
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800874 if (finger[single_id].x <= data->pdata->panel_minx ||
875 finger[single_id].x >= data->pdata->panel_maxx ||
876 finger[single_id].y <= data->pdata->panel_miny ||
877 finger[single_id].y >= data->pdata->panel_maxy) {
878 status = MXT_RELEASE;
879 }
880
Iiro Valkonen7686b102011-02-02 23:21:58 -0800881 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700882 input_report_abs(input_dev, ABS_X, finger[single_id].x);
883 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700884 input_report_abs(input_dev,
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700885 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700886 }
887
888 input_sync(input_dev);
889}
890
Iiro Valkonen7686b102011-02-02 23:21:58 -0800891static void mxt_input_touchevent(struct mxt_data *data,
892 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700893{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800894 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700895 struct device *dev = &data->client->dev;
896 u8 status = message->message[0];
897 int x;
898 int y;
899 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700900 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700901
902 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800903 if (!(status & MXT_DETECT)) {
904 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700905 dev_dbg(dev, "[%d] released\n", id);
906
Iiro Valkonen7686b102011-02-02 23:21:58 -0800907 finger[id].status = MXT_RELEASE;
908 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700909 }
910 return;
911 }
912
913 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800914 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700915 return;
916
Joonyoung Shim910d8052011-04-12 23:14:38 -0700917 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
918 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800919 if (data->pdata->panel_maxx < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700920 x = x >> 2;
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800921 if (data->pdata->panel_maxy < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700922 y = y >> 2;
923
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700924 area = message->message[4];
Yufeng Shen28ac2932011-08-16 00:40:54 -0700925 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700926
927 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800928 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700929 x, y, area);
930
Iiro Valkonen7686b102011-02-02 23:21:58 -0800931 finger[id].status = status & MXT_MOVE ?
932 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700933 finger[id].x = x;
934 finger[id].y = y;
935 finger[id].area = area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700936 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700937
Iiro Valkonen7686b102011-02-02 23:21:58 -0800938 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700939}
940
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800941static void mxt_handle_key_array(struct mxt_data *data,
942 struct mxt_message *message)
943{
944 u32 keys_changed;
945 int i;
946
947 if (!data->pdata->key_codes) {
948 dev_err(&data->client->dev, "keyarray is not supported\n");
949 return;
950 }
951
952 data->keyarray_new = message->message[1] |
953 (message->message[2] << 8) |
954 (message->message[3] << 16) |
955 (message->message[4] << 24);
956
957 keys_changed = data->keyarray_old ^ data->keyarray_new;
958
959 if (!keys_changed) {
960 dev_dbg(&data->client->dev, "no keys changed\n");
961 return;
962 }
963
964 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
965 if (!(keys_changed & (1 << i)))
966 continue;
967
968 input_report_key(data->input_dev, data->pdata->key_codes[i],
969 (data->keyarray_new & (1 << i)));
970 input_sync(data->input_dev);
971 }
972
973 data->keyarray_old = data->keyarray_new;
974}
975
Mohan Pallakab6acab42012-06-13 11:59:04 +0530976static void mxt_release_all(struct mxt_data *data)
977{
978 int id;
979
980 for (id = 0; id < MXT_MAX_FINGER; id++)
981 if (data->finger[id].status)
982 data->finger[id].status = MXT_RELEASE;
983
984 mxt_input_report(data, 0);
985}
986
987static void mxt_handle_touch_supression(struct mxt_data *data, u8 status)
988{
989 dev_dbg(&data->client->dev, "touch suppression\n");
990 /* release all touches */
991 if (status & MXT_TCHSUP_ACTIVE)
992 mxt_release_all(data);
993}
994
Amy Maloche434b7d82013-02-15 11:11:05 +0000995#if defined(CONFIG_SECURE_TOUCH)
996static irqreturn_t mxt_filter_interrupt(struct mxt_data *data)
997{
998 if (atomic_read(&data->st_enabled)) {
999 atomic_cmpxchg(&data->st_pending_irqs, 0, 1);
1000 complete(&data->st_completion);
1001 return IRQ_HANDLED;
1002 }
1003 return IRQ_NONE;
1004}
1005#else
1006static irqreturn_t mxt_filter_interrupt(struct mxt_data *data)
1007{
1008 return IRQ_NONE;
1009}
1010#endif
1011
Iiro Valkonen7686b102011-02-02 23:21:58 -08001012static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001013{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001014 struct mxt_data *data = dev_id;
1015 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001016 struct device *dev = &data->client->dev;
1017 int id;
1018 u8 reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001019
Nick Dyer0a4016c2012-01-18 15:17:59 +05301020 if (data->state != APPMODE) {
1021 dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
1022 return IRQ_HANDLED;
1023 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001024
Amy Maloche434b7d82013-02-15 11:11:05 +00001025 if (IRQ_HANDLED == mxt_filter_interrupt(data))
1026 goto end;
1027
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001028 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001029 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001030 dev_err(dev, "Failed to read message\n");
1031 goto end;
1032 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001033 reportid = message.reportid;
1034
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001035 if (!reportid) {
1036 dev_dbg(dev, "Report id 0 is reserved\n");
1037 continue;
1038 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001039
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001040 id = reportid - data->t9_min_reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001041
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301042 /* check whether report id is part of T9,T15 or T42*/
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001043 if (reportid >= data->t9_min_reportid &&
1044 reportid <= data->t9_max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -08001045 mxt_input_touchevent(data, &message, id);
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001046 else if (reportid >= data->t15_min_reportid &&
1047 reportid <= data->t15_max_reportid)
1048 mxt_handle_key_array(data, &message);
Mohan Pallakab6acab42012-06-13 11:59:04 +05301049 else if (reportid >= data->t42_min_reportid &&
1050 reportid <= data->t42_max_reportid)
1051 mxt_handle_touch_supression(data, message.message[0]);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001052 else
Iiro Valkonen7686b102011-02-02 23:21:58 -08001053 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001054 } while (reportid != 0xff);
1055
1056end:
1057 return IRQ_HANDLED;
1058}
1059
Iiro Valkonen7686b102011-02-02 23:21:58 -08001060static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001061{
Jing Lindc4413c2012-01-16 15:22:52 -08001062 const struct mxt_config_info *config_info = data->config_info;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001063 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001064 struct device *dev = &data->client->dev;
1065 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -08001066 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001067
Jing Lindc4413c2012-01-16 15:22:52 -08001068 if (!config_info) {
Iiro Valkonen71749f52011-02-15 13:36:52 -08001069 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
1070 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001071 }
1072
1073 for (i = 0; i < data->info.object_num; i++) {
1074 object = data->object_table + i;
1075
Iiro Valkonen7686b102011-02-02 23:21:58 -08001076 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001077 continue;
1078
Iiro Valkonen71749f52011-02-15 13:36:52 -08001079 for (j = 0; j < object->size + 1; j++) {
1080 config_offset = index + j;
Jing Lindc4413c2012-01-16 15:22:52 -08001081 if (config_offset > config_info->config_length) {
Iiro Valkonen71749f52011-02-15 13:36:52 -08001082 dev_err(dev, "Not enough config data!\n");
1083 return -EINVAL;
1084 }
Iiro Valkonen7686b102011-02-02 23:21:58 -08001085 mxt_write_object(data, object->type, j,
Jing Lindc4413c2012-01-16 15:22:52 -08001086 config_info->config[config_offset]);
Iiro Valkonen71749f52011-02-15 13:36:52 -08001087 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001088 index += object->size + 1;
1089 }
1090
1091 return 0;
1092}
1093
Iiro Valkonen7686b102011-02-02 23:21:58 -08001094static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001095{
1096 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001097 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001098 int count = 10;
1099 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001100
1101 /* Read dummy message to make high CHG pin */
1102 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001103 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001104 if (error)
1105 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001106 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001107
1108 if (!count) {
1109 dev_err(dev, "CHG pin isn't cleared\n");
1110 return -EBUSY;
1111 }
1112
1113 return 0;
1114}
1115
Iiro Valkonen7686b102011-02-02 23:21:58 -08001116static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001117{
1118 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001119 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001120 int error;
1121 u8 val;
1122
Iiro Valkonen7686b102011-02-02 23:21:58 -08001123 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001124 if (error)
1125 return error;
1126 info->family_id = val;
1127
Iiro Valkonen7686b102011-02-02 23:21:58 -08001128 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001129 if (error)
1130 return error;
1131 info->variant_id = val;
1132
Iiro Valkonen7686b102011-02-02 23:21:58 -08001133 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001134 if (error)
1135 return error;
1136 info->version = val;
1137
Iiro Valkonen7686b102011-02-02 23:21:58 -08001138 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001139 if (error)
1140 return error;
1141 info->build = val;
1142
Iiro Valkonen7686b102011-02-02 23:21:58 -08001143 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001144 if (error)
1145 return error;
1146 info->object_num = val;
1147
1148 return 0;
1149}
1150
Iiro Valkonen7686b102011-02-02 23:21:58 -08001151static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001152{
1153 int error;
1154 int i;
1155 u16 reg;
1156 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001157 u8 buf[MXT_OBJECT_SIZE];
Jing Lindc4413c2012-01-16 15:22:52 -08001158 bool found_t38 = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001159
1160 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001161 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001162
Iiro Valkonen7686b102011-02-02 23:21:58 -08001163 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
1164 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001165 if (error)
1166 return error;
1167
1168 object->type = buf[0];
1169 object->start_address = (buf[2] << 8) | buf[1];
1170 object->size = buf[3];
1171 object->instances = buf[4];
1172 object->num_report_ids = buf[5];
1173
1174 if (object->num_report_ids) {
1175 reportid += object->num_report_ids *
1176 (object->instances + 1);
1177 object->max_reportid = reportid;
1178 }
Jing Lindc4413c2012-01-16 15:22:52 -08001179
1180 /* Calculate index for config major version in config array.
1181 * Major version is the first byte in object T38.
1182 */
Jing Lin8a9472d2012-03-21 15:43:45 -07001183 if (object->type == MXT_SPT_USERDATA_T38) {
1184 data->t38_start_addr = object->start_address;
Jing Lindc4413c2012-01-16 15:22:52 -08001185 found_t38 = true;
Jing Lin8a9472d2012-03-21 15:43:45 -07001186 }
Jing Lindc4413c2012-01-16 15:22:52 -08001187 if (!found_t38 && mxt_object_writable(object->type))
1188 data->cfg_version_idx += object->size + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001189 }
1190
1191 return 0;
1192}
1193
Jing Lin8fadad72012-02-24 10:10:50 -08001194static int compare_versions(const u8 *v1, const u8 *v2)
1195{
1196 int i;
1197
1198 if (!v1 || !v2)
1199 return -EINVAL;
1200
1201 /* The major version number stays the same across different versions for
1202 * a particular controller on a target. The minor and sub-minor version
1203 * numbers indicate which version is newer.
1204 */
1205 if (v1[0] != v2[0])
1206 return -EINVAL;
1207
1208 for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
1209 if (v1[i] > v2[i])
1210 return MXT_CFG_VERSION_LESS; /* v2 is older */
1211
1212 if (v1[i] < v2[i])
1213 return MXT_CFG_VERSION_GREATER; /* v2 is newer */
1214 }
1215
1216 return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
1217}
1218
1219static void mxt_check_config_version(struct mxt_data *data,
1220 const struct mxt_config_info *cfg_info,
1221 bool match_major,
1222 const u8 **cfg_version_found,
1223 bool *found_cfg_major_match)
1224{
1225 const u8 *cfg_version;
1226 int result = -EINVAL;
1227
1228 cfg_version = cfg_info->config + data->cfg_version_idx;
1229
1230 if (*cfg_version_found)
1231 result = compare_versions(*cfg_version_found, cfg_version);
1232
1233 if (match_major) {
1234 if (result >= MXT_CFG_VERSION_EQUAL)
1235 *found_cfg_major_match = true;
1236
1237 if (result == MXT_CFG_VERSION_EQUAL ||
1238 result == MXT_CFG_VERSION_GREATER) {
1239 data->config_info = cfg_info;
1240 data->fw_name = cfg_info->fw_name;
1241 *cfg_version_found = cfg_version;
1242 }
1243
1244 if (result == MXT_CFG_VERSION_GREATER)
1245 data->update_cfg = true;
1246 } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
1247 data->config_info = cfg_info;
1248 data->fw_name = cfg_info->fw_name;
1249 data->update_cfg = true;
1250 *cfg_version_found = cfg_version;
1251 }
1252}
1253
1254/* If the controller's config version has a non-zero major number, call this
1255 * function with match_major = true to look for the latest config present in
1256 * the pdata based on matching family id, variant id, f/w version, build, and
1257 * config major number. If the controller is programmed with wrong config data
1258 * previously, call this function with match_major = false to look for latest
1259 * config based on based on matching family id, variant id, f/w version and
1260 * build only.
1261 */
1262static int mxt_search_config_array(struct mxt_data *data, bool match_major)
Jing Lindc4413c2012-01-16 15:22:52 -08001263{
1264
1265 const struct mxt_platform_data *pdata = data->pdata;
1266 const struct mxt_config_info *cfg_info;
Jing Lin8fadad72012-02-24 10:10:50 -08001267 const struct mxt_info *info = &data->info;
1268 const u8 *cfg_version_found;
1269 bool found_cfg_major_match = false;
Jing Lindc4413c2012-01-16 15:22:52 -08001270 int i;
Jing Lin8fadad72012-02-24 10:10:50 -08001271
1272 cfg_version_found = match_major ? data->cfg_version : NULL;
Jing Lindc4413c2012-01-16 15:22:52 -08001273
1274 for (i = 0; i < pdata->config_array_size; i++) {
1275
1276 cfg_info = &pdata->config_array[i];
1277
1278 if (!cfg_info->config || !cfg_info->config_length)
1279 continue;
1280
1281 if (info->family_id == cfg_info->family_id &&
1282 info->variant_id == cfg_info->variant_id &&
1283 info->version == cfg_info->version &&
1284 info->build == cfg_info->build) {
1285
Jing Lin8fadad72012-02-24 10:10:50 -08001286 mxt_check_config_version(data, cfg_info, match_major,
1287 &cfg_version_found, &found_cfg_major_match);
Jing Lindc4413c2012-01-16 15:22:52 -08001288 }
1289 }
1290
Jing Lin8fadad72012-02-24 10:10:50 -08001291 if (data->config_info || found_cfg_major_match)
1292 return 0;
1293
1294 data->config_info = NULL;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001295 data->fw_name = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001296
Jing Lindc4413c2012-01-16 15:22:52 -08001297 return -EINVAL;
1298}
1299
1300static int mxt_get_config(struct mxt_data *data)
1301{
1302 const struct mxt_platform_data *pdata = data->pdata;
1303 struct device *dev = &data->client->dev;
1304 struct mxt_object *object;
1305 int error;
1306
1307 if (!pdata->config_array || !pdata->config_array_size) {
1308 dev_dbg(dev, "No cfg data provided by platform data\n");
1309 return 0;
1310 }
1311
1312 /* Get current config version */
1313 object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
1314 if (!object) {
1315 dev_err(dev, "Unable to obtain USERDATA object\n");
1316 return -EINVAL;
1317 }
1318
Jing Lin8fadad72012-02-24 10:10:50 -08001319 error = __mxt_read_reg(data->client, object->start_address,
1320 sizeof(data->cfg_version), data->cfg_version);
Jing Lindc4413c2012-01-16 15:22:52 -08001321 if (error) {
1322 dev_err(dev, "Unable to read config version\n");
1323 return error;
1324 }
Jing Lin8fadad72012-02-24 10:10:50 -08001325 dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
1326 data->cfg_version[0], data->cfg_version[1],
1327 data->cfg_version[2]);
Jing Lindc4413c2012-01-16 15:22:52 -08001328
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301329 /* configuration update requires major match */
1330 error = mxt_search_config_array(data, true);
1331
1332 /* if no_force_update is false , try again with false
1333 as the second parameter to mxt_search_config_array */
1334 if (error && (data->no_force_update == false))
1335 error = mxt_search_config_array(data, false);
1336
Jing Lin8fadad72012-02-24 10:10:50 -08001337 if (error) {
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301338 dev_err(dev,
1339 "Unable to find matching config in pdata\n");
1340 return error;
Jing Lin8fadad72012-02-24 10:10:50 -08001341 }
Jing Lindc4413c2012-01-16 15:22:52 -08001342
1343 return 0;
1344}
Jing Lin8fadad72012-02-24 10:10:50 -08001345
Jing Lin64fdd1f2012-12-20 17:08:28 -08001346static void mxt_power_on_delay(struct mxt_data *data)
1347{
1348 const struct mxt_platform_data *pdata = data->pdata;
1349 const struct mxt_config_info *cfg_info;
1350 u32 delay = 0;
1351 int i;
1352
1353 for (i = 0; i < pdata->config_array_size; i++) {
1354 cfg_info = &pdata->config_array[i];
1355
1356 switch (cfg_info->family_id) {
1357 case MXT224_ID:
1358 delay = max_t(u32, delay, MXT224_POWER_ON_TIME);
1359 break;
1360 case MXT224E_ID:
1361 delay = max_t(u32, delay, MXT224E_POWER_ON_TIME);
1362 break;
1363 case MXT336S_ID:
1364 delay = max_t(u32, delay, MXT336S_POWER_ON_TIME);
1365 break;
1366 case MXT1386_ID:
1367 delay = max_t(u32, delay,
1368 max_t(u32, MXT1386_POWER_ON_TIME,
1369 MXT1386E_POWER_ON_TIME));
1370 break;
1371 case MXT1664S_ID:
1372 delay = max_t(u32, delay, MXT1664S_POWER_ON_TIME);
1373 break;
1374 default:
1375 delay = max_t(u32, delay, MXT_POWER_ON_TIME);
1376 }
1377 }
1378
1379 msleep(delay);
1380}
1381
Amy Maloche7e447432011-09-14 11:36:30 -07001382static void mxt_reset_delay(struct mxt_data *data)
1383{
1384 struct mxt_info *info = &data->info;
1385
1386 switch (info->family_id) {
1387 case MXT224_ID:
1388 msleep(MXT224_RESET_TIME);
1389 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -07001390 case MXT224E_ID:
1391 msleep(MXT224E_RESET_TIME);
1392 break;
Amy Maloche41f1cc32012-07-12 13:02:27 -07001393 case MXT336S_ID:
1394 msleep(MXT336S_RESET_TIME);
Jing Lin64fdd1f2012-12-20 17:08:28 -08001395 break;
Amy Maloche7e447432011-09-14 11:36:30 -07001396 case MXT1386_ID:
Jing Lin64fdd1f2012-12-20 17:08:28 -08001397 msleep(max_t(u32, MXT1386_RESET_TIME, MXT1386E_RESET_TIME));
1398 break;
Amy Maloche41f1cc32012-07-12 13:02:27 -07001399 case MXT1664S_ID:
1400 msleep(MXT1664S_RESET_TIME);
Amy Maloche7e447432011-09-14 11:36:30 -07001401 break;
1402 default:
1403 msleep(MXT_RESET_TIME);
1404 }
1405}
1406
Jing Lin8fadad72012-02-24 10:10:50 -08001407static int mxt_backup_nv(struct mxt_data *data)
1408{
1409 int error;
1410 u8 command_register;
1411 int timeout_counter = 0;
1412
1413 /* Backup to memory */
1414 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1415 MXT_COMMAND_BACKUPNV,
1416 MXT_BACKUP_VALUE);
1417 msleep(MXT_BACKUP_TIME);
1418
1419 do {
1420 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
1421 MXT_COMMAND_BACKUPNV,
1422 &command_register);
1423 if (error)
1424 return error;
1425
1426 usleep_range(1000, 2000);
1427
1428 } while ((command_register != 0) && (++timeout_counter <= 100));
1429
1430 if (timeout_counter > 100) {
1431 dev_err(&data->client->dev, "No response after backup!\n");
1432 return -EIO;
1433 }
1434
1435 /* Soft reset */
1436 mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
1437
1438 mxt_reset_delay(data);
1439
1440 return 0;
1441}
1442
Jing Lin412aedc2012-02-28 13:57:19 -08001443static int mxt_save_objects(struct mxt_data *data)
1444{
1445 struct i2c_client *client = data->client;
1446 struct mxt_object *t7_object;
1447 struct mxt_object *t9_object;
1448 struct mxt_object *t15_object;
Mohan Pallakab6acab42012-06-13 11:59:04 +05301449 struct mxt_object *t42_object;
Jing Lin412aedc2012-02-28 13:57:19 -08001450 int error;
1451
1452 /* Store T7 and T9 locally, used in suspend/resume operations */
1453 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
1454 if (!t7_object) {
1455 dev_err(&client->dev, "Failed to get T7 object\n");
1456 return -EINVAL;
1457 }
1458
1459 data->t7_start_addr = t7_object->start_address;
1460 error = __mxt_read_reg(client, data->t7_start_addr,
1461 T7_DATA_SIZE, data->t7_data);
1462 if (error < 0) {
1463 dev_err(&client->dev,
1464 "Failed to save current power state\n");
1465 return error;
1466 }
1467
Jing Lin412aedc2012-02-28 13:57:19 -08001468 /* Store T9, T15's min and max report ids */
1469 t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1470 if (!t9_object) {
1471 dev_err(&client->dev, "Failed to get T9 object\n");
1472 return -EINVAL;
1473 }
1474 data->t9_max_reportid = t9_object->max_reportid;
1475 data->t9_min_reportid = t9_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001476 (t9_object->num_report_ids *
1477 (t9_object->instances + 1)) + 1;
Jing Lin412aedc2012-02-28 13:57:19 -08001478
1479 if (data->pdata->key_codes) {
1480 t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
1481 if (!t15_object)
1482 dev_dbg(&client->dev, "T15 object is not available\n");
1483 else {
1484 data->t15_max_reportid = t15_object->max_reportid;
1485 data->t15_min_reportid = t15_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001486 (t15_object->num_report_ids *
1487 (t15_object->instances + 1)) + 1;
Jing Lin412aedc2012-02-28 13:57:19 -08001488 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001489 }
1490
Mohan Pallakab6acab42012-06-13 11:59:04 +05301491 /* Store T42 min and max report ids */
1492 t42_object = mxt_get_object(data, MXT_PROCI_TOUCHSUPPRESSION_T42);
1493 if (!t42_object)
1494 dev_dbg(&client->dev, "T42 object is not available\n");
1495 else {
1496 data->t42_max_reportid = t42_object->max_reportid;
1497 data->t42_min_reportid = t42_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001498 (t42_object->num_report_ids *
1499 (t42_object->instances + 1)) + 1;
Mohan Pallakab6acab42012-06-13 11:59:04 +05301500 }
1501
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001502 return 0;
1503}
1504
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301505static int mxt_update_cfg(struct mxt_data *data)
1506{
1507 int error;
1508 const u8 *cfg_ver;
1509
1510 /* Get config data from platform data */
1511 error = mxt_get_config(data);
1512 if (error)
1513 dev_dbg(&data->client->dev, "Config info not found.\n");
1514
1515 /* Check register init values */
1516 if (data->config_info && data->config_info->config) {
1517 if (data->update_cfg) {
1518 error = mxt_check_reg_init(data);
1519 if (error) {
1520 dev_err(&data->client->dev,
1521 "Failed to check reg init value\n");
1522 return error;
1523 }
1524
1525 error = mxt_backup_nv(data);
1526 if (error) {
1527 dev_err(&data->client->dev, "Failed to back up NV\n");
1528 return error;
1529 }
1530
1531 cfg_ver = data->config_info->config +
1532 data->cfg_version_idx;
1533 dev_info(&data->client->dev,
1534 "Config updated from %d.%d.%d to %d.%d.%d\n",
1535 data->cfg_version[0], data->cfg_version[1],
1536 data->cfg_version[2],
1537 cfg_ver[0], cfg_ver[1], cfg_ver[2]);
1538
1539 memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
1540 }
1541 } else {
1542 dev_info(&data->client->dev,
1543 "No cfg data defined, skipping check reg init\n");
1544 }
1545
1546 error = mxt_save_objects(data);
1547 if (error)
1548 return error;
1549
1550 return 0;
1551}
1552
1553
1554
Iiro Valkonen7686b102011-02-02 23:21:58 -08001555static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001556{
1557 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001558 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001559 int error;
1560 u8 val;
1561
Iiro Valkonen7686b102011-02-02 23:21:58 -08001562 error = mxt_get_info(data);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301563 if (error) {
1564 /* Try bootloader mode */
1565 error = mxt_switch_to_bootloader_address(data);
1566 if (error)
1567 return error;
1568
1569 error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
1570 if (error)
1571 return error;
1572
1573 dev_err(&client->dev, "Application CRC failure\n");
1574 data->state = BOOTLOADER;
1575
1576 return 0;
1577 }
1578
1579 dev_info(&client->dev,
1580 "Family ID: %d Variant ID: %d Version: %d.%d "
1581 "Build: 0x%02X Object Num: %d\n",
1582 info->family_id, info->variant_id,
1583 info->version >> 4, info->version & 0xf,
1584 info->build, info->object_num);
1585
1586 data->state = APPMODE;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001587
1588 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001589 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001590 GFP_KERNEL);
1591 if (!data->object_table) {
1592 dev_err(&client->dev, "Failed to allocate memory\n");
1593 return -ENOMEM;
1594 }
1595
1596 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001597 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001598 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001599 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001600
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301601 error = mxt_update_cfg(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001602 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001603 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001604 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001605 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001606 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001607 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001608 info->matrix_xsize = val;
1609
Iiro Valkonen7686b102011-02-02 23:21:58 -08001610 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001611 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001612 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001613 info->matrix_ysize = val;
1614
1615 dev_info(&client->dev,
Nick Dyer0a4016c2012-01-18 15:17:59 +05301616 "Matrix X Size: %d Matrix Y Size: %d\n",
1617 info->matrix_xsize, info->matrix_ysize);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001618
1619 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001620
Jing Lin32c72532011-11-03 12:02:33 -07001621free_object_table:
1622 kfree(data->object_table);
1623 return error;
Joonyoung Shim910d8052011-04-12 23:14:38 -07001624}
1625
Iiro Valkonen7686b102011-02-02 23:21:58 -08001626static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001627 struct device_attribute *attr, char *buf)
1628{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001629 struct mxt_data *data = dev_get_drvdata(dev);
1630 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001631 int count = 0;
1632 int i, j;
1633 int error;
1634 u8 val;
1635
1636 for (i = 0; i < data->info.object_num; i++) {
1637 object = data->object_table + i;
1638
Daniel Kurtz626af862011-10-06 15:43:20 -07001639 count += snprintf(buf + count, PAGE_SIZE - count,
1640 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001641 i + 1, object->type);
Daniel Kurtz626af862011-10-06 15:43:20 -07001642 if (count >= PAGE_SIZE)
1643 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001644
Iiro Valkonen7686b102011-02-02 23:21:58 -08001645 if (!mxt_object_readable(object->type)) {
Daniel Kurtz626af862011-10-06 15:43:20 -07001646 count += snprintf(buf + count, PAGE_SIZE - count,
1647 "\n");
1648 if (count >= PAGE_SIZE)
1649 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001650 continue;
1651 }
1652
1653 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001654 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001655 object->type, j, &val);
1656 if (error)
1657 return error;
1658
Daniel Kurtz626af862011-10-06 15:43:20 -07001659 count += snprintf(buf + count, PAGE_SIZE - count,
1660 "\t[%2d]: %02x (%d)\n", j, val, val);
1661 if (count >= PAGE_SIZE)
1662 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001663 }
1664
Daniel Kurtz626af862011-10-06 15:43:20 -07001665 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1666 if (count >= PAGE_SIZE)
1667 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001668 }
1669
1670 return count;
1671}
1672
Jing Lincc974cb2012-02-01 23:13:14 -08001673static int strtobyte(const char *data, u8 *value)
1674{
1675 char str[3];
1676
1677 str[0] = data[0];
1678 str[1] = data[1];
1679 str[2] = '\0';
1680
1681 return kstrtou8(str, 16, value);
1682}
1683
Iiro Valkonen7686b102011-02-02 23:21:58 -08001684static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001685{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001686 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001687 struct i2c_client *client = data->client;
1688 const struct firmware *fw = NULL;
1689 unsigned int frame_size;
Nick Dyer0a4016c2012-01-18 15:17:59 +05301690 unsigned int retry = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001691 unsigned int pos = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001692 int ret, i, max_frame_size;
1693 u8 *frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001694
Jing Lincc974cb2012-02-01 23:13:14 -08001695 switch (data->info.family_id) {
1696 case MXT224_ID:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301697 case MXT224E_ID:
Jing Lincc974cb2012-02-01 23:13:14 -08001698 max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
1699 break;
1700 case MXT1386_ID:
1701 max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
1702 break;
1703 default:
1704 return -EINVAL;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001705 }
1706
Jing Lincc974cb2012-02-01 23:13:14 -08001707 frame = kmalloc(max_frame_size, GFP_KERNEL);
1708 if (!frame) {
1709 dev_err(dev, "Unable to allocate memory for frame data\n");
1710 return -ENOMEM;
1711 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001712
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001713 ret = request_firmware(&fw, fn, dev);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301714 if (ret < 0) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001715 dev_err(dev, "Unable to open firmware %s\n", fn);
Jing Lincc974cb2012-02-01 23:13:14 -08001716 goto free_frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001717 }
1718
Nick Dyer0a4016c2012-01-18 15:17:59 +05301719 if (data->state != BOOTLOADER) {
1720 /* Change to the bootloader mode */
1721 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1722 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1723 mxt_reset_delay(data);
Amy Maloche7e447432011-09-14 11:36:30 -07001724
Nick Dyer0a4016c2012-01-18 15:17:59 +05301725 ret = mxt_switch_to_bootloader_address(data);
1726 if (ret)
1727 goto release_firmware;
1728 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001729
Iiro Valkonen7686b102011-02-02 23:21:58 -08001730 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301731 if (ret) {
1732 /* Bootloader may still be unlocked from previous update
1733 * attempt */
1734 ret = mxt_check_bootloader(client,
1735 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001736
Nick Dyer0a4016c2012-01-18 15:17:59 +05301737 if (ret)
1738 goto return_to_app_mode;
1739 } else {
1740 dev_info(dev, "Unlocking bootloader\n");
1741 /* Unlock bootloader */
1742 mxt_unlock_bootloader(client);
1743 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001744
1745 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001746 ret = mxt_check_bootloader(client,
1747 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001748 if (ret)
Nick Dyer0a4016c2012-01-18 15:17:59 +05301749 goto release_firmware;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001750
Jing Lincc974cb2012-02-01 23:13:14 -08001751 /* Get frame length MSB */
1752 ret = strtobyte(fw->data + pos, frame);
1753 if (ret)
1754 goto release_firmware;
1755
1756 /* Get frame length LSB */
1757 ret = strtobyte(fw->data + pos + 2, frame + 1);
1758 if (ret)
1759 goto release_firmware;
1760
1761 frame_size = ((*frame << 8) | *(frame + 1));
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001762
1763 /* We should add 2 at frame size as the the firmware data is not
1764 * included the CRC bytes.
1765 */
1766 frame_size += 2;
1767
Jing Lincc974cb2012-02-01 23:13:14 -08001768 if (frame_size > max_frame_size) {
1769 dev_err(dev, "Invalid frame size - %d\n", frame_size);
1770 ret = -EINVAL;
1771 goto release_firmware;
1772 }
1773
1774 /* Convert frame data and CRC from hex to binary */
1775 for (i = 2; i < frame_size; i++) {
1776 ret = strtobyte(fw->data + pos + i * 2, frame + i);
1777 if (ret)
1778 goto release_firmware;
1779 }
1780
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001781 /* Write one frame to device */
Jing Lincc974cb2012-02-01 23:13:14 -08001782 mxt_fw_write(client, frame, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001783
Iiro Valkonen7686b102011-02-02 23:21:58 -08001784 ret = mxt_check_bootloader(client,
1785 MXT_FRAME_CRC_PASS);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301786 if (ret) {
1787 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001788
Nick Dyer0a4016c2012-01-18 15:17:59 +05301789 /* Back off by 20ms per retry */
1790 msleep(retry * 20);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001791
Nick Dyer0a4016c2012-01-18 15:17:59 +05301792 if (retry > 20)
1793 goto release_firmware;
1794 } else {
1795 retry = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001796 pos += frame_size * 2;
1797 dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301798 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001799 }
1800
Nick Dyer0a4016c2012-01-18 15:17:59 +05301801return_to_app_mode:
1802 mxt_switch_to_appmode_address(data);
1803release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001804 release_firmware(fw);
Jing Lincc974cb2012-02-01 23:13:14 -08001805free_frame:
1806 kfree(frame);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001807
1808 return ret;
1809}
1810
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001811static const char *
1812mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
1813{
1814 const struct mxt_platform_data *pdata = data->pdata;
1815 const struct mxt_config_info *cfg_info;
1816 const char *fw_name = NULL;
1817 int i;
1818
1819 for (i = 0; i < pdata->config_array_size; i++) {
1820 cfg_info = &pdata->config_array[i];
1821 if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
1822 data->config_info = cfg_info;
1823 data->info.family_id = cfg_info->family_id;
1824 fw_name = cfg_info->fw_name;
1825 }
1826 }
1827
1828 return fw_name;
1829}
1830
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301831static ssize_t mxt_force_cfg_update_store(struct device *dev,
1832 struct device_attribute *attr,
1833 const char *buf, size_t count)
1834{
1835 struct mxt_data *data = dev_get_drvdata(dev);
1836 int flag = buf[0]-'0';
1837 int error;
1838 data->no_force_update = !flag;
1839
1840 if (data->state == APPMODE) {
1841 disable_irq(data->irq);
1842 error = mxt_update_cfg(data);
1843 enable_irq(data->irq);
1844 if (error)
1845 return error;
1846 } else {
1847 dev_err(dev,
1848 "Not in APPMODE, Unable to force cfg update\n");
1849 return -EINVAL;
1850 }
1851
1852 return count;
1853}
1854
Iiro Valkonen7686b102011-02-02 23:21:58 -08001855static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001856 struct device_attribute *attr,
1857 const char *buf, size_t count)
1858{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001859 struct mxt_data *data = dev_get_drvdata(dev);
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301860 int error, address;
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001861 const char *fw_name;
1862 u8 bootldr_id;
Jing Lin8a9472d2012-03-21 15:43:45 -07001863 u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001864
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301865 data->no_force_update = false;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001866 /* If fw_name is set, then the existing firmware has an upgrade */
1867 if (!data->fw_name) {
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001868 /*
1869 * If the device boots up in the bootloader mode, check if
1870 * there is a firmware to upgrade.
1871 */
1872 if (data->state == BOOTLOADER) {
1873 bootldr_id = mxt_get_bootloader_id(data->client);
1874 if (bootldr_id <= 0) {
1875 dev_err(dev,
1876 "Unable to retrieve bootloader id\n");
1877 return -EINVAL;
1878 }
1879 fw_name = mxt_search_fw_name(data, bootldr_id);
1880 if (fw_name == NULL) {
1881 dev_err(dev,
1882 "Unable to find fw from bootloader id\n");
1883 return -EINVAL;
1884 }
1885 } else {
1886 /* In APPMODE, if the f/w name does not exist, quit */
1887 dev_err(dev,
1888 "Firmware name not specified in platform data\n");
1889 return -EINVAL;
1890 }
1891 } else {
1892 fw_name = data->fw_name;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001893 }
1894
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001895 dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001896
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001897 disable_irq(data->irq);
1898
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001899 error = mxt_load_fw(dev, fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001900 if (error) {
1901 dev_err(dev, "The firmware update failed(%d)\n", error);
1902 count = error;
1903 } else {
Nick Dyer0a4016c2012-01-18 15:17:59 +05301904 dev_info(dev, "The firmware update succeeded\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001905
1906 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001907 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001908
Nick Dyer0a4016c2012-01-18 15:17:59 +05301909 data->state = INIT;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001910 kfree(data->object_table);
1911 data->object_table = NULL;
Jing Lincc974cb2012-02-01 23:13:14 -08001912 data->cfg_version_idx = 0;
Jing Lina962ba32012-12-03 09:46:33 -08001913 data->config_info = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001914 data->update_cfg = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001915
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301916 /* T38 object address might have changed, read it from
1917 touch controller */
1918 address = mxt_get_object_address(dev, MXT_SPT_USERDATA_T38);
1919 if (address < 0) {
1920 dev_err(dev, "T38 required for touch operation\n");
1921 return -EINVAL;
1922 }
1923
1924 data->t38_start_addr = address;
1925
Jing Lin8a9472d2012-03-21 15:43:45 -07001926 error = __mxt_write_reg(data->client, data->t38_start_addr,
1927 sizeof(cfg_version), cfg_version);
1928 if (error)
1929 dev_err(dev,
1930 "Unable to zero out config version after fw upgrade\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001931
Iiro Valkonen7686b102011-02-02 23:21:58 -08001932 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001933 }
1934
Nick Dyer0a4016c2012-01-18 15:17:59 +05301935 if (data->state == APPMODE) {
1936 enable_irq(data->irq);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001937
Nick Dyer0a4016c2012-01-18 15:17:59 +05301938 error = mxt_make_highchg(data);
1939 if (error)
1940 return error;
1941 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07001942
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001943 return count;
1944}
1945
Amy Maloche434b7d82013-02-15 11:11:05 +00001946#if defined(CONFIG_SECURE_TOUCH)
1947
1948static ssize_t mxt_secure_touch_enable_show(struct device *dev,
1949 struct device_attribute *attr, char *buf)
1950{
1951 struct mxt_data *data = dev_get_drvdata(dev);
1952 return scnprintf(buf, PAGE_SIZE, "%d", atomic_read(&data->st_enabled));
1953}
1954/*
1955 * Accept only "0" and "1" valid values.
1956 * "0" will reset the st_enabled flag, then wake up the reading process.
1957 * The bus driver is notified via pm_runtime that it is not required to stay
1958 * awake anymore.
1959 * It will also make sure the queue of events is emptied in the controller,
1960 * in case a touch happened in between the secure touch being disabled and
1961 * the local ISR being ungated.
1962 * "1" will set the st_enabled flag and clear the st_pending_irqs flag.
1963 * The bus driver is requested via pm_runtime to stay awake.
1964 */
1965static ssize_t mxt_secure_touch_enable_store(struct device *dev,
1966 struct device_attribute *attr,
1967 const char *buf, size_t count)
1968{
1969 struct mxt_data *data = dev_get_drvdata(dev);
1970 unsigned long value;
1971 int err = 0;
1972
1973 if (count > 2)
1974 return -EINVAL;
1975
1976 err = kstrtoul(buf, 10, &value);
1977 if (err != 0)
1978 return err;
1979
1980 err = count;
1981
1982 switch (value) {
1983 case 0:
1984 if (atomic_read(&data->st_enabled) == 0)
1985 break;
1986
1987 pm_runtime_put(&data->client->adapter->dev);
1988 atomic_set(&data->st_enabled, 0);
1989 complete(&data->st_completion);
1990 mxt_interrupt(data->client->irq, data);
1991 break;
1992 case 1:
1993 if (atomic_read(&data->st_enabled)) {
1994 err = -EBUSY;
1995 break;
1996 }
1997
1998 if (pm_runtime_get(data->client->adapter->dev.parent) < 0) {
1999 dev_err(&data->client->dev, "pm_runtime_get failed\n");
2000 err = -EIO;
2001 break;
2002 }
2003 atomic_set(&data->st_pending_irqs, 0);
2004 atomic_set(&data->st_enabled, 1);
2005 break;
2006 default:
2007 dev_err(&data->client->dev, "unsupported value: %lu\n", value);
2008 err = -EINVAL;
2009 break;
2010 }
2011
2012 return err;
2013}
2014
2015static ssize_t mxt_secure_touch_show(struct device *dev,
2016 struct device_attribute *attr, char *buf)
2017{
2018 struct mxt_data *data = dev_get_drvdata(dev);
2019 int err;
2020
2021 if (atomic_read(&data->st_enabled) == 0)
2022 return -EBADF;
2023
2024 err = wait_for_completion_interruptible(&data->st_completion);
2025
2026 if (err)
2027 return err;
2028
2029 if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) != 1)
2030 return -EBADF;
2031
2032 return scnprintf(buf, PAGE_SIZE, "%u", 1);
2033}
2034
2035static DEVICE_ATTR(secure_touch_enable, 0666, mxt_secure_touch_enable_show,
2036 mxt_secure_touch_enable_store);
2037static DEVICE_ATTR(secure_touch, 0444, mxt_secure_touch_show, NULL);
2038#endif
2039
Iiro Valkonen7686b102011-02-02 23:21:58 -08002040static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
2041static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302042static DEVICE_ATTR(force_cfg_update, 0664, NULL, mxt_force_cfg_update_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002043
Iiro Valkonen7686b102011-02-02 23:21:58 -08002044static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002045 &dev_attr_object.attr,
2046 &dev_attr_update_fw.attr,
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302047 &dev_attr_force_cfg_update.attr,
Amy Maloche434b7d82013-02-15 11:11:05 +00002048#if defined(CONFIG_SECURE_TOUCH)
2049 &dev_attr_secure_touch_enable.attr,
2050 &dev_attr_secure_touch.attr,
2051#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002052 NULL
2053};
2054
Iiro Valkonen7686b102011-02-02 23:21:58 -08002055static const struct attribute_group mxt_attr_group = {
2056 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002057};
2058
Amy Maloche52262212011-09-15 16:46:57 -07002059static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002060{
Jing Lin36aee812011-10-17 17:17:28 -07002061 int error;
2062
Amy Maloche52262212011-09-15 16:46:57 -07002063 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07002064 error = __mxt_write_reg(data->client, data->t7_start_addr,
2065 T7_DATA_SIZE, data->t7_data);
2066 if (error < 0) {
2067 dev_err(&data->client->dev,
2068 "failed to restore old power state\n");
2069 return error;
Amy Maloche52262212011-09-15 16:46:57 -07002070 }
Jing Lin36aee812011-10-17 17:17:28 -07002071
Amy Maloche52262212011-09-15 16:46:57 -07002072 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002073}
2074
Amy Maloche52262212011-09-15 16:46:57 -07002075static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002076{
Jing Lin36aee812011-10-17 17:17:28 -07002077 int error;
2078 u8 t7_data[T7_DATA_SIZE] = {0};
2079
Jing Lin36aee812011-10-17 17:17:28 -07002080 error = __mxt_write_reg(data->client, data->t7_start_addr,
2081 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07002082 if (error < 0) {
2083 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07002084 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07002085 return error;
2086 }
2087
2088 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002089}
2090
Iiro Valkonen7686b102011-02-02 23:21:58 -08002091static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002092{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002093 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07002094 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002095
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08002096 if (data->state == APPMODE) {
2097 error = mxt_start(data);
2098 if (error < 0) {
2099 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
2100 return error;
2101 }
Amy Maloche52262212011-09-15 16:46:57 -07002102 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002103
2104 return 0;
2105}
2106
Iiro Valkonen7686b102011-02-02 23:21:58 -08002107static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002108{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002109 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07002110 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002111
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08002112 if (data->state == APPMODE) {
2113 error = mxt_stop(data);
2114 if (error < 0)
2115 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
2116 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002117}
2118
Amy Malochec331f842012-01-24 10:33:47 -08002119static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
2120{
2121 return (regulator_count_voltages(reg) > 0) ?
2122 regulator_set_optimum_mode(reg, load_uA) : 0;
2123}
2124
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302125static int mxt_power_on(struct mxt_data *data, bool on)
2126{
2127 int rc;
2128
2129 if (on == false)
2130 goto power_off;
2131
Amy Malochec331f842012-01-24 10:33:47 -08002132 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302133 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07002134 dev_err(&data->client->dev,
2135 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302136 return rc;
2137 }
2138
Amy Maloche21115eb2011-11-02 09:04:37 -07002139 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302140 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07002141 dev_err(&data->client->dev,
2142 "Regulator vcc_ana enable failed rc=%d\n", rc);
2143 goto error_reg_en_vcc_ana;
2144 }
2145
2146 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002147 rc = reg_set_optimum_mode_check(data->vcc_dig,
2148 MXT_ACTIVE_LOAD_DIG_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002149 if (rc < 0) {
2150 dev_err(&data->client->dev,
2151 "Regulator vcc_dig set_opt failed rc=%d\n",
2152 rc);
2153 goto error_reg_opt_vcc_dig;
2154 }
2155
2156 rc = regulator_enable(data->vcc_dig);
2157 if (rc) {
2158 dev_err(&data->client->dev,
2159 "Regulator vcc_dig enable failed rc=%d\n", rc);
2160 goto error_reg_en_vcc_dig;
2161 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302162 }
2163
2164 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002165 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302166 if (rc < 0) {
2167 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002168 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302169 goto error_reg_opt_i2c;
2170 }
2171
2172 rc = regulator_enable(data->vcc_i2c);
2173 if (rc) {
2174 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002175 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302176 goto error_reg_en_vcc_i2c;
2177 }
2178 }
2179
Amy Malochef0d7b8d2011-10-17 12:10:51 -07002180 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302181
2182 return 0;
2183
2184error_reg_en_vcc_i2c:
2185 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002186 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302187error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07002188 if (data->pdata->digital_pwr_regulator)
2189 regulator_disable(data->vcc_dig);
2190error_reg_en_vcc_dig:
2191 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002192 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002193error_reg_opt_vcc_dig:
2194 regulator_disable(data->vcc_ana);
2195error_reg_en_vcc_ana:
Amy Malochec331f842012-01-24 10:33:47 -08002196 reg_set_optimum_mode_check(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302197 return rc;
2198
2199power_off:
Amy Malochec331f842012-01-24 10:33:47 -08002200 reg_set_optimum_mode_check(data->vcc_ana, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002201 regulator_disable(data->vcc_ana);
2202 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002203 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002204 regulator_disable(data->vcc_dig);
2205 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302206 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002207 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302208 regulator_disable(data->vcc_i2c);
2209 }
2210 msleep(50);
2211 return 0;
2212}
2213
2214static int mxt_regulator_configure(struct mxt_data *data, bool on)
2215{
2216 int rc;
2217
2218 if (on == false)
2219 goto hw_shutdown;
2220
Amy Maloche21115eb2011-11-02 09:04:37 -07002221 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
2222 if (IS_ERR(data->vcc_ana)) {
2223 rc = PTR_ERR(data->vcc_ana);
2224 dev_err(&data->client->dev,
2225 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302226 return rc;
2227 }
2228
Amy Maloche21115eb2011-11-02 09:04:37 -07002229 if (regulator_count_voltages(data->vcc_ana) > 0) {
2230 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302231 MXT_VTG_MAX_UV);
2232 if (rc) {
2233 dev_err(&data->client->dev,
2234 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07002235 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302236 }
2237 }
Amy Maloche21115eb2011-11-02 09:04:37 -07002238 if (data->pdata->digital_pwr_regulator) {
2239 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
2240 if (IS_ERR(data->vcc_dig)) {
2241 rc = PTR_ERR(data->vcc_dig);
2242 dev_err(&data->client->dev,
2243 "Regulator get dig failed rc=%d\n", rc);
2244 goto error_get_vtg_vcc_dig;
2245 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302246
Amy Maloche21115eb2011-11-02 09:04:37 -07002247 if (regulator_count_voltages(data->vcc_dig) > 0) {
2248 rc = regulator_set_voltage(data->vcc_dig,
2249 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
2250 if (rc) {
2251 dev_err(&data->client->dev,
2252 "regulator set_vtg failed rc=%d\n", rc);
2253 goto error_set_vtg_vcc_dig;
2254 }
2255 }
2256 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302257 if (data->pdata->i2c_pull_up) {
2258 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
2259 if (IS_ERR(data->vcc_i2c)) {
2260 rc = PTR_ERR(data->vcc_i2c);
2261 dev_err(&data->client->dev,
2262 "Regulator get failed rc=%d\n", rc);
2263 goto error_get_vtg_i2c;
2264 }
2265 if (regulator_count_voltages(data->vcc_i2c) > 0) {
2266 rc = regulator_set_voltage(data->vcc_i2c,
2267 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
2268 if (rc) {
2269 dev_err(&data->client->dev,
2270 "regulator set_vtg failed rc=%d\n", rc);
2271 goto error_set_vtg_i2c;
2272 }
2273 }
2274 }
2275
2276 return 0;
2277
2278error_set_vtg_i2c:
2279 regulator_put(data->vcc_i2c);
2280error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07002281 if (data->pdata->digital_pwr_regulator)
2282 if (regulator_count_voltages(data->vcc_dig) > 0)
2283 regulator_set_voltage(data->vcc_dig, 0,
2284 MXT_VTG_DIG_MAX_UV);
2285error_set_vtg_vcc_dig:
2286 if (data->pdata->digital_pwr_regulator)
2287 regulator_put(data->vcc_dig);
2288error_get_vtg_vcc_dig:
2289 if (regulator_count_voltages(data->vcc_ana) > 0)
2290 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2291error_set_vtg_vcc_ana:
2292 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302293 return rc;
2294
2295hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07002296 if (regulator_count_voltages(data->vcc_ana) > 0)
2297 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2298 regulator_put(data->vcc_ana);
2299 if (data->pdata->digital_pwr_regulator) {
2300 if (regulator_count_voltages(data->vcc_dig) > 0)
2301 regulator_set_voltage(data->vcc_dig, 0,
2302 MXT_VTG_DIG_MAX_UV);
2303 regulator_put(data->vcc_dig);
2304 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302305 if (data->pdata->i2c_pull_up) {
2306 if (regulator_count_voltages(data->vcc_i2c) > 0)
2307 regulator_set_voltage(data->vcc_i2c, 0,
2308 MXT_I2C_VTG_MAX_UV);
2309 regulator_put(data->vcc_i2c);
2310 }
2311 return 0;
2312}
2313
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302314#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07002315static int mxt_regulator_lpm(struct mxt_data *data, bool on)
2316{
2317
2318 int rc;
2319
2320 if (on == false)
2321 goto regulator_hpm;
2322
Amy Malochec331f842012-01-24 10:33:47 -08002323 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002324 if (rc < 0) {
2325 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002326 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002327 goto fail_regulator_lpm;
2328 }
2329
Amy Maloche21115eb2011-11-02 09:04:37 -07002330 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002331 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002332 MXT_LPM_LOAD_DIG_UA);
2333 if (rc < 0) {
2334 dev_err(&data->client->dev,
2335 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2336 goto fail_regulator_lpm;
2337 }
2338 }
2339
Jing Linbace50b2011-10-18 22:55:47 -07002340 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002341 rc = reg_set_optimum_mode_check(data->vcc_i2c,
Jing Linbace50b2011-10-18 22:55:47 -07002342 MXT_I2C_LPM_LOAD_UA);
2343 if (rc < 0) {
2344 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002345 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002346 goto fail_regulator_lpm;
2347 }
2348 }
2349
2350 return 0;
2351
2352regulator_hpm:
2353
Amy Malochec331f842012-01-24 10:33:47 -08002354 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002355 if (rc < 0) {
2356 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002357 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002358 goto fail_regulator_hpm;
2359 }
2360
Amy Maloche21115eb2011-11-02 09:04:37 -07002361 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002362 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002363 MXT_ACTIVE_LOAD_DIG_UA);
2364 if (rc < 0) {
2365 dev_err(&data->client->dev,
2366 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2367 goto fail_regulator_hpm;
2368 }
2369 }
2370
Jing Linbace50b2011-10-18 22:55:47 -07002371 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002372 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002373 if (rc < 0) {
2374 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002375 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002376 goto fail_regulator_hpm;
2377 }
2378 }
2379
2380 return 0;
2381
2382fail_regulator_lpm:
Amy Malochec331f842012-01-24 10:33:47 -08002383 reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002384 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002385 reg_set_optimum_mode_check(data->vcc_dig,
2386 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002387 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002388 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002389
2390 return rc;
2391
2392fail_regulator_hpm:
Amy Malochec331f842012-01-24 10:33:47 -08002393 reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002394 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002395 reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002396 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002397 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002398
2399 return rc;
2400}
2401
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302402static int mxt_suspend(struct device *dev)
2403{
2404 struct i2c_client *client = to_i2c_client(dev);
2405 struct mxt_data *data = i2c_get_clientdata(client);
2406 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002407 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302408
2409 mutex_lock(&input_dev->mutex);
2410
Amy Maloche52262212011-09-15 16:46:57 -07002411 if (input_dev->users) {
2412 error = mxt_stop(data);
2413 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002414 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07002415 mutex_unlock(&input_dev->mutex);
2416 return error;
2417 }
2418
2419 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302420
2421 mutex_unlock(&input_dev->mutex);
2422
Jing Linbace50b2011-10-18 22:55:47 -07002423 /* put regulators in low power mode */
2424 error = mxt_regulator_lpm(data, true);
2425 if (error < 0) {
2426 dev_err(dev, "failed to enter low power mode\n");
2427 return error;
2428 }
2429
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302430 return 0;
2431}
2432
2433static int mxt_resume(struct device *dev)
2434{
2435 struct i2c_client *client = to_i2c_client(dev);
2436 struct mxt_data *data = i2c_get_clientdata(client);
2437 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002438 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302439
Jing Linbace50b2011-10-18 22:55:47 -07002440 /* put regulators in high power mode */
2441 error = mxt_regulator_lpm(data, false);
2442 if (error < 0) {
2443 dev_err(dev, "failed to enter high power mode\n");
2444 return error;
2445 }
2446
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302447 mutex_lock(&input_dev->mutex);
2448
Amy Maloche52262212011-09-15 16:46:57 -07002449 if (input_dev->users) {
2450 error = mxt_start(data);
2451 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002452 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07002453 mutex_unlock(&input_dev->mutex);
2454 return error;
2455 }
2456 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302457
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302458 /* calibrate */
2459 if (data->pdata->need_calibration) {
2460 error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
2461 MXT_COMMAND_CALIBRATE, 1);
2462 if (error < 0)
2463 dev_dbg(dev, "sending calibration command failed\n");
2464 }
2465
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302466 mutex_unlock(&input_dev->mutex);
2467
2468 return 0;
2469}
2470
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302471static const struct dev_pm_ops mxt_pm_ops = {
Anurag Singh49d76132013-01-29 12:07:00 -08002472#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302473 .suspend = mxt_suspend,
2474 .resume = mxt_resume,
2475#endif
2476};
2477#endif
2478
Jing Lin6cfc00e2011-11-02 15:15:30 -07002479static int mxt_debugfs_object_show(struct seq_file *m, void *v)
2480{
2481 struct mxt_data *data = m->private;
2482 struct mxt_object *object;
2483 struct device *dev = &data->client->dev;
2484 int i, j, k;
2485 int error;
2486 int obj_size;
2487 u8 val;
2488
2489 for (i = 0; i < data->info.object_num; i++) {
2490 object = data->object_table + i;
2491 obj_size = object->size + 1;
2492
2493 seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
2494
2495 for (j = 0; j < object->instances + 1; j++) {
2496 seq_printf(m, "[Instance %d]\n", j);
2497
2498 for (k = 0; k < obj_size; k++) {
2499 error = mxt_read_object(data, object->type,
2500 j * obj_size + k, &val);
2501 if (error) {
2502 dev_err(dev,
2503 "Failed to read object %d "
2504 "instance %d at offset %d\n",
2505 object->type, j, k);
2506 return error;
2507 }
2508
2509 seq_printf(m, "Byte %d: 0x%02x (%d)\n",
2510 k, val, val);
2511 }
2512 }
2513 }
2514
2515 return 0;
2516}
2517
2518static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
2519{
2520 return single_open(file, mxt_debugfs_object_show, inode->i_private);
2521}
2522
2523static const struct file_operations mxt_object_fops = {
2524 .owner = THIS_MODULE,
2525 .open = mxt_debugfs_object_open,
2526 .read = seq_read,
2527 .release = single_release,
2528};
2529
Stephen Boyd0d578692012-04-25 11:49:18 -07002530static void __devinit mxt_debugfs_init(struct mxt_data *data)
Jing Lin6cfc00e2011-11-02 15:15:30 -07002531{
2532 debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
2533 if (IS_ERR_OR_NULL(debug_base))
2534 pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
2535 if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
2536 0444,
2537 debug_base,
2538 data,
2539 &mxt_object_fops))) {
2540 pr_err("atmel_mxt_ts: Failed to create object file\n");
2541 debugfs_remove_recursive(debug_base);
2542 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002543}
2544
Mohan Pallakad96f5032012-06-18 22:49:10 +05302545#ifdef CONFIG_OF
2546static int mxt_get_dt_coords(struct device *dev, char *name,
2547 struct mxt_platform_data *pdata)
2548{
2549 u32 coords[MXT_COORDS_ARR_SIZE];
2550 struct property *prop;
2551 struct device_node *np = dev->of_node;
2552 int coords_size, rc;
2553
2554 prop = of_find_property(np, name, NULL);
2555 if (!prop)
2556 return -EINVAL;
2557 if (!prop->value)
2558 return -ENODATA;
2559
2560 coords_size = prop->length / sizeof(u32);
2561 if (coords_size != MXT_COORDS_ARR_SIZE) {
2562 dev_err(dev, "invalid %s\n", name);
2563 return -EINVAL;
2564 }
2565
2566 rc = of_property_read_u32_array(np, name, coords, coords_size);
2567 if (rc && (rc != -EINVAL)) {
2568 dev_err(dev, "Unable to read %s\n", name);
2569 return rc;
2570 }
2571
2572 if (strncmp(name, "atmel,panel-coords",
2573 sizeof("atmel,panel-coords")) == 0) {
2574 pdata->panel_minx = coords[0];
2575 pdata->panel_miny = coords[1];
2576 pdata->panel_maxx = coords[2];
2577 pdata->panel_maxy = coords[3];
2578 } else if (strncmp(name, "atmel,display-coords",
2579 sizeof("atmel,display-coords")) == 0) {
2580 pdata->disp_minx = coords[0];
2581 pdata->disp_miny = coords[1];
2582 pdata->disp_maxx = coords[2];
2583 pdata->disp_maxy = coords[3];
2584 } else {
2585 dev_err(dev, "unsupported property %s\n", name);
2586 return -EINVAL;
2587 }
2588
2589 return 0;
2590}
2591
2592static int mxt_parse_config(struct device *dev, struct device_node *np,
2593 struct mxt_config_info *info)
2594{
2595 struct property *prop;
2596 u8 *temp_cfg;
2597
2598 prop = of_find_property(np, "atmel,config", &info->config_length);
2599 if (!prop) {
2600 dev_err(dev, "Looking up %s property in node %s failed",
2601 "atmel,config", np->full_name);
2602 return -ENODEV;
2603 } else if (!info->config_length) {
2604 dev_err(dev, "Invalid length of configuration data\n");
2605 return -EINVAL;
2606 }
2607
2608 temp_cfg = devm_kzalloc(dev,
2609 info->config_length * sizeof(u8), GFP_KERNEL);
2610 if (!temp_cfg) {
2611 dev_err(dev, "Unable to allocate memory to store cfg\n");
2612 return -ENOMEM;
2613 }
2614
2615 memcpy(temp_cfg, prop->value, info->config_length);
2616 info->config = temp_cfg;
2617
2618 return 0;
2619}
2620
2621static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
2622{
2623 int rc;
2624 struct mxt_config_info *info;
2625 struct device_node *temp, *np = dev->of_node;
2626 struct property *prop;
2627 u32 temp_val;
2628
2629 rc = mxt_get_dt_coords(dev, "atmel,panel-coords", pdata);
2630 if (rc)
2631 return rc;
2632
2633 rc = mxt_get_dt_coords(dev, "atmel,display-coords", pdata);
2634 if (rc)
2635 return rc;
2636
2637 /* regulator info */
2638 pdata->i2c_pull_up = of_property_read_bool(np, "atmel,i2c-pull-up");
2639 pdata->digital_pwr_regulator = of_property_read_bool(np,
2640 "atmel,dig-reg-support");
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302641
2642 pdata->no_force_update = of_property_read_bool(np,
2643 "atmel,no-force-update");
2644
Mohan Pallakad96f5032012-06-18 22:49:10 +05302645 /* reset, irq gpio info */
2646 pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
2647 0, &pdata->reset_gpio_flags);
2648 pdata->irq_gpio = of_get_named_gpio_flags(np, "atmel,irq-gpio",
2649 0, &pdata->irq_gpio_flags);
2650
2651 /* keycodes for keyarray object*/
2652 prop = of_find_property(np, "atmel,key-codes", NULL);
2653 if (prop) {
2654 pdata->key_codes = devm_kzalloc(dev,
2655 sizeof(int) * MXT_KEYARRAY_MAX_KEYS,
2656 GFP_KERNEL);
2657 if (!pdata->key_codes)
2658 return -ENOMEM;
2659 if ((prop->length/sizeof(u32)) == MXT_KEYARRAY_MAX_KEYS) {
2660 rc = of_property_read_u32_array(np, "atmel,key-codes",
2661 pdata->key_codes, MXT_KEYARRAY_MAX_KEYS);
2662 if (rc) {
2663 dev_err(dev, "Unable to read key codes\n");
2664 return rc;
2665 }
2666 } else
2667 return -EINVAL;
2668 }
2669
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302670 /* need calibration during wakeup? */
2671 pdata->need_calibration = of_property_read_bool(np,
2672 "atmel,need-calibration");
Mohan Pallakad96f5032012-06-18 22:49:10 +05302673 /* config array size */
2674 pdata->config_array_size = 0;
2675 temp = NULL;
2676 while ((temp = of_get_next_child(np, temp)))
2677 pdata->config_array_size++;
2678
2679 if (!pdata->config_array_size)
2680 return 0;
2681
2682 info = devm_kzalloc(dev, pdata->config_array_size *
2683 sizeof(struct mxt_config_info), GFP_KERNEL);
2684 if (!info) {
2685 dev_err(dev, "Unable to allocate memory\n");
2686 return -ENOMEM;
2687 }
2688
2689 pdata->config_array = info;
2690
2691 for_each_child_of_node(np, temp) {
2692 rc = of_property_read_string(temp, "atmel,fw-name",
2693 &info->fw_name);
2694 if (rc && (rc != -EINVAL)) {
2695 dev_err(dev, "Unable to read fw name\n");
2696 return rc;
2697 }
2698
2699 rc = of_property_read_u32(temp, "atmel,family-id", &temp_val);
2700 if (rc) {
2701 dev_err(dev, "Unable to read family id\n");
2702 return rc;
2703 } else
2704 info->family_id = (u8) temp_val;
2705
2706 rc = of_property_read_u32(temp, "atmel,variant-id", &temp_val);
2707 if (rc) {
2708 dev_err(dev, "Unable to read variant id\n");
2709 return rc;
2710 } else
2711 info->variant_id = (u8) temp_val;
2712
2713 rc = of_property_read_u32(temp, "atmel,version", &temp_val);
2714 if (rc) {
2715 dev_err(dev, "Unable to read controller version\n");
2716 return rc;
2717 } else
2718 info->version = (u8) temp_val;
2719
2720 rc = of_property_read_u32(temp, "atmel,build", &temp_val);
2721 if (rc) {
2722 dev_err(dev, "Unable to read build id\n");
2723 return rc;
2724 } else
2725 info->build = (u8) temp_val;
2726
Steve Mucklee1533542013-02-13 15:03:16 -08002727 info->bootldr_id = of_property_read_u32(temp,
Mohan Pallakad96f5032012-06-18 22:49:10 +05302728 "atmel,bootldr-id", &temp_val);
2729 if (rc) {
2730 dev_err(dev, "Unable to read bootldr-id\n");
2731 return rc;
2732 } else
2733 info->bootldr_id = (u8) temp_val;
2734
2735 rc = mxt_parse_config(dev, temp, info);
2736 if (rc) {
2737 dev_err(dev, "Unable to parse config data\n");
2738 return rc;
2739 }
2740 info++;
2741 }
2742
2743 return 0;
2744}
2745#else
2746static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
2747{
2748 return -ENODEV;
2749}
2750#endif
2751
Anurag Singh49d76132013-01-29 12:07:00 -08002752#if defined(CONFIG_FB)
2753static int fb_notifier_callback(struct notifier_block *self,
2754 unsigned long event, void *data)
2755{
2756 struct fb_event *evdata = data;
2757 int *blank;
2758 struct mxt_data *mxt_dev_data =
2759 container_of(self, struct mxt_data, fb_notif);
2760
2761 if (evdata && evdata->data && event == FB_EVENT_BLANK && mxt_dev_data &&
2762 mxt_dev_data->client) {
2763 blank = evdata->data;
2764 if (*blank == FB_BLANK_UNBLANK)
2765 mxt_resume(&mxt_dev_data->client->dev);
2766 else if (*blank == FB_BLANK_POWERDOWN)
2767 mxt_suspend(&mxt_dev_data->client->dev);
2768 }
2769
2770 return 0;
2771}
2772#elif defined(CONFIG_HAS_EARLYSUSPEND)
2773static void mxt_early_suspend(struct early_suspend *h)
2774{
2775 struct mxt_data *data = container_of(h, struct mxt_data,
2776 early_suspend);
2777 mxt_suspend(&data->client->dev);
2778}
2779
2780static void mxt_late_resume(struct early_suspend *h)
2781{
2782 struct mxt_data *data = container_of(h, struct mxt_data,
2783 early_suspend);
2784 mxt_resume(&data->client->dev);
2785}
2786
2787#endif
2788
Amy Maloche434b7d82013-02-15 11:11:05 +00002789#if defined(CONFIG_SECURE_TOUCH)
2790static void __devinit secure_touch_init(struct mxt_data *data)
2791{
2792 init_completion(&data->st_completion);
2793}
2794#else
2795static void __devinit secure_touch_init(struct mxt_data *data)
2796{
2797}
2798#endif
2799
Iiro Valkonen7686b102011-02-02 23:21:58 -08002800static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002801 const struct i2c_device_id *id)
2802{
Mohan Pallakad96f5032012-06-18 22:49:10 +05302803 struct mxt_platform_data *pdata;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002804 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002805 struct input_dev *input_dev;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002806 int error, i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002807
Mohan Pallakad96f5032012-06-18 22:49:10 +05302808 if (client->dev.of_node) {
2809 pdata = devm_kzalloc(&client->dev,
2810 sizeof(struct mxt_platform_data), GFP_KERNEL);
2811 if (!pdata) {
2812 dev_err(&client->dev, "Failed to allocate memory\n");
2813 return -ENOMEM;
2814 }
2815
2816 error = mxt_parse_dt(&client->dev, pdata);
2817 if (error)
2818 return error;
2819 } else
2820 pdata = client->dev.platform_data;
2821
Iiro Valkonen919ed892011-02-15 13:36:52 -08002822 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002823 return -EINVAL;
2824
Iiro Valkonen7686b102011-02-02 23:21:58 -08002825 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002826 input_dev = input_allocate_device();
2827 if (!data || !input_dev) {
2828 dev_err(&client->dev, "Failed to allocate memory\n");
2829 error = -ENOMEM;
2830 goto err_free_mem;
2831 }
2832
Nick Dyer0a4016c2012-01-18 15:17:59 +05302833 data->state = INIT;
Amy Maloche83c385a2012-02-01 10:32:03 +05302834 input_dev->name = "atmel_mxt_ts";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002835 input_dev->id.bustype = BUS_I2C;
2836 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002837 input_dev->open = mxt_input_open;
2838 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002839
Joonyoung Shim910d8052011-04-12 23:14:38 -07002840 data->client = client;
2841 data->input_dev = input_dev;
2842 data->pdata = pdata;
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302843 data->no_force_update = pdata->no_force_update;
Joonyoung Shim910d8052011-04-12 23:14:38 -07002844
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002845 __set_bit(EV_ABS, input_dev->evbit);
2846 __set_bit(EV_KEY, input_dev->evbit);
2847 __set_bit(BTN_TOUCH, input_dev->keybit);
Amy Maloche9d0faa02012-06-19 12:37:39 -07002848 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002849
2850 /* For single touch */
2851 input_set_abs_params(input_dev, ABS_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002852 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002853 input_set_abs_params(input_dev, ABS_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002854 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002855 input_set_abs_params(input_dev, ABS_PRESSURE,
2856 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002857
2858 /* For multi touch */
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -07002859 input_mt_init_slots(input_dev, MXT_MAX_FINGER);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002860 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08002861 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002862 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002863 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002864 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002865 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002866 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2867 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002868
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002869 /* set key array supported keys */
2870 if (pdata->key_codes) {
2871 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
2872 if (pdata->key_codes[i])
2873 input_set_capability(input_dev, EV_KEY,
2874 pdata->key_codes[i]);
2875 }
2876 }
2877
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002878 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002879 i2c_set_clientdata(client, data);
2880
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302881 if (pdata->init_hw)
2882 error = pdata->init_hw(true);
2883 else
2884 error = mxt_regulator_configure(data, true);
2885 if (error) {
2886 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07002887 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302888 }
2889
2890 if (pdata->power_on)
2891 error = pdata->power_on(true);
2892 else
2893 error = mxt_power_on(data, true);
2894 if (error) {
2895 dev_err(&client->dev, "Failed to power on hardware\n");
2896 goto err_regulator_on;
2897 }
2898
Amy Maloche08266db2011-11-04 11:07:16 -07002899 if (gpio_is_valid(pdata->irq_gpio)) {
2900 /* configure touchscreen irq gpio */
Mohan Pallakad96f5032012-06-18 22:49:10 +05302901 error = gpio_request(pdata->irq_gpio, "mxt_irq_gpio");
Amy Maloche08266db2011-11-04 11:07:16 -07002902 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302903 dev_err(&client->dev, "unable to request gpio [%d]\n",
Amy Maloche08266db2011-11-04 11:07:16 -07002904 pdata->irq_gpio);
2905 goto err_power_on;
2906 }
2907 error = gpio_direction_input(pdata->irq_gpio);
2908 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302909 dev_err(&client->dev,
2910 "unable to set direction for gpio [%d]\n",
2911 pdata->irq_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002912 goto err_irq_gpio_req;
2913 }
Mohan Pallakad96f5032012-06-18 22:49:10 +05302914 data->irq = client->irq = gpio_to_irq(pdata->irq_gpio);
2915 } else {
2916 dev_err(&client->dev, "irq gpio not provided\n");
2917 goto err_power_on;
Amy Maloche08266db2011-11-04 11:07:16 -07002918 }
2919
2920 if (gpio_is_valid(pdata->reset_gpio)) {
2921 /* configure touchscreen reset out gpio */
Mohan Pallakad96f5032012-06-18 22:49:10 +05302922 error = gpio_request(pdata->reset_gpio, "mxt_reset_gpio");
Amy Maloche08266db2011-11-04 11:07:16 -07002923 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302924 dev_err(&client->dev, "unable to request gpio [%d]\n",
2925 pdata->reset_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002926 goto err_irq_gpio_req;
2927 }
2928
Mohan Pallakad96f5032012-06-18 22:49:10 +05302929 error = gpio_direction_output(pdata->reset_gpio, 1);
Amy Maloche08266db2011-11-04 11:07:16 -07002930 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302931 dev_err(&client->dev,
2932 "unable to set direction for gpio [%d]\n",
2933 pdata->reset_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002934 goto err_reset_gpio_req;
2935 }
2936 }
2937
Jing Lin64fdd1f2012-12-20 17:08:28 -08002938 mxt_power_on_delay(data);
2939
Iiro Valkonen7686b102011-02-02 23:21:58 -08002940 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002941 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07002942 goto err_reset_gpio_req;
Jing Lin64fdd1f2012-12-20 17:08:28 -08002943
Iiro Valkonen7686b102011-02-02 23:21:58 -08002944 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08002945 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002946 if (error) {
2947 dev_err(&client->dev, "Failed to register interrupt\n");
2948 goto err_free_object;
2949 }
2950
Nick Dyer0a4016c2012-01-18 15:17:59 +05302951 if (data->state == APPMODE) {
2952 error = mxt_make_highchg(data);
2953 if (error) {
2954 dev_err(&client->dev, "Failed to make high CHG\n");
2955 goto err_free_irq;
2956 }
2957 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07002958
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002959 error = input_register_device(input_dev);
2960 if (error)
2961 goto err_free_irq;
2962
Iiro Valkonen7686b102011-02-02 23:21:58 -08002963 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002964 if (error)
2965 goto err_unregister_device;
2966
Anurag Singh49d76132013-01-29 12:07:00 -08002967#if defined(CONFIG_FB)
2968 data->fb_notif.notifier_call = fb_notifier_callback;
2969
2970 error = fb_register_client(&data->fb_notif);
2971
2972 if (error)
2973 dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
2974 error);
2975#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302976 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
2977 MXT_SUSPEND_LEVEL;
2978 data->early_suspend.suspend = mxt_early_suspend;
2979 data->early_suspend.resume = mxt_late_resume;
2980 register_early_suspend(&data->early_suspend);
2981#endif
2982
Jing Lin6cfc00e2011-11-02 15:15:30 -07002983 mxt_debugfs_init(data);
2984
Amy Maloche434b7d82013-02-15 11:11:05 +00002985 secure_touch_init(data);
2986
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002987 return 0;
2988
2989err_unregister_device:
2990 input_unregister_device(input_dev);
2991 input_dev = NULL;
2992err_free_irq:
2993 free_irq(client->irq, data);
2994err_free_object:
2995 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07002996err_reset_gpio_req:
2997 if (gpio_is_valid(pdata->reset_gpio))
2998 gpio_free(pdata->reset_gpio);
2999err_irq_gpio_req:
3000 if (gpio_is_valid(pdata->irq_gpio))
3001 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05303002err_power_on:
3003 if (pdata->power_on)
3004 pdata->power_on(false);
3005 else
3006 mxt_power_on(data, false);
3007err_regulator_on:
3008 if (pdata->init_hw)
3009 pdata->init_hw(false);
3010 else
3011 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003012err_free_mem:
3013 input_free_device(input_dev);
3014 kfree(data);
3015 return error;
3016}
3017
Iiro Valkonen7686b102011-02-02 23:21:58 -08003018static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003019{
Iiro Valkonen7686b102011-02-02 23:21:58 -08003020 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003021
Iiro Valkonen7686b102011-02-02 23:21:58 -08003022 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003023 free_irq(data->irq, data);
3024 input_unregister_device(data->input_dev);
Anurag Singh49d76132013-01-29 12:07:00 -08003025#if defined(CONFIG_FB)
3026 if (fb_unregister_client(&data->fb_notif))
3027 dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
3028#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +05303029 unregister_early_suspend(&data->early_suspend);
3030#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05303031
3032 if (data->pdata->power_on)
3033 data->pdata->power_on(false);
3034 else
3035 mxt_power_on(data, false);
3036
3037 if (data->pdata->init_hw)
3038 data->pdata->init_hw(false);
3039 else
3040 mxt_regulator_configure(data, false);
3041
Mohan Pallakabfe8f302012-01-02 18:32:08 +08003042 if (gpio_is_valid(data->pdata->reset_gpio))
3043 gpio_free(data->pdata->reset_gpio);
3044
3045 if (gpio_is_valid(data->pdata->irq_gpio))
3046 gpio_free(data->pdata->irq_gpio);
3047
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003048 kfree(data->object_table);
3049 kfree(data);
3050
Jing Lin6cfc00e2011-11-02 15:15:30 -07003051 debugfs_remove_recursive(debug_base);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003052
3053 return 0;
3054}
3055
Iiro Valkonen7686b102011-02-02 23:21:58 -08003056static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003057 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08003058 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08003059 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003060 { }
3061};
Iiro Valkonen7686b102011-02-02 23:21:58 -08003062MODULE_DEVICE_TABLE(i2c, mxt_id);
Amy Maloche56cb58c2012-08-23 13:21:03 -07003063#ifdef CONFIG_OF
Mohan Pallakad96f5032012-06-18 22:49:10 +05303064static struct of_device_id mxt_match_table[] = {
3065 { .compatible = "atmel,mxt-ts",},
3066 { },
3067};
3068#else
3069#define mxt_match_table NULL
3070#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003071
Iiro Valkonen7686b102011-02-02 23:21:58 -08003072static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003073 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08003074 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003075 .owner = THIS_MODULE,
Mohan Pallakad96f5032012-06-18 22:49:10 +05303076 .of_match_table = mxt_match_table,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08003077#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08003078 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08003079#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003080 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08003081 .probe = mxt_probe,
3082 .remove = __devexit_p(mxt_remove),
3083 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003084};
3085
Axel Lin1b92c1c2012-03-16 23:05:41 -07003086module_i2c_driver(mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003087
3088/* Module information */
3089MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08003090MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003091MODULE_LICENSE("GPL");