blob: 29b269a268d9c85f21d2a067f7ba654f7a31feaf [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 Malochee3146fb2013-04-12 14:59:16 -0700131#define MXT_SPT_EXTRANOISESUPCTRLS_T58 58
Amy Maloche41f1cc32012-07-12 13:02:27 -0700132#define MXT_SPT_TIMER_T61 61
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700133
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700134/* MXT_GEN_COMMAND_T6 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800135#define MXT_COMMAND_RESET 0
136#define MXT_COMMAND_BACKUPNV 1
137#define MXT_COMMAND_CALIBRATE 2
138#define MXT_COMMAND_REPORTALL 3
139#define MXT_COMMAND_DIAGNOSTIC 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700140
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700141/* MXT_GEN_POWER_T7 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800142#define MXT_POWER_IDLEACQINT 0
143#define MXT_POWER_ACTVACQINT 1
144#define MXT_POWER_ACTV2IDLETO 2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700145
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700146/* MXT_GEN_ACQUIRE_T8 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800147#define MXT_ACQUIRE_CHRGTIME 0
148#define MXT_ACQUIRE_TCHDRIFT 2
149#define MXT_ACQUIRE_DRIFTST 3
150#define MXT_ACQUIRE_TCHAUTOCAL 4
151#define MXT_ACQUIRE_SYNC 5
152#define MXT_ACQUIRE_ATCHCALST 6
153#define MXT_ACQUIRE_ATCHCALSTHR 7
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700154
Iiro Valkonene8645592011-11-18 12:56:19 -0800155/* MXT_TOUCH_MULT_T9 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800156#define MXT_TOUCH_CTRL 0
157#define MXT_TOUCH_XORIGIN 1
158#define MXT_TOUCH_YORIGIN 2
159#define MXT_TOUCH_XSIZE 3
160#define MXT_TOUCH_YSIZE 4
161#define MXT_TOUCH_BLEN 6
162#define MXT_TOUCH_TCHTHR 7
163#define MXT_TOUCH_TCHDI 8
164#define MXT_TOUCH_ORIENT 9
165#define MXT_TOUCH_MOVHYSTI 11
166#define MXT_TOUCH_MOVHYSTN 12
167#define MXT_TOUCH_NUMTOUCH 14
168#define MXT_TOUCH_MRGHYST 15
169#define MXT_TOUCH_MRGTHR 16
170#define MXT_TOUCH_AMPHYST 17
171#define MXT_TOUCH_XRANGE_LSB 18
172#define MXT_TOUCH_XRANGE_MSB 19
173#define MXT_TOUCH_YRANGE_LSB 20
174#define MXT_TOUCH_YRANGE_MSB 21
175#define MXT_TOUCH_XLOCLIP 22
176#define MXT_TOUCH_XHICLIP 23
177#define MXT_TOUCH_YLOCLIP 24
178#define MXT_TOUCH_YHICLIP 25
179#define MXT_TOUCH_XEDGECTRL 26
180#define MXT_TOUCH_XEDGEDIST 27
181#define MXT_TOUCH_YEDGECTRL 28
182#define MXT_TOUCH_YEDGEDIST 29
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700183#define MXT_TOUCH_JUMPLIMIT 30
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700184
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700185/* MXT_PROCI_GRIPFACE_T20 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800186#define MXT_GRIPFACE_CTRL 0
187#define MXT_GRIPFACE_XLOGRIP 1
188#define MXT_GRIPFACE_XHIGRIP 2
189#define MXT_GRIPFACE_YLOGRIP 3
190#define MXT_GRIPFACE_YHIGRIP 4
191#define MXT_GRIPFACE_MAXTCHS 5
192#define MXT_GRIPFACE_SZTHR1 7
193#define MXT_GRIPFACE_SZTHR2 8
194#define MXT_GRIPFACE_SHPTHR1 9
195#define MXT_GRIPFACE_SHPTHR2 10
196#define MXT_GRIPFACE_SUPEXTTO 11
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700197
Iiro Valkonen7686b102011-02-02 23:21:58 -0800198/* MXT_PROCI_NOISE field */
199#define MXT_NOISE_CTRL 0
200#define MXT_NOISE_OUTFLEN 1
201#define MXT_NOISE_GCAFUL_LSB 3
202#define MXT_NOISE_GCAFUL_MSB 4
203#define MXT_NOISE_GCAFLL_LSB 5
204#define MXT_NOISE_GCAFLL_MSB 6
205#define MXT_NOISE_ACTVGCAFVALID 7
206#define MXT_NOISE_NOISETHR 8
207#define MXT_NOISE_FREQHOPSCALE 10
208#define MXT_NOISE_FREQ0 11
209#define MXT_NOISE_FREQ1 12
210#define MXT_NOISE_FREQ2 13
211#define MXT_NOISE_FREQ3 14
212#define MXT_NOISE_FREQ4 15
213#define MXT_NOISE_IDLEGCAFVALID 16
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700214
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700215/* MXT_SPT_COMMSCONFIG_T18 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800216#define MXT_COMMS_CTRL 0
217#define MXT_COMMS_CMD 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700218
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700219/* MXT_SPT_CTECONFIG_T28 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800220#define MXT_CTE_CTRL 0
221#define MXT_CTE_CMD 1
222#define MXT_CTE_MODE 2
223#define MXT_CTE_IDLEGCAFDEPTH 3
224#define MXT_CTE_ACTVGCAFDEPTH 4
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700225#define MXT_CTE_VOLTAGE 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700226
Iiro Valkonen7686b102011-02-02 23:21:58 -0800227#define MXT_VOLTAGE_DEFAULT 2700000
228#define MXT_VOLTAGE_STEP 10000
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700229
Amy Maloche21115eb2011-11-02 09:04:37 -0700230/* Analog voltage @2.7 V */
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530231#define MXT_VTG_MIN_UV 2700000
232#define MXT_VTG_MAX_UV 3300000
233#define MXT_ACTIVE_LOAD_UA 15000
Jing Linbace50b2011-10-18 22:55:47 -0700234#define MXT_LPM_LOAD_UA 10
Amy Maloche21115eb2011-11-02 09:04:37 -0700235/* Digital voltage @1.8 V */
236#define MXT_VTG_DIG_MIN_UV 1800000
237#define MXT_VTG_DIG_MAX_UV 1800000
238#define MXT_ACTIVE_LOAD_DIG_UA 10000
239#define MXT_LPM_LOAD_DIG_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530240
241#define MXT_I2C_VTG_MIN_UV 1800000
242#define MXT_I2C_VTG_MAX_UV 1800000
243#define MXT_I2C_LOAD_UA 10000
Jing Linbace50b2011-10-18 22:55:47 -0700244#define MXT_I2C_LPM_LOAD_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530245
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700246/* Define for MXT_GEN_COMMAND_T6 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800247#define MXT_BOOT_VALUE 0xa5
248#define MXT_BACKUP_VALUE 0x55
249#define MXT_BACKUP_TIME 25 /* msec */
Jing Lin64fdd1f2012-12-20 17:08:28 -0800250
251/* Software reset delay */
252#define MXT224_RESET_TIME 64 /* msec */
253#define MXT224E_RESET_TIME 21 /* msec */
Amy Maloche41f1cc32012-07-12 13:02:27 -0700254#define MXT336S_RESET_TIME 25 /* msec */
Jing Lin64fdd1f2012-12-20 17:08:28 -0800255#define MXT1386_RESET_TIME 250 /* msec */
256#define MXT1386E_RESET_TIME 229 /* msec */
257#define MXT1664S_RESET_TIME 280 /* msec */
Amy Maloche7e447432011-09-14 11:36:30 -0700258#define MXT_RESET_TIME 250 /* msec */
Jing Linc7fc4052011-12-21 16:16:19 -0800259#define MXT_RESET_NOCHGREAD 400 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700260
Jing Lin64fdd1f2012-12-20 17:08:28 -0800261/* Power on delay */
262#define MXT224_POWER_ON_TIME 40 /* msec */
263#define MXT224E_POWER_ON_TIME 21 /* msec */
264#define MXT336S_POWER_ON_TIME 25 /* msec */
265#define MXT1386_POWER_ON_TIME 90 /* msec */
266#define MXT1386E_POWER_ON_TIME 81 /* msec */
267#define MXT1664S_POWER_ON_TIME 65 /* msec */
268#define MXT_POWER_ON_TIME 100 /* msec */
269
Nick Dyer0a4016c2012-01-18 15:17:59 +0530270#define MXT_FWRESET_TIME 1000 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700271
Jing Lin36aee812011-10-17 17:17:28 -0700272#define MXT_WAKE_TIME 25
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700273
274/* Command to unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800275#define MXT_UNLOCK_CMD_MSB 0xaa
276#define MXT_UNLOCK_CMD_LSB 0xdc
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700277
278/* Bootloader mode status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800279#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
280#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
281#define MXT_FRAME_CRC_CHECK 0x02
282#define MXT_FRAME_CRC_FAIL 0x03
283#define MXT_FRAME_CRC_PASS 0x04
284#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
285#define MXT_BOOT_STATUS_MASK 0x3f
Nick Dyer0a4016c2012-01-18 15:17:59 +0530286#define MXT_BOOT_EXTENDED_ID (1 << 5)
287#define MXT_BOOT_ID_MASK 0x1f
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700288
289/* Touch status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800290#define MXT_SUPPRESS (1 << 1)
291#define MXT_AMP (1 << 2)
292#define MXT_VECTOR (1 << 3)
293#define MXT_MOVE (1 << 4)
294#define MXT_RELEASE (1 << 5)
295#define MXT_PRESS (1 << 6)
296#define MXT_DETECT (1 << 7)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700297
Joonyoung Shim910d8052011-04-12 23:14:38 -0700298/* Touch orient bits */
299#define MXT_XY_SWITCH (1 << 0)
300#define MXT_X_INVERT (1 << 1)
301#define MXT_Y_INVERT (1 << 2)
302
Mohan Pallakab6acab42012-06-13 11:59:04 +0530303/* Touch suppression */
304#define MXT_TCHSUP_ACTIVE (1 << 0)
305
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700306/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800307#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700308
Iiro Valkonen7686b102011-02-02 23:21:58 -0800309#define MXT_MAX_FINGER 10
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700310
Jing Lin36aee812011-10-17 17:17:28 -0700311#define T7_DATA_SIZE 3
312#define MXT_MAX_RW_TRIES 3
313#define MXT_BLOCK_SIZE 256
Jing Lin8fadad72012-02-24 10:10:50 -0800314#define MXT_CFG_VERSION_LEN 3
315#define MXT_CFG_VERSION_EQUAL 0
316#define MXT_CFG_VERSION_LESS 1
317#define MXT_CFG_VERSION_GREATER 2
Mohan Pallakaab51f2b2011-09-29 18:17:35 +0530318
Mohan Pallakad96f5032012-06-18 22:49:10 +0530319#define MXT_COORDS_ARR_SIZE 4
320
Jing Lin6cfc00e2011-11-02 15:15:30 -0700321#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
322#define MXT_DEBUGFS_FILE "object"
323
Iiro Valkonen7686b102011-02-02 23:21:58 -0800324struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700325 u8 family_id;
326 u8 variant_id;
327 u8 version;
328 u8 build;
329 u8 matrix_xsize;
330 u8 matrix_ysize;
331 u8 object_num;
332};
333
Iiro Valkonen7686b102011-02-02 23:21:58 -0800334struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700335 u8 type;
336 u16 start_address;
337 u8 size;
338 u8 instances;
339 u8 num_report_ids;
340
341 /* to map object and message */
342 u8 max_reportid;
343};
344
Iiro Valkonen7686b102011-02-02 23:21:58 -0800345struct mxt_message {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700346 u8 reportid;
347 u8 message[7];
348 u8 checksum;
349};
350
Iiro Valkonen7686b102011-02-02 23:21:58 -0800351struct mxt_finger {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700352 int status;
353 int x;
354 int y;
355 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700356 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700357};
358
359/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800360struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700361 struct i2c_client *client;
362 struct input_dev *input_dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800363 const struct mxt_platform_data *pdata;
Jing Lindc4413c2012-01-16 15:22:52 -0800364 const struct mxt_config_info *config_info;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530365 enum mxt_device_state state;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800366 struct mxt_object *object_table;
367 struct mxt_info info;
368 struct mxt_finger finger[MXT_MAX_FINGER];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700369 unsigned int irq;
Amy Maloche21115eb2011-11-02 09:04:37 -0700370 struct regulator *vcc_ana;
371 struct regulator *vcc_dig;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530372 struct regulator *vcc_i2c;
Amy Maloche265fc3c2013-01-17 11:50:24 -0800373 struct mxt_address_pair addr_pair;
Anurag Singh49d76132013-01-29 12:07:00 -0800374#if defined(CONFIG_FB)
375 struct notifier_block fb_notif;
376#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +0530377 struct early_suspend early_suspend;
378#endif
Jing Lin36aee812011-10-17 17:17:28 -0700379
Amy Maloche52262212011-09-15 16:46:57 -0700380 u8 t7_data[T7_DATA_SIZE];
Jing Lin36aee812011-10-17 17:17:28 -0700381 u16 t7_start_addr;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800382 u32 keyarray_old;
383 u32 keyarray_new;
384 u8 t9_max_reportid;
385 u8 t9_min_reportid;
386 u8 t15_max_reportid;
387 u8 t15_min_reportid;
Mohan Pallakab6acab42012-06-13 11:59:04 +0530388 u8 t42_max_reportid;
389 u8 t42_min_reportid;
Jing Lin8fadad72012-02-24 10:10:50 -0800390 u8 cfg_version[MXT_CFG_VERSION_LEN];
Jing Lindc4413c2012-01-16 15:22:52 -0800391 int cfg_version_idx;
Jing Lin8a9472d2012-03-21 15:43:45 -0700392 int t38_start_addr;
Jing Lin8fadad72012-02-24 10:10:50 -0800393 bool update_cfg;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -0800394 const char *fw_name;
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +0530395 bool no_force_update;
Amy Maloche434b7d82013-02-15 11:11:05 +0000396#if defined(CONFIG_SECURE_TOUCH)
397 atomic_t st_enabled;
398 atomic_t st_pending_irqs;
399 struct completion st_completion;
Amy Maloche20f970c2013-04-10 13:04:52 +0100400 struct completion st_powerdown;
Amy Maloche434b7d82013-02-15 11:11:05 +0000401#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700402};
403
Jing Lin6cfc00e2011-11-02 15:15:30 -0700404static struct dentry *debug_base;
405
Iiro Valkonen7686b102011-02-02 23:21:58 -0800406static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700407{
408 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700409 case MXT_GEN_MESSAGE_T5:
410 case MXT_GEN_COMMAND_T6:
411 case MXT_GEN_POWER_T7:
412 case MXT_GEN_ACQUIRE_T8:
413 case MXT_GEN_DATASOURCE_T53:
414 case MXT_TOUCH_MULTI_T9:
415 case MXT_TOUCH_KEYARRAY_T15:
416 case MXT_TOUCH_PROXIMITY_T23:
417 case MXT_TOUCH_PROXKEY_T52:
418 case MXT_PROCI_GRIPFACE_T20:
419 case MXT_PROCG_NOISE_T22:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700420 case MXT_PROCG_NOISE_T62:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700421 case MXT_PROCI_ONETOUCH_T24:
422 case MXT_PROCI_TWOTOUCH_T27:
423 case MXT_PROCI_GRIP_T40:
424 case MXT_PROCI_PALM_T41:
425 case MXT_PROCI_TOUCHSUPPRESSION_T42:
426 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800427 case MXT_PROCI_SHIELDLESS_T56:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700428 case MXT_PROCI_EXTRATSDATA_T57:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700429 case MXT_PROCG_NOISESUPPRESSION_T48:
430 case MXT_SPT_COMMSCONFIG_T18:
431 case MXT_SPT_GPIOPWM_T19:
432 case MXT_SPT_SELFTEST_T25:
433 case MXT_SPT_CTECONFIG_T28:
434 case MXT_SPT_USERDATA_T38:
435 case MXT_SPT_DIGITIZER_T43:
436 case MXT_SPT_CTECONFIG_T46:
Amy Malochee3146fb2013-04-12 14:59:16 -0700437 case MXT_SPT_EXTRANOISESUPCTRLS_T58:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700438 case MXT_SPT_TIMER_T61:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530439 case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700440 return true;
441 default:
442 return false;
443 }
444}
445
Iiro Valkonen7686b102011-02-02 23:21:58 -0800446static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700447{
448 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700449 case MXT_GEN_COMMAND_T6:
450 case MXT_GEN_POWER_T7:
451 case MXT_GEN_ACQUIRE_T8:
452 case MXT_TOUCH_MULTI_T9:
453 case MXT_TOUCH_KEYARRAY_T15:
454 case MXT_TOUCH_PROXIMITY_T23:
455 case MXT_TOUCH_PROXKEY_T52:
456 case MXT_PROCI_GRIPFACE_T20:
457 case MXT_PROCG_NOISE_T22:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700458 case MXT_PROCG_NOISE_T62:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700459 case MXT_PROCI_ONETOUCH_T24:
460 case MXT_PROCI_TWOTOUCH_T27:
461 case MXT_PROCI_GRIP_T40:
462 case MXT_PROCI_PALM_T41:
463 case MXT_PROCI_TOUCHSUPPRESSION_T42:
464 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800465 case MXT_PROCI_SHIELDLESS_T56:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700466 case MXT_PROCI_EXTRATSDATA_T57:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700467 case MXT_PROCG_NOISESUPPRESSION_T48:
468 case MXT_SPT_COMMSCONFIG_T18:
469 case MXT_SPT_GPIOPWM_T19:
470 case MXT_SPT_SELFTEST_T25:
471 case MXT_SPT_CTECONFIG_T28:
Iiro Valkonene8645592011-11-18 12:56:19 -0800472 case MXT_SPT_USERDATA_T38:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700473 case MXT_SPT_DIGITIZER_T43:
474 case MXT_SPT_CTECONFIG_T46:
Amy Malochee3146fb2013-04-12 14:59:16 -0700475 case MXT_SPT_EXTRANOISESUPCTRLS_T58:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700476 case MXT_SPT_TIMER_T61:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530477 case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700478 return true;
479 default:
480 return false;
481 }
482}
483
Iiro Valkonen7686b102011-02-02 23:21:58 -0800484static void mxt_dump_message(struct device *dev,
485 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700486{
487 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
488 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
489 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
490 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
491 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
492 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
493 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
494 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
495 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
496}
497
Amy Maloche265fc3c2013-01-17 11:50:24 -0800498static int mxt_lookup_bootloader_address(struct mxt_data *data)
Amy Maloche71b8f022013-01-17 11:50:24 -0800499{
Steve Mucklee1533542013-02-13 15:03:16 -0800500 int i;
Amy Maloche265fc3c2013-01-17 11:50:24 -0800501
502 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
503 if (mxt_slave_addresses[i].application ==
504 data->client->addr) {
505 data->addr_pair.bootloader =
506 mxt_slave_addresses[i].bootloader;
507 return 0;
508 }
509 }
510
511 dev_err(&data->client->dev, "Address 0x%02x not found in address table",
512 data->client->addr);
513 return -EINVAL;
514
515};
516
517static int mxt_switch_to_bootloader_address(struct mxt_data *data)
518{
Nick Dyer0a4016c2012-01-18 15:17:59 +0530519 struct i2c_client *client = data->client;
520
521 if (data->state == BOOTLOADER) {
522 dev_err(&client->dev, "Already in BOOTLOADER state\n");
523 return -EINVAL;
524 }
525
Amy Maloche265fc3c2013-01-17 11:50:24 -0800526 dev_info(&client->dev, "Changing to bootloader address: 0x%02x -> 0x%02x",
527 client->addr, data->addr_pair.bootloader);
Nick Dyer0a4016c2012-01-18 15:17:59 +0530528
Amy Maloche265fc3c2013-01-17 11:50:24 -0800529 client->addr = data->addr_pair.bootloader;
530 data->state = BOOTLOADER;
531 return 0;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530532}
533
534static int mxt_switch_to_appmode_address(struct mxt_data *data)
535{
Nick Dyer0a4016c2012-01-18 15:17:59 +0530536 struct i2c_client *client = data->client;
537
538 if (data->state == APPMODE) {
539 dev_err(&client->dev, "Already in APPMODE state\n");
540 return -EINVAL;
541 }
542
Amy Maloche265fc3c2013-01-17 11:50:24 -0800543 dev_info(&client->dev, "Changing to application mode address: " \
544 "0x%02x -> 0x%02x", client->addr,
545 data->addr_pair.application);
Nick Dyer0a4016c2012-01-18 15:17:59 +0530546
Amy Maloche265fc3c2013-01-17 11:50:24 -0800547 client->addr = data->addr_pair.application;
548 data->state = APPMODE;
549 return 0;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530550}
551
552static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
553{
554 u8 buf[3];
555
556 if (val | MXT_BOOT_EXTENDED_ID) {
557 dev_dbg(&client->dev,
558 "Retrieving extended mode ID information");
559
560 if (i2c_master_recv(client, &buf[0], 3) != 3) {
561 dev_err(&client->dev, "%s: i2c recv failed\n",
562 __func__);
563 return -EIO;
564 }
565
566 dev_info(&client->dev, "Bootloader ID:%d Version:%d",
567 buf[1], buf[2]);
568
569 return buf[0];
570 } else {
571 dev_info(&client->dev, "Bootloader ID:%d",
572 val & MXT_BOOT_ID_MASK);
573
574 return val;
575 }
576}
577
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -0800578static int mxt_get_bootloader_id(struct i2c_client *client)
579{
580 u8 val;
581 u8 buf[3];
582
583 if (i2c_master_recv(client, &val, 1) != 1) {
584 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
585 return -EIO;
586 }
587
588 if (val | MXT_BOOT_EXTENDED_ID) {
589 if (i2c_master_recv(client, &buf[0], 3) != 3) {
590 dev_err(&client->dev, "%s: i2c recv failed\n",
591 __func__);
592 return -EIO;
593 }
594 return buf[1];
595 } else {
596 dev_info(&client->dev, "Bootloader ID:%d",
597 val & MXT_BOOT_ID_MASK);
598
599 return val & MXT_BOOT_ID_MASK;
600 }
601}
602
Iiro Valkonen7686b102011-02-02 23:21:58 -0800603static int mxt_check_bootloader(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530604 unsigned int state)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700605{
606 u8 val;
607
608recheck:
609 if (i2c_master_recv(client, &val, 1) != 1) {
610 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
611 return -EIO;
612 }
613
614 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800615 case MXT_WAITING_BOOTLOAD_CMD:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530616 val = mxt_get_bootloader_version(client, val);
617 val &= ~MXT_BOOT_STATUS_MASK;
618 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800619 case MXT_WAITING_FRAME_DATA:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530620 case MXT_APP_CRC_FAIL:
Iiro Valkonen7686b102011-02-02 23:21:58 -0800621 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700622 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800623 case MXT_FRAME_CRC_PASS:
624 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700625 goto recheck;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530626 if (val == MXT_FRAME_CRC_FAIL) {
627 dev_err(&client->dev, "Bootloader CRC fail\n");
628 return -EINVAL;
629 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700630 break;
631 default:
632 return -EINVAL;
633 }
634
635 if (val != state) {
Nick Dyer0a4016c2012-01-18 15:17:59 +0530636 dev_err(&client->dev, "Invalid bootloader mode state %X\n",
637 val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700638 return -EINVAL;
639 }
640
641 return 0;
642}
643
Iiro Valkonen7686b102011-02-02 23:21:58 -0800644static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700645{
646 u8 buf[2];
647
Iiro Valkonen7686b102011-02-02 23:21:58 -0800648 buf[0] = MXT_UNLOCK_CMD_LSB;
649 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700650
651 if (i2c_master_send(client, buf, 2) != 2) {
652 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
653 return -EIO;
654 }
655
656 return 0;
657}
658
Iiro Valkonen7686b102011-02-02 23:21:58 -0800659static int mxt_fw_write(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530660 const u8 *data, unsigned int frame_size)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700661{
662 if (i2c_master_send(client, data, frame_size) != frame_size) {
663 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
664 return -EIO;
665 }
666
667 return 0;
668}
669
Iiro Valkonen7686b102011-02-02 23:21:58 -0800670static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700671 u16 reg, u16 len, void *val)
672{
673 struct i2c_msg xfer[2];
674 u8 buf[2];
Jing Lin36aee812011-10-17 17:17:28 -0700675 int i = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700676
677 buf[0] = reg & 0xff;
678 buf[1] = (reg >> 8) & 0xff;
679
680 /* Write register */
681 xfer[0].addr = client->addr;
682 xfer[0].flags = 0;
683 xfer[0].len = 2;
684 xfer[0].buf = buf;
685
686 /* Read data */
687 xfer[1].addr = client->addr;
688 xfer[1].flags = I2C_M_RD;
689 xfer[1].len = len;
690 xfer[1].buf = val;
691
Jing Lin36aee812011-10-17 17:17:28 -0700692 do {
693 if (i2c_transfer(client->adapter, xfer, 2) == 2)
694 return 0;
695 msleep(MXT_WAKE_TIME);
696 } while (++i < MXT_MAX_RW_TRIES);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700697
Jing Lin36aee812011-10-17 17:17:28 -0700698 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
699 return -EIO;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700700}
701
Iiro Valkonen7686b102011-02-02 23:21:58 -0800702static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700703{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800704 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700705}
706
Jing Lin36aee812011-10-17 17:17:28 -0700707static int __mxt_write_reg(struct i2c_client *client,
708 u16 addr, u16 length, u8 *value)
709{
710 u8 buf[MXT_BLOCK_SIZE + 2];
711 int i, tries = 0;
712
713 if (length > MXT_BLOCK_SIZE)
714 return -EINVAL;
715
716 buf[0] = addr & 0xff;
717 buf[1] = (addr >> 8) & 0xff;
718 for (i = 0; i < length; i++)
719 buf[i + 2] = *value++;
720
721 do {
722 if (i2c_master_send(client, buf, length + 2) == (length + 2))
723 return 0;
724 msleep(MXT_WAKE_TIME);
725 } while (++tries < MXT_MAX_RW_TRIES);
726
727 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
728 return -EIO;
729}
730
Iiro Valkonen7686b102011-02-02 23:21:58 -0800731static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700732{
Jing Lin36aee812011-10-17 17:17:28 -0700733 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700734}
735
Iiro Valkonen7686b102011-02-02 23:21:58 -0800736static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700737 u16 reg, u8 *object_buf)
738{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800739 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700740 object_buf);
741}
742
Iiro Valkonen7686b102011-02-02 23:21:58 -0800743static struct mxt_object *
744mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700745{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800746 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700747 int i;
748
749 for (i = 0; i < data->info.object_num; i++) {
750 object = data->object_table + i;
751 if (object->type == type)
752 return object;
753 }
754
755 dev_err(&data->client->dev, "Invalid object type\n");
756 return NULL;
757}
758
Iiro Valkonen7686b102011-02-02 23:21:58 -0800759static int mxt_read_message(struct mxt_data *data,
760 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700761{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800762 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700763 u16 reg;
764
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700765 object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700766 if (!object)
767 return -EINVAL;
768
769 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800770 return __mxt_read_reg(data->client, reg,
771 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700772}
773
Iiro Valkonen7686b102011-02-02 23:21:58 -0800774static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700775 u8 type, u8 offset, u8 *val)
776{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800777 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700778 u16 reg;
779
Iiro Valkonen7686b102011-02-02 23:21:58 -0800780 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700781 if (!object)
782 return -EINVAL;
783
784 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800785 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700786}
787
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530788static int mxt_get_object_address(struct device *dev, u8 type)
789{
790 struct mxt_data *data = dev_get_drvdata(dev);
791 u8 obj_num, obj_buf[MXT_OBJECT_SIZE];
792 u16 reg;
793 int i, error;
794
795 error = mxt_read_reg(data->client, MXT_OBJECT_NUM, &obj_num);
796
797 if (error) {
798 dev_err(dev, "reading number of objects failed\n");
799 return -EINVAL;
800 }
801
802 for (i = 0; i < obj_num; i++) {
803 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
804 error = mxt_read_object_table(data->client,
805 reg, obj_buf);
806 if (error)
807 return error;
808
809 if (obj_buf[0] == type)
810 return obj_buf[2] << 8 | obj_buf[1];
811 }
812 /* If control reaches here, i = obj_num and object not found */
813 dev_err(dev, "Requested object %d not found.\n", type);
814 return -EINVAL;
815
816}
817
Iiro Valkonen7686b102011-02-02 23:21:58 -0800818static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700819 u8 type, u8 offset, u8 val)
820{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800821 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700822 u16 reg;
823
Iiro Valkonen7686b102011-02-02 23:21:58 -0800824 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700825 if (!object)
826 return -EINVAL;
827
828 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800829 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700830}
831
Iiro Valkonen7686b102011-02-02 23:21:58 -0800832static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700833{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800834 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700835 struct input_dev *input_dev = data->input_dev;
836 int status = finger[single_id].status;
837 int finger_num = 0;
838 int id;
839
Iiro Valkonen7686b102011-02-02 23:21:58 -0800840 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700841 if (!finger[id].status)
842 continue;
843
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700844 input_mt_slot(input_dev, id);
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800845 /* Firmware reports min/max values when the touch is
846 * outside screen area. Send a release event in
847 * such cases to avoid unwanted touches.
848 */
849 if (finger[id].x <= data->pdata->panel_minx ||
850 finger[id].x >= data->pdata->panel_maxx ||
851 finger[id].y <= data->pdata->panel_miny ||
852 finger[id].y >= data->pdata->panel_maxy) {
853 finger[id].status = MXT_RELEASE;
854 }
855
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700856 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
857 finger[id].status != MXT_RELEASE);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700858
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700859 if (finger[id].status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700860 finger_num++;
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700861 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
862 finger[id].area);
863 input_report_abs(input_dev, ABS_MT_POSITION_X,
864 finger[id].x);
865 input_report_abs(input_dev, ABS_MT_POSITION_Y,
866 finger[id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700867 input_report_abs(input_dev, ABS_MT_PRESSURE,
Anirudh Ghayal279a2ae52012-05-18 18:07:46 +0530868 finger[id].pressure);
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700869 } else {
870 finger[id].status = 0;
871 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700872 }
873
874 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
875
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800876 if (finger[single_id].x <= data->pdata->panel_minx ||
877 finger[single_id].x >= data->pdata->panel_maxx ||
878 finger[single_id].y <= data->pdata->panel_miny ||
879 finger[single_id].y >= data->pdata->panel_maxy) {
880 status = MXT_RELEASE;
881 }
882
Iiro Valkonen7686b102011-02-02 23:21:58 -0800883 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700884 input_report_abs(input_dev, ABS_X, finger[single_id].x);
885 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700886 input_report_abs(input_dev,
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700887 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700888 }
889
890 input_sync(input_dev);
891}
892
Amy Maloche1b7ac702013-02-21 19:47:53 -0800893static void mxt_release_all(struct mxt_data *data)
894{
895 int id;
896
897 for (id = 0; id < MXT_MAX_FINGER; id++)
898 if (data->finger[id].status)
899 data->finger[id].status = MXT_RELEASE;
900
901 mxt_input_report(data, 0);
902}
903
Iiro Valkonen7686b102011-02-02 23:21:58 -0800904static void mxt_input_touchevent(struct mxt_data *data,
905 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700906{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800907 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700908 struct device *dev = &data->client->dev;
909 u8 status = message->message[0];
910 int x;
911 int y;
912 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700913 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700914
Amy Maloche1b7ac702013-02-21 19:47:53 -0800915 if (status & MXT_SUPPRESS) {
916 mxt_release_all(data);
917 return;
918 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700919 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800920 if (!(status & MXT_DETECT)) {
921 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700922 dev_dbg(dev, "[%d] released\n", id);
923
Iiro Valkonen7686b102011-02-02 23:21:58 -0800924 finger[id].status = MXT_RELEASE;
925 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700926 }
927 return;
928 }
929
930 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800931 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700932 return;
933
Joonyoung Shim910d8052011-04-12 23:14:38 -0700934 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
935 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800936 if (data->pdata->panel_maxx < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700937 x = x >> 2;
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800938 if (data->pdata->panel_maxy < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700939 y = y >> 2;
940
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700941 area = message->message[4];
Yufeng Shen28ac2932011-08-16 00:40:54 -0700942 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700943
944 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800945 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700946 x, y, area);
947
Iiro Valkonen7686b102011-02-02 23:21:58 -0800948 finger[id].status = status & MXT_MOVE ?
949 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700950 finger[id].x = x;
951 finger[id].y = y;
952 finger[id].area = area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700953 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700954
Iiro Valkonen7686b102011-02-02 23:21:58 -0800955 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700956}
957
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800958static void mxt_handle_key_array(struct mxt_data *data,
959 struct mxt_message *message)
960{
961 u32 keys_changed;
962 int i;
963
964 if (!data->pdata->key_codes) {
965 dev_err(&data->client->dev, "keyarray is not supported\n");
966 return;
967 }
968
969 data->keyarray_new = message->message[1] |
970 (message->message[2] << 8) |
971 (message->message[3] << 16) |
972 (message->message[4] << 24);
973
974 keys_changed = data->keyarray_old ^ data->keyarray_new;
975
976 if (!keys_changed) {
977 dev_dbg(&data->client->dev, "no keys changed\n");
978 return;
979 }
980
981 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
982 if (!(keys_changed & (1 << i)))
983 continue;
984
985 input_report_key(data->input_dev, data->pdata->key_codes[i],
986 (data->keyarray_new & (1 << i)));
987 input_sync(data->input_dev);
988 }
989
990 data->keyarray_old = data->keyarray_new;
991}
992
Amy Maloche1b7ac702013-02-21 19:47:53 -0800993static void mxt_handle_touch_suppression(struct mxt_data *data, u8 status)
Mohan Pallakab6acab42012-06-13 11:59:04 +0530994{
995 dev_dbg(&data->client->dev, "touch suppression\n");
996 /* release all touches */
997 if (status & MXT_TCHSUP_ACTIVE)
998 mxt_release_all(data);
999}
1000
Amy Maloche434b7d82013-02-15 11:11:05 +00001001#if defined(CONFIG_SECURE_TOUCH)
1002static irqreturn_t mxt_filter_interrupt(struct mxt_data *data)
1003{
1004 if (atomic_read(&data->st_enabled)) {
Amy Maloche20f970c2013-04-10 13:04:52 +01001005 if (atomic_cmpxchg(&data->st_pending_irqs, 0, 1) == 0)
1006 complete(&data->st_completion);
Amy Maloche434b7d82013-02-15 11:11:05 +00001007 return IRQ_HANDLED;
1008 }
1009 return IRQ_NONE;
1010}
1011#else
1012static irqreturn_t mxt_filter_interrupt(struct mxt_data *data)
1013{
1014 return IRQ_NONE;
1015}
1016#endif
1017
Iiro Valkonen7686b102011-02-02 23:21:58 -08001018static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001019{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001020 struct mxt_data *data = dev_id;
1021 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001022 struct device *dev = &data->client->dev;
1023 int id;
1024 u8 reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001025
Nick Dyer0a4016c2012-01-18 15:17:59 +05301026 if (data->state != APPMODE) {
1027 dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
1028 return IRQ_HANDLED;
1029 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001030
Amy Maloche434b7d82013-02-15 11:11:05 +00001031 if (IRQ_HANDLED == mxt_filter_interrupt(data))
1032 goto end;
1033
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001034 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001035 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001036 dev_err(dev, "Failed to read message\n");
1037 goto end;
1038 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001039 reportid = message.reportid;
1040
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001041 if (!reportid) {
1042 dev_dbg(dev, "Report id 0 is reserved\n");
1043 continue;
1044 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001045
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001046 id = reportid - data->t9_min_reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001047
Amy Maloche1b7ac702013-02-21 19:47:53 -08001048 /* check whether report id is part of T9, T15 or T42 */
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001049 if (reportid >= data->t9_min_reportid &&
1050 reportid <= data->t9_max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -08001051 mxt_input_touchevent(data, &message, id);
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001052 else if (reportid >= data->t15_min_reportid &&
1053 reportid <= data->t15_max_reportid)
1054 mxt_handle_key_array(data, &message);
Mohan Pallakab6acab42012-06-13 11:59:04 +05301055 else if (reportid >= data->t42_min_reportid &&
Amy Maloche1b7ac702013-02-21 19:47:53 -08001056 reportid <= data->t42_max_reportid)
1057 mxt_handle_touch_suppression(data,
1058 message.message[0]);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001059 else
Iiro Valkonen7686b102011-02-02 23:21:58 -08001060 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001061 } while (reportid != 0xff);
1062
1063end:
1064 return IRQ_HANDLED;
1065}
1066
Iiro Valkonen7686b102011-02-02 23:21:58 -08001067static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001068{
Jing Lindc4413c2012-01-16 15:22:52 -08001069 const struct mxt_config_info *config_info = data->config_info;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001070 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001071 struct device *dev = &data->client->dev;
1072 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -08001073 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001074
Jing Lindc4413c2012-01-16 15:22:52 -08001075 if (!config_info) {
Iiro Valkonen71749f52011-02-15 13:36:52 -08001076 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
1077 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001078 }
1079
1080 for (i = 0; i < data->info.object_num; i++) {
1081 object = data->object_table + i;
1082
Iiro Valkonen7686b102011-02-02 23:21:58 -08001083 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001084 continue;
1085
Iiro Valkonen71749f52011-02-15 13:36:52 -08001086 for (j = 0; j < object->size + 1; j++) {
1087 config_offset = index + j;
Jing Lindc4413c2012-01-16 15:22:52 -08001088 if (config_offset > config_info->config_length) {
Iiro Valkonen71749f52011-02-15 13:36:52 -08001089 dev_err(dev, "Not enough config data!\n");
1090 return -EINVAL;
1091 }
Iiro Valkonen7686b102011-02-02 23:21:58 -08001092 mxt_write_object(data, object->type, j,
Jing Lindc4413c2012-01-16 15:22:52 -08001093 config_info->config[config_offset]);
Iiro Valkonen71749f52011-02-15 13:36:52 -08001094 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001095 index += object->size + 1;
1096 }
1097
1098 return 0;
1099}
1100
Iiro Valkonen7686b102011-02-02 23:21:58 -08001101static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001102{
1103 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001104 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001105 int count = 10;
1106 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001107
1108 /* Read dummy message to make high CHG pin */
1109 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001110 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001111 if (error)
1112 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001113 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001114
1115 if (!count) {
1116 dev_err(dev, "CHG pin isn't cleared\n");
1117 return -EBUSY;
1118 }
1119
1120 return 0;
1121}
1122
Iiro Valkonen7686b102011-02-02 23:21:58 -08001123static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001124{
1125 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001126 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001127 int error;
1128 u8 val;
1129
Iiro Valkonen7686b102011-02-02 23:21:58 -08001130 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001131 if (error)
1132 return error;
1133 info->family_id = val;
1134
Iiro Valkonen7686b102011-02-02 23:21:58 -08001135 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001136 if (error)
1137 return error;
1138 info->variant_id = val;
1139
Iiro Valkonen7686b102011-02-02 23:21:58 -08001140 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001141 if (error)
1142 return error;
1143 info->version = val;
1144
Iiro Valkonen7686b102011-02-02 23:21:58 -08001145 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001146 if (error)
1147 return error;
1148 info->build = val;
1149
Iiro Valkonen7686b102011-02-02 23:21:58 -08001150 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001151 if (error)
1152 return error;
1153 info->object_num = val;
1154
1155 return 0;
1156}
1157
Iiro Valkonen7686b102011-02-02 23:21:58 -08001158static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001159{
1160 int error;
1161 int i;
1162 u16 reg;
1163 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001164 u8 buf[MXT_OBJECT_SIZE];
Jing Lindc4413c2012-01-16 15:22:52 -08001165 bool found_t38 = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001166
1167 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001168 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001169
Iiro Valkonen7686b102011-02-02 23:21:58 -08001170 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
1171 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001172 if (error)
1173 return error;
1174
1175 object->type = buf[0];
1176 object->start_address = (buf[2] << 8) | buf[1];
1177 object->size = buf[3];
1178 object->instances = buf[4];
1179 object->num_report_ids = buf[5];
1180
1181 if (object->num_report_ids) {
1182 reportid += object->num_report_ids *
1183 (object->instances + 1);
1184 object->max_reportid = reportid;
1185 }
Jing Lindc4413c2012-01-16 15:22:52 -08001186
1187 /* Calculate index for config major version in config array.
1188 * Major version is the first byte in object T38.
1189 */
Jing Lin8a9472d2012-03-21 15:43:45 -07001190 if (object->type == MXT_SPT_USERDATA_T38) {
1191 data->t38_start_addr = object->start_address;
Jing Lindc4413c2012-01-16 15:22:52 -08001192 found_t38 = true;
Jing Lin8a9472d2012-03-21 15:43:45 -07001193 }
Jing Lindc4413c2012-01-16 15:22:52 -08001194 if (!found_t38 && mxt_object_writable(object->type))
1195 data->cfg_version_idx += object->size + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001196 }
1197
1198 return 0;
1199}
1200
Jing Lin8fadad72012-02-24 10:10:50 -08001201static int compare_versions(const u8 *v1, const u8 *v2)
1202{
1203 int i;
1204
1205 if (!v1 || !v2)
1206 return -EINVAL;
1207
1208 /* The major version number stays the same across different versions for
1209 * a particular controller on a target. The minor and sub-minor version
1210 * numbers indicate which version is newer.
1211 */
1212 if (v1[0] != v2[0])
1213 return -EINVAL;
1214
1215 for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
1216 if (v1[i] > v2[i])
1217 return MXT_CFG_VERSION_LESS; /* v2 is older */
1218
1219 if (v1[i] < v2[i])
1220 return MXT_CFG_VERSION_GREATER; /* v2 is newer */
1221 }
1222
1223 return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
1224}
1225
1226static void mxt_check_config_version(struct mxt_data *data,
1227 const struct mxt_config_info *cfg_info,
1228 bool match_major,
1229 const u8 **cfg_version_found,
1230 bool *found_cfg_major_match)
1231{
1232 const u8 *cfg_version;
1233 int result = -EINVAL;
1234
1235 cfg_version = cfg_info->config + data->cfg_version_idx;
1236
1237 if (*cfg_version_found)
1238 result = compare_versions(*cfg_version_found, cfg_version);
1239
1240 if (match_major) {
1241 if (result >= MXT_CFG_VERSION_EQUAL)
1242 *found_cfg_major_match = true;
1243
1244 if (result == MXT_CFG_VERSION_EQUAL ||
1245 result == MXT_CFG_VERSION_GREATER) {
1246 data->config_info = cfg_info;
1247 data->fw_name = cfg_info->fw_name;
1248 *cfg_version_found = cfg_version;
1249 }
1250
1251 if (result == MXT_CFG_VERSION_GREATER)
1252 data->update_cfg = true;
1253 } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
1254 data->config_info = cfg_info;
1255 data->fw_name = cfg_info->fw_name;
1256 data->update_cfg = true;
1257 *cfg_version_found = cfg_version;
1258 }
1259}
1260
1261/* If the controller's config version has a non-zero major number, call this
1262 * function with match_major = true to look for the latest config present in
1263 * the pdata based on matching family id, variant id, f/w version, build, and
1264 * config major number. If the controller is programmed with wrong config data
1265 * previously, call this function with match_major = false to look for latest
1266 * config based on based on matching family id, variant id, f/w version and
1267 * build only.
1268 */
1269static int mxt_search_config_array(struct mxt_data *data, bool match_major)
Jing Lindc4413c2012-01-16 15:22:52 -08001270{
1271
1272 const struct mxt_platform_data *pdata = data->pdata;
1273 const struct mxt_config_info *cfg_info;
Jing Lin8fadad72012-02-24 10:10:50 -08001274 const struct mxt_info *info = &data->info;
1275 const u8 *cfg_version_found;
1276 bool found_cfg_major_match = false;
Jing Lindc4413c2012-01-16 15:22:52 -08001277 int i;
Jing Lin8fadad72012-02-24 10:10:50 -08001278
1279 cfg_version_found = match_major ? data->cfg_version : NULL;
Jing Lindc4413c2012-01-16 15:22:52 -08001280
1281 for (i = 0; i < pdata->config_array_size; i++) {
1282
1283 cfg_info = &pdata->config_array[i];
1284
1285 if (!cfg_info->config || !cfg_info->config_length)
1286 continue;
1287
1288 if (info->family_id == cfg_info->family_id &&
1289 info->variant_id == cfg_info->variant_id &&
1290 info->version == cfg_info->version &&
1291 info->build == cfg_info->build) {
1292
Jing Lin8fadad72012-02-24 10:10:50 -08001293 mxt_check_config_version(data, cfg_info, match_major,
1294 &cfg_version_found, &found_cfg_major_match);
Jing Lindc4413c2012-01-16 15:22:52 -08001295 }
1296 }
1297
Jing Lin8fadad72012-02-24 10:10:50 -08001298 if (data->config_info || found_cfg_major_match)
1299 return 0;
1300
1301 data->config_info = NULL;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001302 data->fw_name = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001303
Jing Lindc4413c2012-01-16 15:22:52 -08001304 return -EINVAL;
1305}
1306
1307static int mxt_get_config(struct mxt_data *data)
1308{
1309 const struct mxt_platform_data *pdata = data->pdata;
1310 struct device *dev = &data->client->dev;
1311 struct mxt_object *object;
1312 int error;
1313
1314 if (!pdata->config_array || !pdata->config_array_size) {
1315 dev_dbg(dev, "No cfg data provided by platform data\n");
1316 return 0;
1317 }
1318
1319 /* Get current config version */
1320 object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
1321 if (!object) {
1322 dev_err(dev, "Unable to obtain USERDATA object\n");
1323 return -EINVAL;
1324 }
1325
Jing Lin8fadad72012-02-24 10:10:50 -08001326 error = __mxt_read_reg(data->client, object->start_address,
1327 sizeof(data->cfg_version), data->cfg_version);
Jing Lindc4413c2012-01-16 15:22:52 -08001328 if (error) {
1329 dev_err(dev, "Unable to read config version\n");
1330 return error;
1331 }
Jing Lin8fadad72012-02-24 10:10:50 -08001332 dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
1333 data->cfg_version[0], data->cfg_version[1],
1334 data->cfg_version[2]);
Jing Lindc4413c2012-01-16 15:22:52 -08001335
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301336 /* configuration update requires major match */
1337 error = mxt_search_config_array(data, true);
1338
1339 /* if no_force_update is false , try again with false
1340 as the second parameter to mxt_search_config_array */
1341 if (error && (data->no_force_update == false))
1342 error = mxt_search_config_array(data, false);
1343
Jing Lin8fadad72012-02-24 10:10:50 -08001344 if (error) {
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301345 dev_err(dev,
1346 "Unable to find matching config in pdata\n");
1347 return error;
Jing Lin8fadad72012-02-24 10:10:50 -08001348 }
Jing Lindc4413c2012-01-16 15:22:52 -08001349
1350 return 0;
1351}
Jing Lin8fadad72012-02-24 10:10:50 -08001352
Jing Lin64fdd1f2012-12-20 17:08:28 -08001353static void mxt_power_on_delay(struct mxt_data *data)
1354{
1355 const struct mxt_platform_data *pdata = data->pdata;
1356 const struct mxt_config_info *cfg_info;
1357 u32 delay = 0;
1358 int i;
1359
1360 for (i = 0; i < pdata->config_array_size; i++) {
1361 cfg_info = &pdata->config_array[i];
1362
1363 switch (cfg_info->family_id) {
1364 case MXT224_ID:
1365 delay = max_t(u32, delay, MXT224_POWER_ON_TIME);
1366 break;
1367 case MXT224E_ID:
1368 delay = max_t(u32, delay, MXT224E_POWER_ON_TIME);
1369 break;
1370 case MXT336S_ID:
1371 delay = max_t(u32, delay, MXT336S_POWER_ON_TIME);
1372 break;
1373 case MXT1386_ID:
1374 delay = max_t(u32, delay,
1375 max_t(u32, MXT1386_POWER_ON_TIME,
1376 MXT1386E_POWER_ON_TIME));
1377 break;
1378 case MXT1664S_ID:
1379 delay = max_t(u32, delay, MXT1664S_POWER_ON_TIME);
1380 break;
1381 default:
1382 delay = max_t(u32, delay, MXT_POWER_ON_TIME);
1383 }
1384 }
1385
1386 msleep(delay);
1387}
1388
Amy Maloche7e447432011-09-14 11:36:30 -07001389static void mxt_reset_delay(struct mxt_data *data)
1390{
1391 struct mxt_info *info = &data->info;
1392
1393 switch (info->family_id) {
1394 case MXT224_ID:
1395 msleep(MXT224_RESET_TIME);
1396 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -07001397 case MXT224E_ID:
1398 msleep(MXT224E_RESET_TIME);
1399 break;
Amy Maloche41f1cc32012-07-12 13:02:27 -07001400 case MXT336S_ID:
1401 msleep(MXT336S_RESET_TIME);
Jing Lin64fdd1f2012-12-20 17:08:28 -08001402 break;
Amy Maloche7e447432011-09-14 11:36:30 -07001403 case MXT1386_ID:
Jing Lin64fdd1f2012-12-20 17:08:28 -08001404 msleep(max_t(u32, MXT1386_RESET_TIME, MXT1386E_RESET_TIME));
1405 break;
Amy Maloche41f1cc32012-07-12 13:02:27 -07001406 case MXT1664S_ID:
1407 msleep(MXT1664S_RESET_TIME);
Amy Maloche7e447432011-09-14 11:36:30 -07001408 break;
1409 default:
1410 msleep(MXT_RESET_TIME);
1411 }
1412}
1413
Jing Lin8fadad72012-02-24 10:10:50 -08001414static int mxt_backup_nv(struct mxt_data *data)
1415{
1416 int error;
1417 u8 command_register;
1418 int timeout_counter = 0;
1419
1420 /* Backup to memory */
1421 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1422 MXT_COMMAND_BACKUPNV,
1423 MXT_BACKUP_VALUE);
1424 msleep(MXT_BACKUP_TIME);
1425
1426 do {
1427 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
1428 MXT_COMMAND_BACKUPNV,
1429 &command_register);
1430 if (error)
1431 return error;
1432
1433 usleep_range(1000, 2000);
1434
1435 } while ((command_register != 0) && (++timeout_counter <= 100));
1436
1437 if (timeout_counter > 100) {
1438 dev_err(&data->client->dev, "No response after backup!\n");
1439 return -EIO;
1440 }
1441
1442 /* Soft reset */
1443 mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
1444
1445 mxt_reset_delay(data);
1446
1447 return 0;
1448}
1449
Jing Lin412aedc2012-02-28 13:57:19 -08001450static int mxt_save_objects(struct mxt_data *data)
1451{
1452 struct i2c_client *client = data->client;
1453 struct mxt_object *t7_object;
1454 struct mxt_object *t9_object;
1455 struct mxt_object *t15_object;
Mohan Pallakab6acab42012-06-13 11:59:04 +05301456 struct mxt_object *t42_object;
Jing Lin412aedc2012-02-28 13:57:19 -08001457 int error;
1458
1459 /* Store T7 and T9 locally, used in suspend/resume operations */
1460 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
1461 if (!t7_object) {
1462 dev_err(&client->dev, "Failed to get T7 object\n");
1463 return -EINVAL;
1464 }
1465
1466 data->t7_start_addr = t7_object->start_address;
1467 error = __mxt_read_reg(client, data->t7_start_addr,
1468 T7_DATA_SIZE, data->t7_data);
1469 if (error < 0) {
1470 dev_err(&client->dev,
1471 "Failed to save current power state\n");
1472 return error;
1473 }
1474
Jing Lin412aedc2012-02-28 13:57:19 -08001475 /* Store T9, T15's min and max report ids */
1476 t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1477 if (!t9_object) {
1478 dev_err(&client->dev, "Failed to get T9 object\n");
1479 return -EINVAL;
1480 }
1481 data->t9_max_reportid = t9_object->max_reportid;
1482 data->t9_min_reportid = t9_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001483 (t9_object->num_report_ids *
1484 (t9_object->instances + 1)) + 1;
Jing Lin412aedc2012-02-28 13:57:19 -08001485
1486 if (data->pdata->key_codes) {
1487 t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
1488 if (!t15_object)
1489 dev_dbg(&client->dev, "T15 object is not available\n");
1490 else {
1491 data->t15_max_reportid = t15_object->max_reportid;
1492 data->t15_min_reportid = t15_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001493 (t15_object->num_report_ids *
1494 (t15_object->instances + 1)) + 1;
Jing Lin412aedc2012-02-28 13:57:19 -08001495 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001496 }
1497
Mohan Pallakab6acab42012-06-13 11:59:04 +05301498 /* Store T42 min and max report ids */
1499 t42_object = mxt_get_object(data, MXT_PROCI_TOUCHSUPPRESSION_T42);
1500 if (!t42_object)
1501 dev_dbg(&client->dev, "T42 object is not available\n");
1502 else {
1503 data->t42_max_reportid = t42_object->max_reportid;
1504 data->t42_min_reportid = t42_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001505 (t42_object->num_report_ids *
1506 (t42_object->instances + 1)) + 1;
Mohan Pallakab6acab42012-06-13 11:59:04 +05301507 }
1508
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001509 return 0;
1510}
1511
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301512static int mxt_update_cfg(struct mxt_data *data)
1513{
1514 int error;
1515 const u8 *cfg_ver;
1516
1517 /* Get config data from platform data */
1518 error = mxt_get_config(data);
1519 if (error)
1520 dev_dbg(&data->client->dev, "Config info not found.\n");
1521
1522 /* Check register init values */
1523 if (data->config_info && data->config_info->config) {
1524 if (data->update_cfg) {
1525 error = mxt_check_reg_init(data);
1526 if (error) {
1527 dev_err(&data->client->dev,
1528 "Failed to check reg init value\n");
1529 return error;
1530 }
1531
1532 error = mxt_backup_nv(data);
1533 if (error) {
1534 dev_err(&data->client->dev, "Failed to back up NV\n");
1535 return error;
1536 }
1537
1538 cfg_ver = data->config_info->config +
1539 data->cfg_version_idx;
1540 dev_info(&data->client->dev,
1541 "Config updated from %d.%d.%d to %d.%d.%d\n",
1542 data->cfg_version[0], data->cfg_version[1],
1543 data->cfg_version[2],
1544 cfg_ver[0], cfg_ver[1], cfg_ver[2]);
1545
1546 memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
1547 }
1548 } else {
1549 dev_info(&data->client->dev,
1550 "No cfg data defined, skipping check reg init\n");
1551 }
1552
1553 error = mxt_save_objects(data);
1554 if (error)
1555 return error;
1556
1557 return 0;
1558}
1559
1560
1561
Iiro Valkonen7686b102011-02-02 23:21:58 -08001562static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001563{
1564 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001565 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001566 int error;
1567 u8 val;
1568
Iiro Valkonen7686b102011-02-02 23:21:58 -08001569 error = mxt_get_info(data);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301570 if (error) {
1571 /* Try bootloader mode */
1572 error = mxt_switch_to_bootloader_address(data);
1573 if (error)
1574 return error;
1575
1576 error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
1577 if (error)
1578 return error;
1579
1580 dev_err(&client->dev, "Application CRC failure\n");
1581 data->state = BOOTLOADER;
1582
1583 return 0;
1584 }
1585
1586 dev_info(&client->dev,
1587 "Family ID: %d Variant ID: %d Version: %d.%d "
1588 "Build: 0x%02X Object Num: %d\n",
1589 info->family_id, info->variant_id,
1590 info->version >> 4, info->version & 0xf,
1591 info->build, info->object_num);
1592
1593 data->state = APPMODE;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001594
1595 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001596 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001597 GFP_KERNEL);
1598 if (!data->object_table) {
1599 dev_err(&client->dev, "Failed to allocate memory\n");
1600 return -ENOMEM;
1601 }
1602
1603 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001604 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001605 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001606 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001607
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301608 error = mxt_update_cfg(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001609 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001610 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001611 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001612 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001613 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001614 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001615 info->matrix_xsize = val;
1616
Iiro Valkonen7686b102011-02-02 23:21:58 -08001617 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001618 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001619 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001620 info->matrix_ysize = val;
1621
1622 dev_info(&client->dev,
Nick Dyer0a4016c2012-01-18 15:17:59 +05301623 "Matrix X Size: %d Matrix Y Size: %d\n",
1624 info->matrix_xsize, info->matrix_ysize);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001625
1626 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001627
Jing Lin32c72532011-11-03 12:02:33 -07001628free_object_table:
1629 kfree(data->object_table);
1630 return error;
Joonyoung Shim910d8052011-04-12 23:14:38 -07001631}
1632
Iiro Valkonen7686b102011-02-02 23:21:58 -08001633static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001634 struct device_attribute *attr, char *buf)
1635{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001636 struct mxt_data *data = dev_get_drvdata(dev);
1637 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001638 int count = 0;
1639 int i, j;
1640 int error;
1641 u8 val;
1642
1643 for (i = 0; i < data->info.object_num; i++) {
1644 object = data->object_table + i;
1645
Daniel Kurtz626af862011-10-06 15:43:20 -07001646 count += snprintf(buf + count, PAGE_SIZE - count,
1647 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001648 i + 1, object->type);
Daniel Kurtz626af862011-10-06 15:43:20 -07001649 if (count >= PAGE_SIZE)
1650 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001651
Iiro Valkonen7686b102011-02-02 23:21:58 -08001652 if (!mxt_object_readable(object->type)) {
Daniel Kurtz626af862011-10-06 15:43:20 -07001653 count += snprintf(buf + count, PAGE_SIZE - count,
1654 "\n");
1655 if (count >= PAGE_SIZE)
1656 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001657 continue;
1658 }
1659
1660 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001661 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001662 object->type, j, &val);
1663 if (error)
1664 return error;
1665
Daniel Kurtz626af862011-10-06 15:43:20 -07001666 count += snprintf(buf + count, PAGE_SIZE - count,
1667 "\t[%2d]: %02x (%d)\n", j, val, val);
1668 if (count >= PAGE_SIZE)
1669 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001670 }
1671
Daniel Kurtz626af862011-10-06 15:43:20 -07001672 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1673 if (count >= PAGE_SIZE)
1674 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001675 }
1676
1677 return count;
1678}
1679
Jing Lincc974cb2012-02-01 23:13:14 -08001680static int strtobyte(const char *data, u8 *value)
1681{
1682 char str[3];
1683
1684 str[0] = data[0];
1685 str[1] = data[1];
1686 str[2] = '\0';
1687
1688 return kstrtou8(str, 16, value);
1689}
1690
Iiro Valkonen7686b102011-02-02 23:21:58 -08001691static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001692{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001693 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001694 struct i2c_client *client = data->client;
1695 const struct firmware *fw = NULL;
1696 unsigned int frame_size;
Nick Dyer0a4016c2012-01-18 15:17:59 +05301697 unsigned int retry = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001698 unsigned int pos = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001699 int ret, i, max_frame_size;
1700 u8 *frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001701
Jing Lincc974cb2012-02-01 23:13:14 -08001702 switch (data->info.family_id) {
1703 case MXT224_ID:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301704 case MXT224E_ID:
Amy Maloche265fc3c2013-01-17 11:50:24 -08001705 case MXT336S_ID:
Jing Lincc974cb2012-02-01 23:13:14 -08001706 max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
1707 break;
1708 case MXT1386_ID:
Amy Maloche265fc3c2013-01-17 11:50:24 -08001709 case MXT1664S_ID:
Jing Lincc974cb2012-02-01 23:13:14 -08001710 max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
1711 break;
1712 default:
1713 return -EINVAL;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001714 }
1715
Jing Lincc974cb2012-02-01 23:13:14 -08001716 frame = kmalloc(max_frame_size, GFP_KERNEL);
1717 if (!frame) {
1718 dev_err(dev, "Unable to allocate memory for frame data\n");
1719 return -ENOMEM;
1720 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001721
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001722 ret = request_firmware(&fw, fn, dev);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301723 if (ret < 0) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001724 dev_err(dev, "Unable to open firmware %s\n", fn);
Jing Lincc974cb2012-02-01 23:13:14 -08001725 goto free_frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001726 }
1727
Nick Dyer0a4016c2012-01-18 15:17:59 +05301728 if (data->state != BOOTLOADER) {
1729 /* Change to the bootloader mode */
1730 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1731 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1732 mxt_reset_delay(data);
Amy Maloche7e447432011-09-14 11:36:30 -07001733
Nick Dyer0a4016c2012-01-18 15:17:59 +05301734 ret = mxt_switch_to_bootloader_address(data);
1735 if (ret)
1736 goto release_firmware;
1737 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001738
Iiro Valkonen7686b102011-02-02 23:21:58 -08001739 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301740 if (ret) {
1741 /* Bootloader may still be unlocked from previous update
1742 * attempt */
1743 ret = mxt_check_bootloader(client,
1744 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001745
Nick Dyer0a4016c2012-01-18 15:17:59 +05301746 if (ret)
1747 goto return_to_app_mode;
1748 } else {
1749 dev_info(dev, "Unlocking bootloader\n");
1750 /* Unlock bootloader */
1751 mxt_unlock_bootloader(client);
1752 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001753
1754 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001755 ret = mxt_check_bootloader(client,
1756 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001757 if (ret)
Nick Dyer0a4016c2012-01-18 15:17:59 +05301758 goto release_firmware;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001759
Jing Lincc974cb2012-02-01 23:13:14 -08001760 /* Get frame length MSB */
1761 ret = strtobyte(fw->data + pos, frame);
1762 if (ret)
1763 goto release_firmware;
1764
1765 /* Get frame length LSB */
1766 ret = strtobyte(fw->data + pos + 2, frame + 1);
1767 if (ret)
1768 goto release_firmware;
1769
1770 frame_size = ((*frame << 8) | *(frame + 1));
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001771
1772 /* We should add 2 at frame size as the the firmware data is not
1773 * included the CRC bytes.
1774 */
1775 frame_size += 2;
1776
Jing Lincc974cb2012-02-01 23:13:14 -08001777 if (frame_size > max_frame_size) {
1778 dev_err(dev, "Invalid frame size - %d\n", frame_size);
1779 ret = -EINVAL;
1780 goto release_firmware;
1781 }
1782
1783 /* Convert frame data and CRC from hex to binary */
1784 for (i = 2; i < frame_size; i++) {
1785 ret = strtobyte(fw->data + pos + i * 2, frame + i);
1786 if (ret)
1787 goto release_firmware;
1788 }
1789
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001790 /* Write one frame to device */
Jing Lincc974cb2012-02-01 23:13:14 -08001791 mxt_fw_write(client, frame, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001792
Iiro Valkonen7686b102011-02-02 23:21:58 -08001793 ret = mxt_check_bootloader(client,
1794 MXT_FRAME_CRC_PASS);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301795 if (ret) {
1796 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001797
Nick Dyer0a4016c2012-01-18 15:17:59 +05301798 /* Back off by 20ms per retry */
1799 msleep(retry * 20);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001800
Nick Dyer0a4016c2012-01-18 15:17:59 +05301801 if (retry > 20)
1802 goto release_firmware;
1803 } else {
1804 retry = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001805 pos += frame_size * 2;
1806 dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301807 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001808 }
1809
Nick Dyer0a4016c2012-01-18 15:17:59 +05301810return_to_app_mode:
1811 mxt_switch_to_appmode_address(data);
1812release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001813 release_firmware(fw);
Jing Lincc974cb2012-02-01 23:13:14 -08001814free_frame:
1815 kfree(frame);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001816
1817 return ret;
1818}
1819
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001820static const char *
1821mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
1822{
1823 const struct mxt_platform_data *pdata = data->pdata;
1824 const struct mxt_config_info *cfg_info;
1825 const char *fw_name = NULL;
1826 int i;
1827
1828 for (i = 0; i < pdata->config_array_size; i++) {
1829 cfg_info = &pdata->config_array[i];
1830 if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
1831 data->config_info = cfg_info;
1832 data->info.family_id = cfg_info->family_id;
1833 fw_name = cfg_info->fw_name;
1834 }
1835 }
1836
1837 return fw_name;
1838}
1839
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301840static ssize_t mxt_force_cfg_update_store(struct device *dev,
1841 struct device_attribute *attr,
1842 const char *buf, size_t count)
1843{
1844 struct mxt_data *data = dev_get_drvdata(dev);
1845 int flag = buf[0]-'0';
1846 int error;
1847 data->no_force_update = !flag;
1848
1849 if (data->state == APPMODE) {
1850 disable_irq(data->irq);
1851 error = mxt_update_cfg(data);
1852 enable_irq(data->irq);
1853 if (error)
1854 return error;
1855 } else {
1856 dev_err(dev,
1857 "Not in APPMODE, Unable to force cfg update\n");
1858 return -EINVAL;
1859 }
1860
1861 return count;
1862}
1863
Iiro Valkonen7686b102011-02-02 23:21:58 -08001864static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001865 struct device_attribute *attr,
1866 const char *buf, size_t count)
1867{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001868 struct mxt_data *data = dev_get_drvdata(dev);
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301869 int error, address;
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001870 const char *fw_name;
1871 u8 bootldr_id;
Jing Lin8a9472d2012-03-21 15:43:45 -07001872 u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001873
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301874 data->no_force_update = false;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001875 /* If fw_name is set, then the existing firmware has an upgrade */
1876 if (!data->fw_name) {
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001877 /*
1878 * If the device boots up in the bootloader mode, check if
1879 * there is a firmware to upgrade.
1880 */
1881 if (data->state == BOOTLOADER) {
1882 bootldr_id = mxt_get_bootloader_id(data->client);
1883 if (bootldr_id <= 0) {
1884 dev_err(dev,
1885 "Unable to retrieve bootloader id\n");
1886 return -EINVAL;
1887 }
1888 fw_name = mxt_search_fw_name(data, bootldr_id);
1889 if (fw_name == NULL) {
1890 dev_err(dev,
1891 "Unable to find fw from bootloader id\n");
1892 return -EINVAL;
1893 }
1894 } else {
1895 /* In APPMODE, if the f/w name does not exist, quit */
1896 dev_err(dev,
1897 "Firmware name not specified in platform data\n");
1898 return -EINVAL;
1899 }
1900 } else {
1901 fw_name = data->fw_name;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001902 }
1903
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001904 dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001905
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001906 disable_irq(data->irq);
1907
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001908 error = mxt_load_fw(dev, fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001909 if (error) {
1910 dev_err(dev, "The firmware update failed(%d)\n", error);
1911 count = error;
1912 } else {
Nick Dyer0a4016c2012-01-18 15:17:59 +05301913 dev_info(dev, "The firmware update succeeded\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001914
1915 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001916 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001917
Nick Dyer0a4016c2012-01-18 15:17:59 +05301918 data->state = INIT;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001919 kfree(data->object_table);
1920 data->object_table = NULL;
Jing Lincc974cb2012-02-01 23:13:14 -08001921 data->cfg_version_idx = 0;
Jing Lina962ba32012-12-03 09:46:33 -08001922 data->config_info = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001923 data->update_cfg = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001924
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301925 /* T38 object address might have changed, read it from
1926 touch controller */
1927 address = mxt_get_object_address(dev, MXT_SPT_USERDATA_T38);
1928 if (address < 0) {
1929 dev_err(dev, "T38 required for touch operation\n");
1930 return -EINVAL;
1931 }
1932
1933 data->t38_start_addr = address;
1934
Jing Lin8a9472d2012-03-21 15:43:45 -07001935 error = __mxt_write_reg(data->client, data->t38_start_addr,
1936 sizeof(cfg_version), cfg_version);
1937 if (error)
1938 dev_err(dev,
1939 "Unable to zero out config version after fw upgrade\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001940
Iiro Valkonen7686b102011-02-02 23:21:58 -08001941 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001942 }
1943
Nick Dyer0a4016c2012-01-18 15:17:59 +05301944 if (data->state == APPMODE) {
1945 enable_irq(data->irq);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001946
Nick Dyer0a4016c2012-01-18 15:17:59 +05301947 error = mxt_make_highchg(data);
1948 if (error)
1949 return error;
1950 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07001951
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001952 return count;
1953}
1954
Amy Maloche434b7d82013-02-15 11:11:05 +00001955#if defined(CONFIG_SECURE_TOUCH)
1956
1957static ssize_t mxt_secure_touch_enable_show(struct device *dev,
1958 struct device_attribute *attr, char *buf)
1959{
1960 struct mxt_data *data = dev_get_drvdata(dev);
1961 return scnprintf(buf, PAGE_SIZE, "%d", atomic_read(&data->st_enabled));
1962}
1963/*
1964 * Accept only "0" and "1" valid values.
1965 * "0" will reset the st_enabled flag, then wake up the reading process.
1966 * The bus driver is notified via pm_runtime that it is not required to stay
1967 * awake anymore.
1968 * It will also make sure the queue of events is emptied in the controller,
1969 * in case a touch happened in between the secure touch being disabled and
1970 * the local ISR being ungated.
1971 * "1" will set the st_enabled flag and clear the st_pending_irqs flag.
1972 * The bus driver is requested via pm_runtime to stay awake.
1973 */
1974static ssize_t mxt_secure_touch_enable_store(struct device *dev,
1975 struct device_attribute *attr,
1976 const char *buf, size_t count)
1977{
1978 struct mxt_data *data = dev_get_drvdata(dev);
1979 unsigned long value;
1980 int err = 0;
1981
1982 if (count > 2)
1983 return -EINVAL;
1984
1985 err = kstrtoul(buf, 10, &value);
1986 if (err != 0)
1987 return err;
1988
1989 err = count;
1990
1991 switch (value) {
1992 case 0:
1993 if (atomic_read(&data->st_enabled) == 0)
1994 break;
1995
1996 pm_runtime_put(&data->client->adapter->dev);
1997 atomic_set(&data->st_enabled, 0);
1998 complete(&data->st_completion);
1999 mxt_interrupt(data->client->irq, data);
Amy Maloche20f970c2013-04-10 13:04:52 +01002000 complete(&data->st_powerdown);
Amy Maloche434b7d82013-02-15 11:11:05 +00002001 break;
2002 case 1:
2003 if (atomic_read(&data->st_enabled)) {
2004 err = -EBUSY;
2005 break;
2006 }
2007
2008 if (pm_runtime_get(data->client->adapter->dev.parent) < 0) {
2009 dev_err(&data->client->dev, "pm_runtime_get failed\n");
2010 err = -EIO;
2011 break;
2012 }
Amy Maloche20f970c2013-04-10 13:04:52 +01002013 INIT_COMPLETION(data->st_completion);
2014 INIT_COMPLETION(data->st_powerdown);
Amy Maloche434b7d82013-02-15 11:11:05 +00002015 atomic_set(&data->st_pending_irqs, 0);
2016 atomic_set(&data->st_enabled, 1);
2017 break;
2018 default:
2019 dev_err(&data->client->dev, "unsupported value: %lu\n", value);
2020 err = -EINVAL;
2021 break;
2022 }
2023
2024 return err;
2025}
2026
2027static ssize_t mxt_secure_touch_show(struct device *dev,
2028 struct device_attribute *attr, char *buf)
2029{
2030 struct mxt_data *data = dev_get_drvdata(dev);
2031 int err;
2032
2033 if (atomic_read(&data->st_enabled) == 0)
2034 return -EBADF;
2035
2036 err = wait_for_completion_interruptible(&data->st_completion);
2037
2038 if (err)
2039 return err;
2040
2041 if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) != 1)
Amy Maloche20f970c2013-04-10 13:04:52 +01002042 return -EINVAL;
Amy Maloche434b7d82013-02-15 11:11:05 +00002043
2044 return scnprintf(buf, PAGE_SIZE, "%u", 1);
2045}
2046
2047static DEVICE_ATTR(secure_touch_enable, 0666, mxt_secure_touch_enable_show,
2048 mxt_secure_touch_enable_store);
2049static DEVICE_ATTR(secure_touch, 0444, mxt_secure_touch_show, NULL);
2050#endif
2051
Iiro Valkonen7686b102011-02-02 23:21:58 -08002052static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
2053static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302054static DEVICE_ATTR(force_cfg_update, 0664, NULL, mxt_force_cfg_update_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002055
Iiro Valkonen7686b102011-02-02 23:21:58 -08002056static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002057 &dev_attr_object.attr,
2058 &dev_attr_update_fw.attr,
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302059 &dev_attr_force_cfg_update.attr,
Amy Maloche434b7d82013-02-15 11:11:05 +00002060#if defined(CONFIG_SECURE_TOUCH)
2061 &dev_attr_secure_touch_enable.attr,
2062 &dev_attr_secure_touch.attr,
2063#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002064 NULL
2065};
2066
Iiro Valkonen7686b102011-02-02 23:21:58 -08002067static const struct attribute_group mxt_attr_group = {
2068 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002069};
2070
Amy Maloche20f970c2013-04-10 13:04:52 +01002071
2072#if defined(CONFIG_SECURE_TOUCH)
2073static void mxt_secure_touch_stop(struct mxt_data *data)
2074{
2075 if (atomic_read(&data->st_enabled)) {
2076 complete(&data->st_completion);
2077 wait_for_completion_interruptible(&data->st_powerdown);
2078 }
2079}
2080#else
2081static void mxt_secure_touch_stop(struct mxt_data *data)
2082{
2083}
2084#endif
2085
Amy Maloche52262212011-09-15 16:46:57 -07002086static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002087{
Jing Lin36aee812011-10-17 17:17:28 -07002088 int error;
Amy Maloche20f970c2013-04-10 13:04:52 +01002089 mxt_secure_touch_stop(data);
Jing Lin36aee812011-10-17 17:17:28 -07002090
Amy Maloche52262212011-09-15 16:46:57 -07002091 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07002092 error = __mxt_write_reg(data->client, data->t7_start_addr,
2093 T7_DATA_SIZE, data->t7_data);
2094 if (error < 0) {
2095 dev_err(&data->client->dev,
2096 "failed to restore old power state\n");
2097 return error;
Amy Maloche52262212011-09-15 16:46:57 -07002098 }
Jing Lin36aee812011-10-17 17:17:28 -07002099
Amy Maloche52262212011-09-15 16:46:57 -07002100 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002101}
2102
Amy Maloche52262212011-09-15 16:46:57 -07002103static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002104{
Jing Lin36aee812011-10-17 17:17:28 -07002105 int error;
2106 u8 t7_data[T7_DATA_SIZE] = {0};
Amy Maloche20f970c2013-04-10 13:04:52 +01002107 mxt_secure_touch_stop(data);
Jing Lin36aee812011-10-17 17:17:28 -07002108
Jing Lin36aee812011-10-17 17:17:28 -07002109 error = __mxt_write_reg(data->client, data->t7_start_addr,
2110 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07002111 if (error < 0) {
2112 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07002113 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07002114 return error;
2115 }
2116
2117 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002118}
2119
Iiro Valkonen7686b102011-02-02 23:21:58 -08002120static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002121{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002122 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07002123 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002124
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08002125 if (data->state == APPMODE) {
2126 error = mxt_start(data);
2127 if (error < 0) {
2128 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
2129 return error;
2130 }
Amy Maloche52262212011-09-15 16:46:57 -07002131 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002132
2133 return 0;
2134}
2135
Iiro Valkonen7686b102011-02-02 23:21:58 -08002136static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002137{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002138 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07002139 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002140
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08002141 if (data->state == APPMODE) {
2142 error = mxt_stop(data);
2143 if (error < 0)
2144 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
2145 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002146}
2147
Amy Malochec331f842012-01-24 10:33:47 -08002148static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
2149{
2150 return (regulator_count_voltages(reg) > 0) ?
2151 regulator_set_optimum_mode(reg, load_uA) : 0;
2152}
2153
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302154static int mxt_power_on(struct mxt_data *data, bool on)
2155{
2156 int rc;
2157
2158 if (on == false)
2159 goto power_off;
2160
Amy Malochec331f842012-01-24 10:33:47 -08002161 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302162 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07002163 dev_err(&data->client->dev,
2164 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302165 return rc;
2166 }
2167
Amy Maloche21115eb2011-11-02 09:04:37 -07002168 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302169 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07002170 dev_err(&data->client->dev,
2171 "Regulator vcc_ana enable failed rc=%d\n", rc);
2172 goto error_reg_en_vcc_ana;
2173 }
2174
2175 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002176 rc = reg_set_optimum_mode_check(data->vcc_dig,
2177 MXT_ACTIVE_LOAD_DIG_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002178 if (rc < 0) {
2179 dev_err(&data->client->dev,
2180 "Regulator vcc_dig set_opt failed rc=%d\n",
2181 rc);
2182 goto error_reg_opt_vcc_dig;
2183 }
2184
2185 rc = regulator_enable(data->vcc_dig);
2186 if (rc) {
2187 dev_err(&data->client->dev,
2188 "Regulator vcc_dig enable failed rc=%d\n", rc);
2189 goto error_reg_en_vcc_dig;
2190 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302191 }
2192
2193 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002194 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302195 if (rc < 0) {
2196 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002197 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302198 goto error_reg_opt_i2c;
2199 }
2200
2201 rc = regulator_enable(data->vcc_i2c);
2202 if (rc) {
2203 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002204 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302205 goto error_reg_en_vcc_i2c;
2206 }
2207 }
2208
Amy Malochef0d7b8d2011-10-17 12:10:51 -07002209 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302210
2211 return 0;
2212
2213error_reg_en_vcc_i2c:
2214 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002215 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302216error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07002217 if (data->pdata->digital_pwr_regulator)
2218 regulator_disable(data->vcc_dig);
2219error_reg_en_vcc_dig:
2220 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002221 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002222error_reg_opt_vcc_dig:
2223 regulator_disable(data->vcc_ana);
2224error_reg_en_vcc_ana:
Amy Malochec331f842012-01-24 10:33:47 -08002225 reg_set_optimum_mode_check(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302226 return rc;
2227
2228power_off:
Amy Malochec331f842012-01-24 10:33:47 -08002229 reg_set_optimum_mode_check(data->vcc_ana, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002230 regulator_disable(data->vcc_ana);
2231 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002232 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002233 regulator_disable(data->vcc_dig);
2234 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302235 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002236 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302237 regulator_disable(data->vcc_i2c);
2238 }
2239 msleep(50);
2240 return 0;
2241}
2242
2243static int mxt_regulator_configure(struct mxt_data *data, bool on)
2244{
2245 int rc;
2246
2247 if (on == false)
2248 goto hw_shutdown;
2249
Amy Maloche21115eb2011-11-02 09:04:37 -07002250 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
2251 if (IS_ERR(data->vcc_ana)) {
2252 rc = PTR_ERR(data->vcc_ana);
2253 dev_err(&data->client->dev,
2254 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302255 return rc;
2256 }
2257
Amy Maloche21115eb2011-11-02 09:04:37 -07002258 if (regulator_count_voltages(data->vcc_ana) > 0) {
2259 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302260 MXT_VTG_MAX_UV);
2261 if (rc) {
2262 dev_err(&data->client->dev,
2263 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07002264 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302265 }
2266 }
Amy Maloche21115eb2011-11-02 09:04:37 -07002267 if (data->pdata->digital_pwr_regulator) {
2268 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
2269 if (IS_ERR(data->vcc_dig)) {
2270 rc = PTR_ERR(data->vcc_dig);
2271 dev_err(&data->client->dev,
2272 "Regulator get dig failed rc=%d\n", rc);
2273 goto error_get_vtg_vcc_dig;
2274 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302275
Amy Maloche21115eb2011-11-02 09:04:37 -07002276 if (regulator_count_voltages(data->vcc_dig) > 0) {
2277 rc = regulator_set_voltage(data->vcc_dig,
2278 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
2279 if (rc) {
2280 dev_err(&data->client->dev,
2281 "regulator set_vtg failed rc=%d\n", rc);
2282 goto error_set_vtg_vcc_dig;
2283 }
2284 }
2285 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302286 if (data->pdata->i2c_pull_up) {
2287 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
2288 if (IS_ERR(data->vcc_i2c)) {
2289 rc = PTR_ERR(data->vcc_i2c);
2290 dev_err(&data->client->dev,
2291 "Regulator get failed rc=%d\n", rc);
2292 goto error_get_vtg_i2c;
2293 }
2294 if (regulator_count_voltages(data->vcc_i2c) > 0) {
2295 rc = regulator_set_voltage(data->vcc_i2c,
2296 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
2297 if (rc) {
2298 dev_err(&data->client->dev,
2299 "regulator set_vtg failed rc=%d\n", rc);
2300 goto error_set_vtg_i2c;
2301 }
2302 }
2303 }
2304
2305 return 0;
2306
2307error_set_vtg_i2c:
2308 regulator_put(data->vcc_i2c);
2309error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07002310 if (data->pdata->digital_pwr_regulator)
2311 if (regulator_count_voltages(data->vcc_dig) > 0)
2312 regulator_set_voltage(data->vcc_dig, 0,
2313 MXT_VTG_DIG_MAX_UV);
2314error_set_vtg_vcc_dig:
2315 if (data->pdata->digital_pwr_regulator)
2316 regulator_put(data->vcc_dig);
2317error_get_vtg_vcc_dig:
2318 if (regulator_count_voltages(data->vcc_ana) > 0)
2319 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2320error_set_vtg_vcc_ana:
2321 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302322 return rc;
2323
2324hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07002325 if (regulator_count_voltages(data->vcc_ana) > 0)
2326 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2327 regulator_put(data->vcc_ana);
2328 if (data->pdata->digital_pwr_regulator) {
2329 if (regulator_count_voltages(data->vcc_dig) > 0)
2330 regulator_set_voltage(data->vcc_dig, 0,
2331 MXT_VTG_DIG_MAX_UV);
2332 regulator_put(data->vcc_dig);
2333 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302334 if (data->pdata->i2c_pull_up) {
2335 if (regulator_count_voltages(data->vcc_i2c) > 0)
2336 regulator_set_voltage(data->vcc_i2c, 0,
2337 MXT_I2C_VTG_MAX_UV);
2338 regulator_put(data->vcc_i2c);
2339 }
2340 return 0;
2341}
2342
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302343#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07002344static int mxt_regulator_lpm(struct mxt_data *data, bool on)
2345{
2346
2347 int rc;
2348
2349 if (on == false)
2350 goto regulator_hpm;
2351
Amy Malochec331f842012-01-24 10:33:47 -08002352 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002353 if (rc < 0) {
2354 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002355 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002356 goto fail_regulator_lpm;
2357 }
2358
Amy Maloche21115eb2011-11-02 09:04:37 -07002359 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002360 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002361 MXT_LPM_LOAD_DIG_UA);
2362 if (rc < 0) {
2363 dev_err(&data->client->dev,
2364 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2365 goto fail_regulator_lpm;
2366 }
2367 }
2368
Jing Linbace50b2011-10-18 22:55:47 -07002369 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002370 rc = reg_set_optimum_mode_check(data->vcc_i2c,
Jing Linbace50b2011-10-18 22:55:47 -07002371 MXT_I2C_LPM_LOAD_UA);
2372 if (rc < 0) {
2373 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002374 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002375 goto fail_regulator_lpm;
2376 }
2377 }
2378
2379 return 0;
2380
2381regulator_hpm:
2382
Amy Malochec331f842012-01-24 10:33:47 -08002383 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002384 if (rc < 0) {
2385 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002386 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002387 goto fail_regulator_hpm;
2388 }
2389
Amy Maloche21115eb2011-11-02 09:04:37 -07002390 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002391 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002392 MXT_ACTIVE_LOAD_DIG_UA);
2393 if (rc < 0) {
2394 dev_err(&data->client->dev,
2395 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2396 goto fail_regulator_hpm;
2397 }
2398 }
2399
Jing Linbace50b2011-10-18 22:55:47 -07002400 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002401 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002402 if (rc < 0) {
2403 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002404 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002405 goto fail_regulator_hpm;
2406 }
2407 }
2408
2409 return 0;
2410
2411fail_regulator_lpm:
Amy Malochec331f842012-01-24 10:33:47 -08002412 reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002413 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002414 reg_set_optimum_mode_check(data->vcc_dig,
2415 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002416 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002417 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002418
2419 return rc;
2420
2421fail_regulator_hpm:
Amy Malochec331f842012-01-24 10:33:47 -08002422 reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002423 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002424 reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002425 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002426 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002427
2428 return rc;
2429}
2430
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302431static int mxt_suspend(struct device *dev)
2432{
2433 struct i2c_client *client = to_i2c_client(dev);
2434 struct mxt_data *data = i2c_get_clientdata(client);
2435 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002436 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302437
2438 mutex_lock(&input_dev->mutex);
2439
Amy Maloche52262212011-09-15 16:46:57 -07002440 if (input_dev->users) {
2441 error = mxt_stop(data);
2442 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002443 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07002444 mutex_unlock(&input_dev->mutex);
2445 return error;
2446 }
2447
2448 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302449
2450 mutex_unlock(&input_dev->mutex);
2451
Jing Linbace50b2011-10-18 22:55:47 -07002452 /* put regulators in low power mode */
2453 error = mxt_regulator_lpm(data, true);
2454 if (error < 0) {
2455 dev_err(dev, "failed to enter low power mode\n");
2456 return error;
2457 }
2458
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302459 return 0;
2460}
2461
2462static int mxt_resume(struct device *dev)
2463{
2464 struct i2c_client *client = to_i2c_client(dev);
2465 struct mxt_data *data = i2c_get_clientdata(client);
2466 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002467 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302468
Jing Linbace50b2011-10-18 22:55:47 -07002469 /* put regulators in high power mode */
2470 error = mxt_regulator_lpm(data, false);
2471 if (error < 0) {
2472 dev_err(dev, "failed to enter high power mode\n");
2473 return error;
2474 }
2475
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302476 mutex_lock(&input_dev->mutex);
2477
Amy Maloche52262212011-09-15 16:46:57 -07002478 if (input_dev->users) {
2479 error = mxt_start(data);
2480 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002481 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07002482 mutex_unlock(&input_dev->mutex);
2483 return error;
2484 }
2485 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302486
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302487 /* calibrate */
2488 if (data->pdata->need_calibration) {
Amy Maloche20f970c2013-04-10 13:04:52 +01002489 mxt_secure_touch_stop(data);
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302490 error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
2491 MXT_COMMAND_CALIBRATE, 1);
2492 if (error < 0)
2493 dev_dbg(dev, "sending calibration command failed\n");
2494 }
2495
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302496 mutex_unlock(&input_dev->mutex);
2497
2498 return 0;
2499}
2500
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302501static const struct dev_pm_ops mxt_pm_ops = {
Anurag Singh49d76132013-01-29 12:07:00 -08002502#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302503 .suspend = mxt_suspend,
2504 .resume = mxt_resume,
2505#endif
2506};
2507#endif
2508
Jing Lin6cfc00e2011-11-02 15:15:30 -07002509static int mxt_debugfs_object_show(struct seq_file *m, void *v)
2510{
2511 struct mxt_data *data = m->private;
2512 struct mxt_object *object;
2513 struct device *dev = &data->client->dev;
2514 int i, j, k;
2515 int error;
2516 int obj_size;
2517 u8 val;
2518
2519 for (i = 0; i < data->info.object_num; i++) {
2520 object = data->object_table + i;
2521 obj_size = object->size + 1;
2522
2523 seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
2524
2525 for (j = 0; j < object->instances + 1; j++) {
2526 seq_printf(m, "[Instance %d]\n", j);
2527
2528 for (k = 0; k < obj_size; k++) {
2529 error = mxt_read_object(data, object->type,
2530 j * obj_size + k, &val);
2531 if (error) {
2532 dev_err(dev,
2533 "Failed to read object %d "
2534 "instance %d at offset %d\n",
2535 object->type, j, k);
2536 return error;
2537 }
2538
2539 seq_printf(m, "Byte %d: 0x%02x (%d)\n",
2540 k, val, val);
2541 }
2542 }
2543 }
2544
2545 return 0;
2546}
2547
2548static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
2549{
2550 return single_open(file, mxt_debugfs_object_show, inode->i_private);
2551}
2552
2553static const struct file_operations mxt_object_fops = {
2554 .owner = THIS_MODULE,
2555 .open = mxt_debugfs_object_open,
2556 .read = seq_read,
2557 .release = single_release,
2558};
2559
Stephen Boyd0d578692012-04-25 11:49:18 -07002560static void __devinit mxt_debugfs_init(struct mxt_data *data)
Jing Lin6cfc00e2011-11-02 15:15:30 -07002561{
2562 debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
2563 if (IS_ERR_OR_NULL(debug_base))
2564 pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
2565 if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
2566 0444,
2567 debug_base,
2568 data,
2569 &mxt_object_fops))) {
2570 pr_err("atmel_mxt_ts: Failed to create object file\n");
2571 debugfs_remove_recursive(debug_base);
2572 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002573}
2574
Mohan Pallakad96f5032012-06-18 22:49:10 +05302575#ifdef CONFIG_OF
2576static int mxt_get_dt_coords(struct device *dev, char *name,
2577 struct mxt_platform_data *pdata)
2578{
2579 u32 coords[MXT_COORDS_ARR_SIZE];
2580 struct property *prop;
2581 struct device_node *np = dev->of_node;
2582 int coords_size, rc;
2583
2584 prop = of_find_property(np, name, NULL);
2585 if (!prop)
2586 return -EINVAL;
2587 if (!prop->value)
2588 return -ENODATA;
2589
2590 coords_size = prop->length / sizeof(u32);
2591 if (coords_size != MXT_COORDS_ARR_SIZE) {
2592 dev_err(dev, "invalid %s\n", name);
2593 return -EINVAL;
2594 }
2595
2596 rc = of_property_read_u32_array(np, name, coords, coords_size);
2597 if (rc && (rc != -EINVAL)) {
2598 dev_err(dev, "Unable to read %s\n", name);
2599 return rc;
2600 }
2601
2602 if (strncmp(name, "atmel,panel-coords",
2603 sizeof("atmel,panel-coords")) == 0) {
2604 pdata->panel_minx = coords[0];
2605 pdata->panel_miny = coords[1];
2606 pdata->panel_maxx = coords[2];
2607 pdata->panel_maxy = coords[3];
2608 } else if (strncmp(name, "atmel,display-coords",
2609 sizeof("atmel,display-coords")) == 0) {
2610 pdata->disp_minx = coords[0];
2611 pdata->disp_miny = coords[1];
2612 pdata->disp_maxx = coords[2];
2613 pdata->disp_maxy = coords[3];
2614 } else {
2615 dev_err(dev, "unsupported property %s\n", name);
2616 return -EINVAL;
2617 }
2618
2619 return 0;
2620}
2621
2622static int mxt_parse_config(struct device *dev, struct device_node *np,
2623 struct mxt_config_info *info)
2624{
2625 struct property *prop;
2626 u8 *temp_cfg;
2627
2628 prop = of_find_property(np, "atmel,config", &info->config_length);
2629 if (!prop) {
2630 dev_err(dev, "Looking up %s property in node %s failed",
2631 "atmel,config", np->full_name);
2632 return -ENODEV;
2633 } else if (!info->config_length) {
2634 dev_err(dev, "Invalid length of configuration data\n");
2635 return -EINVAL;
2636 }
2637
2638 temp_cfg = devm_kzalloc(dev,
2639 info->config_length * sizeof(u8), GFP_KERNEL);
2640 if (!temp_cfg) {
2641 dev_err(dev, "Unable to allocate memory to store cfg\n");
2642 return -ENOMEM;
2643 }
2644
2645 memcpy(temp_cfg, prop->value, info->config_length);
2646 info->config = temp_cfg;
2647
2648 return 0;
2649}
2650
2651static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
2652{
2653 int rc;
2654 struct mxt_config_info *info;
2655 struct device_node *temp, *np = dev->of_node;
2656 struct property *prop;
2657 u32 temp_val;
2658
2659 rc = mxt_get_dt_coords(dev, "atmel,panel-coords", pdata);
2660 if (rc)
2661 return rc;
2662
2663 rc = mxt_get_dt_coords(dev, "atmel,display-coords", pdata);
2664 if (rc)
2665 return rc;
2666
2667 /* regulator info */
2668 pdata->i2c_pull_up = of_property_read_bool(np, "atmel,i2c-pull-up");
2669 pdata->digital_pwr_regulator = of_property_read_bool(np,
2670 "atmel,dig-reg-support");
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302671
2672 pdata->no_force_update = of_property_read_bool(np,
2673 "atmel,no-force-update");
2674
Mohan Pallakad96f5032012-06-18 22:49:10 +05302675 /* reset, irq gpio info */
2676 pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
2677 0, &pdata->reset_gpio_flags);
2678 pdata->irq_gpio = of_get_named_gpio_flags(np, "atmel,irq-gpio",
2679 0, &pdata->irq_gpio_flags);
2680
2681 /* keycodes for keyarray object*/
2682 prop = of_find_property(np, "atmel,key-codes", NULL);
2683 if (prop) {
2684 pdata->key_codes = devm_kzalloc(dev,
2685 sizeof(int) * MXT_KEYARRAY_MAX_KEYS,
2686 GFP_KERNEL);
2687 if (!pdata->key_codes)
2688 return -ENOMEM;
2689 if ((prop->length/sizeof(u32)) == MXT_KEYARRAY_MAX_KEYS) {
2690 rc = of_property_read_u32_array(np, "atmel,key-codes",
2691 pdata->key_codes, MXT_KEYARRAY_MAX_KEYS);
2692 if (rc) {
2693 dev_err(dev, "Unable to read key codes\n");
2694 return rc;
2695 }
2696 } else
2697 return -EINVAL;
2698 }
2699
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302700 /* need calibration during wakeup? */
2701 pdata->need_calibration = of_property_read_bool(np,
2702 "atmel,need-calibration");
Mohan Pallakad96f5032012-06-18 22:49:10 +05302703 /* config array size */
2704 pdata->config_array_size = 0;
2705 temp = NULL;
2706 while ((temp = of_get_next_child(np, temp)))
2707 pdata->config_array_size++;
2708
2709 if (!pdata->config_array_size)
2710 return 0;
2711
2712 info = devm_kzalloc(dev, pdata->config_array_size *
2713 sizeof(struct mxt_config_info), GFP_KERNEL);
2714 if (!info) {
2715 dev_err(dev, "Unable to allocate memory\n");
2716 return -ENOMEM;
2717 }
2718
Amy Maloche265fc3c2013-01-17 11:50:24 -08002719 rc = of_property_read_u32(np, "atmel,bl-addr", &temp_val);
2720 if (rc && (rc != -EINVAL))
2721 dev_err(dev, "Unable to read bootloader address\n");
2722 else if (rc != -EINVAL)
2723 pdata->bl_addr = (u8) temp_val;
2724
Mohan Pallakad96f5032012-06-18 22:49:10 +05302725 pdata->config_array = info;
2726
2727 for_each_child_of_node(np, temp) {
2728 rc = of_property_read_string(temp, "atmel,fw-name",
2729 &info->fw_name);
2730 if (rc && (rc != -EINVAL)) {
2731 dev_err(dev, "Unable to read fw name\n");
2732 return rc;
2733 }
2734
2735 rc = of_property_read_u32(temp, "atmel,family-id", &temp_val);
2736 if (rc) {
2737 dev_err(dev, "Unable to read family id\n");
2738 return rc;
2739 } else
2740 info->family_id = (u8) temp_val;
2741
2742 rc = of_property_read_u32(temp, "atmel,variant-id", &temp_val);
2743 if (rc) {
2744 dev_err(dev, "Unable to read variant id\n");
2745 return rc;
2746 } else
2747 info->variant_id = (u8) temp_val;
2748
2749 rc = of_property_read_u32(temp, "atmel,version", &temp_val);
2750 if (rc) {
2751 dev_err(dev, "Unable to read controller version\n");
2752 return rc;
2753 } else
2754 info->version = (u8) temp_val;
2755
2756 rc = of_property_read_u32(temp, "atmel,build", &temp_val);
2757 if (rc) {
2758 dev_err(dev, "Unable to read build id\n");
2759 return rc;
2760 } else
2761 info->build = (u8) temp_val;
2762
Amy Maloche265fc3c2013-01-17 11:50:24 -08002763 rc = of_property_read_u32(temp,
Mohan Pallakad96f5032012-06-18 22:49:10 +05302764 "atmel,bootldr-id", &temp_val);
Amy Maloche265fc3c2013-01-17 11:50:24 -08002765 if (rc && (rc != -EINVAL))
Mohan Pallakad96f5032012-06-18 22:49:10 +05302766 dev_err(dev, "Unable to read bootldr-id\n");
Amy Maloche265fc3c2013-01-17 11:50:24 -08002767 else if (rc != -EINVAL)
Mohan Pallakad96f5032012-06-18 22:49:10 +05302768 info->bootldr_id = (u8) temp_val;
2769
2770 rc = mxt_parse_config(dev, temp, info);
2771 if (rc) {
2772 dev_err(dev, "Unable to parse config data\n");
2773 return rc;
2774 }
2775 info++;
2776 }
2777
2778 return 0;
2779}
2780#else
2781static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
2782{
2783 return -ENODEV;
2784}
2785#endif
2786
Anurag Singh49d76132013-01-29 12:07:00 -08002787#if defined(CONFIG_FB)
2788static int fb_notifier_callback(struct notifier_block *self,
2789 unsigned long event, void *data)
2790{
2791 struct fb_event *evdata = data;
2792 int *blank;
2793 struct mxt_data *mxt_dev_data =
2794 container_of(self, struct mxt_data, fb_notif);
2795
2796 if (evdata && evdata->data && event == FB_EVENT_BLANK && mxt_dev_data &&
2797 mxt_dev_data->client) {
2798 blank = evdata->data;
2799 if (*blank == FB_BLANK_UNBLANK)
2800 mxt_resume(&mxt_dev_data->client->dev);
2801 else if (*blank == FB_BLANK_POWERDOWN)
2802 mxt_suspend(&mxt_dev_data->client->dev);
2803 }
2804
2805 return 0;
2806}
2807#elif defined(CONFIG_HAS_EARLYSUSPEND)
2808static void mxt_early_suspend(struct early_suspend *h)
2809{
2810 struct mxt_data *data = container_of(h, struct mxt_data,
2811 early_suspend);
2812 mxt_suspend(&data->client->dev);
2813}
2814
2815static void mxt_late_resume(struct early_suspend *h)
2816{
2817 struct mxt_data *data = container_of(h, struct mxt_data,
2818 early_suspend);
2819 mxt_resume(&data->client->dev);
2820}
2821
2822#endif
2823
Amy Maloche434b7d82013-02-15 11:11:05 +00002824#if defined(CONFIG_SECURE_TOUCH)
Amy Maloche20f970c2013-04-10 13:04:52 +01002825static void __devinit mxt_secure_touch_init(struct mxt_data *data)
Amy Maloche434b7d82013-02-15 11:11:05 +00002826{
2827 init_completion(&data->st_completion);
Amy Maloche20f970c2013-04-10 13:04:52 +01002828 init_completion(&data->st_powerdown);
Amy Maloche434b7d82013-02-15 11:11:05 +00002829}
2830#else
Amy Maloche20f970c2013-04-10 13:04:52 +01002831static void __devinit mxt_secure_touch_init(struct mxt_data *data)
Amy Maloche434b7d82013-02-15 11:11:05 +00002832{
2833}
2834#endif
2835
Iiro Valkonen7686b102011-02-02 23:21:58 -08002836static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002837 const struct i2c_device_id *id)
2838{
Mohan Pallakad96f5032012-06-18 22:49:10 +05302839 struct mxt_platform_data *pdata;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002840 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002841 struct input_dev *input_dev;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002842 int error, i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002843
Mohan Pallakad96f5032012-06-18 22:49:10 +05302844 if (client->dev.of_node) {
2845 pdata = devm_kzalloc(&client->dev,
2846 sizeof(struct mxt_platform_data), GFP_KERNEL);
2847 if (!pdata) {
2848 dev_err(&client->dev, "Failed to allocate memory\n");
2849 return -ENOMEM;
2850 }
2851
2852 error = mxt_parse_dt(&client->dev, pdata);
2853 if (error)
2854 return error;
2855 } else
2856 pdata = client->dev.platform_data;
2857
Iiro Valkonen919ed892011-02-15 13:36:52 -08002858 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002859 return -EINVAL;
2860
Iiro Valkonen7686b102011-02-02 23:21:58 -08002861 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002862 input_dev = input_allocate_device();
2863 if (!data || !input_dev) {
2864 dev_err(&client->dev, "Failed to allocate memory\n");
2865 error = -ENOMEM;
2866 goto err_free_mem;
2867 }
2868
Nick Dyer0a4016c2012-01-18 15:17:59 +05302869 data->state = INIT;
Amy Maloche83c385a2012-02-01 10:32:03 +05302870 input_dev->name = "atmel_mxt_ts";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002871 input_dev->id.bustype = BUS_I2C;
2872 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002873 input_dev->open = mxt_input_open;
2874 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002875
Joonyoung Shim910d8052011-04-12 23:14:38 -07002876 data->client = client;
2877 data->input_dev = input_dev;
2878 data->pdata = pdata;
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302879 data->no_force_update = pdata->no_force_update;
Joonyoung Shim910d8052011-04-12 23:14:38 -07002880
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002881 __set_bit(EV_ABS, input_dev->evbit);
2882 __set_bit(EV_KEY, input_dev->evbit);
2883 __set_bit(BTN_TOUCH, input_dev->keybit);
Amy Maloche9d0faa02012-06-19 12:37:39 -07002884 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002885
2886 /* For single touch */
2887 input_set_abs_params(input_dev, ABS_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002888 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002889 input_set_abs_params(input_dev, ABS_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002890 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002891 input_set_abs_params(input_dev, ABS_PRESSURE,
2892 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002893
2894 /* For multi touch */
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -07002895 input_mt_init_slots(input_dev, MXT_MAX_FINGER);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002896 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08002897 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002898 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002899 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002900 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002901 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002902 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2903 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002904
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002905 /* set key array supported keys */
2906 if (pdata->key_codes) {
2907 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
2908 if (pdata->key_codes[i])
2909 input_set_capability(input_dev, EV_KEY,
2910 pdata->key_codes[i]);
2911 }
2912 }
2913
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002914 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002915 i2c_set_clientdata(client, data);
2916
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302917 if (pdata->init_hw)
2918 error = pdata->init_hw(true);
2919 else
2920 error = mxt_regulator_configure(data, true);
2921 if (error) {
2922 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07002923 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302924 }
2925
2926 if (pdata->power_on)
2927 error = pdata->power_on(true);
2928 else
2929 error = mxt_power_on(data, true);
2930 if (error) {
2931 dev_err(&client->dev, "Failed to power on hardware\n");
2932 goto err_regulator_on;
2933 }
2934
Amy Maloche08266db2011-11-04 11:07:16 -07002935 if (gpio_is_valid(pdata->irq_gpio)) {
2936 /* configure touchscreen irq gpio */
Mohan Pallakad96f5032012-06-18 22:49:10 +05302937 error = gpio_request(pdata->irq_gpio, "mxt_irq_gpio");
Amy Maloche08266db2011-11-04 11:07:16 -07002938 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302939 dev_err(&client->dev, "unable to request gpio [%d]\n",
Amy Maloche08266db2011-11-04 11:07:16 -07002940 pdata->irq_gpio);
2941 goto err_power_on;
2942 }
2943 error = gpio_direction_input(pdata->irq_gpio);
2944 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302945 dev_err(&client->dev,
2946 "unable to set direction for gpio [%d]\n",
2947 pdata->irq_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002948 goto err_irq_gpio_req;
2949 }
Mohan Pallakad96f5032012-06-18 22:49:10 +05302950 data->irq = client->irq = gpio_to_irq(pdata->irq_gpio);
2951 } else {
2952 dev_err(&client->dev, "irq gpio not provided\n");
2953 goto err_power_on;
Amy Maloche08266db2011-11-04 11:07:16 -07002954 }
2955
2956 if (gpio_is_valid(pdata->reset_gpio)) {
2957 /* configure touchscreen reset out gpio */
Mohan Pallakad96f5032012-06-18 22:49:10 +05302958 error = gpio_request(pdata->reset_gpio, "mxt_reset_gpio");
Amy Maloche08266db2011-11-04 11:07:16 -07002959 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302960 dev_err(&client->dev, "unable to request gpio [%d]\n",
2961 pdata->reset_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002962 goto err_irq_gpio_req;
2963 }
2964
Mohan Pallakad96f5032012-06-18 22:49:10 +05302965 error = gpio_direction_output(pdata->reset_gpio, 1);
Amy Maloche08266db2011-11-04 11:07:16 -07002966 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302967 dev_err(&client->dev,
2968 "unable to set direction for gpio [%d]\n",
2969 pdata->reset_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002970 goto err_reset_gpio_req;
2971 }
2972 }
2973
Jing Lin64fdd1f2012-12-20 17:08:28 -08002974 mxt_power_on_delay(data);
2975
Amy Maloche265fc3c2013-01-17 11:50:24 -08002976 data->addr_pair.application = data->client->addr;
2977
2978 if (pdata->bl_addr)
2979 data->addr_pair.bootloader = pdata->bl_addr;
2980 else
2981 mxt_lookup_bootloader_address(data);
2982
Iiro Valkonen7686b102011-02-02 23:21:58 -08002983 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002984 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07002985 goto err_reset_gpio_req;
Jing Lin64fdd1f2012-12-20 17:08:28 -08002986
Iiro Valkonen7686b102011-02-02 23:21:58 -08002987 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08002988 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002989 if (error) {
2990 dev_err(&client->dev, "Failed to register interrupt\n");
2991 goto err_free_object;
2992 }
2993
Nick Dyer0a4016c2012-01-18 15:17:59 +05302994 if (data->state == APPMODE) {
2995 error = mxt_make_highchg(data);
2996 if (error) {
2997 dev_err(&client->dev, "Failed to make high CHG\n");
2998 goto err_free_irq;
2999 }
3000 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07003001
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003002 error = input_register_device(input_dev);
3003 if (error)
3004 goto err_free_irq;
3005
Iiro Valkonen7686b102011-02-02 23:21:58 -08003006 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003007 if (error)
3008 goto err_unregister_device;
3009
Anurag Singh49d76132013-01-29 12:07:00 -08003010#if defined(CONFIG_FB)
3011 data->fb_notif.notifier_call = fb_notifier_callback;
3012
3013 error = fb_register_client(&data->fb_notif);
3014
3015 if (error)
3016 dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
3017 error);
3018#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +05303019 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
3020 MXT_SUSPEND_LEVEL;
3021 data->early_suspend.suspend = mxt_early_suspend;
3022 data->early_suspend.resume = mxt_late_resume;
3023 register_early_suspend(&data->early_suspend);
3024#endif
3025
Jing Lin6cfc00e2011-11-02 15:15:30 -07003026 mxt_debugfs_init(data);
3027
Amy Maloche20f970c2013-04-10 13:04:52 +01003028 mxt_secure_touch_init(data);
Amy Maloche434b7d82013-02-15 11:11:05 +00003029
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003030 return 0;
3031
3032err_unregister_device:
3033 input_unregister_device(input_dev);
3034 input_dev = NULL;
3035err_free_irq:
3036 free_irq(client->irq, data);
3037err_free_object:
3038 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07003039err_reset_gpio_req:
3040 if (gpio_is_valid(pdata->reset_gpio))
3041 gpio_free(pdata->reset_gpio);
3042err_irq_gpio_req:
3043 if (gpio_is_valid(pdata->irq_gpio))
3044 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05303045err_power_on:
3046 if (pdata->power_on)
3047 pdata->power_on(false);
3048 else
3049 mxt_power_on(data, false);
3050err_regulator_on:
3051 if (pdata->init_hw)
3052 pdata->init_hw(false);
3053 else
3054 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003055err_free_mem:
3056 input_free_device(input_dev);
3057 kfree(data);
3058 return error;
3059}
3060
Iiro Valkonen7686b102011-02-02 23:21:58 -08003061static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003062{
Iiro Valkonen7686b102011-02-02 23:21:58 -08003063 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003064
Iiro Valkonen7686b102011-02-02 23:21:58 -08003065 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003066 free_irq(data->irq, data);
3067 input_unregister_device(data->input_dev);
Anurag Singh49d76132013-01-29 12:07:00 -08003068#if defined(CONFIG_FB)
3069 if (fb_unregister_client(&data->fb_notif))
3070 dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
3071#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +05303072 unregister_early_suspend(&data->early_suspend);
3073#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05303074
3075 if (data->pdata->power_on)
3076 data->pdata->power_on(false);
3077 else
3078 mxt_power_on(data, false);
3079
3080 if (data->pdata->init_hw)
3081 data->pdata->init_hw(false);
3082 else
3083 mxt_regulator_configure(data, false);
3084
Mohan Pallakabfe8f302012-01-02 18:32:08 +08003085 if (gpio_is_valid(data->pdata->reset_gpio))
3086 gpio_free(data->pdata->reset_gpio);
3087
3088 if (gpio_is_valid(data->pdata->irq_gpio))
3089 gpio_free(data->pdata->irq_gpio);
3090
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003091 kfree(data->object_table);
3092 kfree(data);
3093
Jing Lin6cfc00e2011-11-02 15:15:30 -07003094 debugfs_remove_recursive(debug_base);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003095
3096 return 0;
3097}
3098
Iiro Valkonen7686b102011-02-02 23:21:58 -08003099static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003100 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08003101 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08003102 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003103 { }
3104};
Iiro Valkonen7686b102011-02-02 23:21:58 -08003105MODULE_DEVICE_TABLE(i2c, mxt_id);
Amy Maloche56cb58c2012-08-23 13:21:03 -07003106#ifdef CONFIG_OF
Mohan Pallakad96f5032012-06-18 22:49:10 +05303107static struct of_device_id mxt_match_table[] = {
3108 { .compatible = "atmel,mxt-ts",},
3109 { },
3110};
3111#else
3112#define mxt_match_table NULL
3113#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003114
Iiro Valkonen7686b102011-02-02 23:21:58 -08003115static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003116 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08003117 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003118 .owner = THIS_MODULE,
Mohan Pallakad96f5032012-06-18 22:49:10 +05303119 .of_match_table = mxt_match_table,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08003120#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08003121 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08003122#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003123 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08003124 .probe = mxt_probe,
3125 .remove = __devexit_p(mxt_remove),
3126 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003127};
3128
Axel Lin1b92c1c2012-03-16 23:05:41 -07003129module_i2c_driver(mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003130
3131/* Module information */
3132MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08003133MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003134MODULE_LICENSE("GPL");