blob: 0ea230a6d39d814fcb4ca0f0d3aa1fb84ab926d6 [file] [log] [blame]
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001/*
Iiro Valkonen7686b102011-02-02 23:21:58 -08002 * Atmel maXTouch Touchscreen driver
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003 *
4 * Copyright (C) 2010 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
Anurag Singh49d76132013-01-29 12:07:00 -08006 * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07007 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/firmware.h>
19#include <linux/i2c.h>
Dmitry Torokhov964de522011-02-02 23:21:58 -080020#include <linux/i2c/atmel_mxt_ts.h>
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -070021#include <linux/input/mt.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070022#include <linux/interrupt.h>
23#include <linux/slab.h>
Amy Maloche08266db2011-11-04 11:07:16 -070024#include <linux/gpio.h>
Jing Lin6cfc00e2011-11-02 15:15:30 -070025#include <linux/debugfs.h>
26#include <linux/seq_file.h>
Anirudh Ghayala498e4d2011-08-09 19:10:12 +053027#include <linux/regulator/consumer.h>
Jing Lincc974cb2012-02-01 23:13:14 -080028#include <linux/string.h>
Mohan Pallakad96f5032012-06-18 22:49:10 +053029#include <linux/of_gpio.h>
Anurag Singh49d76132013-01-29 12:07:00 -080030
31#if defined(CONFIG_FB)
32#include <linux/notifier.h>
33#include <linux/fb.h>
34
35#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +053036#include <linux/earlysuspend.h>
37/* Early-suspend level */
38#define MXT_SUSPEND_LEVEL 1
39#endif
40
Amy Maloche434b7d82013-02-15 11:11:05 +000041#if defined(CONFIG_SECURE_TOUCH)
42#include <linux/completion.h>
43#include <linux/pm_runtime.h>
44#include <linux/errno.h>
45#include <asm/system.h>
46#include <linux/atomic.h>
47#endif
48
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070049/* Family ID */
50#define MXT224_ID 0x80
Amy Maloche380cc0b2011-11-03 12:55:04 -070051#define MXT224E_ID 0x81
Amy Maloche41f1cc32012-07-12 13:02:27 -070052#define MXT336S_ID 0x82
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070053#define MXT1386_ID 0xA0
Amy Maloche41f1cc32012-07-12 13:02:27 -070054#define MXT1664S_ID 0xA2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070055
56/* Version */
Iiro Valkonen7686b102011-02-02 23:21:58 -080057#define MXT_VER_20 20
58#define MXT_VER_21 21
59#define MXT_VER_22 22
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070060
Nick Dyer0a4016c2012-01-18 15:17:59 +053061/* I2C slave address pairs */
62struct mxt_address_pair {
63 int bootloader;
64 int application;
65};
66
67static const struct mxt_address_pair mxt_slave_addresses[] = {
68 { 0x24, 0x4a },
69 { 0x25, 0x4b },
70 { 0x25, 0x4b },
71 { 0x26, 0x4c },
72 { 0x27, 0x4d },
73 { 0x34, 0x5a },
74 { 0x35, 0x5b },
75 { 0 },
76};
77
78enum mxt_device_state { INIT, APPMODE, BOOTLOADER };
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070079
80/* Firmware */
Iiro Valkonen7686b102011-02-02 23:21:58 -080081#define MXT_FW_NAME "maxtouch.fw"
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070082
Jing Lincc974cb2012-02-01 23:13:14 -080083/* Firmware frame size including frame data and CRC */
84#define MXT_SINGLE_FW_MAX_FRAME_SIZE 278
85#define MXT_CHIPSET_FW_MAX_FRAME_SIZE 534
86
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070087/* Registers */
Iiro Valkonen7686b102011-02-02 23:21:58 -080088#define MXT_FAMILY_ID 0x00
89#define MXT_VARIANT_ID 0x01
90#define MXT_VERSION 0x02
91#define MXT_BUILD 0x03
92#define MXT_MATRIX_X_SIZE 0x04
93#define MXT_MATRIX_Y_SIZE 0x05
94#define MXT_OBJECT_NUM 0x06
95#define MXT_OBJECT_START 0x07
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070096
Iiro Valkonen7686b102011-02-02 23:21:58 -080097#define MXT_OBJECT_SIZE 6
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070098
99/* Object types */
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700100#define MXT_DEBUG_DIAGNOSTIC_T37 37
101#define MXT_GEN_MESSAGE_T5 5
102#define MXT_GEN_COMMAND_T6 6
103#define MXT_GEN_POWER_T7 7
104#define MXT_GEN_ACQUIRE_T8 8
105#define MXT_GEN_DATASOURCE_T53 53
106#define MXT_TOUCH_MULTI_T9 9
107#define MXT_TOUCH_KEYARRAY_T15 15
108#define MXT_TOUCH_PROXIMITY_T23 23
109#define MXT_TOUCH_PROXKEY_T52 52
110#define MXT_PROCI_GRIPFACE_T20 20
111#define MXT_PROCG_NOISE_T22 22
Amy Maloche41f1cc32012-07-12 13:02:27 -0700112#define MXT_PROCG_NOISE_T62 62
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700113#define MXT_PROCI_ONETOUCH_T24 24
114#define MXT_PROCI_TWOTOUCH_T27 27
115#define MXT_PROCI_GRIP_T40 40
116#define MXT_PROCI_PALM_T41 41
117#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
118#define MXT_PROCI_STYLUS_T47 47
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530119#define MXT_PROCI_ADAPTIVETHRESHOLD_T55 55
Jing Linc7fc4052011-12-21 16:16:19 -0800120#define MXT_PROCI_SHIELDLESS_T56 56
Amy Maloche41f1cc32012-07-12 13:02:27 -0700121#define MXT_PROCI_EXTRATSDATA_T57 57
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700122#define MXT_PROCG_NOISESUPPRESSION_T48 48
123#define MXT_SPT_COMMSCONFIG_T18 18
124#define MXT_SPT_GPIOPWM_T19 19
125#define MXT_SPT_SELFTEST_T25 25
126#define MXT_SPT_CTECONFIG_T28 28
127#define MXT_SPT_USERDATA_T38 38
128#define MXT_SPT_DIGITIZER_T43 43
129#define MXT_SPT_MESSAGECOUNT_T44 44
130#define MXT_SPT_CTECONFIG_T46 46
Amy Maloche41f1cc32012-07-12 13:02:27 -0700131#define MXT_SPT_TIMER_T61 61
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700132
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700133/* MXT_GEN_COMMAND_T6 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800134#define MXT_COMMAND_RESET 0
135#define MXT_COMMAND_BACKUPNV 1
136#define MXT_COMMAND_CALIBRATE 2
137#define MXT_COMMAND_REPORTALL 3
138#define MXT_COMMAND_DIAGNOSTIC 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700139
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700140/* MXT_GEN_POWER_T7 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800141#define MXT_POWER_IDLEACQINT 0
142#define MXT_POWER_ACTVACQINT 1
143#define MXT_POWER_ACTV2IDLETO 2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700144
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700145/* MXT_GEN_ACQUIRE_T8 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800146#define MXT_ACQUIRE_CHRGTIME 0
147#define MXT_ACQUIRE_TCHDRIFT 2
148#define MXT_ACQUIRE_DRIFTST 3
149#define MXT_ACQUIRE_TCHAUTOCAL 4
150#define MXT_ACQUIRE_SYNC 5
151#define MXT_ACQUIRE_ATCHCALST 6
152#define MXT_ACQUIRE_ATCHCALSTHR 7
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700153
Iiro Valkonene8645592011-11-18 12:56:19 -0800154/* MXT_TOUCH_MULT_T9 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800155#define MXT_TOUCH_CTRL 0
156#define MXT_TOUCH_XORIGIN 1
157#define MXT_TOUCH_YORIGIN 2
158#define MXT_TOUCH_XSIZE 3
159#define MXT_TOUCH_YSIZE 4
160#define MXT_TOUCH_BLEN 6
161#define MXT_TOUCH_TCHTHR 7
162#define MXT_TOUCH_TCHDI 8
163#define MXT_TOUCH_ORIENT 9
164#define MXT_TOUCH_MOVHYSTI 11
165#define MXT_TOUCH_MOVHYSTN 12
166#define MXT_TOUCH_NUMTOUCH 14
167#define MXT_TOUCH_MRGHYST 15
168#define MXT_TOUCH_MRGTHR 16
169#define MXT_TOUCH_AMPHYST 17
170#define MXT_TOUCH_XRANGE_LSB 18
171#define MXT_TOUCH_XRANGE_MSB 19
172#define MXT_TOUCH_YRANGE_LSB 20
173#define MXT_TOUCH_YRANGE_MSB 21
174#define MXT_TOUCH_XLOCLIP 22
175#define MXT_TOUCH_XHICLIP 23
176#define MXT_TOUCH_YLOCLIP 24
177#define MXT_TOUCH_YHICLIP 25
178#define MXT_TOUCH_XEDGECTRL 26
179#define MXT_TOUCH_XEDGEDIST 27
180#define MXT_TOUCH_YEDGECTRL 28
181#define MXT_TOUCH_YEDGEDIST 29
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700182#define MXT_TOUCH_JUMPLIMIT 30
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700183
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700184/* MXT_PROCI_GRIPFACE_T20 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800185#define MXT_GRIPFACE_CTRL 0
186#define MXT_GRIPFACE_XLOGRIP 1
187#define MXT_GRIPFACE_XHIGRIP 2
188#define MXT_GRIPFACE_YLOGRIP 3
189#define MXT_GRIPFACE_YHIGRIP 4
190#define MXT_GRIPFACE_MAXTCHS 5
191#define MXT_GRIPFACE_SZTHR1 7
192#define MXT_GRIPFACE_SZTHR2 8
193#define MXT_GRIPFACE_SHPTHR1 9
194#define MXT_GRIPFACE_SHPTHR2 10
195#define MXT_GRIPFACE_SUPEXTTO 11
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700196
Iiro Valkonen7686b102011-02-02 23:21:58 -0800197/* MXT_PROCI_NOISE field */
198#define MXT_NOISE_CTRL 0
199#define MXT_NOISE_OUTFLEN 1
200#define MXT_NOISE_GCAFUL_LSB 3
201#define MXT_NOISE_GCAFUL_MSB 4
202#define MXT_NOISE_GCAFLL_LSB 5
203#define MXT_NOISE_GCAFLL_MSB 6
204#define MXT_NOISE_ACTVGCAFVALID 7
205#define MXT_NOISE_NOISETHR 8
206#define MXT_NOISE_FREQHOPSCALE 10
207#define MXT_NOISE_FREQ0 11
208#define MXT_NOISE_FREQ1 12
209#define MXT_NOISE_FREQ2 13
210#define MXT_NOISE_FREQ3 14
211#define MXT_NOISE_FREQ4 15
212#define MXT_NOISE_IDLEGCAFVALID 16
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700213
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700214/* MXT_SPT_COMMSCONFIG_T18 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800215#define MXT_COMMS_CTRL 0
216#define MXT_COMMS_CMD 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700217
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700218/* MXT_SPT_CTECONFIG_T28 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800219#define MXT_CTE_CTRL 0
220#define MXT_CTE_CMD 1
221#define MXT_CTE_MODE 2
222#define MXT_CTE_IDLEGCAFDEPTH 3
223#define MXT_CTE_ACTVGCAFDEPTH 4
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700224#define MXT_CTE_VOLTAGE 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700225
Iiro Valkonen7686b102011-02-02 23:21:58 -0800226#define MXT_VOLTAGE_DEFAULT 2700000
227#define MXT_VOLTAGE_STEP 10000
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700228
Amy Maloche21115eb2011-11-02 09:04:37 -0700229/* Analog voltage @2.7 V */
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530230#define MXT_VTG_MIN_UV 2700000
231#define MXT_VTG_MAX_UV 3300000
232#define MXT_ACTIVE_LOAD_UA 15000
Jing Linbace50b2011-10-18 22:55:47 -0700233#define MXT_LPM_LOAD_UA 10
Amy Maloche21115eb2011-11-02 09:04:37 -0700234/* Digital voltage @1.8 V */
235#define MXT_VTG_DIG_MIN_UV 1800000
236#define MXT_VTG_DIG_MAX_UV 1800000
237#define MXT_ACTIVE_LOAD_DIG_UA 10000
238#define MXT_LPM_LOAD_DIG_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530239
240#define MXT_I2C_VTG_MIN_UV 1800000
241#define MXT_I2C_VTG_MAX_UV 1800000
242#define MXT_I2C_LOAD_UA 10000
Jing Linbace50b2011-10-18 22:55:47 -0700243#define MXT_I2C_LPM_LOAD_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530244
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700245/* Define for MXT_GEN_COMMAND_T6 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800246#define MXT_BOOT_VALUE 0xa5
247#define MXT_BACKUP_VALUE 0x55
248#define MXT_BACKUP_TIME 25 /* msec */
Jing Lin64fdd1f2012-12-20 17:08:28 -0800249
250/* Software reset delay */
251#define MXT224_RESET_TIME 64 /* msec */
252#define MXT224E_RESET_TIME 21 /* msec */
Amy Maloche41f1cc32012-07-12 13:02:27 -0700253#define MXT336S_RESET_TIME 25 /* msec */
Jing Lin64fdd1f2012-12-20 17:08:28 -0800254#define MXT1386_RESET_TIME 250 /* msec */
255#define MXT1386E_RESET_TIME 229 /* msec */
256#define MXT1664S_RESET_TIME 280 /* msec */
Amy Maloche7e447432011-09-14 11:36:30 -0700257#define MXT_RESET_TIME 250 /* msec */
Jing Linc7fc4052011-12-21 16:16:19 -0800258#define MXT_RESET_NOCHGREAD 400 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700259
Jing Lin64fdd1f2012-12-20 17:08:28 -0800260/* Power on delay */
261#define MXT224_POWER_ON_TIME 40 /* msec */
262#define MXT224E_POWER_ON_TIME 21 /* msec */
263#define MXT336S_POWER_ON_TIME 25 /* msec */
264#define MXT1386_POWER_ON_TIME 90 /* msec */
265#define MXT1386E_POWER_ON_TIME 81 /* msec */
266#define MXT1664S_POWER_ON_TIME 65 /* msec */
267#define MXT_POWER_ON_TIME 100 /* msec */
268
Nick Dyer0a4016c2012-01-18 15:17:59 +0530269#define MXT_FWRESET_TIME 1000 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700270
Jing Lin36aee812011-10-17 17:17:28 -0700271#define MXT_WAKE_TIME 25
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700272
273/* Command to unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800274#define MXT_UNLOCK_CMD_MSB 0xaa
275#define MXT_UNLOCK_CMD_LSB 0xdc
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700276
277/* Bootloader mode status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800278#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
279#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
280#define MXT_FRAME_CRC_CHECK 0x02
281#define MXT_FRAME_CRC_FAIL 0x03
282#define MXT_FRAME_CRC_PASS 0x04
283#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
284#define MXT_BOOT_STATUS_MASK 0x3f
Nick Dyer0a4016c2012-01-18 15:17:59 +0530285#define MXT_BOOT_EXTENDED_ID (1 << 5)
286#define MXT_BOOT_ID_MASK 0x1f
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700287
288/* Touch status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800289#define MXT_SUPPRESS (1 << 1)
290#define MXT_AMP (1 << 2)
291#define MXT_VECTOR (1 << 3)
292#define MXT_MOVE (1 << 4)
293#define MXT_RELEASE (1 << 5)
294#define MXT_PRESS (1 << 6)
295#define MXT_DETECT (1 << 7)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700296
Joonyoung Shim910d8052011-04-12 23:14:38 -0700297/* Touch orient bits */
298#define MXT_XY_SWITCH (1 << 0)
299#define MXT_X_INVERT (1 << 1)
300#define MXT_Y_INVERT (1 << 2)
301
Mohan Pallakab6acab42012-06-13 11:59:04 +0530302/* Touch suppression */
303#define MXT_TCHSUP_ACTIVE (1 << 0)
304
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700305/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800306#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700307
Iiro Valkonen7686b102011-02-02 23:21:58 -0800308#define MXT_MAX_FINGER 10
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700309
Jing Lin36aee812011-10-17 17:17:28 -0700310#define T7_DATA_SIZE 3
311#define MXT_MAX_RW_TRIES 3
312#define MXT_BLOCK_SIZE 256
Jing Lin8fadad72012-02-24 10:10:50 -0800313#define MXT_CFG_VERSION_LEN 3
314#define MXT_CFG_VERSION_EQUAL 0
315#define MXT_CFG_VERSION_LESS 1
316#define MXT_CFG_VERSION_GREATER 2
Mohan Pallakaab51f2b2011-09-29 18:17:35 +0530317
Mohan Pallakad96f5032012-06-18 22:49:10 +0530318#define MXT_COORDS_ARR_SIZE 4
319
Jing Lin6cfc00e2011-11-02 15:15:30 -0700320#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
321#define MXT_DEBUGFS_FILE "object"
322
Iiro Valkonen7686b102011-02-02 23:21:58 -0800323struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700324 u8 family_id;
325 u8 variant_id;
326 u8 version;
327 u8 build;
328 u8 matrix_xsize;
329 u8 matrix_ysize;
330 u8 object_num;
331};
332
Iiro Valkonen7686b102011-02-02 23:21:58 -0800333struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700334 u8 type;
335 u16 start_address;
336 u8 size;
337 u8 instances;
338 u8 num_report_ids;
339
340 /* to map object and message */
341 u8 max_reportid;
342};
343
Iiro Valkonen7686b102011-02-02 23:21:58 -0800344struct mxt_message {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700345 u8 reportid;
346 u8 message[7];
347 u8 checksum;
348};
349
Iiro Valkonen7686b102011-02-02 23:21:58 -0800350struct mxt_finger {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700351 int status;
352 int x;
353 int y;
354 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700355 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700356};
357
358/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800359struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700360 struct i2c_client *client;
361 struct input_dev *input_dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800362 const struct mxt_platform_data *pdata;
Jing Lindc4413c2012-01-16 15:22:52 -0800363 const struct mxt_config_info *config_info;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530364 enum mxt_device_state state;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800365 struct mxt_object *object_table;
366 struct mxt_info info;
367 struct mxt_finger finger[MXT_MAX_FINGER];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700368 unsigned int irq;
Amy Maloche21115eb2011-11-02 09:04:37 -0700369 struct regulator *vcc_ana;
370 struct regulator *vcc_dig;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530371 struct regulator *vcc_i2c;
Amy Maloche265fc3c2013-01-17 11:50:24 -0800372 struct mxt_address_pair addr_pair;
Anurag Singh49d76132013-01-29 12:07:00 -0800373#if defined(CONFIG_FB)
374 struct notifier_block fb_notif;
375#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +0530376 struct early_suspend early_suspend;
377#endif
Jing Lin36aee812011-10-17 17:17:28 -0700378
Amy Maloche52262212011-09-15 16:46:57 -0700379 u8 t7_data[T7_DATA_SIZE];
Jing Lin36aee812011-10-17 17:17:28 -0700380 u16 t7_start_addr;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800381 u32 keyarray_old;
382 u32 keyarray_new;
383 u8 t9_max_reportid;
384 u8 t9_min_reportid;
385 u8 t15_max_reportid;
386 u8 t15_min_reportid;
Mohan Pallakab6acab42012-06-13 11:59:04 +0530387 u8 t42_max_reportid;
388 u8 t42_min_reportid;
Jing Lin8fadad72012-02-24 10:10:50 -0800389 u8 cfg_version[MXT_CFG_VERSION_LEN];
Jing Lindc4413c2012-01-16 15:22:52 -0800390 int cfg_version_idx;
Jing Lin8a9472d2012-03-21 15:43:45 -0700391 int t38_start_addr;
Jing Lin8fadad72012-02-24 10:10:50 -0800392 bool update_cfg;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -0800393 const char *fw_name;
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +0530394 bool no_force_update;
Amy Maloche434b7d82013-02-15 11:11:05 +0000395#if defined(CONFIG_SECURE_TOUCH)
396 atomic_t st_enabled;
397 atomic_t st_pending_irqs;
398 struct completion st_completion;
399#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700400};
401
Jing Lin6cfc00e2011-11-02 15:15:30 -0700402static struct dentry *debug_base;
403
Iiro Valkonen7686b102011-02-02 23:21:58 -0800404static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700405{
406 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700407 case MXT_GEN_MESSAGE_T5:
408 case MXT_GEN_COMMAND_T6:
409 case MXT_GEN_POWER_T7:
410 case MXT_GEN_ACQUIRE_T8:
411 case MXT_GEN_DATASOURCE_T53:
412 case MXT_TOUCH_MULTI_T9:
413 case MXT_TOUCH_KEYARRAY_T15:
414 case MXT_TOUCH_PROXIMITY_T23:
415 case MXT_TOUCH_PROXKEY_T52:
416 case MXT_PROCI_GRIPFACE_T20:
417 case MXT_PROCG_NOISE_T22:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700418 case MXT_PROCG_NOISE_T62:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700419 case MXT_PROCI_ONETOUCH_T24:
420 case MXT_PROCI_TWOTOUCH_T27:
421 case MXT_PROCI_GRIP_T40:
422 case MXT_PROCI_PALM_T41:
423 case MXT_PROCI_TOUCHSUPPRESSION_T42:
424 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800425 case MXT_PROCI_SHIELDLESS_T56:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700426 case MXT_PROCI_EXTRATSDATA_T57:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700427 case MXT_PROCG_NOISESUPPRESSION_T48:
428 case MXT_SPT_COMMSCONFIG_T18:
429 case MXT_SPT_GPIOPWM_T19:
430 case MXT_SPT_SELFTEST_T25:
431 case MXT_SPT_CTECONFIG_T28:
432 case MXT_SPT_USERDATA_T38:
433 case MXT_SPT_DIGITIZER_T43:
434 case MXT_SPT_CTECONFIG_T46:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700435 case MXT_SPT_TIMER_T61:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530436 case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700437 return true;
438 default:
439 return false;
440 }
441}
442
Iiro Valkonen7686b102011-02-02 23:21:58 -0800443static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700444{
445 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700446 case MXT_GEN_COMMAND_T6:
447 case MXT_GEN_POWER_T7:
448 case MXT_GEN_ACQUIRE_T8:
449 case MXT_TOUCH_MULTI_T9:
450 case MXT_TOUCH_KEYARRAY_T15:
451 case MXT_TOUCH_PROXIMITY_T23:
452 case MXT_TOUCH_PROXKEY_T52:
453 case MXT_PROCI_GRIPFACE_T20:
454 case MXT_PROCG_NOISE_T22:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700455 case MXT_PROCG_NOISE_T62:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700456 case MXT_PROCI_ONETOUCH_T24:
457 case MXT_PROCI_TWOTOUCH_T27:
458 case MXT_PROCI_GRIP_T40:
459 case MXT_PROCI_PALM_T41:
460 case MXT_PROCI_TOUCHSUPPRESSION_T42:
461 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800462 case MXT_PROCI_SHIELDLESS_T56:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700463 case MXT_PROCI_EXTRATSDATA_T57:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700464 case MXT_PROCG_NOISESUPPRESSION_T48:
465 case MXT_SPT_COMMSCONFIG_T18:
466 case MXT_SPT_GPIOPWM_T19:
467 case MXT_SPT_SELFTEST_T25:
468 case MXT_SPT_CTECONFIG_T28:
Iiro Valkonene8645592011-11-18 12:56:19 -0800469 case MXT_SPT_USERDATA_T38:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700470 case MXT_SPT_DIGITIZER_T43:
471 case MXT_SPT_CTECONFIG_T46:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700472 case MXT_SPT_TIMER_T61:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530473 case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700474 return true;
475 default:
476 return false;
477 }
478}
479
Iiro Valkonen7686b102011-02-02 23:21:58 -0800480static void mxt_dump_message(struct device *dev,
481 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700482{
483 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
484 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
485 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
486 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
487 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
488 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
489 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
490 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
491 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
492}
493
Amy Maloche265fc3c2013-01-17 11:50:24 -0800494static int mxt_lookup_bootloader_address(struct mxt_data *data)
Amy Maloche71b8f022013-01-17 11:50:24 -0800495{
Steve Mucklee1533542013-02-13 15:03:16 -0800496 int i;
Amy Maloche265fc3c2013-01-17 11:50:24 -0800497
498 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
499 if (mxt_slave_addresses[i].application ==
500 data->client->addr) {
501 data->addr_pair.bootloader =
502 mxt_slave_addresses[i].bootloader;
503 return 0;
504 }
505 }
506
507 dev_err(&data->client->dev, "Address 0x%02x not found in address table",
508 data->client->addr);
509 return -EINVAL;
510
511};
512
513static int mxt_switch_to_bootloader_address(struct mxt_data *data)
514{
Nick Dyer0a4016c2012-01-18 15:17:59 +0530515 struct i2c_client *client = data->client;
516
517 if (data->state == BOOTLOADER) {
518 dev_err(&client->dev, "Already in BOOTLOADER state\n");
519 return -EINVAL;
520 }
521
Amy Maloche265fc3c2013-01-17 11:50:24 -0800522 dev_info(&client->dev, "Changing to bootloader address: 0x%02x -> 0x%02x",
523 client->addr, data->addr_pair.bootloader);
Nick Dyer0a4016c2012-01-18 15:17:59 +0530524
Amy Maloche265fc3c2013-01-17 11:50:24 -0800525 client->addr = data->addr_pair.bootloader;
526 data->state = BOOTLOADER;
527 return 0;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530528}
529
530static int mxt_switch_to_appmode_address(struct mxt_data *data)
531{
Nick Dyer0a4016c2012-01-18 15:17:59 +0530532 struct i2c_client *client = data->client;
533
534 if (data->state == APPMODE) {
535 dev_err(&client->dev, "Already in APPMODE state\n");
536 return -EINVAL;
537 }
538
Amy Maloche265fc3c2013-01-17 11:50:24 -0800539 dev_info(&client->dev, "Changing to application mode address: " \
540 "0x%02x -> 0x%02x", client->addr,
541 data->addr_pair.application);
Nick Dyer0a4016c2012-01-18 15:17:59 +0530542
Amy Maloche265fc3c2013-01-17 11:50:24 -0800543 client->addr = data->addr_pair.application;
544 data->state = APPMODE;
545 return 0;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530546}
547
548static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
549{
550 u8 buf[3];
551
552 if (val | MXT_BOOT_EXTENDED_ID) {
553 dev_dbg(&client->dev,
554 "Retrieving extended mode ID information");
555
556 if (i2c_master_recv(client, &buf[0], 3) != 3) {
557 dev_err(&client->dev, "%s: i2c recv failed\n",
558 __func__);
559 return -EIO;
560 }
561
562 dev_info(&client->dev, "Bootloader ID:%d Version:%d",
563 buf[1], buf[2]);
564
565 return buf[0];
566 } else {
567 dev_info(&client->dev, "Bootloader ID:%d",
568 val & MXT_BOOT_ID_MASK);
569
570 return val;
571 }
572}
573
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -0800574static int mxt_get_bootloader_id(struct i2c_client *client)
575{
576 u8 val;
577 u8 buf[3];
578
579 if (i2c_master_recv(client, &val, 1) != 1) {
580 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
581 return -EIO;
582 }
583
584 if (val | MXT_BOOT_EXTENDED_ID) {
585 if (i2c_master_recv(client, &buf[0], 3) != 3) {
586 dev_err(&client->dev, "%s: i2c recv failed\n",
587 __func__);
588 return -EIO;
589 }
590 return buf[1];
591 } else {
592 dev_info(&client->dev, "Bootloader ID:%d",
593 val & MXT_BOOT_ID_MASK);
594
595 return val & MXT_BOOT_ID_MASK;
596 }
597}
598
Iiro Valkonen7686b102011-02-02 23:21:58 -0800599static int mxt_check_bootloader(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530600 unsigned int state)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700601{
602 u8 val;
603
604recheck:
605 if (i2c_master_recv(client, &val, 1) != 1) {
606 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
607 return -EIO;
608 }
609
610 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800611 case MXT_WAITING_BOOTLOAD_CMD:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530612 val = mxt_get_bootloader_version(client, val);
613 val &= ~MXT_BOOT_STATUS_MASK;
614 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800615 case MXT_WAITING_FRAME_DATA:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530616 case MXT_APP_CRC_FAIL:
Iiro Valkonen7686b102011-02-02 23:21:58 -0800617 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700618 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800619 case MXT_FRAME_CRC_PASS:
620 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700621 goto recheck;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530622 if (val == MXT_FRAME_CRC_FAIL) {
623 dev_err(&client->dev, "Bootloader CRC fail\n");
624 return -EINVAL;
625 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700626 break;
627 default:
628 return -EINVAL;
629 }
630
631 if (val != state) {
Nick Dyer0a4016c2012-01-18 15:17:59 +0530632 dev_err(&client->dev, "Invalid bootloader mode state %X\n",
633 val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700634 return -EINVAL;
635 }
636
637 return 0;
638}
639
Iiro Valkonen7686b102011-02-02 23:21:58 -0800640static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700641{
642 u8 buf[2];
643
Iiro Valkonen7686b102011-02-02 23:21:58 -0800644 buf[0] = MXT_UNLOCK_CMD_LSB;
645 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700646
647 if (i2c_master_send(client, buf, 2) != 2) {
648 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
649 return -EIO;
650 }
651
652 return 0;
653}
654
Iiro Valkonen7686b102011-02-02 23:21:58 -0800655static int mxt_fw_write(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530656 const u8 *data, unsigned int frame_size)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700657{
658 if (i2c_master_send(client, data, frame_size) != frame_size) {
659 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
660 return -EIO;
661 }
662
663 return 0;
664}
665
Iiro Valkonen7686b102011-02-02 23:21:58 -0800666static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700667 u16 reg, u16 len, void *val)
668{
669 struct i2c_msg xfer[2];
670 u8 buf[2];
Jing Lin36aee812011-10-17 17:17:28 -0700671 int i = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700672
673 buf[0] = reg & 0xff;
674 buf[1] = (reg >> 8) & 0xff;
675
676 /* Write register */
677 xfer[0].addr = client->addr;
678 xfer[0].flags = 0;
679 xfer[0].len = 2;
680 xfer[0].buf = buf;
681
682 /* Read data */
683 xfer[1].addr = client->addr;
684 xfer[1].flags = I2C_M_RD;
685 xfer[1].len = len;
686 xfer[1].buf = val;
687
Jing Lin36aee812011-10-17 17:17:28 -0700688 do {
689 if (i2c_transfer(client->adapter, xfer, 2) == 2)
690 return 0;
691 msleep(MXT_WAKE_TIME);
692 } while (++i < MXT_MAX_RW_TRIES);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700693
Jing Lin36aee812011-10-17 17:17:28 -0700694 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
695 return -EIO;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700696}
697
Iiro Valkonen7686b102011-02-02 23:21:58 -0800698static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700699{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800700 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700701}
702
Jing Lin36aee812011-10-17 17:17:28 -0700703static int __mxt_write_reg(struct i2c_client *client,
704 u16 addr, u16 length, u8 *value)
705{
706 u8 buf[MXT_BLOCK_SIZE + 2];
707 int i, tries = 0;
708
709 if (length > MXT_BLOCK_SIZE)
710 return -EINVAL;
711
712 buf[0] = addr & 0xff;
713 buf[1] = (addr >> 8) & 0xff;
714 for (i = 0; i < length; i++)
715 buf[i + 2] = *value++;
716
717 do {
718 if (i2c_master_send(client, buf, length + 2) == (length + 2))
719 return 0;
720 msleep(MXT_WAKE_TIME);
721 } while (++tries < MXT_MAX_RW_TRIES);
722
723 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
724 return -EIO;
725}
726
Iiro Valkonen7686b102011-02-02 23:21:58 -0800727static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700728{
Jing Lin36aee812011-10-17 17:17:28 -0700729 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700730}
731
Iiro Valkonen7686b102011-02-02 23:21:58 -0800732static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700733 u16 reg, u8 *object_buf)
734{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800735 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700736 object_buf);
737}
738
Iiro Valkonen7686b102011-02-02 23:21:58 -0800739static struct mxt_object *
740mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700741{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800742 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700743 int i;
744
745 for (i = 0; i < data->info.object_num; i++) {
746 object = data->object_table + i;
747 if (object->type == type)
748 return object;
749 }
750
751 dev_err(&data->client->dev, "Invalid object type\n");
752 return NULL;
753}
754
Iiro Valkonen7686b102011-02-02 23:21:58 -0800755static int mxt_read_message(struct mxt_data *data,
756 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700757{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800758 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700759 u16 reg;
760
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700761 object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700762 if (!object)
763 return -EINVAL;
764
765 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800766 return __mxt_read_reg(data->client, reg,
767 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700768}
769
Iiro Valkonen7686b102011-02-02 23:21:58 -0800770static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700771 u8 type, u8 offset, u8 *val)
772{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800773 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700774 u16 reg;
775
Iiro Valkonen7686b102011-02-02 23:21:58 -0800776 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700777 if (!object)
778 return -EINVAL;
779
780 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800781 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700782}
783
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530784static int mxt_get_object_address(struct device *dev, u8 type)
785{
786 struct mxt_data *data = dev_get_drvdata(dev);
787 u8 obj_num, obj_buf[MXT_OBJECT_SIZE];
788 u16 reg;
789 int i, error;
790
791 error = mxt_read_reg(data->client, MXT_OBJECT_NUM, &obj_num);
792
793 if (error) {
794 dev_err(dev, "reading number of objects failed\n");
795 return -EINVAL;
796 }
797
798 for (i = 0; i < obj_num; i++) {
799 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
800 error = mxt_read_object_table(data->client,
801 reg, obj_buf);
802 if (error)
803 return error;
804
805 if (obj_buf[0] == type)
806 return obj_buf[2] << 8 | obj_buf[1];
807 }
808 /* If control reaches here, i = obj_num and object not found */
809 dev_err(dev, "Requested object %d not found.\n", type);
810 return -EINVAL;
811
812}
813
Iiro Valkonen7686b102011-02-02 23:21:58 -0800814static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700815 u8 type, u8 offset, u8 val)
816{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800817 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700818 u16 reg;
819
Iiro Valkonen7686b102011-02-02 23:21:58 -0800820 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700821 if (!object)
822 return -EINVAL;
823
824 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800825 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700826}
827
Iiro Valkonen7686b102011-02-02 23:21:58 -0800828static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700829{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800830 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700831 struct input_dev *input_dev = data->input_dev;
832 int status = finger[single_id].status;
833 int finger_num = 0;
834 int id;
835
Iiro Valkonen7686b102011-02-02 23:21:58 -0800836 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700837 if (!finger[id].status)
838 continue;
839
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700840 input_mt_slot(input_dev, id);
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800841 /* Firmware reports min/max values when the touch is
842 * outside screen area. Send a release event in
843 * such cases to avoid unwanted touches.
844 */
845 if (finger[id].x <= data->pdata->panel_minx ||
846 finger[id].x >= data->pdata->panel_maxx ||
847 finger[id].y <= data->pdata->panel_miny ||
848 finger[id].y >= data->pdata->panel_maxy) {
849 finger[id].status = MXT_RELEASE;
850 }
851
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700852 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
853 finger[id].status != MXT_RELEASE);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700854
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700855 if (finger[id].status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700856 finger_num++;
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700857 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
858 finger[id].area);
859 input_report_abs(input_dev, ABS_MT_POSITION_X,
860 finger[id].x);
861 input_report_abs(input_dev, ABS_MT_POSITION_Y,
862 finger[id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700863 input_report_abs(input_dev, ABS_MT_PRESSURE,
Anirudh Ghayal279a2ae52012-05-18 18:07:46 +0530864 finger[id].pressure);
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700865 } else {
866 finger[id].status = 0;
867 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700868 }
869
870 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
871
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800872 if (finger[single_id].x <= data->pdata->panel_minx ||
873 finger[single_id].x >= data->pdata->panel_maxx ||
874 finger[single_id].y <= data->pdata->panel_miny ||
875 finger[single_id].y >= data->pdata->panel_maxy) {
876 status = MXT_RELEASE;
877 }
878
Iiro Valkonen7686b102011-02-02 23:21:58 -0800879 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700880 input_report_abs(input_dev, ABS_X, finger[single_id].x);
881 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700882 input_report_abs(input_dev,
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700883 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700884 }
885
886 input_sync(input_dev);
887}
888
Amy Maloche1b7ac702013-02-21 19:47:53 -0800889static void mxt_release_all(struct mxt_data *data)
890{
891 int id;
892
893 for (id = 0; id < MXT_MAX_FINGER; id++)
894 if (data->finger[id].status)
895 data->finger[id].status = MXT_RELEASE;
896
897 mxt_input_report(data, 0);
898}
899
Iiro Valkonen7686b102011-02-02 23:21:58 -0800900static void mxt_input_touchevent(struct mxt_data *data,
901 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700902{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800903 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700904 struct device *dev = &data->client->dev;
905 u8 status = message->message[0];
906 int x;
907 int y;
908 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700909 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700910
Amy Maloche1b7ac702013-02-21 19:47:53 -0800911 if (status & MXT_SUPPRESS) {
912 mxt_release_all(data);
913 return;
914 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700915 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800916 if (!(status & MXT_DETECT)) {
917 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700918 dev_dbg(dev, "[%d] released\n", id);
919
Iiro Valkonen7686b102011-02-02 23:21:58 -0800920 finger[id].status = MXT_RELEASE;
921 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700922 }
923 return;
924 }
925
926 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800927 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700928 return;
929
Joonyoung Shim910d8052011-04-12 23:14:38 -0700930 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
931 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800932 if (data->pdata->panel_maxx < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700933 x = x >> 2;
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800934 if (data->pdata->panel_maxy < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700935 y = y >> 2;
936
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700937 area = message->message[4];
Yufeng Shen28ac2932011-08-16 00:40:54 -0700938 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700939
940 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800941 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700942 x, y, area);
943
Iiro Valkonen7686b102011-02-02 23:21:58 -0800944 finger[id].status = status & MXT_MOVE ?
945 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700946 finger[id].x = x;
947 finger[id].y = y;
948 finger[id].area = area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700949 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700950
Iiro Valkonen7686b102011-02-02 23:21:58 -0800951 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700952}
953
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800954static void mxt_handle_key_array(struct mxt_data *data,
955 struct mxt_message *message)
956{
957 u32 keys_changed;
958 int i;
959
960 if (!data->pdata->key_codes) {
961 dev_err(&data->client->dev, "keyarray is not supported\n");
962 return;
963 }
964
965 data->keyarray_new = message->message[1] |
966 (message->message[2] << 8) |
967 (message->message[3] << 16) |
968 (message->message[4] << 24);
969
970 keys_changed = data->keyarray_old ^ data->keyarray_new;
971
972 if (!keys_changed) {
973 dev_dbg(&data->client->dev, "no keys changed\n");
974 return;
975 }
976
977 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
978 if (!(keys_changed & (1 << i)))
979 continue;
980
981 input_report_key(data->input_dev, data->pdata->key_codes[i],
982 (data->keyarray_new & (1 << i)));
983 input_sync(data->input_dev);
984 }
985
986 data->keyarray_old = data->keyarray_new;
987}
988
Amy Maloche1b7ac702013-02-21 19:47:53 -0800989static void mxt_handle_touch_suppression(struct mxt_data *data, u8 status)
Mohan Pallakab6acab42012-06-13 11:59:04 +0530990{
991 dev_dbg(&data->client->dev, "touch suppression\n");
992 /* release all touches */
993 if (status & MXT_TCHSUP_ACTIVE)
994 mxt_release_all(data);
995}
996
Amy Maloche434b7d82013-02-15 11:11:05 +0000997#if defined(CONFIG_SECURE_TOUCH)
998static irqreturn_t mxt_filter_interrupt(struct mxt_data *data)
999{
1000 if (atomic_read(&data->st_enabled)) {
1001 atomic_cmpxchg(&data->st_pending_irqs, 0, 1);
1002 complete(&data->st_completion);
1003 return IRQ_HANDLED;
1004 }
1005 return IRQ_NONE;
1006}
1007#else
1008static irqreturn_t mxt_filter_interrupt(struct mxt_data *data)
1009{
1010 return IRQ_NONE;
1011}
1012#endif
1013
Iiro Valkonen7686b102011-02-02 23:21:58 -08001014static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001015{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001016 struct mxt_data *data = dev_id;
1017 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001018 struct device *dev = &data->client->dev;
1019 int id;
1020 u8 reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001021
Nick Dyer0a4016c2012-01-18 15:17:59 +05301022 if (data->state != APPMODE) {
1023 dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
1024 return IRQ_HANDLED;
1025 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001026
Amy Maloche434b7d82013-02-15 11:11:05 +00001027 if (IRQ_HANDLED == mxt_filter_interrupt(data))
1028 goto end;
1029
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001030 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001031 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001032 dev_err(dev, "Failed to read message\n");
1033 goto end;
1034 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001035 reportid = message.reportid;
1036
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001037 if (!reportid) {
1038 dev_dbg(dev, "Report id 0 is reserved\n");
1039 continue;
1040 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001041
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001042 id = reportid - data->t9_min_reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001043
Amy Maloche1b7ac702013-02-21 19:47:53 -08001044 /* check whether report id is part of T9, T15 or T42 */
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001045 if (reportid >= data->t9_min_reportid &&
1046 reportid <= data->t9_max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -08001047 mxt_input_touchevent(data, &message, id);
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001048 else if (reportid >= data->t15_min_reportid &&
1049 reportid <= data->t15_max_reportid)
1050 mxt_handle_key_array(data, &message);
Mohan Pallakab6acab42012-06-13 11:59:04 +05301051 else if (reportid >= data->t42_min_reportid &&
Amy Maloche1b7ac702013-02-21 19:47:53 -08001052 reportid <= data->t42_max_reportid)
1053 mxt_handle_touch_suppression(data,
1054 message.message[0]);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001055 else
Iiro Valkonen7686b102011-02-02 23:21:58 -08001056 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001057 } while (reportid != 0xff);
1058
1059end:
1060 return IRQ_HANDLED;
1061}
1062
Iiro Valkonen7686b102011-02-02 23:21:58 -08001063static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001064{
Jing Lindc4413c2012-01-16 15:22:52 -08001065 const struct mxt_config_info *config_info = data->config_info;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001066 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001067 struct device *dev = &data->client->dev;
1068 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -08001069 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001070
Jing Lindc4413c2012-01-16 15:22:52 -08001071 if (!config_info) {
Iiro Valkonen71749f52011-02-15 13:36:52 -08001072 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
1073 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001074 }
1075
1076 for (i = 0; i < data->info.object_num; i++) {
1077 object = data->object_table + i;
1078
Iiro Valkonen7686b102011-02-02 23:21:58 -08001079 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001080 continue;
1081
Iiro Valkonen71749f52011-02-15 13:36:52 -08001082 for (j = 0; j < object->size + 1; j++) {
1083 config_offset = index + j;
Jing Lindc4413c2012-01-16 15:22:52 -08001084 if (config_offset > config_info->config_length) {
Iiro Valkonen71749f52011-02-15 13:36:52 -08001085 dev_err(dev, "Not enough config data!\n");
1086 return -EINVAL;
1087 }
Iiro Valkonen7686b102011-02-02 23:21:58 -08001088 mxt_write_object(data, object->type, j,
Jing Lindc4413c2012-01-16 15:22:52 -08001089 config_info->config[config_offset]);
Iiro Valkonen71749f52011-02-15 13:36:52 -08001090 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001091 index += object->size + 1;
1092 }
1093
1094 return 0;
1095}
1096
Iiro Valkonen7686b102011-02-02 23:21:58 -08001097static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001098{
1099 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001100 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001101 int count = 10;
1102 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001103
1104 /* Read dummy message to make high CHG pin */
1105 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001106 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001107 if (error)
1108 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001109 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001110
1111 if (!count) {
1112 dev_err(dev, "CHG pin isn't cleared\n");
1113 return -EBUSY;
1114 }
1115
1116 return 0;
1117}
1118
Iiro Valkonen7686b102011-02-02 23:21:58 -08001119static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001120{
1121 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001122 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001123 int error;
1124 u8 val;
1125
Iiro Valkonen7686b102011-02-02 23:21:58 -08001126 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001127 if (error)
1128 return error;
1129 info->family_id = val;
1130
Iiro Valkonen7686b102011-02-02 23:21:58 -08001131 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001132 if (error)
1133 return error;
1134 info->variant_id = val;
1135
Iiro Valkonen7686b102011-02-02 23:21:58 -08001136 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001137 if (error)
1138 return error;
1139 info->version = val;
1140
Iiro Valkonen7686b102011-02-02 23:21:58 -08001141 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001142 if (error)
1143 return error;
1144 info->build = val;
1145
Iiro Valkonen7686b102011-02-02 23:21:58 -08001146 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001147 if (error)
1148 return error;
1149 info->object_num = val;
1150
1151 return 0;
1152}
1153
Iiro Valkonen7686b102011-02-02 23:21:58 -08001154static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001155{
1156 int error;
1157 int i;
1158 u16 reg;
1159 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001160 u8 buf[MXT_OBJECT_SIZE];
Jing Lindc4413c2012-01-16 15:22:52 -08001161 bool found_t38 = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001162
1163 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001164 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001165
Iiro Valkonen7686b102011-02-02 23:21:58 -08001166 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
1167 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001168 if (error)
1169 return error;
1170
1171 object->type = buf[0];
1172 object->start_address = (buf[2] << 8) | buf[1];
1173 object->size = buf[3];
1174 object->instances = buf[4];
1175 object->num_report_ids = buf[5];
1176
1177 if (object->num_report_ids) {
1178 reportid += object->num_report_ids *
1179 (object->instances + 1);
1180 object->max_reportid = reportid;
1181 }
Jing Lindc4413c2012-01-16 15:22:52 -08001182
1183 /* Calculate index for config major version in config array.
1184 * Major version is the first byte in object T38.
1185 */
Jing Lin8a9472d2012-03-21 15:43:45 -07001186 if (object->type == MXT_SPT_USERDATA_T38) {
1187 data->t38_start_addr = object->start_address;
Jing Lindc4413c2012-01-16 15:22:52 -08001188 found_t38 = true;
Jing Lin8a9472d2012-03-21 15:43:45 -07001189 }
Jing Lindc4413c2012-01-16 15:22:52 -08001190 if (!found_t38 && mxt_object_writable(object->type))
1191 data->cfg_version_idx += object->size + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001192 }
1193
1194 return 0;
1195}
1196
Jing Lin8fadad72012-02-24 10:10:50 -08001197static int compare_versions(const u8 *v1, const u8 *v2)
1198{
1199 int i;
1200
1201 if (!v1 || !v2)
1202 return -EINVAL;
1203
1204 /* The major version number stays the same across different versions for
1205 * a particular controller on a target. The minor and sub-minor version
1206 * numbers indicate which version is newer.
1207 */
1208 if (v1[0] != v2[0])
1209 return -EINVAL;
1210
1211 for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
1212 if (v1[i] > v2[i])
1213 return MXT_CFG_VERSION_LESS; /* v2 is older */
1214
1215 if (v1[i] < v2[i])
1216 return MXT_CFG_VERSION_GREATER; /* v2 is newer */
1217 }
1218
1219 return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
1220}
1221
1222static void mxt_check_config_version(struct mxt_data *data,
1223 const struct mxt_config_info *cfg_info,
1224 bool match_major,
1225 const u8 **cfg_version_found,
1226 bool *found_cfg_major_match)
1227{
1228 const u8 *cfg_version;
1229 int result = -EINVAL;
1230
1231 cfg_version = cfg_info->config + data->cfg_version_idx;
1232
1233 if (*cfg_version_found)
1234 result = compare_versions(*cfg_version_found, cfg_version);
1235
1236 if (match_major) {
1237 if (result >= MXT_CFG_VERSION_EQUAL)
1238 *found_cfg_major_match = true;
1239
1240 if (result == MXT_CFG_VERSION_EQUAL ||
1241 result == MXT_CFG_VERSION_GREATER) {
1242 data->config_info = cfg_info;
1243 data->fw_name = cfg_info->fw_name;
1244 *cfg_version_found = cfg_version;
1245 }
1246
1247 if (result == MXT_CFG_VERSION_GREATER)
1248 data->update_cfg = true;
1249 } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
1250 data->config_info = cfg_info;
1251 data->fw_name = cfg_info->fw_name;
1252 data->update_cfg = true;
1253 *cfg_version_found = cfg_version;
1254 }
1255}
1256
1257/* If the controller's config version has a non-zero major number, call this
1258 * function with match_major = true to look for the latest config present in
1259 * the pdata based on matching family id, variant id, f/w version, build, and
1260 * config major number. If the controller is programmed with wrong config data
1261 * previously, call this function with match_major = false to look for latest
1262 * config based on based on matching family id, variant id, f/w version and
1263 * build only.
1264 */
1265static int mxt_search_config_array(struct mxt_data *data, bool match_major)
Jing Lindc4413c2012-01-16 15:22:52 -08001266{
1267
1268 const struct mxt_platform_data *pdata = data->pdata;
1269 const struct mxt_config_info *cfg_info;
Jing Lin8fadad72012-02-24 10:10:50 -08001270 const struct mxt_info *info = &data->info;
1271 const u8 *cfg_version_found;
1272 bool found_cfg_major_match = false;
Jing Lindc4413c2012-01-16 15:22:52 -08001273 int i;
Jing Lin8fadad72012-02-24 10:10:50 -08001274
1275 cfg_version_found = match_major ? data->cfg_version : NULL;
Jing Lindc4413c2012-01-16 15:22:52 -08001276
1277 for (i = 0; i < pdata->config_array_size; i++) {
1278
1279 cfg_info = &pdata->config_array[i];
1280
1281 if (!cfg_info->config || !cfg_info->config_length)
1282 continue;
1283
1284 if (info->family_id == cfg_info->family_id &&
1285 info->variant_id == cfg_info->variant_id &&
1286 info->version == cfg_info->version &&
1287 info->build == cfg_info->build) {
1288
Jing Lin8fadad72012-02-24 10:10:50 -08001289 mxt_check_config_version(data, cfg_info, match_major,
1290 &cfg_version_found, &found_cfg_major_match);
Jing Lindc4413c2012-01-16 15:22:52 -08001291 }
1292 }
1293
Jing Lin8fadad72012-02-24 10:10:50 -08001294 if (data->config_info || found_cfg_major_match)
1295 return 0;
1296
1297 data->config_info = NULL;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001298 data->fw_name = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001299
Jing Lindc4413c2012-01-16 15:22:52 -08001300 return -EINVAL;
1301}
1302
1303static int mxt_get_config(struct mxt_data *data)
1304{
1305 const struct mxt_platform_data *pdata = data->pdata;
1306 struct device *dev = &data->client->dev;
1307 struct mxt_object *object;
1308 int error;
1309
1310 if (!pdata->config_array || !pdata->config_array_size) {
1311 dev_dbg(dev, "No cfg data provided by platform data\n");
1312 return 0;
1313 }
1314
1315 /* Get current config version */
1316 object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
1317 if (!object) {
1318 dev_err(dev, "Unable to obtain USERDATA object\n");
1319 return -EINVAL;
1320 }
1321
Jing Lin8fadad72012-02-24 10:10:50 -08001322 error = __mxt_read_reg(data->client, object->start_address,
1323 sizeof(data->cfg_version), data->cfg_version);
Jing Lindc4413c2012-01-16 15:22:52 -08001324 if (error) {
1325 dev_err(dev, "Unable to read config version\n");
1326 return error;
1327 }
Jing Lin8fadad72012-02-24 10:10:50 -08001328 dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
1329 data->cfg_version[0], data->cfg_version[1],
1330 data->cfg_version[2]);
Jing Lindc4413c2012-01-16 15:22:52 -08001331
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301332 /* configuration update requires major match */
1333 error = mxt_search_config_array(data, true);
1334
1335 /* if no_force_update is false , try again with false
1336 as the second parameter to mxt_search_config_array */
1337 if (error && (data->no_force_update == false))
1338 error = mxt_search_config_array(data, false);
1339
Jing Lin8fadad72012-02-24 10:10:50 -08001340 if (error) {
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301341 dev_err(dev,
1342 "Unable to find matching config in pdata\n");
1343 return error;
Jing Lin8fadad72012-02-24 10:10:50 -08001344 }
Jing Lindc4413c2012-01-16 15:22:52 -08001345
1346 return 0;
1347}
Jing Lin8fadad72012-02-24 10:10:50 -08001348
Jing Lin64fdd1f2012-12-20 17:08:28 -08001349static void mxt_power_on_delay(struct mxt_data *data)
1350{
1351 const struct mxt_platform_data *pdata = data->pdata;
1352 const struct mxt_config_info *cfg_info;
1353 u32 delay = 0;
1354 int i;
1355
1356 for (i = 0; i < pdata->config_array_size; i++) {
1357 cfg_info = &pdata->config_array[i];
1358
1359 switch (cfg_info->family_id) {
1360 case MXT224_ID:
1361 delay = max_t(u32, delay, MXT224_POWER_ON_TIME);
1362 break;
1363 case MXT224E_ID:
1364 delay = max_t(u32, delay, MXT224E_POWER_ON_TIME);
1365 break;
1366 case MXT336S_ID:
1367 delay = max_t(u32, delay, MXT336S_POWER_ON_TIME);
1368 break;
1369 case MXT1386_ID:
1370 delay = max_t(u32, delay,
1371 max_t(u32, MXT1386_POWER_ON_TIME,
1372 MXT1386E_POWER_ON_TIME));
1373 break;
1374 case MXT1664S_ID:
1375 delay = max_t(u32, delay, MXT1664S_POWER_ON_TIME);
1376 break;
1377 default:
1378 delay = max_t(u32, delay, MXT_POWER_ON_TIME);
1379 }
1380 }
1381
1382 msleep(delay);
1383}
1384
Amy Maloche7e447432011-09-14 11:36:30 -07001385static void mxt_reset_delay(struct mxt_data *data)
1386{
1387 struct mxt_info *info = &data->info;
1388
1389 switch (info->family_id) {
1390 case MXT224_ID:
1391 msleep(MXT224_RESET_TIME);
1392 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -07001393 case MXT224E_ID:
1394 msleep(MXT224E_RESET_TIME);
1395 break;
Amy Maloche41f1cc32012-07-12 13:02:27 -07001396 case MXT336S_ID:
1397 msleep(MXT336S_RESET_TIME);
Jing Lin64fdd1f2012-12-20 17:08:28 -08001398 break;
Amy Maloche7e447432011-09-14 11:36:30 -07001399 case MXT1386_ID:
Jing Lin64fdd1f2012-12-20 17:08:28 -08001400 msleep(max_t(u32, MXT1386_RESET_TIME, MXT1386E_RESET_TIME));
1401 break;
Amy Maloche41f1cc32012-07-12 13:02:27 -07001402 case MXT1664S_ID:
1403 msleep(MXT1664S_RESET_TIME);
Amy Maloche7e447432011-09-14 11:36:30 -07001404 break;
1405 default:
1406 msleep(MXT_RESET_TIME);
1407 }
1408}
1409
Jing Lin8fadad72012-02-24 10:10:50 -08001410static int mxt_backup_nv(struct mxt_data *data)
1411{
1412 int error;
1413 u8 command_register;
1414 int timeout_counter = 0;
1415
1416 /* Backup to memory */
1417 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1418 MXT_COMMAND_BACKUPNV,
1419 MXT_BACKUP_VALUE);
1420 msleep(MXT_BACKUP_TIME);
1421
1422 do {
1423 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
1424 MXT_COMMAND_BACKUPNV,
1425 &command_register);
1426 if (error)
1427 return error;
1428
1429 usleep_range(1000, 2000);
1430
1431 } while ((command_register != 0) && (++timeout_counter <= 100));
1432
1433 if (timeout_counter > 100) {
1434 dev_err(&data->client->dev, "No response after backup!\n");
1435 return -EIO;
1436 }
1437
1438 /* Soft reset */
1439 mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
1440
1441 mxt_reset_delay(data);
1442
1443 return 0;
1444}
1445
Jing Lin412aedc2012-02-28 13:57:19 -08001446static int mxt_save_objects(struct mxt_data *data)
1447{
1448 struct i2c_client *client = data->client;
1449 struct mxt_object *t7_object;
1450 struct mxt_object *t9_object;
1451 struct mxt_object *t15_object;
Mohan Pallakab6acab42012-06-13 11:59:04 +05301452 struct mxt_object *t42_object;
Jing Lin412aedc2012-02-28 13:57:19 -08001453 int error;
1454
1455 /* Store T7 and T9 locally, used in suspend/resume operations */
1456 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
1457 if (!t7_object) {
1458 dev_err(&client->dev, "Failed to get T7 object\n");
1459 return -EINVAL;
1460 }
1461
1462 data->t7_start_addr = t7_object->start_address;
1463 error = __mxt_read_reg(client, data->t7_start_addr,
1464 T7_DATA_SIZE, data->t7_data);
1465 if (error < 0) {
1466 dev_err(&client->dev,
1467 "Failed to save current power state\n");
1468 return error;
1469 }
1470
Jing Lin412aedc2012-02-28 13:57:19 -08001471 /* Store T9, T15's min and max report ids */
1472 t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1473 if (!t9_object) {
1474 dev_err(&client->dev, "Failed to get T9 object\n");
1475 return -EINVAL;
1476 }
1477 data->t9_max_reportid = t9_object->max_reportid;
1478 data->t9_min_reportid = t9_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001479 (t9_object->num_report_ids *
1480 (t9_object->instances + 1)) + 1;
Jing Lin412aedc2012-02-28 13:57:19 -08001481
1482 if (data->pdata->key_codes) {
1483 t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
1484 if (!t15_object)
1485 dev_dbg(&client->dev, "T15 object is not available\n");
1486 else {
1487 data->t15_max_reportid = t15_object->max_reportid;
1488 data->t15_min_reportid = t15_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001489 (t15_object->num_report_ids *
1490 (t15_object->instances + 1)) + 1;
Jing Lin412aedc2012-02-28 13:57:19 -08001491 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001492 }
1493
Mohan Pallakab6acab42012-06-13 11:59:04 +05301494 /* Store T42 min and max report ids */
1495 t42_object = mxt_get_object(data, MXT_PROCI_TOUCHSUPPRESSION_T42);
1496 if (!t42_object)
1497 dev_dbg(&client->dev, "T42 object is not available\n");
1498 else {
1499 data->t42_max_reportid = t42_object->max_reportid;
1500 data->t42_min_reportid = t42_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001501 (t42_object->num_report_ids *
1502 (t42_object->instances + 1)) + 1;
Mohan Pallakab6acab42012-06-13 11:59:04 +05301503 }
1504
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001505 return 0;
1506}
1507
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301508static int mxt_update_cfg(struct mxt_data *data)
1509{
1510 int error;
1511 const u8 *cfg_ver;
1512
1513 /* Get config data from platform data */
1514 error = mxt_get_config(data);
1515 if (error)
1516 dev_dbg(&data->client->dev, "Config info not found.\n");
1517
1518 /* Check register init values */
1519 if (data->config_info && data->config_info->config) {
1520 if (data->update_cfg) {
1521 error = mxt_check_reg_init(data);
1522 if (error) {
1523 dev_err(&data->client->dev,
1524 "Failed to check reg init value\n");
1525 return error;
1526 }
1527
1528 error = mxt_backup_nv(data);
1529 if (error) {
1530 dev_err(&data->client->dev, "Failed to back up NV\n");
1531 return error;
1532 }
1533
1534 cfg_ver = data->config_info->config +
1535 data->cfg_version_idx;
1536 dev_info(&data->client->dev,
1537 "Config updated from %d.%d.%d to %d.%d.%d\n",
1538 data->cfg_version[0], data->cfg_version[1],
1539 data->cfg_version[2],
1540 cfg_ver[0], cfg_ver[1], cfg_ver[2]);
1541
1542 memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
1543 }
1544 } else {
1545 dev_info(&data->client->dev,
1546 "No cfg data defined, skipping check reg init\n");
1547 }
1548
1549 error = mxt_save_objects(data);
1550 if (error)
1551 return error;
1552
1553 return 0;
1554}
1555
1556
1557
Iiro Valkonen7686b102011-02-02 23:21:58 -08001558static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001559{
1560 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001561 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001562 int error;
1563 u8 val;
1564
Iiro Valkonen7686b102011-02-02 23:21:58 -08001565 error = mxt_get_info(data);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301566 if (error) {
1567 /* Try bootloader mode */
1568 error = mxt_switch_to_bootloader_address(data);
1569 if (error)
1570 return error;
1571
1572 error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
1573 if (error)
1574 return error;
1575
1576 dev_err(&client->dev, "Application CRC failure\n");
1577 data->state = BOOTLOADER;
1578
1579 return 0;
1580 }
1581
1582 dev_info(&client->dev,
1583 "Family ID: %d Variant ID: %d Version: %d.%d "
1584 "Build: 0x%02X Object Num: %d\n",
1585 info->family_id, info->variant_id,
1586 info->version >> 4, info->version & 0xf,
1587 info->build, info->object_num);
1588
1589 data->state = APPMODE;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001590
1591 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001592 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001593 GFP_KERNEL);
1594 if (!data->object_table) {
1595 dev_err(&client->dev, "Failed to allocate memory\n");
1596 return -ENOMEM;
1597 }
1598
1599 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001600 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001601 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001602 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001603
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301604 error = mxt_update_cfg(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 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001608 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
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 info->matrix_xsize = val;
1612
Iiro Valkonen7686b102011-02-02 23:21:58 -08001613 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001614 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001615 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001616 info->matrix_ysize = val;
1617
1618 dev_info(&client->dev,
Nick Dyer0a4016c2012-01-18 15:17:59 +05301619 "Matrix X Size: %d Matrix Y Size: %d\n",
1620 info->matrix_xsize, info->matrix_ysize);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001621
1622 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001623
Jing Lin32c72532011-11-03 12:02:33 -07001624free_object_table:
1625 kfree(data->object_table);
1626 return error;
Joonyoung Shim910d8052011-04-12 23:14:38 -07001627}
1628
Iiro Valkonen7686b102011-02-02 23:21:58 -08001629static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001630 struct device_attribute *attr, char *buf)
1631{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001632 struct mxt_data *data = dev_get_drvdata(dev);
1633 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001634 int count = 0;
1635 int i, j;
1636 int error;
1637 u8 val;
1638
1639 for (i = 0; i < data->info.object_num; i++) {
1640 object = data->object_table + i;
1641
Daniel Kurtz626af862011-10-06 15:43:20 -07001642 count += snprintf(buf + count, PAGE_SIZE - count,
1643 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001644 i + 1, object->type);
Daniel Kurtz626af862011-10-06 15:43:20 -07001645 if (count >= PAGE_SIZE)
1646 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001647
Iiro Valkonen7686b102011-02-02 23:21:58 -08001648 if (!mxt_object_readable(object->type)) {
Daniel Kurtz626af862011-10-06 15:43:20 -07001649 count += snprintf(buf + count, PAGE_SIZE - count,
1650 "\n");
1651 if (count >= PAGE_SIZE)
1652 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001653 continue;
1654 }
1655
1656 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001657 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001658 object->type, j, &val);
1659 if (error)
1660 return error;
1661
Daniel Kurtz626af862011-10-06 15:43:20 -07001662 count += snprintf(buf + count, PAGE_SIZE - count,
1663 "\t[%2d]: %02x (%d)\n", j, val, val);
1664 if (count >= PAGE_SIZE)
1665 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001666 }
1667
Daniel Kurtz626af862011-10-06 15:43:20 -07001668 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1669 if (count >= PAGE_SIZE)
1670 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001671 }
1672
1673 return count;
1674}
1675
Jing Lincc974cb2012-02-01 23:13:14 -08001676static int strtobyte(const char *data, u8 *value)
1677{
1678 char str[3];
1679
1680 str[0] = data[0];
1681 str[1] = data[1];
1682 str[2] = '\0';
1683
1684 return kstrtou8(str, 16, value);
1685}
1686
Iiro Valkonen7686b102011-02-02 23:21:58 -08001687static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001688{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001689 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001690 struct i2c_client *client = data->client;
1691 const struct firmware *fw = NULL;
1692 unsigned int frame_size;
Nick Dyer0a4016c2012-01-18 15:17:59 +05301693 unsigned int retry = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001694 unsigned int pos = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001695 int ret, i, max_frame_size;
1696 u8 *frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001697
Jing Lincc974cb2012-02-01 23:13:14 -08001698 switch (data->info.family_id) {
1699 case MXT224_ID:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301700 case MXT224E_ID:
Amy Maloche265fc3c2013-01-17 11:50:24 -08001701 case MXT336S_ID:
Jing Lincc974cb2012-02-01 23:13:14 -08001702 max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
1703 break;
1704 case MXT1386_ID:
Amy Maloche265fc3c2013-01-17 11:50:24 -08001705 case MXT1664S_ID:
Jing Lincc974cb2012-02-01 23:13:14 -08001706 max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
1707 break;
1708 default:
1709 return -EINVAL;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001710 }
1711
Jing Lincc974cb2012-02-01 23:13:14 -08001712 frame = kmalloc(max_frame_size, GFP_KERNEL);
1713 if (!frame) {
1714 dev_err(dev, "Unable to allocate memory for frame data\n");
1715 return -ENOMEM;
1716 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001717
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001718 ret = request_firmware(&fw, fn, dev);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301719 if (ret < 0) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001720 dev_err(dev, "Unable to open firmware %s\n", fn);
Jing Lincc974cb2012-02-01 23:13:14 -08001721 goto free_frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001722 }
1723
Nick Dyer0a4016c2012-01-18 15:17:59 +05301724 if (data->state != BOOTLOADER) {
1725 /* Change to the bootloader mode */
1726 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1727 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1728 mxt_reset_delay(data);
Amy Maloche7e447432011-09-14 11:36:30 -07001729
Nick Dyer0a4016c2012-01-18 15:17:59 +05301730 ret = mxt_switch_to_bootloader_address(data);
1731 if (ret)
1732 goto release_firmware;
1733 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001734
Iiro Valkonen7686b102011-02-02 23:21:58 -08001735 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301736 if (ret) {
1737 /* Bootloader may still be unlocked from previous update
1738 * attempt */
1739 ret = mxt_check_bootloader(client,
1740 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001741
Nick Dyer0a4016c2012-01-18 15:17:59 +05301742 if (ret)
1743 goto return_to_app_mode;
1744 } else {
1745 dev_info(dev, "Unlocking bootloader\n");
1746 /* Unlock bootloader */
1747 mxt_unlock_bootloader(client);
1748 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001749
1750 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001751 ret = mxt_check_bootloader(client,
1752 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001753 if (ret)
Nick Dyer0a4016c2012-01-18 15:17:59 +05301754 goto release_firmware;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001755
Jing Lincc974cb2012-02-01 23:13:14 -08001756 /* Get frame length MSB */
1757 ret = strtobyte(fw->data + pos, frame);
1758 if (ret)
1759 goto release_firmware;
1760
1761 /* Get frame length LSB */
1762 ret = strtobyte(fw->data + pos + 2, frame + 1);
1763 if (ret)
1764 goto release_firmware;
1765
1766 frame_size = ((*frame << 8) | *(frame + 1));
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001767
1768 /* We should add 2 at frame size as the the firmware data is not
1769 * included the CRC bytes.
1770 */
1771 frame_size += 2;
1772
Jing Lincc974cb2012-02-01 23:13:14 -08001773 if (frame_size > max_frame_size) {
1774 dev_err(dev, "Invalid frame size - %d\n", frame_size);
1775 ret = -EINVAL;
1776 goto release_firmware;
1777 }
1778
1779 /* Convert frame data and CRC from hex to binary */
1780 for (i = 2; i < frame_size; i++) {
1781 ret = strtobyte(fw->data + pos + i * 2, frame + i);
1782 if (ret)
1783 goto release_firmware;
1784 }
1785
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001786 /* Write one frame to device */
Jing Lincc974cb2012-02-01 23:13:14 -08001787 mxt_fw_write(client, frame, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001788
Iiro Valkonen7686b102011-02-02 23:21:58 -08001789 ret = mxt_check_bootloader(client,
1790 MXT_FRAME_CRC_PASS);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301791 if (ret) {
1792 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001793
Nick Dyer0a4016c2012-01-18 15:17:59 +05301794 /* Back off by 20ms per retry */
1795 msleep(retry * 20);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001796
Nick Dyer0a4016c2012-01-18 15:17:59 +05301797 if (retry > 20)
1798 goto release_firmware;
1799 } else {
1800 retry = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001801 pos += frame_size * 2;
1802 dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301803 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001804 }
1805
Nick Dyer0a4016c2012-01-18 15:17:59 +05301806return_to_app_mode:
1807 mxt_switch_to_appmode_address(data);
1808release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001809 release_firmware(fw);
Jing Lincc974cb2012-02-01 23:13:14 -08001810free_frame:
1811 kfree(frame);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001812
1813 return ret;
1814}
1815
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001816static const char *
1817mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
1818{
1819 const struct mxt_platform_data *pdata = data->pdata;
1820 const struct mxt_config_info *cfg_info;
1821 const char *fw_name = NULL;
1822 int i;
1823
1824 for (i = 0; i < pdata->config_array_size; i++) {
1825 cfg_info = &pdata->config_array[i];
1826 if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
1827 data->config_info = cfg_info;
1828 data->info.family_id = cfg_info->family_id;
1829 fw_name = cfg_info->fw_name;
1830 }
1831 }
1832
1833 return fw_name;
1834}
1835
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301836static ssize_t mxt_force_cfg_update_store(struct device *dev,
1837 struct device_attribute *attr,
1838 const char *buf, size_t count)
1839{
1840 struct mxt_data *data = dev_get_drvdata(dev);
1841 int flag = buf[0]-'0';
1842 int error;
1843 data->no_force_update = !flag;
1844
1845 if (data->state == APPMODE) {
1846 disable_irq(data->irq);
1847 error = mxt_update_cfg(data);
1848 enable_irq(data->irq);
1849 if (error)
1850 return error;
1851 } else {
1852 dev_err(dev,
1853 "Not in APPMODE, Unable to force cfg update\n");
1854 return -EINVAL;
1855 }
1856
1857 return count;
1858}
1859
Iiro Valkonen7686b102011-02-02 23:21:58 -08001860static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001861 struct device_attribute *attr,
1862 const char *buf, size_t count)
1863{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001864 struct mxt_data *data = dev_get_drvdata(dev);
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301865 int error, address;
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001866 const char *fw_name;
1867 u8 bootldr_id;
Jing Lin8a9472d2012-03-21 15:43:45 -07001868 u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001869
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301870 data->no_force_update = false;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001871 /* If fw_name is set, then the existing firmware has an upgrade */
1872 if (!data->fw_name) {
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001873 /*
1874 * If the device boots up in the bootloader mode, check if
1875 * there is a firmware to upgrade.
1876 */
1877 if (data->state == BOOTLOADER) {
1878 bootldr_id = mxt_get_bootloader_id(data->client);
1879 if (bootldr_id <= 0) {
1880 dev_err(dev,
1881 "Unable to retrieve bootloader id\n");
1882 return -EINVAL;
1883 }
1884 fw_name = mxt_search_fw_name(data, bootldr_id);
1885 if (fw_name == NULL) {
1886 dev_err(dev,
1887 "Unable to find fw from bootloader id\n");
1888 return -EINVAL;
1889 }
1890 } else {
1891 /* In APPMODE, if the f/w name does not exist, quit */
1892 dev_err(dev,
1893 "Firmware name not specified in platform data\n");
1894 return -EINVAL;
1895 }
1896 } else {
1897 fw_name = data->fw_name;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001898 }
1899
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001900 dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001901
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001902 disable_irq(data->irq);
1903
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001904 error = mxt_load_fw(dev, fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001905 if (error) {
1906 dev_err(dev, "The firmware update failed(%d)\n", error);
1907 count = error;
1908 } else {
Nick Dyer0a4016c2012-01-18 15:17:59 +05301909 dev_info(dev, "The firmware update succeeded\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001910
1911 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001912 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001913
Nick Dyer0a4016c2012-01-18 15:17:59 +05301914 data->state = INIT;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001915 kfree(data->object_table);
1916 data->object_table = NULL;
Jing Lincc974cb2012-02-01 23:13:14 -08001917 data->cfg_version_idx = 0;
Jing Lina962ba32012-12-03 09:46:33 -08001918 data->config_info = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001919 data->update_cfg = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001920
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301921 /* T38 object address might have changed, read it from
1922 touch controller */
1923 address = mxt_get_object_address(dev, MXT_SPT_USERDATA_T38);
1924 if (address < 0) {
1925 dev_err(dev, "T38 required for touch operation\n");
1926 return -EINVAL;
1927 }
1928
1929 data->t38_start_addr = address;
1930
Jing Lin8a9472d2012-03-21 15:43:45 -07001931 error = __mxt_write_reg(data->client, data->t38_start_addr,
1932 sizeof(cfg_version), cfg_version);
1933 if (error)
1934 dev_err(dev,
1935 "Unable to zero out config version after fw upgrade\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001936
Iiro Valkonen7686b102011-02-02 23:21:58 -08001937 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001938 }
1939
Nick Dyer0a4016c2012-01-18 15:17:59 +05301940 if (data->state == APPMODE) {
1941 enable_irq(data->irq);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001942
Nick Dyer0a4016c2012-01-18 15:17:59 +05301943 error = mxt_make_highchg(data);
1944 if (error)
1945 return error;
1946 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07001947
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001948 return count;
1949}
1950
Amy Maloche434b7d82013-02-15 11:11:05 +00001951#if defined(CONFIG_SECURE_TOUCH)
1952
1953static ssize_t mxt_secure_touch_enable_show(struct device *dev,
1954 struct device_attribute *attr, char *buf)
1955{
1956 struct mxt_data *data = dev_get_drvdata(dev);
1957 return scnprintf(buf, PAGE_SIZE, "%d", atomic_read(&data->st_enabled));
1958}
1959/*
1960 * Accept only "0" and "1" valid values.
1961 * "0" will reset the st_enabled flag, then wake up the reading process.
1962 * The bus driver is notified via pm_runtime that it is not required to stay
1963 * awake anymore.
1964 * It will also make sure the queue of events is emptied in the controller,
1965 * in case a touch happened in between the secure touch being disabled and
1966 * the local ISR being ungated.
1967 * "1" will set the st_enabled flag and clear the st_pending_irqs flag.
1968 * The bus driver is requested via pm_runtime to stay awake.
1969 */
1970static ssize_t mxt_secure_touch_enable_store(struct device *dev,
1971 struct device_attribute *attr,
1972 const char *buf, size_t count)
1973{
1974 struct mxt_data *data = dev_get_drvdata(dev);
1975 unsigned long value;
1976 int err = 0;
1977
1978 if (count > 2)
1979 return -EINVAL;
1980
1981 err = kstrtoul(buf, 10, &value);
1982 if (err != 0)
1983 return err;
1984
1985 err = count;
1986
1987 switch (value) {
1988 case 0:
1989 if (atomic_read(&data->st_enabled) == 0)
1990 break;
1991
1992 pm_runtime_put(&data->client->adapter->dev);
1993 atomic_set(&data->st_enabled, 0);
1994 complete(&data->st_completion);
1995 mxt_interrupt(data->client->irq, data);
1996 break;
1997 case 1:
1998 if (atomic_read(&data->st_enabled)) {
1999 err = -EBUSY;
2000 break;
2001 }
2002
2003 if (pm_runtime_get(data->client->adapter->dev.parent) < 0) {
2004 dev_err(&data->client->dev, "pm_runtime_get failed\n");
2005 err = -EIO;
2006 break;
2007 }
2008 atomic_set(&data->st_pending_irqs, 0);
2009 atomic_set(&data->st_enabled, 1);
2010 break;
2011 default:
2012 dev_err(&data->client->dev, "unsupported value: %lu\n", value);
2013 err = -EINVAL;
2014 break;
2015 }
2016
2017 return err;
2018}
2019
2020static ssize_t mxt_secure_touch_show(struct device *dev,
2021 struct device_attribute *attr, char *buf)
2022{
2023 struct mxt_data *data = dev_get_drvdata(dev);
2024 int err;
2025
2026 if (atomic_read(&data->st_enabled) == 0)
2027 return -EBADF;
2028
2029 err = wait_for_completion_interruptible(&data->st_completion);
2030
2031 if (err)
2032 return err;
2033
2034 if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) != 1)
2035 return -EBADF;
2036
2037 return scnprintf(buf, PAGE_SIZE, "%u", 1);
2038}
2039
2040static DEVICE_ATTR(secure_touch_enable, 0666, mxt_secure_touch_enable_show,
2041 mxt_secure_touch_enable_store);
2042static DEVICE_ATTR(secure_touch, 0444, mxt_secure_touch_show, NULL);
2043#endif
2044
Iiro Valkonen7686b102011-02-02 23:21:58 -08002045static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
2046static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302047static DEVICE_ATTR(force_cfg_update, 0664, NULL, mxt_force_cfg_update_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002048
Iiro Valkonen7686b102011-02-02 23:21:58 -08002049static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002050 &dev_attr_object.attr,
2051 &dev_attr_update_fw.attr,
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302052 &dev_attr_force_cfg_update.attr,
Amy Maloche434b7d82013-02-15 11:11:05 +00002053#if defined(CONFIG_SECURE_TOUCH)
2054 &dev_attr_secure_touch_enable.attr,
2055 &dev_attr_secure_touch.attr,
2056#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002057 NULL
2058};
2059
Iiro Valkonen7686b102011-02-02 23:21:58 -08002060static const struct attribute_group mxt_attr_group = {
2061 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002062};
2063
Amy Maloche52262212011-09-15 16:46:57 -07002064static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002065{
Jing Lin36aee812011-10-17 17:17:28 -07002066 int error;
2067
Amy Maloche52262212011-09-15 16:46:57 -07002068 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07002069 error = __mxt_write_reg(data->client, data->t7_start_addr,
2070 T7_DATA_SIZE, data->t7_data);
2071 if (error < 0) {
2072 dev_err(&data->client->dev,
2073 "failed to restore old power state\n");
2074 return error;
Amy Maloche52262212011-09-15 16:46:57 -07002075 }
Jing Lin36aee812011-10-17 17:17:28 -07002076
Amy Maloche52262212011-09-15 16:46:57 -07002077 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002078}
2079
Amy Maloche52262212011-09-15 16:46:57 -07002080static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002081{
Jing Lin36aee812011-10-17 17:17:28 -07002082 int error;
2083 u8 t7_data[T7_DATA_SIZE] = {0};
2084
Jing Lin36aee812011-10-17 17:17:28 -07002085 error = __mxt_write_reg(data->client, data->t7_start_addr,
2086 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07002087 if (error < 0) {
2088 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07002089 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07002090 return error;
2091 }
2092
2093 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002094}
2095
Iiro Valkonen7686b102011-02-02 23:21:58 -08002096static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002097{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002098 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07002099 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002100
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08002101 if (data->state == APPMODE) {
2102 error = mxt_start(data);
2103 if (error < 0) {
2104 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
2105 return error;
2106 }
Amy Maloche52262212011-09-15 16:46:57 -07002107 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002108
2109 return 0;
2110}
2111
Iiro Valkonen7686b102011-02-02 23:21:58 -08002112static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002113{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002114 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07002115 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002116
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08002117 if (data->state == APPMODE) {
2118 error = mxt_stop(data);
2119 if (error < 0)
2120 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
2121 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002122}
2123
Amy Malochec331f842012-01-24 10:33:47 -08002124static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
2125{
2126 return (regulator_count_voltages(reg) > 0) ?
2127 regulator_set_optimum_mode(reg, load_uA) : 0;
2128}
2129
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302130static int mxt_power_on(struct mxt_data *data, bool on)
2131{
2132 int rc;
2133
2134 if (on == false)
2135 goto power_off;
2136
Amy Malochec331f842012-01-24 10:33:47 -08002137 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302138 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07002139 dev_err(&data->client->dev,
2140 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302141 return rc;
2142 }
2143
Amy Maloche21115eb2011-11-02 09:04:37 -07002144 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302145 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07002146 dev_err(&data->client->dev,
2147 "Regulator vcc_ana enable failed rc=%d\n", rc);
2148 goto error_reg_en_vcc_ana;
2149 }
2150
2151 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002152 rc = reg_set_optimum_mode_check(data->vcc_dig,
2153 MXT_ACTIVE_LOAD_DIG_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002154 if (rc < 0) {
2155 dev_err(&data->client->dev,
2156 "Regulator vcc_dig set_opt failed rc=%d\n",
2157 rc);
2158 goto error_reg_opt_vcc_dig;
2159 }
2160
2161 rc = regulator_enable(data->vcc_dig);
2162 if (rc) {
2163 dev_err(&data->client->dev,
2164 "Regulator vcc_dig enable failed rc=%d\n", rc);
2165 goto error_reg_en_vcc_dig;
2166 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302167 }
2168
2169 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002170 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302171 if (rc < 0) {
2172 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002173 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302174 goto error_reg_opt_i2c;
2175 }
2176
2177 rc = regulator_enable(data->vcc_i2c);
2178 if (rc) {
2179 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002180 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302181 goto error_reg_en_vcc_i2c;
2182 }
2183 }
2184
Amy Malochef0d7b8d2011-10-17 12:10:51 -07002185 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302186
2187 return 0;
2188
2189error_reg_en_vcc_i2c:
2190 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002191 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302192error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07002193 if (data->pdata->digital_pwr_regulator)
2194 regulator_disable(data->vcc_dig);
2195error_reg_en_vcc_dig:
2196 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002197 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002198error_reg_opt_vcc_dig:
2199 regulator_disable(data->vcc_ana);
2200error_reg_en_vcc_ana:
Amy Malochec331f842012-01-24 10:33:47 -08002201 reg_set_optimum_mode_check(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302202 return rc;
2203
2204power_off:
Amy Malochec331f842012-01-24 10:33:47 -08002205 reg_set_optimum_mode_check(data->vcc_ana, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002206 regulator_disable(data->vcc_ana);
2207 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002208 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002209 regulator_disable(data->vcc_dig);
2210 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302211 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002212 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302213 regulator_disable(data->vcc_i2c);
2214 }
2215 msleep(50);
2216 return 0;
2217}
2218
2219static int mxt_regulator_configure(struct mxt_data *data, bool on)
2220{
2221 int rc;
2222
2223 if (on == false)
2224 goto hw_shutdown;
2225
Amy Maloche21115eb2011-11-02 09:04:37 -07002226 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
2227 if (IS_ERR(data->vcc_ana)) {
2228 rc = PTR_ERR(data->vcc_ana);
2229 dev_err(&data->client->dev,
2230 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302231 return rc;
2232 }
2233
Amy Maloche21115eb2011-11-02 09:04:37 -07002234 if (regulator_count_voltages(data->vcc_ana) > 0) {
2235 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302236 MXT_VTG_MAX_UV);
2237 if (rc) {
2238 dev_err(&data->client->dev,
2239 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07002240 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302241 }
2242 }
Amy Maloche21115eb2011-11-02 09:04:37 -07002243 if (data->pdata->digital_pwr_regulator) {
2244 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
2245 if (IS_ERR(data->vcc_dig)) {
2246 rc = PTR_ERR(data->vcc_dig);
2247 dev_err(&data->client->dev,
2248 "Regulator get dig failed rc=%d\n", rc);
2249 goto error_get_vtg_vcc_dig;
2250 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302251
Amy Maloche21115eb2011-11-02 09:04:37 -07002252 if (regulator_count_voltages(data->vcc_dig) > 0) {
2253 rc = regulator_set_voltage(data->vcc_dig,
2254 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
2255 if (rc) {
2256 dev_err(&data->client->dev,
2257 "regulator set_vtg failed rc=%d\n", rc);
2258 goto error_set_vtg_vcc_dig;
2259 }
2260 }
2261 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302262 if (data->pdata->i2c_pull_up) {
2263 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
2264 if (IS_ERR(data->vcc_i2c)) {
2265 rc = PTR_ERR(data->vcc_i2c);
2266 dev_err(&data->client->dev,
2267 "Regulator get failed rc=%d\n", rc);
2268 goto error_get_vtg_i2c;
2269 }
2270 if (regulator_count_voltages(data->vcc_i2c) > 0) {
2271 rc = regulator_set_voltage(data->vcc_i2c,
2272 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
2273 if (rc) {
2274 dev_err(&data->client->dev,
2275 "regulator set_vtg failed rc=%d\n", rc);
2276 goto error_set_vtg_i2c;
2277 }
2278 }
2279 }
2280
2281 return 0;
2282
2283error_set_vtg_i2c:
2284 regulator_put(data->vcc_i2c);
2285error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07002286 if (data->pdata->digital_pwr_regulator)
2287 if (regulator_count_voltages(data->vcc_dig) > 0)
2288 regulator_set_voltage(data->vcc_dig, 0,
2289 MXT_VTG_DIG_MAX_UV);
2290error_set_vtg_vcc_dig:
2291 if (data->pdata->digital_pwr_regulator)
2292 regulator_put(data->vcc_dig);
2293error_get_vtg_vcc_dig:
2294 if (regulator_count_voltages(data->vcc_ana) > 0)
2295 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2296error_set_vtg_vcc_ana:
2297 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302298 return rc;
2299
2300hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07002301 if (regulator_count_voltages(data->vcc_ana) > 0)
2302 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2303 regulator_put(data->vcc_ana);
2304 if (data->pdata->digital_pwr_regulator) {
2305 if (regulator_count_voltages(data->vcc_dig) > 0)
2306 regulator_set_voltage(data->vcc_dig, 0,
2307 MXT_VTG_DIG_MAX_UV);
2308 regulator_put(data->vcc_dig);
2309 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302310 if (data->pdata->i2c_pull_up) {
2311 if (regulator_count_voltages(data->vcc_i2c) > 0)
2312 regulator_set_voltage(data->vcc_i2c, 0,
2313 MXT_I2C_VTG_MAX_UV);
2314 regulator_put(data->vcc_i2c);
2315 }
2316 return 0;
2317}
2318
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302319#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07002320static int mxt_regulator_lpm(struct mxt_data *data, bool on)
2321{
2322
2323 int rc;
2324
2325 if (on == false)
2326 goto regulator_hpm;
2327
Amy Malochec331f842012-01-24 10:33:47 -08002328 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002329 if (rc < 0) {
2330 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002331 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002332 goto fail_regulator_lpm;
2333 }
2334
Amy Maloche21115eb2011-11-02 09:04:37 -07002335 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002336 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002337 MXT_LPM_LOAD_DIG_UA);
2338 if (rc < 0) {
2339 dev_err(&data->client->dev,
2340 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2341 goto fail_regulator_lpm;
2342 }
2343 }
2344
Jing Linbace50b2011-10-18 22:55:47 -07002345 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002346 rc = reg_set_optimum_mode_check(data->vcc_i2c,
Jing Linbace50b2011-10-18 22:55:47 -07002347 MXT_I2C_LPM_LOAD_UA);
2348 if (rc < 0) {
2349 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002350 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002351 goto fail_regulator_lpm;
2352 }
2353 }
2354
2355 return 0;
2356
2357regulator_hpm:
2358
Amy Malochec331f842012-01-24 10:33:47 -08002359 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002360 if (rc < 0) {
2361 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002362 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002363 goto fail_regulator_hpm;
2364 }
2365
Amy Maloche21115eb2011-11-02 09:04:37 -07002366 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002367 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002368 MXT_ACTIVE_LOAD_DIG_UA);
2369 if (rc < 0) {
2370 dev_err(&data->client->dev,
2371 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2372 goto fail_regulator_hpm;
2373 }
2374 }
2375
Jing Linbace50b2011-10-18 22:55:47 -07002376 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002377 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002378 if (rc < 0) {
2379 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002380 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002381 goto fail_regulator_hpm;
2382 }
2383 }
2384
2385 return 0;
2386
2387fail_regulator_lpm:
Amy Malochec331f842012-01-24 10:33:47 -08002388 reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002389 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002390 reg_set_optimum_mode_check(data->vcc_dig,
2391 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002392 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002393 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002394
2395 return rc;
2396
2397fail_regulator_hpm:
Amy Malochec331f842012-01-24 10:33:47 -08002398 reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002399 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002400 reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002401 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002402 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002403
2404 return rc;
2405}
2406
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302407static int mxt_suspend(struct device *dev)
2408{
2409 struct i2c_client *client = to_i2c_client(dev);
2410 struct mxt_data *data = i2c_get_clientdata(client);
2411 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002412 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302413
2414 mutex_lock(&input_dev->mutex);
2415
Amy Maloche52262212011-09-15 16:46:57 -07002416 if (input_dev->users) {
2417 error = mxt_stop(data);
2418 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002419 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07002420 mutex_unlock(&input_dev->mutex);
2421 return error;
2422 }
2423
2424 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302425
2426 mutex_unlock(&input_dev->mutex);
2427
Jing Linbace50b2011-10-18 22:55:47 -07002428 /* put regulators in low power mode */
2429 error = mxt_regulator_lpm(data, true);
2430 if (error < 0) {
2431 dev_err(dev, "failed to enter low power mode\n");
2432 return error;
2433 }
2434
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302435 return 0;
2436}
2437
2438static int mxt_resume(struct device *dev)
2439{
2440 struct i2c_client *client = to_i2c_client(dev);
2441 struct mxt_data *data = i2c_get_clientdata(client);
2442 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002443 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302444
Jing Linbace50b2011-10-18 22:55:47 -07002445 /* put regulators in high power mode */
2446 error = mxt_regulator_lpm(data, false);
2447 if (error < 0) {
2448 dev_err(dev, "failed to enter high power mode\n");
2449 return error;
2450 }
2451
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302452 mutex_lock(&input_dev->mutex);
2453
Amy Maloche52262212011-09-15 16:46:57 -07002454 if (input_dev->users) {
2455 error = mxt_start(data);
2456 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002457 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07002458 mutex_unlock(&input_dev->mutex);
2459 return error;
2460 }
2461 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302462
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302463 /* calibrate */
2464 if (data->pdata->need_calibration) {
2465 error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
2466 MXT_COMMAND_CALIBRATE, 1);
2467 if (error < 0)
2468 dev_dbg(dev, "sending calibration command failed\n");
2469 }
2470
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302471 mutex_unlock(&input_dev->mutex);
2472
2473 return 0;
2474}
2475
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302476static const struct dev_pm_ops mxt_pm_ops = {
Anurag Singh49d76132013-01-29 12:07:00 -08002477#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302478 .suspend = mxt_suspend,
2479 .resume = mxt_resume,
2480#endif
2481};
2482#endif
2483
Jing Lin6cfc00e2011-11-02 15:15:30 -07002484static int mxt_debugfs_object_show(struct seq_file *m, void *v)
2485{
2486 struct mxt_data *data = m->private;
2487 struct mxt_object *object;
2488 struct device *dev = &data->client->dev;
2489 int i, j, k;
2490 int error;
2491 int obj_size;
2492 u8 val;
2493
2494 for (i = 0; i < data->info.object_num; i++) {
2495 object = data->object_table + i;
2496 obj_size = object->size + 1;
2497
2498 seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
2499
2500 for (j = 0; j < object->instances + 1; j++) {
2501 seq_printf(m, "[Instance %d]\n", j);
2502
2503 for (k = 0; k < obj_size; k++) {
2504 error = mxt_read_object(data, object->type,
2505 j * obj_size + k, &val);
2506 if (error) {
2507 dev_err(dev,
2508 "Failed to read object %d "
2509 "instance %d at offset %d\n",
2510 object->type, j, k);
2511 return error;
2512 }
2513
2514 seq_printf(m, "Byte %d: 0x%02x (%d)\n",
2515 k, val, val);
2516 }
2517 }
2518 }
2519
2520 return 0;
2521}
2522
2523static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
2524{
2525 return single_open(file, mxt_debugfs_object_show, inode->i_private);
2526}
2527
2528static const struct file_operations mxt_object_fops = {
2529 .owner = THIS_MODULE,
2530 .open = mxt_debugfs_object_open,
2531 .read = seq_read,
2532 .release = single_release,
2533};
2534
Stephen Boyd0d578692012-04-25 11:49:18 -07002535static void __devinit mxt_debugfs_init(struct mxt_data *data)
Jing Lin6cfc00e2011-11-02 15:15:30 -07002536{
2537 debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
2538 if (IS_ERR_OR_NULL(debug_base))
2539 pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
2540 if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
2541 0444,
2542 debug_base,
2543 data,
2544 &mxt_object_fops))) {
2545 pr_err("atmel_mxt_ts: Failed to create object file\n");
2546 debugfs_remove_recursive(debug_base);
2547 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002548}
2549
Mohan Pallakad96f5032012-06-18 22:49:10 +05302550#ifdef CONFIG_OF
2551static int mxt_get_dt_coords(struct device *dev, char *name,
2552 struct mxt_platform_data *pdata)
2553{
2554 u32 coords[MXT_COORDS_ARR_SIZE];
2555 struct property *prop;
2556 struct device_node *np = dev->of_node;
2557 int coords_size, rc;
2558
2559 prop = of_find_property(np, name, NULL);
2560 if (!prop)
2561 return -EINVAL;
2562 if (!prop->value)
2563 return -ENODATA;
2564
2565 coords_size = prop->length / sizeof(u32);
2566 if (coords_size != MXT_COORDS_ARR_SIZE) {
2567 dev_err(dev, "invalid %s\n", name);
2568 return -EINVAL;
2569 }
2570
2571 rc = of_property_read_u32_array(np, name, coords, coords_size);
2572 if (rc && (rc != -EINVAL)) {
2573 dev_err(dev, "Unable to read %s\n", name);
2574 return rc;
2575 }
2576
2577 if (strncmp(name, "atmel,panel-coords",
2578 sizeof("atmel,panel-coords")) == 0) {
2579 pdata->panel_minx = coords[0];
2580 pdata->panel_miny = coords[1];
2581 pdata->panel_maxx = coords[2];
2582 pdata->panel_maxy = coords[3];
2583 } else if (strncmp(name, "atmel,display-coords",
2584 sizeof("atmel,display-coords")) == 0) {
2585 pdata->disp_minx = coords[0];
2586 pdata->disp_miny = coords[1];
2587 pdata->disp_maxx = coords[2];
2588 pdata->disp_maxy = coords[3];
2589 } else {
2590 dev_err(dev, "unsupported property %s\n", name);
2591 return -EINVAL;
2592 }
2593
2594 return 0;
2595}
2596
2597static int mxt_parse_config(struct device *dev, struct device_node *np,
2598 struct mxt_config_info *info)
2599{
2600 struct property *prop;
2601 u8 *temp_cfg;
2602
2603 prop = of_find_property(np, "atmel,config", &info->config_length);
2604 if (!prop) {
2605 dev_err(dev, "Looking up %s property in node %s failed",
2606 "atmel,config", np->full_name);
2607 return -ENODEV;
2608 } else if (!info->config_length) {
2609 dev_err(dev, "Invalid length of configuration data\n");
2610 return -EINVAL;
2611 }
2612
2613 temp_cfg = devm_kzalloc(dev,
2614 info->config_length * sizeof(u8), GFP_KERNEL);
2615 if (!temp_cfg) {
2616 dev_err(dev, "Unable to allocate memory to store cfg\n");
2617 return -ENOMEM;
2618 }
2619
2620 memcpy(temp_cfg, prop->value, info->config_length);
2621 info->config = temp_cfg;
2622
2623 return 0;
2624}
2625
2626static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
2627{
2628 int rc;
2629 struct mxt_config_info *info;
2630 struct device_node *temp, *np = dev->of_node;
2631 struct property *prop;
2632 u32 temp_val;
2633
2634 rc = mxt_get_dt_coords(dev, "atmel,panel-coords", pdata);
2635 if (rc)
2636 return rc;
2637
2638 rc = mxt_get_dt_coords(dev, "atmel,display-coords", pdata);
2639 if (rc)
2640 return rc;
2641
2642 /* regulator info */
2643 pdata->i2c_pull_up = of_property_read_bool(np, "atmel,i2c-pull-up");
2644 pdata->digital_pwr_regulator = of_property_read_bool(np,
2645 "atmel,dig-reg-support");
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302646
2647 pdata->no_force_update = of_property_read_bool(np,
2648 "atmel,no-force-update");
2649
Mohan Pallakad96f5032012-06-18 22:49:10 +05302650 /* reset, irq gpio info */
2651 pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
2652 0, &pdata->reset_gpio_flags);
2653 pdata->irq_gpio = of_get_named_gpio_flags(np, "atmel,irq-gpio",
2654 0, &pdata->irq_gpio_flags);
2655
2656 /* keycodes for keyarray object*/
2657 prop = of_find_property(np, "atmel,key-codes", NULL);
2658 if (prop) {
2659 pdata->key_codes = devm_kzalloc(dev,
2660 sizeof(int) * MXT_KEYARRAY_MAX_KEYS,
2661 GFP_KERNEL);
2662 if (!pdata->key_codes)
2663 return -ENOMEM;
2664 if ((prop->length/sizeof(u32)) == MXT_KEYARRAY_MAX_KEYS) {
2665 rc = of_property_read_u32_array(np, "atmel,key-codes",
2666 pdata->key_codes, MXT_KEYARRAY_MAX_KEYS);
2667 if (rc) {
2668 dev_err(dev, "Unable to read key codes\n");
2669 return rc;
2670 }
2671 } else
2672 return -EINVAL;
2673 }
2674
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302675 /* need calibration during wakeup? */
2676 pdata->need_calibration = of_property_read_bool(np,
2677 "atmel,need-calibration");
Mohan Pallakad96f5032012-06-18 22:49:10 +05302678 /* config array size */
2679 pdata->config_array_size = 0;
2680 temp = NULL;
2681 while ((temp = of_get_next_child(np, temp)))
2682 pdata->config_array_size++;
2683
2684 if (!pdata->config_array_size)
2685 return 0;
2686
2687 info = devm_kzalloc(dev, pdata->config_array_size *
2688 sizeof(struct mxt_config_info), GFP_KERNEL);
2689 if (!info) {
2690 dev_err(dev, "Unable to allocate memory\n");
2691 return -ENOMEM;
2692 }
2693
Amy Maloche265fc3c2013-01-17 11:50:24 -08002694 rc = of_property_read_u32(np, "atmel,bl-addr", &temp_val);
2695 if (rc && (rc != -EINVAL))
2696 dev_err(dev, "Unable to read bootloader address\n");
2697 else if (rc != -EINVAL)
2698 pdata->bl_addr = (u8) temp_val;
2699
Mohan Pallakad96f5032012-06-18 22:49:10 +05302700 pdata->config_array = info;
2701
2702 for_each_child_of_node(np, temp) {
2703 rc = of_property_read_string(temp, "atmel,fw-name",
2704 &info->fw_name);
2705 if (rc && (rc != -EINVAL)) {
2706 dev_err(dev, "Unable to read fw name\n");
2707 return rc;
2708 }
2709
2710 rc = of_property_read_u32(temp, "atmel,family-id", &temp_val);
2711 if (rc) {
2712 dev_err(dev, "Unable to read family id\n");
2713 return rc;
2714 } else
2715 info->family_id = (u8) temp_val;
2716
2717 rc = of_property_read_u32(temp, "atmel,variant-id", &temp_val);
2718 if (rc) {
2719 dev_err(dev, "Unable to read variant id\n");
2720 return rc;
2721 } else
2722 info->variant_id = (u8) temp_val;
2723
2724 rc = of_property_read_u32(temp, "atmel,version", &temp_val);
2725 if (rc) {
2726 dev_err(dev, "Unable to read controller version\n");
2727 return rc;
2728 } else
2729 info->version = (u8) temp_val;
2730
2731 rc = of_property_read_u32(temp, "atmel,build", &temp_val);
2732 if (rc) {
2733 dev_err(dev, "Unable to read build id\n");
2734 return rc;
2735 } else
2736 info->build = (u8) temp_val;
2737
Amy Maloche265fc3c2013-01-17 11:50:24 -08002738 rc = of_property_read_u32(temp,
Mohan Pallakad96f5032012-06-18 22:49:10 +05302739 "atmel,bootldr-id", &temp_val);
Amy Maloche265fc3c2013-01-17 11:50:24 -08002740 if (rc && (rc != -EINVAL))
Mohan Pallakad96f5032012-06-18 22:49:10 +05302741 dev_err(dev, "Unable to read bootldr-id\n");
Amy Maloche265fc3c2013-01-17 11:50:24 -08002742 else if (rc != -EINVAL)
Mohan Pallakad96f5032012-06-18 22:49:10 +05302743 info->bootldr_id = (u8) temp_val;
2744
2745 rc = mxt_parse_config(dev, temp, info);
2746 if (rc) {
2747 dev_err(dev, "Unable to parse config data\n");
2748 return rc;
2749 }
2750 info++;
2751 }
2752
2753 return 0;
2754}
2755#else
2756static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
2757{
2758 return -ENODEV;
2759}
2760#endif
2761
Anurag Singh49d76132013-01-29 12:07:00 -08002762#if defined(CONFIG_FB)
2763static int fb_notifier_callback(struct notifier_block *self,
2764 unsigned long event, void *data)
2765{
2766 struct fb_event *evdata = data;
2767 int *blank;
2768 struct mxt_data *mxt_dev_data =
2769 container_of(self, struct mxt_data, fb_notif);
2770
2771 if (evdata && evdata->data && event == FB_EVENT_BLANK && mxt_dev_data &&
2772 mxt_dev_data->client) {
2773 blank = evdata->data;
2774 if (*blank == FB_BLANK_UNBLANK)
2775 mxt_resume(&mxt_dev_data->client->dev);
2776 else if (*blank == FB_BLANK_POWERDOWN)
2777 mxt_suspend(&mxt_dev_data->client->dev);
2778 }
2779
2780 return 0;
2781}
2782#elif defined(CONFIG_HAS_EARLYSUSPEND)
2783static void mxt_early_suspend(struct early_suspend *h)
2784{
2785 struct mxt_data *data = container_of(h, struct mxt_data,
2786 early_suspend);
2787 mxt_suspend(&data->client->dev);
2788}
2789
2790static void mxt_late_resume(struct early_suspend *h)
2791{
2792 struct mxt_data *data = container_of(h, struct mxt_data,
2793 early_suspend);
2794 mxt_resume(&data->client->dev);
2795}
2796
2797#endif
2798
Amy Maloche434b7d82013-02-15 11:11:05 +00002799#if defined(CONFIG_SECURE_TOUCH)
2800static void __devinit secure_touch_init(struct mxt_data *data)
2801{
2802 init_completion(&data->st_completion);
2803}
2804#else
2805static void __devinit secure_touch_init(struct mxt_data *data)
2806{
2807}
2808#endif
2809
Iiro Valkonen7686b102011-02-02 23:21:58 -08002810static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002811 const struct i2c_device_id *id)
2812{
Mohan Pallakad96f5032012-06-18 22:49:10 +05302813 struct mxt_platform_data *pdata;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002814 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002815 struct input_dev *input_dev;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002816 int error, i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002817
Mohan Pallakad96f5032012-06-18 22:49:10 +05302818 if (client->dev.of_node) {
2819 pdata = devm_kzalloc(&client->dev,
2820 sizeof(struct mxt_platform_data), GFP_KERNEL);
2821 if (!pdata) {
2822 dev_err(&client->dev, "Failed to allocate memory\n");
2823 return -ENOMEM;
2824 }
2825
2826 error = mxt_parse_dt(&client->dev, pdata);
2827 if (error)
2828 return error;
2829 } else
2830 pdata = client->dev.platform_data;
2831
Iiro Valkonen919ed892011-02-15 13:36:52 -08002832 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002833 return -EINVAL;
2834
Iiro Valkonen7686b102011-02-02 23:21:58 -08002835 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002836 input_dev = input_allocate_device();
2837 if (!data || !input_dev) {
2838 dev_err(&client->dev, "Failed to allocate memory\n");
2839 error = -ENOMEM;
2840 goto err_free_mem;
2841 }
2842
Nick Dyer0a4016c2012-01-18 15:17:59 +05302843 data->state = INIT;
Amy Maloche83c385a2012-02-01 10:32:03 +05302844 input_dev->name = "atmel_mxt_ts";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002845 input_dev->id.bustype = BUS_I2C;
2846 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002847 input_dev->open = mxt_input_open;
2848 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002849
Joonyoung Shim910d8052011-04-12 23:14:38 -07002850 data->client = client;
2851 data->input_dev = input_dev;
2852 data->pdata = pdata;
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302853 data->no_force_update = pdata->no_force_update;
Joonyoung Shim910d8052011-04-12 23:14:38 -07002854
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002855 __set_bit(EV_ABS, input_dev->evbit);
2856 __set_bit(EV_KEY, input_dev->evbit);
2857 __set_bit(BTN_TOUCH, input_dev->keybit);
Amy Maloche9d0faa02012-06-19 12:37:39 -07002858 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002859
2860 /* For single touch */
2861 input_set_abs_params(input_dev, ABS_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002862 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002863 input_set_abs_params(input_dev, ABS_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002864 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002865 input_set_abs_params(input_dev, ABS_PRESSURE,
2866 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002867
2868 /* For multi touch */
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -07002869 input_mt_init_slots(input_dev, MXT_MAX_FINGER);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002870 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08002871 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002872 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002873 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002874 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002875 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002876 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2877 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002878
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002879 /* set key array supported keys */
2880 if (pdata->key_codes) {
2881 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
2882 if (pdata->key_codes[i])
2883 input_set_capability(input_dev, EV_KEY,
2884 pdata->key_codes[i]);
2885 }
2886 }
2887
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002888 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002889 i2c_set_clientdata(client, data);
2890
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302891 if (pdata->init_hw)
2892 error = pdata->init_hw(true);
2893 else
2894 error = mxt_regulator_configure(data, true);
2895 if (error) {
2896 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07002897 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302898 }
2899
2900 if (pdata->power_on)
2901 error = pdata->power_on(true);
2902 else
2903 error = mxt_power_on(data, true);
2904 if (error) {
2905 dev_err(&client->dev, "Failed to power on hardware\n");
2906 goto err_regulator_on;
2907 }
2908
Amy Maloche08266db2011-11-04 11:07:16 -07002909 if (gpio_is_valid(pdata->irq_gpio)) {
2910 /* configure touchscreen irq gpio */
Mohan Pallakad96f5032012-06-18 22:49:10 +05302911 error = gpio_request(pdata->irq_gpio, "mxt_irq_gpio");
Amy Maloche08266db2011-11-04 11:07:16 -07002912 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302913 dev_err(&client->dev, "unable to request gpio [%d]\n",
Amy Maloche08266db2011-11-04 11:07:16 -07002914 pdata->irq_gpio);
2915 goto err_power_on;
2916 }
2917 error = gpio_direction_input(pdata->irq_gpio);
2918 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302919 dev_err(&client->dev,
2920 "unable to set direction for gpio [%d]\n",
2921 pdata->irq_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002922 goto err_irq_gpio_req;
2923 }
Mohan Pallakad96f5032012-06-18 22:49:10 +05302924 data->irq = client->irq = gpio_to_irq(pdata->irq_gpio);
2925 } else {
2926 dev_err(&client->dev, "irq gpio not provided\n");
2927 goto err_power_on;
Amy Maloche08266db2011-11-04 11:07:16 -07002928 }
2929
2930 if (gpio_is_valid(pdata->reset_gpio)) {
2931 /* configure touchscreen reset out gpio */
Mohan Pallakad96f5032012-06-18 22:49:10 +05302932 error = gpio_request(pdata->reset_gpio, "mxt_reset_gpio");
Amy Maloche08266db2011-11-04 11:07:16 -07002933 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302934 dev_err(&client->dev, "unable to request gpio [%d]\n",
2935 pdata->reset_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002936 goto err_irq_gpio_req;
2937 }
2938
Mohan Pallakad96f5032012-06-18 22:49:10 +05302939 error = gpio_direction_output(pdata->reset_gpio, 1);
Amy Maloche08266db2011-11-04 11:07:16 -07002940 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302941 dev_err(&client->dev,
2942 "unable to set direction for gpio [%d]\n",
2943 pdata->reset_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002944 goto err_reset_gpio_req;
2945 }
2946 }
2947
Jing Lin64fdd1f2012-12-20 17:08:28 -08002948 mxt_power_on_delay(data);
2949
Amy Maloche265fc3c2013-01-17 11:50:24 -08002950 data->addr_pair.application = data->client->addr;
2951
2952 if (pdata->bl_addr)
2953 data->addr_pair.bootloader = pdata->bl_addr;
2954 else
2955 mxt_lookup_bootloader_address(data);
2956
Iiro Valkonen7686b102011-02-02 23:21:58 -08002957 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002958 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07002959 goto err_reset_gpio_req;
Jing Lin64fdd1f2012-12-20 17:08:28 -08002960
Iiro Valkonen7686b102011-02-02 23:21:58 -08002961 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08002962 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002963 if (error) {
2964 dev_err(&client->dev, "Failed to register interrupt\n");
2965 goto err_free_object;
2966 }
2967
Nick Dyer0a4016c2012-01-18 15:17:59 +05302968 if (data->state == APPMODE) {
2969 error = mxt_make_highchg(data);
2970 if (error) {
2971 dev_err(&client->dev, "Failed to make high CHG\n");
2972 goto err_free_irq;
2973 }
2974 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07002975
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002976 error = input_register_device(input_dev);
2977 if (error)
2978 goto err_free_irq;
2979
Iiro Valkonen7686b102011-02-02 23:21:58 -08002980 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002981 if (error)
2982 goto err_unregister_device;
2983
Anurag Singh49d76132013-01-29 12:07:00 -08002984#if defined(CONFIG_FB)
2985 data->fb_notif.notifier_call = fb_notifier_callback;
2986
2987 error = fb_register_client(&data->fb_notif);
2988
2989 if (error)
2990 dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
2991 error);
2992#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302993 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
2994 MXT_SUSPEND_LEVEL;
2995 data->early_suspend.suspend = mxt_early_suspend;
2996 data->early_suspend.resume = mxt_late_resume;
2997 register_early_suspend(&data->early_suspend);
2998#endif
2999
Jing Lin6cfc00e2011-11-02 15:15:30 -07003000 mxt_debugfs_init(data);
3001
Amy Maloche434b7d82013-02-15 11:11:05 +00003002 secure_touch_init(data);
3003
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003004 return 0;
3005
3006err_unregister_device:
3007 input_unregister_device(input_dev);
3008 input_dev = NULL;
3009err_free_irq:
3010 free_irq(client->irq, data);
3011err_free_object:
3012 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07003013err_reset_gpio_req:
3014 if (gpio_is_valid(pdata->reset_gpio))
3015 gpio_free(pdata->reset_gpio);
3016err_irq_gpio_req:
3017 if (gpio_is_valid(pdata->irq_gpio))
3018 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05303019err_power_on:
3020 if (pdata->power_on)
3021 pdata->power_on(false);
3022 else
3023 mxt_power_on(data, false);
3024err_regulator_on:
3025 if (pdata->init_hw)
3026 pdata->init_hw(false);
3027 else
3028 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003029err_free_mem:
3030 input_free_device(input_dev);
3031 kfree(data);
3032 return error;
3033}
3034
Iiro Valkonen7686b102011-02-02 23:21:58 -08003035static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003036{
Iiro Valkonen7686b102011-02-02 23:21:58 -08003037 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003038
Iiro Valkonen7686b102011-02-02 23:21:58 -08003039 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003040 free_irq(data->irq, data);
3041 input_unregister_device(data->input_dev);
Anurag Singh49d76132013-01-29 12:07:00 -08003042#if defined(CONFIG_FB)
3043 if (fb_unregister_client(&data->fb_notif))
3044 dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
3045#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +05303046 unregister_early_suspend(&data->early_suspend);
3047#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05303048
3049 if (data->pdata->power_on)
3050 data->pdata->power_on(false);
3051 else
3052 mxt_power_on(data, false);
3053
3054 if (data->pdata->init_hw)
3055 data->pdata->init_hw(false);
3056 else
3057 mxt_regulator_configure(data, false);
3058
Mohan Pallakabfe8f302012-01-02 18:32:08 +08003059 if (gpio_is_valid(data->pdata->reset_gpio))
3060 gpio_free(data->pdata->reset_gpio);
3061
3062 if (gpio_is_valid(data->pdata->irq_gpio))
3063 gpio_free(data->pdata->irq_gpio);
3064
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003065 kfree(data->object_table);
3066 kfree(data);
3067
Jing Lin6cfc00e2011-11-02 15:15:30 -07003068 debugfs_remove_recursive(debug_base);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003069
3070 return 0;
3071}
3072
Iiro Valkonen7686b102011-02-02 23:21:58 -08003073static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003074 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08003075 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08003076 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003077 { }
3078};
Iiro Valkonen7686b102011-02-02 23:21:58 -08003079MODULE_DEVICE_TABLE(i2c, mxt_id);
Amy Maloche56cb58c2012-08-23 13:21:03 -07003080#ifdef CONFIG_OF
Mohan Pallakad96f5032012-06-18 22:49:10 +05303081static struct of_device_id mxt_match_table[] = {
3082 { .compatible = "atmel,mxt-ts",},
3083 { },
3084};
3085#else
3086#define mxt_match_table NULL
3087#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003088
Iiro Valkonen7686b102011-02-02 23:21:58 -08003089static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003090 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08003091 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003092 .owner = THIS_MODULE,
Mohan Pallakad96f5032012-06-18 22:49:10 +05303093 .of_match_table = mxt_match_table,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08003094#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08003095 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08003096#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003097 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08003098 .probe = mxt_probe,
3099 .remove = __devexit_p(mxt_remove),
3100 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003101};
3102
Axel Lin1b92c1c2012-03-16 23:05:41 -07003103module_i2c_driver(mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003104
3105/* Module information */
3106MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08003107MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003108MODULE_LICENSE("GPL");