blob: 1d56a0a0f8d84a6f5dc80339daa0be9f53fab447 [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
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070041/* Family ID */
42#define MXT224_ID 0x80
Amy Maloche380cc0b2011-11-03 12:55:04 -070043#define MXT224E_ID 0x81
Amy Maloche41f1cc32012-07-12 13:02:27 -070044#define MXT336S_ID 0x82
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070045#define MXT1386_ID 0xA0
Amy Maloche41f1cc32012-07-12 13:02:27 -070046#define MXT1664S_ID 0xA2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070047
48/* Version */
Iiro Valkonen7686b102011-02-02 23:21:58 -080049#define MXT_VER_20 20
50#define MXT_VER_21 21
51#define MXT_VER_22 22
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070052
Nick Dyer0a4016c2012-01-18 15:17:59 +053053/* I2C slave address pairs */
54struct mxt_address_pair {
55 int bootloader;
56 int application;
57};
58
59static const struct mxt_address_pair mxt_slave_addresses[] = {
60 { 0x24, 0x4a },
61 { 0x25, 0x4b },
62 { 0x25, 0x4b },
63 { 0x26, 0x4c },
64 { 0x27, 0x4d },
65 { 0x34, 0x5a },
66 { 0x35, 0x5b },
67 { 0 },
68};
69
70enum mxt_device_state { INIT, APPMODE, BOOTLOADER };
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070071
72/* Firmware */
Iiro Valkonen7686b102011-02-02 23:21:58 -080073#define MXT_FW_NAME "maxtouch.fw"
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070074
Jing Lincc974cb2012-02-01 23:13:14 -080075/* Firmware frame size including frame data and CRC */
76#define MXT_SINGLE_FW_MAX_FRAME_SIZE 278
77#define MXT_CHIPSET_FW_MAX_FRAME_SIZE 534
78
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070079/* Registers */
Iiro Valkonen7686b102011-02-02 23:21:58 -080080#define MXT_FAMILY_ID 0x00
81#define MXT_VARIANT_ID 0x01
82#define MXT_VERSION 0x02
83#define MXT_BUILD 0x03
84#define MXT_MATRIX_X_SIZE 0x04
85#define MXT_MATRIX_Y_SIZE 0x05
86#define MXT_OBJECT_NUM 0x06
87#define MXT_OBJECT_START 0x07
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070088
Iiro Valkonen7686b102011-02-02 23:21:58 -080089#define MXT_OBJECT_SIZE 6
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070090
91/* Object types */
Iiro Valkonen81c88a72011-07-04 03:08:25 -070092#define MXT_DEBUG_DIAGNOSTIC_T37 37
93#define MXT_GEN_MESSAGE_T5 5
94#define MXT_GEN_COMMAND_T6 6
95#define MXT_GEN_POWER_T7 7
96#define MXT_GEN_ACQUIRE_T8 8
97#define MXT_GEN_DATASOURCE_T53 53
98#define MXT_TOUCH_MULTI_T9 9
99#define MXT_TOUCH_KEYARRAY_T15 15
100#define MXT_TOUCH_PROXIMITY_T23 23
101#define MXT_TOUCH_PROXKEY_T52 52
102#define MXT_PROCI_GRIPFACE_T20 20
103#define MXT_PROCG_NOISE_T22 22
Amy Maloche41f1cc32012-07-12 13:02:27 -0700104#define MXT_PROCG_NOISE_T62 62
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700105#define MXT_PROCI_ONETOUCH_T24 24
106#define MXT_PROCI_TWOTOUCH_T27 27
107#define MXT_PROCI_GRIP_T40 40
108#define MXT_PROCI_PALM_T41 41
109#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
110#define MXT_PROCI_STYLUS_T47 47
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530111#define MXT_PROCI_ADAPTIVETHRESHOLD_T55 55
Jing Linc7fc4052011-12-21 16:16:19 -0800112#define MXT_PROCI_SHIELDLESS_T56 56
Amy Maloche41f1cc32012-07-12 13:02:27 -0700113#define MXT_PROCI_EXTRATSDATA_T57 57
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700114#define MXT_PROCG_NOISESUPPRESSION_T48 48
115#define MXT_SPT_COMMSCONFIG_T18 18
116#define MXT_SPT_GPIOPWM_T19 19
117#define MXT_SPT_SELFTEST_T25 25
118#define MXT_SPT_CTECONFIG_T28 28
119#define MXT_SPT_USERDATA_T38 38
120#define MXT_SPT_DIGITIZER_T43 43
121#define MXT_SPT_MESSAGECOUNT_T44 44
122#define MXT_SPT_CTECONFIG_T46 46
Amy Maloche41f1cc32012-07-12 13:02:27 -0700123#define MXT_SPT_TIMER_T61 61
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700124
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700125/* MXT_GEN_COMMAND_T6 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800126#define MXT_COMMAND_RESET 0
127#define MXT_COMMAND_BACKUPNV 1
128#define MXT_COMMAND_CALIBRATE 2
129#define MXT_COMMAND_REPORTALL 3
130#define MXT_COMMAND_DIAGNOSTIC 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700131
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700132/* MXT_GEN_POWER_T7 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800133#define MXT_POWER_IDLEACQINT 0
134#define MXT_POWER_ACTVACQINT 1
135#define MXT_POWER_ACTV2IDLETO 2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700136
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700137/* MXT_GEN_ACQUIRE_T8 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800138#define MXT_ACQUIRE_CHRGTIME 0
139#define MXT_ACQUIRE_TCHDRIFT 2
140#define MXT_ACQUIRE_DRIFTST 3
141#define MXT_ACQUIRE_TCHAUTOCAL 4
142#define MXT_ACQUIRE_SYNC 5
143#define MXT_ACQUIRE_ATCHCALST 6
144#define MXT_ACQUIRE_ATCHCALSTHR 7
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700145
Iiro Valkonene8645592011-11-18 12:56:19 -0800146/* MXT_TOUCH_MULT_T9 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800147#define MXT_TOUCH_CTRL 0
148#define MXT_TOUCH_XORIGIN 1
149#define MXT_TOUCH_YORIGIN 2
150#define MXT_TOUCH_XSIZE 3
151#define MXT_TOUCH_YSIZE 4
152#define MXT_TOUCH_BLEN 6
153#define MXT_TOUCH_TCHTHR 7
154#define MXT_TOUCH_TCHDI 8
155#define MXT_TOUCH_ORIENT 9
156#define MXT_TOUCH_MOVHYSTI 11
157#define MXT_TOUCH_MOVHYSTN 12
158#define MXT_TOUCH_NUMTOUCH 14
159#define MXT_TOUCH_MRGHYST 15
160#define MXT_TOUCH_MRGTHR 16
161#define MXT_TOUCH_AMPHYST 17
162#define MXT_TOUCH_XRANGE_LSB 18
163#define MXT_TOUCH_XRANGE_MSB 19
164#define MXT_TOUCH_YRANGE_LSB 20
165#define MXT_TOUCH_YRANGE_MSB 21
166#define MXT_TOUCH_XLOCLIP 22
167#define MXT_TOUCH_XHICLIP 23
168#define MXT_TOUCH_YLOCLIP 24
169#define MXT_TOUCH_YHICLIP 25
170#define MXT_TOUCH_XEDGECTRL 26
171#define MXT_TOUCH_XEDGEDIST 27
172#define MXT_TOUCH_YEDGECTRL 28
173#define MXT_TOUCH_YEDGEDIST 29
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700174#define MXT_TOUCH_JUMPLIMIT 30
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700175
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700176/* MXT_PROCI_GRIPFACE_T20 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800177#define MXT_GRIPFACE_CTRL 0
178#define MXT_GRIPFACE_XLOGRIP 1
179#define MXT_GRIPFACE_XHIGRIP 2
180#define MXT_GRIPFACE_YLOGRIP 3
181#define MXT_GRIPFACE_YHIGRIP 4
182#define MXT_GRIPFACE_MAXTCHS 5
183#define MXT_GRIPFACE_SZTHR1 7
184#define MXT_GRIPFACE_SZTHR2 8
185#define MXT_GRIPFACE_SHPTHR1 9
186#define MXT_GRIPFACE_SHPTHR2 10
187#define MXT_GRIPFACE_SUPEXTTO 11
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700188
Iiro Valkonen7686b102011-02-02 23:21:58 -0800189/* MXT_PROCI_NOISE field */
190#define MXT_NOISE_CTRL 0
191#define MXT_NOISE_OUTFLEN 1
192#define MXT_NOISE_GCAFUL_LSB 3
193#define MXT_NOISE_GCAFUL_MSB 4
194#define MXT_NOISE_GCAFLL_LSB 5
195#define MXT_NOISE_GCAFLL_MSB 6
196#define MXT_NOISE_ACTVGCAFVALID 7
197#define MXT_NOISE_NOISETHR 8
198#define MXT_NOISE_FREQHOPSCALE 10
199#define MXT_NOISE_FREQ0 11
200#define MXT_NOISE_FREQ1 12
201#define MXT_NOISE_FREQ2 13
202#define MXT_NOISE_FREQ3 14
203#define MXT_NOISE_FREQ4 15
204#define MXT_NOISE_IDLEGCAFVALID 16
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700205
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700206/* MXT_SPT_COMMSCONFIG_T18 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800207#define MXT_COMMS_CTRL 0
208#define MXT_COMMS_CMD 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700209
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700210/* MXT_SPT_CTECONFIG_T28 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800211#define MXT_CTE_CTRL 0
212#define MXT_CTE_CMD 1
213#define MXT_CTE_MODE 2
214#define MXT_CTE_IDLEGCAFDEPTH 3
215#define MXT_CTE_ACTVGCAFDEPTH 4
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700216#define MXT_CTE_VOLTAGE 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700217
Iiro Valkonen7686b102011-02-02 23:21:58 -0800218#define MXT_VOLTAGE_DEFAULT 2700000
219#define MXT_VOLTAGE_STEP 10000
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700220
Amy Maloche21115eb2011-11-02 09:04:37 -0700221/* Analog voltage @2.7 V */
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530222#define MXT_VTG_MIN_UV 2700000
223#define MXT_VTG_MAX_UV 3300000
224#define MXT_ACTIVE_LOAD_UA 15000
Jing Linbace50b2011-10-18 22:55:47 -0700225#define MXT_LPM_LOAD_UA 10
Amy Maloche21115eb2011-11-02 09:04:37 -0700226/* Digital voltage @1.8 V */
227#define MXT_VTG_DIG_MIN_UV 1800000
228#define MXT_VTG_DIG_MAX_UV 1800000
229#define MXT_ACTIVE_LOAD_DIG_UA 10000
230#define MXT_LPM_LOAD_DIG_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530231
232#define MXT_I2C_VTG_MIN_UV 1800000
233#define MXT_I2C_VTG_MAX_UV 1800000
234#define MXT_I2C_LOAD_UA 10000
Jing Linbace50b2011-10-18 22:55:47 -0700235#define MXT_I2C_LPM_LOAD_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530236
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700237/* Define for MXT_GEN_COMMAND_T6 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800238#define MXT_BOOT_VALUE 0xa5
239#define MXT_BACKUP_VALUE 0x55
240#define MXT_BACKUP_TIME 25 /* msec */
Jing Lin64fdd1f2012-12-20 17:08:28 -0800241
242/* Software reset delay */
243#define MXT224_RESET_TIME 64 /* msec */
244#define MXT224E_RESET_TIME 21 /* msec */
Amy Maloche41f1cc32012-07-12 13:02:27 -0700245#define MXT336S_RESET_TIME 25 /* msec */
Jing Lin64fdd1f2012-12-20 17:08:28 -0800246#define MXT1386_RESET_TIME 250 /* msec */
247#define MXT1386E_RESET_TIME 229 /* msec */
248#define MXT1664S_RESET_TIME 280 /* msec */
Amy Maloche7e447432011-09-14 11:36:30 -0700249#define MXT_RESET_TIME 250 /* msec */
Jing Linc7fc4052011-12-21 16:16:19 -0800250#define MXT_RESET_NOCHGREAD 400 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700251
Jing Lin64fdd1f2012-12-20 17:08:28 -0800252/* Power on delay */
253#define MXT224_POWER_ON_TIME 40 /* msec */
254#define MXT224E_POWER_ON_TIME 21 /* msec */
255#define MXT336S_POWER_ON_TIME 25 /* msec */
256#define MXT1386_POWER_ON_TIME 90 /* msec */
257#define MXT1386E_POWER_ON_TIME 81 /* msec */
258#define MXT1664S_POWER_ON_TIME 65 /* msec */
259#define MXT_POWER_ON_TIME 100 /* msec */
260
Nick Dyer0a4016c2012-01-18 15:17:59 +0530261#define MXT_FWRESET_TIME 1000 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700262
Jing Lin36aee812011-10-17 17:17:28 -0700263#define MXT_WAKE_TIME 25
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700264
265/* Command to unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800266#define MXT_UNLOCK_CMD_MSB 0xaa
267#define MXT_UNLOCK_CMD_LSB 0xdc
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700268
269/* Bootloader mode status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800270#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
271#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
272#define MXT_FRAME_CRC_CHECK 0x02
273#define MXT_FRAME_CRC_FAIL 0x03
274#define MXT_FRAME_CRC_PASS 0x04
275#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
276#define MXT_BOOT_STATUS_MASK 0x3f
Nick Dyer0a4016c2012-01-18 15:17:59 +0530277#define MXT_BOOT_EXTENDED_ID (1 << 5)
278#define MXT_BOOT_ID_MASK 0x1f
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700279
280/* Touch status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800281#define MXT_SUPPRESS (1 << 1)
282#define MXT_AMP (1 << 2)
283#define MXT_VECTOR (1 << 3)
284#define MXT_MOVE (1 << 4)
285#define MXT_RELEASE (1 << 5)
286#define MXT_PRESS (1 << 6)
287#define MXT_DETECT (1 << 7)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700288
Joonyoung Shim910d8052011-04-12 23:14:38 -0700289/* Touch orient bits */
290#define MXT_XY_SWITCH (1 << 0)
291#define MXT_X_INVERT (1 << 1)
292#define MXT_Y_INVERT (1 << 2)
293
Mohan Pallakab6acab42012-06-13 11:59:04 +0530294/* Touch suppression */
295#define MXT_TCHSUP_ACTIVE (1 << 0)
296
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700297/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800298#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700299
Iiro Valkonen7686b102011-02-02 23:21:58 -0800300#define MXT_MAX_FINGER 10
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700301
Jing Lin36aee812011-10-17 17:17:28 -0700302#define T7_DATA_SIZE 3
303#define MXT_MAX_RW_TRIES 3
304#define MXT_BLOCK_SIZE 256
Jing Lin8fadad72012-02-24 10:10:50 -0800305#define MXT_CFG_VERSION_LEN 3
306#define MXT_CFG_VERSION_EQUAL 0
307#define MXT_CFG_VERSION_LESS 1
308#define MXT_CFG_VERSION_GREATER 2
Mohan Pallakaab51f2b2011-09-29 18:17:35 +0530309
Mohan Pallakad96f5032012-06-18 22:49:10 +0530310#define MXT_COORDS_ARR_SIZE 4
311
Jing Lin6cfc00e2011-11-02 15:15:30 -0700312#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
313#define MXT_DEBUGFS_FILE "object"
314
Iiro Valkonen7686b102011-02-02 23:21:58 -0800315struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700316 u8 family_id;
317 u8 variant_id;
318 u8 version;
319 u8 build;
320 u8 matrix_xsize;
321 u8 matrix_ysize;
322 u8 object_num;
323};
324
Iiro Valkonen7686b102011-02-02 23:21:58 -0800325struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700326 u8 type;
327 u16 start_address;
328 u8 size;
329 u8 instances;
330 u8 num_report_ids;
331
332 /* to map object and message */
333 u8 max_reportid;
334};
335
Iiro Valkonen7686b102011-02-02 23:21:58 -0800336struct mxt_message {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700337 u8 reportid;
338 u8 message[7];
339 u8 checksum;
340};
341
Iiro Valkonen7686b102011-02-02 23:21:58 -0800342struct mxt_finger {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700343 int status;
344 int x;
345 int y;
346 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700347 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700348};
349
350/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800351struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700352 struct i2c_client *client;
353 struct input_dev *input_dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800354 const struct mxt_platform_data *pdata;
Jing Lindc4413c2012-01-16 15:22:52 -0800355 const struct mxt_config_info *config_info;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530356 enum mxt_device_state state;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800357 struct mxt_object *object_table;
358 struct mxt_info info;
359 struct mxt_finger finger[MXT_MAX_FINGER];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700360 unsigned int irq;
Amy Maloche21115eb2011-11-02 09:04:37 -0700361 struct regulator *vcc_ana;
362 struct regulator *vcc_dig;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530363 struct regulator *vcc_i2c;
Anurag Singh49d76132013-01-29 12:07:00 -0800364#if defined(CONFIG_FB)
365 struct notifier_block fb_notif;
366#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +0530367 struct early_suspend early_suspend;
368#endif
Jing Lin36aee812011-10-17 17:17:28 -0700369
Amy Maloche52262212011-09-15 16:46:57 -0700370 u8 t7_data[T7_DATA_SIZE];
Jing Lin36aee812011-10-17 17:17:28 -0700371 u16 t7_start_addr;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800372 u32 keyarray_old;
373 u32 keyarray_new;
374 u8 t9_max_reportid;
375 u8 t9_min_reportid;
376 u8 t15_max_reportid;
377 u8 t15_min_reportid;
Mohan Pallakab6acab42012-06-13 11:59:04 +0530378 u8 t42_max_reportid;
379 u8 t42_min_reportid;
Jing Lin8fadad72012-02-24 10:10:50 -0800380 u8 cfg_version[MXT_CFG_VERSION_LEN];
Jing Lindc4413c2012-01-16 15:22:52 -0800381 int cfg_version_idx;
Jing Lin8a9472d2012-03-21 15:43:45 -0700382 int t38_start_addr;
Jing Lin8fadad72012-02-24 10:10:50 -0800383 bool update_cfg;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -0800384 const char *fw_name;
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +0530385 bool no_force_update;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700386};
387
Jing Lin6cfc00e2011-11-02 15:15:30 -0700388static struct dentry *debug_base;
389
Iiro Valkonen7686b102011-02-02 23:21:58 -0800390static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700391{
392 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700393 case MXT_GEN_MESSAGE_T5:
394 case MXT_GEN_COMMAND_T6:
395 case MXT_GEN_POWER_T7:
396 case MXT_GEN_ACQUIRE_T8:
397 case MXT_GEN_DATASOURCE_T53:
398 case MXT_TOUCH_MULTI_T9:
399 case MXT_TOUCH_KEYARRAY_T15:
400 case MXT_TOUCH_PROXIMITY_T23:
401 case MXT_TOUCH_PROXKEY_T52:
402 case MXT_PROCI_GRIPFACE_T20:
403 case MXT_PROCG_NOISE_T22:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700404 case MXT_PROCG_NOISE_T62:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700405 case MXT_PROCI_ONETOUCH_T24:
406 case MXT_PROCI_TWOTOUCH_T27:
407 case MXT_PROCI_GRIP_T40:
408 case MXT_PROCI_PALM_T41:
409 case MXT_PROCI_TOUCHSUPPRESSION_T42:
410 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800411 case MXT_PROCI_SHIELDLESS_T56:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700412 case MXT_PROCI_EXTRATSDATA_T57:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700413 case MXT_PROCG_NOISESUPPRESSION_T48:
414 case MXT_SPT_COMMSCONFIG_T18:
415 case MXT_SPT_GPIOPWM_T19:
416 case MXT_SPT_SELFTEST_T25:
417 case MXT_SPT_CTECONFIG_T28:
418 case MXT_SPT_USERDATA_T38:
419 case MXT_SPT_DIGITIZER_T43:
420 case MXT_SPT_CTECONFIG_T46:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700421 case MXT_SPT_TIMER_T61:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530422 case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700423 return true;
424 default:
425 return false;
426 }
427}
428
Iiro Valkonen7686b102011-02-02 23:21:58 -0800429static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700430{
431 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700432 case MXT_GEN_COMMAND_T6:
433 case MXT_GEN_POWER_T7:
434 case MXT_GEN_ACQUIRE_T8:
435 case MXT_TOUCH_MULTI_T9:
436 case MXT_TOUCH_KEYARRAY_T15:
437 case MXT_TOUCH_PROXIMITY_T23:
438 case MXT_TOUCH_PROXKEY_T52:
439 case MXT_PROCI_GRIPFACE_T20:
440 case MXT_PROCG_NOISE_T22:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700441 case MXT_PROCG_NOISE_T62:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700442 case MXT_PROCI_ONETOUCH_T24:
443 case MXT_PROCI_TWOTOUCH_T27:
444 case MXT_PROCI_GRIP_T40:
445 case MXT_PROCI_PALM_T41:
446 case MXT_PROCI_TOUCHSUPPRESSION_T42:
447 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800448 case MXT_PROCI_SHIELDLESS_T56:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700449 case MXT_PROCI_EXTRATSDATA_T57:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700450 case MXT_PROCG_NOISESUPPRESSION_T48:
451 case MXT_SPT_COMMSCONFIG_T18:
452 case MXT_SPT_GPIOPWM_T19:
453 case MXT_SPT_SELFTEST_T25:
454 case MXT_SPT_CTECONFIG_T28:
Iiro Valkonene8645592011-11-18 12:56:19 -0800455 case MXT_SPT_USERDATA_T38:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700456 case MXT_SPT_DIGITIZER_T43:
457 case MXT_SPT_CTECONFIG_T46:
Amy Maloche41f1cc32012-07-12 13:02:27 -0700458 case MXT_SPT_TIMER_T61:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530459 case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700460 return true;
461 default:
462 return false;
463 }
464}
465
Iiro Valkonen7686b102011-02-02 23:21:58 -0800466static void mxt_dump_message(struct device *dev,
467 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700468{
469 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
470 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
471 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
472 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
473 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
474 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
475 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
476 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
477 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
478}
479
Amy Maloche71b8f022013-01-17 11:50:24 -0800480static int mxt_switch_to_bootloader_address(struct mxt_data *data)
481{
Steve Mucklee1533542013-02-13 15:03:16 -0800482 int i;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530483 struct i2c_client *client = data->client;
484
485 if (data->state == BOOTLOADER) {
486 dev_err(&client->dev, "Already in BOOTLOADER state\n");
487 return -EINVAL;
488 }
489
Steve Mucklee1533542013-02-13 15:03:16 -0800490 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
491 if (mxt_slave_addresses[i].application == client->addr) {
492 dev_info(&client->dev, "Changing to bootloader address: "
493 "%02x -> %02x",
494 client->addr,
495 mxt_slave_addresses[i].bootloader);
Nick Dyer0a4016c2012-01-18 15:17:59 +0530496
Steve Mucklee1533542013-02-13 15:03:16 -0800497 client->addr = mxt_slave_addresses[i].bootloader;
498 data->state = BOOTLOADER;
499 return 0;
500 }
501 }
502
503 dev_err(&client->dev, "Address 0x%02x not found in address table",
504 client->addr);
505 return -EINVAL;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530506}
507
508static int mxt_switch_to_appmode_address(struct mxt_data *data)
509{
Steve Mucklee1533542013-02-13 15:03:16 -0800510 int i;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530511 struct i2c_client *client = data->client;
512
513 if (data->state == APPMODE) {
514 dev_err(&client->dev, "Already in APPMODE state\n");
515 return -EINVAL;
516 }
517
Steve Mucklee1533542013-02-13 15:03:16 -0800518 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
519 if (mxt_slave_addresses[i].bootloader == client->addr) {
520 dev_info(&client->dev,
521 "Changing to application mode address: "
522 "0x%02x -> 0x%02x",
523 client->addr,
524 mxt_slave_addresses[i].application);
Nick Dyer0a4016c2012-01-18 15:17:59 +0530525
Steve Mucklee1533542013-02-13 15:03:16 -0800526 client->addr = mxt_slave_addresses[i].application;
527 data->state = APPMODE;
528 return 0;
529 }
530 }
531
532 dev_err(&client->dev, "Address 0x%02x not found in address table",
533 client->addr);
534 return -EINVAL;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530535}
536
537static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
538{
539 u8 buf[3];
540
541 if (val | MXT_BOOT_EXTENDED_ID) {
542 dev_dbg(&client->dev,
543 "Retrieving extended mode ID information");
544
545 if (i2c_master_recv(client, &buf[0], 3) != 3) {
546 dev_err(&client->dev, "%s: i2c recv failed\n",
547 __func__);
548 return -EIO;
549 }
550
551 dev_info(&client->dev, "Bootloader ID:%d Version:%d",
552 buf[1], buf[2]);
553
554 return buf[0];
555 } else {
556 dev_info(&client->dev, "Bootloader ID:%d",
557 val & MXT_BOOT_ID_MASK);
558
559 return val;
560 }
561}
562
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -0800563static int mxt_get_bootloader_id(struct i2c_client *client)
564{
565 u8 val;
566 u8 buf[3];
567
568 if (i2c_master_recv(client, &val, 1) != 1) {
569 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
570 return -EIO;
571 }
572
573 if (val | MXT_BOOT_EXTENDED_ID) {
574 if (i2c_master_recv(client, &buf[0], 3) != 3) {
575 dev_err(&client->dev, "%s: i2c recv failed\n",
576 __func__);
577 return -EIO;
578 }
579 return buf[1];
580 } else {
581 dev_info(&client->dev, "Bootloader ID:%d",
582 val & MXT_BOOT_ID_MASK);
583
584 return val & MXT_BOOT_ID_MASK;
585 }
586}
587
Iiro Valkonen7686b102011-02-02 23:21:58 -0800588static int mxt_check_bootloader(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530589 unsigned int state)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700590{
591 u8 val;
592
593recheck:
594 if (i2c_master_recv(client, &val, 1) != 1) {
595 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
596 return -EIO;
597 }
598
599 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800600 case MXT_WAITING_BOOTLOAD_CMD:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530601 val = mxt_get_bootloader_version(client, val);
602 val &= ~MXT_BOOT_STATUS_MASK;
603 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800604 case MXT_WAITING_FRAME_DATA:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530605 case MXT_APP_CRC_FAIL:
Iiro Valkonen7686b102011-02-02 23:21:58 -0800606 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700607 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800608 case MXT_FRAME_CRC_PASS:
609 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700610 goto recheck;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530611 if (val == MXT_FRAME_CRC_FAIL) {
612 dev_err(&client->dev, "Bootloader CRC fail\n");
613 return -EINVAL;
614 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700615 break;
616 default:
617 return -EINVAL;
618 }
619
620 if (val != state) {
Nick Dyer0a4016c2012-01-18 15:17:59 +0530621 dev_err(&client->dev, "Invalid bootloader mode state %X\n",
622 val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700623 return -EINVAL;
624 }
625
626 return 0;
627}
628
Iiro Valkonen7686b102011-02-02 23:21:58 -0800629static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700630{
631 u8 buf[2];
632
Iiro Valkonen7686b102011-02-02 23:21:58 -0800633 buf[0] = MXT_UNLOCK_CMD_LSB;
634 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700635
636 if (i2c_master_send(client, buf, 2) != 2) {
637 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
638 return -EIO;
639 }
640
641 return 0;
642}
643
Iiro Valkonen7686b102011-02-02 23:21:58 -0800644static int mxt_fw_write(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530645 const u8 *data, unsigned int frame_size)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700646{
647 if (i2c_master_send(client, data, frame_size) != frame_size) {
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_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700656 u16 reg, u16 len, void *val)
657{
658 struct i2c_msg xfer[2];
659 u8 buf[2];
Jing Lin36aee812011-10-17 17:17:28 -0700660 int i = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700661
662 buf[0] = reg & 0xff;
663 buf[1] = (reg >> 8) & 0xff;
664
665 /* Write register */
666 xfer[0].addr = client->addr;
667 xfer[0].flags = 0;
668 xfer[0].len = 2;
669 xfer[0].buf = buf;
670
671 /* Read data */
672 xfer[1].addr = client->addr;
673 xfer[1].flags = I2C_M_RD;
674 xfer[1].len = len;
675 xfer[1].buf = val;
676
Jing Lin36aee812011-10-17 17:17:28 -0700677 do {
678 if (i2c_transfer(client->adapter, xfer, 2) == 2)
679 return 0;
680 msleep(MXT_WAKE_TIME);
681 } while (++i < MXT_MAX_RW_TRIES);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700682
Jing Lin36aee812011-10-17 17:17:28 -0700683 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
684 return -EIO;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700685}
686
Iiro Valkonen7686b102011-02-02 23:21:58 -0800687static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700688{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800689 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700690}
691
Jing Lin36aee812011-10-17 17:17:28 -0700692static int __mxt_write_reg(struct i2c_client *client,
693 u16 addr, u16 length, u8 *value)
694{
695 u8 buf[MXT_BLOCK_SIZE + 2];
696 int i, tries = 0;
697
698 if (length > MXT_BLOCK_SIZE)
699 return -EINVAL;
700
701 buf[0] = addr & 0xff;
702 buf[1] = (addr >> 8) & 0xff;
703 for (i = 0; i < length; i++)
704 buf[i + 2] = *value++;
705
706 do {
707 if (i2c_master_send(client, buf, length + 2) == (length + 2))
708 return 0;
709 msleep(MXT_WAKE_TIME);
710 } while (++tries < MXT_MAX_RW_TRIES);
711
712 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
713 return -EIO;
714}
715
Iiro Valkonen7686b102011-02-02 23:21:58 -0800716static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700717{
Jing Lin36aee812011-10-17 17:17:28 -0700718 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700719}
720
Iiro Valkonen7686b102011-02-02 23:21:58 -0800721static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700722 u16 reg, u8 *object_buf)
723{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800724 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700725 object_buf);
726}
727
Iiro Valkonen7686b102011-02-02 23:21:58 -0800728static struct mxt_object *
729mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700730{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800731 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700732 int i;
733
734 for (i = 0; i < data->info.object_num; i++) {
735 object = data->object_table + i;
736 if (object->type == type)
737 return object;
738 }
739
740 dev_err(&data->client->dev, "Invalid object type\n");
741 return NULL;
742}
743
Iiro Valkonen7686b102011-02-02 23:21:58 -0800744static int mxt_read_message(struct mxt_data *data,
745 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700746{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800747 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700748 u16 reg;
749
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700750 object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700751 if (!object)
752 return -EINVAL;
753
754 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800755 return __mxt_read_reg(data->client, reg,
756 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700757}
758
Iiro Valkonen7686b102011-02-02 23:21:58 -0800759static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700760 u8 type, u8 offset, u8 *val)
761{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800762 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700763 u16 reg;
764
Iiro Valkonen7686b102011-02-02 23:21:58 -0800765 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700766 if (!object)
767 return -EINVAL;
768
769 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800770 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700771}
772
Mohan Pallaka78fe53c2012-07-09 14:32:28 +0530773static int mxt_get_object_address(struct device *dev, u8 type)
774{
775 struct mxt_data *data = dev_get_drvdata(dev);
776 u8 obj_num, obj_buf[MXT_OBJECT_SIZE];
777 u16 reg;
778 int i, error;
779
780 error = mxt_read_reg(data->client, MXT_OBJECT_NUM, &obj_num);
781
782 if (error) {
783 dev_err(dev, "reading number of objects failed\n");
784 return -EINVAL;
785 }
786
787 for (i = 0; i < obj_num; i++) {
788 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
789 error = mxt_read_object_table(data->client,
790 reg, obj_buf);
791 if (error)
792 return error;
793
794 if (obj_buf[0] == type)
795 return obj_buf[2] << 8 | obj_buf[1];
796 }
797 /* If control reaches here, i = obj_num and object not found */
798 dev_err(dev, "Requested object %d not found.\n", type);
799 return -EINVAL;
800
801}
802
Iiro Valkonen7686b102011-02-02 23:21:58 -0800803static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700804 u8 type, u8 offset, u8 val)
805{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800806 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700807 u16 reg;
808
Iiro Valkonen7686b102011-02-02 23:21:58 -0800809 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700810 if (!object)
811 return -EINVAL;
812
813 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800814 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700815}
816
Iiro Valkonen7686b102011-02-02 23:21:58 -0800817static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700818{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800819 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700820 struct input_dev *input_dev = data->input_dev;
821 int status = finger[single_id].status;
822 int finger_num = 0;
823 int id;
824
Iiro Valkonen7686b102011-02-02 23:21:58 -0800825 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700826 if (!finger[id].status)
827 continue;
828
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700829 input_mt_slot(input_dev, id);
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800830 /* Firmware reports min/max values when the touch is
831 * outside screen area. Send a release event in
832 * such cases to avoid unwanted touches.
833 */
834 if (finger[id].x <= data->pdata->panel_minx ||
835 finger[id].x >= data->pdata->panel_maxx ||
836 finger[id].y <= data->pdata->panel_miny ||
837 finger[id].y >= data->pdata->panel_maxy) {
838 finger[id].status = MXT_RELEASE;
839 }
840
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700841 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
842 finger[id].status != MXT_RELEASE);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700843
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700844 if (finger[id].status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700845 finger_num++;
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700846 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
847 finger[id].area);
848 input_report_abs(input_dev, ABS_MT_POSITION_X,
849 finger[id].x);
850 input_report_abs(input_dev, ABS_MT_POSITION_Y,
851 finger[id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700852 input_report_abs(input_dev, ABS_MT_PRESSURE,
Anirudh Ghayal279a2ae52012-05-18 18:07:46 +0530853 finger[id].pressure);
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700854 } else {
855 finger[id].status = 0;
856 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700857 }
858
859 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
860
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800861 if (finger[single_id].x <= data->pdata->panel_minx ||
862 finger[single_id].x >= data->pdata->panel_maxx ||
863 finger[single_id].y <= data->pdata->panel_miny ||
864 finger[single_id].y >= data->pdata->panel_maxy) {
865 status = MXT_RELEASE;
866 }
867
Iiro Valkonen7686b102011-02-02 23:21:58 -0800868 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700869 input_report_abs(input_dev, ABS_X, finger[single_id].x);
870 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700871 input_report_abs(input_dev,
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700872 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700873 }
874
875 input_sync(input_dev);
876}
877
Iiro Valkonen7686b102011-02-02 23:21:58 -0800878static void mxt_input_touchevent(struct mxt_data *data,
879 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700880{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800881 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700882 struct device *dev = &data->client->dev;
883 u8 status = message->message[0];
884 int x;
885 int y;
886 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700887 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700888
889 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800890 if (!(status & MXT_DETECT)) {
891 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700892 dev_dbg(dev, "[%d] released\n", id);
893
Iiro Valkonen7686b102011-02-02 23:21:58 -0800894 finger[id].status = MXT_RELEASE;
895 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700896 }
897 return;
898 }
899
900 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800901 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700902 return;
903
Joonyoung Shim910d8052011-04-12 23:14:38 -0700904 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
905 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800906 if (data->pdata->panel_maxx < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700907 x = x >> 2;
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800908 if (data->pdata->panel_maxy < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700909 y = y >> 2;
910
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700911 area = message->message[4];
Yufeng Shen28ac2932011-08-16 00:40:54 -0700912 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700913
914 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800915 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700916 x, y, area);
917
Iiro Valkonen7686b102011-02-02 23:21:58 -0800918 finger[id].status = status & MXT_MOVE ?
919 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700920 finger[id].x = x;
921 finger[id].y = y;
922 finger[id].area = area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700923 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700924
Iiro Valkonen7686b102011-02-02 23:21:58 -0800925 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700926}
927
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800928static void mxt_handle_key_array(struct mxt_data *data,
929 struct mxt_message *message)
930{
931 u32 keys_changed;
932 int i;
933
934 if (!data->pdata->key_codes) {
935 dev_err(&data->client->dev, "keyarray is not supported\n");
936 return;
937 }
938
939 data->keyarray_new = message->message[1] |
940 (message->message[2] << 8) |
941 (message->message[3] << 16) |
942 (message->message[4] << 24);
943
944 keys_changed = data->keyarray_old ^ data->keyarray_new;
945
946 if (!keys_changed) {
947 dev_dbg(&data->client->dev, "no keys changed\n");
948 return;
949 }
950
951 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
952 if (!(keys_changed & (1 << i)))
953 continue;
954
955 input_report_key(data->input_dev, data->pdata->key_codes[i],
956 (data->keyarray_new & (1 << i)));
957 input_sync(data->input_dev);
958 }
959
960 data->keyarray_old = data->keyarray_new;
961}
962
Mohan Pallakab6acab42012-06-13 11:59:04 +0530963static void mxt_release_all(struct mxt_data *data)
964{
965 int id;
966
967 for (id = 0; id < MXT_MAX_FINGER; id++)
968 if (data->finger[id].status)
969 data->finger[id].status = MXT_RELEASE;
970
971 mxt_input_report(data, 0);
972}
973
974static void mxt_handle_touch_supression(struct mxt_data *data, u8 status)
975{
976 dev_dbg(&data->client->dev, "touch suppression\n");
977 /* release all touches */
978 if (status & MXT_TCHSUP_ACTIVE)
979 mxt_release_all(data);
980}
981
Iiro Valkonen7686b102011-02-02 23:21:58 -0800982static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700983{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800984 struct mxt_data *data = dev_id;
985 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700986 struct device *dev = &data->client->dev;
987 int id;
988 u8 reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700989
Nick Dyer0a4016c2012-01-18 15:17:59 +0530990 if (data->state != APPMODE) {
991 dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
992 return IRQ_HANDLED;
993 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700994
995 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800996 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700997 dev_err(dev, "Failed to read message\n");
998 goto end;
999 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001000 reportid = message.reportid;
1001
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001002 if (!reportid) {
1003 dev_dbg(dev, "Report id 0 is reserved\n");
1004 continue;
1005 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001006
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001007 id = reportid - data->t9_min_reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001008
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301009 /* check whether report id is part of T9,T15 or T42*/
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001010 if (reportid >= data->t9_min_reportid &&
1011 reportid <= data->t9_max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -08001012 mxt_input_touchevent(data, &message, id);
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001013 else if (reportid >= data->t15_min_reportid &&
1014 reportid <= data->t15_max_reportid)
1015 mxt_handle_key_array(data, &message);
Mohan Pallakab6acab42012-06-13 11:59:04 +05301016 else if (reportid >= data->t42_min_reportid &&
1017 reportid <= data->t42_max_reportid)
1018 mxt_handle_touch_supression(data, message.message[0]);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001019 else
Iiro Valkonen7686b102011-02-02 23:21:58 -08001020 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001021 } while (reportid != 0xff);
1022
1023end:
1024 return IRQ_HANDLED;
1025}
1026
Iiro Valkonen7686b102011-02-02 23:21:58 -08001027static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001028{
Jing Lindc4413c2012-01-16 15:22:52 -08001029 const struct mxt_config_info *config_info = data->config_info;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001030 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001031 struct device *dev = &data->client->dev;
1032 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -08001033 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001034
Jing Lindc4413c2012-01-16 15:22:52 -08001035 if (!config_info) {
Iiro Valkonen71749f52011-02-15 13:36:52 -08001036 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
1037 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001038 }
1039
1040 for (i = 0; i < data->info.object_num; i++) {
1041 object = data->object_table + i;
1042
Iiro Valkonen7686b102011-02-02 23:21:58 -08001043 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001044 continue;
1045
Iiro Valkonen71749f52011-02-15 13:36:52 -08001046 for (j = 0; j < object->size + 1; j++) {
1047 config_offset = index + j;
Jing Lindc4413c2012-01-16 15:22:52 -08001048 if (config_offset > config_info->config_length) {
Iiro Valkonen71749f52011-02-15 13:36:52 -08001049 dev_err(dev, "Not enough config data!\n");
1050 return -EINVAL;
1051 }
Iiro Valkonen7686b102011-02-02 23:21:58 -08001052 mxt_write_object(data, object->type, j,
Jing Lindc4413c2012-01-16 15:22:52 -08001053 config_info->config[config_offset]);
Iiro Valkonen71749f52011-02-15 13:36:52 -08001054 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001055 index += object->size + 1;
1056 }
1057
1058 return 0;
1059}
1060
Iiro Valkonen7686b102011-02-02 23:21:58 -08001061static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001062{
1063 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001064 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001065 int count = 10;
1066 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001067
1068 /* Read dummy message to make high CHG pin */
1069 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001070 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001071 if (error)
1072 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001073 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001074
1075 if (!count) {
1076 dev_err(dev, "CHG pin isn't cleared\n");
1077 return -EBUSY;
1078 }
1079
1080 return 0;
1081}
1082
Iiro Valkonen7686b102011-02-02 23:21:58 -08001083static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001084{
1085 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001086 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001087 int error;
1088 u8 val;
1089
Iiro Valkonen7686b102011-02-02 23:21:58 -08001090 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001091 if (error)
1092 return error;
1093 info->family_id = val;
1094
Iiro Valkonen7686b102011-02-02 23:21:58 -08001095 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001096 if (error)
1097 return error;
1098 info->variant_id = val;
1099
Iiro Valkonen7686b102011-02-02 23:21:58 -08001100 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001101 if (error)
1102 return error;
1103 info->version = val;
1104
Iiro Valkonen7686b102011-02-02 23:21:58 -08001105 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001106 if (error)
1107 return error;
1108 info->build = val;
1109
Iiro Valkonen7686b102011-02-02 23:21:58 -08001110 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001111 if (error)
1112 return error;
1113 info->object_num = val;
1114
1115 return 0;
1116}
1117
Iiro Valkonen7686b102011-02-02 23:21:58 -08001118static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001119{
1120 int error;
1121 int i;
1122 u16 reg;
1123 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001124 u8 buf[MXT_OBJECT_SIZE];
Jing Lindc4413c2012-01-16 15:22:52 -08001125 bool found_t38 = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001126
1127 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001128 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001129
Iiro Valkonen7686b102011-02-02 23:21:58 -08001130 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
1131 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001132 if (error)
1133 return error;
1134
1135 object->type = buf[0];
1136 object->start_address = (buf[2] << 8) | buf[1];
1137 object->size = buf[3];
1138 object->instances = buf[4];
1139 object->num_report_ids = buf[5];
1140
1141 if (object->num_report_ids) {
1142 reportid += object->num_report_ids *
1143 (object->instances + 1);
1144 object->max_reportid = reportid;
1145 }
Jing Lindc4413c2012-01-16 15:22:52 -08001146
1147 /* Calculate index for config major version in config array.
1148 * Major version is the first byte in object T38.
1149 */
Jing Lin8a9472d2012-03-21 15:43:45 -07001150 if (object->type == MXT_SPT_USERDATA_T38) {
1151 data->t38_start_addr = object->start_address;
Jing Lindc4413c2012-01-16 15:22:52 -08001152 found_t38 = true;
Jing Lin8a9472d2012-03-21 15:43:45 -07001153 }
Jing Lindc4413c2012-01-16 15:22:52 -08001154 if (!found_t38 && mxt_object_writable(object->type))
1155 data->cfg_version_idx += object->size + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001156 }
1157
1158 return 0;
1159}
1160
Jing Lin8fadad72012-02-24 10:10:50 -08001161static int compare_versions(const u8 *v1, const u8 *v2)
1162{
1163 int i;
1164
1165 if (!v1 || !v2)
1166 return -EINVAL;
1167
1168 /* The major version number stays the same across different versions for
1169 * a particular controller on a target. The minor and sub-minor version
1170 * numbers indicate which version is newer.
1171 */
1172 if (v1[0] != v2[0])
1173 return -EINVAL;
1174
1175 for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
1176 if (v1[i] > v2[i])
1177 return MXT_CFG_VERSION_LESS; /* v2 is older */
1178
1179 if (v1[i] < v2[i])
1180 return MXT_CFG_VERSION_GREATER; /* v2 is newer */
1181 }
1182
1183 return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
1184}
1185
1186static void mxt_check_config_version(struct mxt_data *data,
1187 const struct mxt_config_info *cfg_info,
1188 bool match_major,
1189 const u8 **cfg_version_found,
1190 bool *found_cfg_major_match)
1191{
1192 const u8 *cfg_version;
1193 int result = -EINVAL;
1194
1195 cfg_version = cfg_info->config + data->cfg_version_idx;
1196
1197 if (*cfg_version_found)
1198 result = compare_versions(*cfg_version_found, cfg_version);
1199
1200 if (match_major) {
1201 if (result >= MXT_CFG_VERSION_EQUAL)
1202 *found_cfg_major_match = true;
1203
1204 if (result == MXT_CFG_VERSION_EQUAL ||
1205 result == MXT_CFG_VERSION_GREATER) {
1206 data->config_info = cfg_info;
1207 data->fw_name = cfg_info->fw_name;
1208 *cfg_version_found = cfg_version;
1209 }
1210
1211 if (result == MXT_CFG_VERSION_GREATER)
1212 data->update_cfg = true;
1213 } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
1214 data->config_info = cfg_info;
1215 data->fw_name = cfg_info->fw_name;
1216 data->update_cfg = true;
1217 *cfg_version_found = cfg_version;
1218 }
1219}
1220
1221/* If the controller's config version has a non-zero major number, call this
1222 * function with match_major = true to look for the latest config present in
1223 * the pdata based on matching family id, variant id, f/w version, build, and
1224 * config major number. If the controller is programmed with wrong config data
1225 * previously, call this function with match_major = false to look for latest
1226 * config based on based on matching family id, variant id, f/w version and
1227 * build only.
1228 */
1229static int mxt_search_config_array(struct mxt_data *data, bool match_major)
Jing Lindc4413c2012-01-16 15:22:52 -08001230{
1231
1232 const struct mxt_platform_data *pdata = data->pdata;
1233 const struct mxt_config_info *cfg_info;
Jing Lin8fadad72012-02-24 10:10:50 -08001234 const struct mxt_info *info = &data->info;
1235 const u8 *cfg_version_found;
1236 bool found_cfg_major_match = false;
Jing Lindc4413c2012-01-16 15:22:52 -08001237 int i;
Jing Lin8fadad72012-02-24 10:10:50 -08001238
1239 cfg_version_found = match_major ? data->cfg_version : NULL;
Jing Lindc4413c2012-01-16 15:22:52 -08001240
1241 for (i = 0; i < pdata->config_array_size; i++) {
1242
1243 cfg_info = &pdata->config_array[i];
1244
1245 if (!cfg_info->config || !cfg_info->config_length)
1246 continue;
1247
1248 if (info->family_id == cfg_info->family_id &&
1249 info->variant_id == cfg_info->variant_id &&
1250 info->version == cfg_info->version &&
1251 info->build == cfg_info->build) {
1252
Jing Lin8fadad72012-02-24 10:10:50 -08001253 mxt_check_config_version(data, cfg_info, match_major,
1254 &cfg_version_found, &found_cfg_major_match);
Jing Lindc4413c2012-01-16 15:22:52 -08001255 }
1256 }
1257
Jing Lin8fadad72012-02-24 10:10:50 -08001258 if (data->config_info || found_cfg_major_match)
1259 return 0;
1260
1261 data->config_info = NULL;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001262 data->fw_name = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001263
Jing Lindc4413c2012-01-16 15:22:52 -08001264 return -EINVAL;
1265}
1266
1267static int mxt_get_config(struct mxt_data *data)
1268{
1269 const struct mxt_platform_data *pdata = data->pdata;
1270 struct device *dev = &data->client->dev;
1271 struct mxt_object *object;
1272 int error;
1273
1274 if (!pdata->config_array || !pdata->config_array_size) {
1275 dev_dbg(dev, "No cfg data provided by platform data\n");
1276 return 0;
1277 }
1278
1279 /* Get current config version */
1280 object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
1281 if (!object) {
1282 dev_err(dev, "Unable to obtain USERDATA object\n");
1283 return -EINVAL;
1284 }
1285
Jing Lin8fadad72012-02-24 10:10:50 -08001286 error = __mxt_read_reg(data->client, object->start_address,
1287 sizeof(data->cfg_version), data->cfg_version);
Jing Lindc4413c2012-01-16 15:22:52 -08001288 if (error) {
1289 dev_err(dev, "Unable to read config version\n");
1290 return error;
1291 }
Jing Lin8fadad72012-02-24 10:10:50 -08001292 dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
1293 data->cfg_version[0], data->cfg_version[1],
1294 data->cfg_version[2]);
Jing Lindc4413c2012-01-16 15:22:52 -08001295
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301296 /* configuration update requires major match */
1297 error = mxt_search_config_array(data, true);
1298
1299 /* if no_force_update is false , try again with false
1300 as the second parameter to mxt_search_config_array */
1301 if (error && (data->no_force_update == false))
1302 error = mxt_search_config_array(data, false);
1303
Jing Lin8fadad72012-02-24 10:10:50 -08001304 if (error) {
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301305 dev_err(dev,
1306 "Unable to find matching config in pdata\n");
1307 return error;
Jing Lin8fadad72012-02-24 10:10:50 -08001308 }
Jing Lindc4413c2012-01-16 15:22:52 -08001309
1310 return 0;
1311}
Jing Lin8fadad72012-02-24 10:10:50 -08001312
Jing Lin64fdd1f2012-12-20 17:08:28 -08001313static void mxt_power_on_delay(struct mxt_data *data)
1314{
1315 const struct mxt_platform_data *pdata = data->pdata;
1316 const struct mxt_config_info *cfg_info;
1317 u32 delay = 0;
1318 int i;
1319
1320 for (i = 0; i < pdata->config_array_size; i++) {
1321 cfg_info = &pdata->config_array[i];
1322
1323 switch (cfg_info->family_id) {
1324 case MXT224_ID:
1325 delay = max_t(u32, delay, MXT224_POWER_ON_TIME);
1326 break;
1327 case MXT224E_ID:
1328 delay = max_t(u32, delay, MXT224E_POWER_ON_TIME);
1329 break;
1330 case MXT336S_ID:
1331 delay = max_t(u32, delay, MXT336S_POWER_ON_TIME);
1332 break;
1333 case MXT1386_ID:
1334 delay = max_t(u32, delay,
1335 max_t(u32, MXT1386_POWER_ON_TIME,
1336 MXT1386E_POWER_ON_TIME));
1337 break;
1338 case MXT1664S_ID:
1339 delay = max_t(u32, delay, MXT1664S_POWER_ON_TIME);
1340 break;
1341 default:
1342 delay = max_t(u32, delay, MXT_POWER_ON_TIME);
1343 }
1344 }
1345
1346 msleep(delay);
1347}
1348
Amy Maloche7e447432011-09-14 11:36:30 -07001349static void mxt_reset_delay(struct mxt_data *data)
1350{
1351 struct mxt_info *info = &data->info;
1352
1353 switch (info->family_id) {
1354 case MXT224_ID:
1355 msleep(MXT224_RESET_TIME);
1356 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -07001357 case MXT224E_ID:
1358 msleep(MXT224E_RESET_TIME);
1359 break;
Amy Maloche41f1cc32012-07-12 13:02:27 -07001360 case MXT336S_ID:
1361 msleep(MXT336S_RESET_TIME);
Jing Lin64fdd1f2012-12-20 17:08:28 -08001362 break;
Amy Maloche7e447432011-09-14 11:36:30 -07001363 case MXT1386_ID:
Jing Lin64fdd1f2012-12-20 17:08:28 -08001364 msleep(max_t(u32, MXT1386_RESET_TIME, MXT1386E_RESET_TIME));
1365 break;
Amy Maloche41f1cc32012-07-12 13:02:27 -07001366 case MXT1664S_ID:
1367 msleep(MXT1664S_RESET_TIME);
Amy Maloche7e447432011-09-14 11:36:30 -07001368 break;
1369 default:
1370 msleep(MXT_RESET_TIME);
1371 }
1372}
1373
Jing Lin8fadad72012-02-24 10:10:50 -08001374static int mxt_backup_nv(struct mxt_data *data)
1375{
1376 int error;
1377 u8 command_register;
1378 int timeout_counter = 0;
1379
1380 /* Backup to memory */
1381 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1382 MXT_COMMAND_BACKUPNV,
1383 MXT_BACKUP_VALUE);
1384 msleep(MXT_BACKUP_TIME);
1385
1386 do {
1387 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
1388 MXT_COMMAND_BACKUPNV,
1389 &command_register);
1390 if (error)
1391 return error;
1392
1393 usleep_range(1000, 2000);
1394
1395 } while ((command_register != 0) && (++timeout_counter <= 100));
1396
1397 if (timeout_counter > 100) {
1398 dev_err(&data->client->dev, "No response after backup!\n");
1399 return -EIO;
1400 }
1401
1402 /* Soft reset */
1403 mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
1404
1405 mxt_reset_delay(data);
1406
1407 return 0;
1408}
1409
Jing Lin412aedc2012-02-28 13:57:19 -08001410static int mxt_save_objects(struct mxt_data *data)
1411{
1412 struct i2c_client *client = data->client;
1413 struct mxt_object *t7_object;
1414 struct mxt_object *t9_object;
1415 struct mxt_object *t15_object;
Mohan Pallakab6acab42012-06-13 11:59:04 +05301416 struct mxt_object *t42_object;
Jing Lin412aedc2012-02-28 13:57:19 -08001417 int error;
1418
1419 /* Store T7 and T9 locally, used in suspend/resume operations */
1420 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
1421 if (!t7_object) {
1422 dev_err(&client->dev, "Failed to get T7 object\n");
1423 return -EINVAL;
1424 }
1425
1426 data->t7_start_addr = t7_object->start_address;
1427 error = __mxt_read_reg(client, data->t7_start_addr,
1428 T7_DATA_SIZE, data->t7_data);
1429 if (error < 0) {
1430 dev_err(&client->dev,
1431 "Failed to save current power state\n");
1432 return error;
1433 }
1434
Jing Lin412aedc2012-02-28 13:57:19 -08001435 /* Store T9, T15's min and max report ids */
1436 t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1437 if (!t9_object) {
1438 dev_err(&client->dev, "Failed to get T9 object\n");
1439 return -EINVAL;
1440 }
1441 data->t9_max_reportid = t9_object->max_reportid;
1442 data->t9_min_reportid = t9_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001443 (t9_object->num_report_ids *
1444 (t9_object->instances + 1)) + 1;
Jing Lin412aedc2012-02-28 13:57:19 -08001445
1446 if (data->pdata->key_codes) {
1447 t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
1448 if (!t15_object)
1449 dev_dbg(&client->dev, "T15 object is not available\n");
1450 else {
1451 data->t15_max_reportid = t15_object->max_reportid;
1452 data->t15_min_reportid = t15_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001453 (t15_object->num_report_ids *
1454 (t15_object->instances + 1)) + 1;
Jing Lin412aedc2012-02-28 13:57:19 -08001455 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001456 }
1457
Mohan Pallakab6acab42012-06-13 11:59:04 +05301458 /* Store T42 min and max report ids */
1459 t42_object = mxt_get_object(data, MXT_PROCI_TOUCHSUPPRESSION_T42);
1460 if (!t42_object)
1461 dev_dbg(&client->dev, "T42 object is not available\n");
1462 else {
1463 data->t42_max_reportid = t42_object->max_reportid;
1464 data->t42_min_reportid = t42_object->max_reportid -
Amy Malochee8a03c52012-09-24 16:33:35 -07001465 (t42_object->num_report_ids *
1466 (t42_object->instances + 1)) + 1;
Mohan Pallakab6acab42012-06-13 11:59:04 +05301467 }
1468
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001469 return 0;
1470}
1471
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301472static int mxt_update_cfg(struct mxt_data *data)
1473{
1474 int error;
1475 const u8 *cfg_ver;
1476
1477 /* Get config data from platform data */
1478 error = mxt_get_config(data);
1479 if (error)
1480 dev_dbg(&data->client->dev, "Config info not found.\n");
1481
1482 /* Check register init values */
1483 if (data->config_info && data->config_info->config) {
1484 if (data->update_cfg) {
1485 error = mxt_check_reg_init(data);
1486 if (error) {
1487 dev_err(&data->client->dev,
1488 "Failed to check reg init value\n");
1489 return error;
1490 }
1491
1492 error = mxt_backup_nv(data);
1493 if (error) {
1494 dev_err(&data->client->dev, "Failed to back up NV\n");
1495 return error;
1496 }
1497
1498 cfg_ver = data->config_info->config +
1499 data->cfg_version_idx;
1500 dev_info(&data->client->dev,
1501 "Config updated from %d.%d.%d to %d.%d.%d\n",
1502 data->cfg_version[0], data->cfg_version[1],
1503 data->cfg_version[2],
1504 cfg_ver[0], cfg_ver[1], cfg_ver[2]);
1505
1506 memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
1507 }
1508 } else {
1509 dev_info(&data->client->dev,
1510 "No cfg data defined, skipping check reg init\n");
1511 }
1512
1513 error = mxt_save_objects(data);
1514 if (error)
1515 return error;
1516
1517 return 0;
1518}
1519
1520
1521
Iiro Valkonen7686b102011-02-02 23:21:58 -08001522static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001523{
1524 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001525 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001526 int error;
1527 u8 val;
1528
Iiro Valkonen7686b102011-02-02 23:21:58 -08001529 error = mxt_get_info(data);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301530 if (error) {
1531 /* Try bootloader mode */
1532 error = mxt_switch_to_bootloader_address(data);
1533 if (error)
1534 return error;
1535
1536 error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
1537 if (error)
1538 return error;
1539
1540 dev_err(&client->dev, "Application CRC failure\n");
1541 data->state = BOOTLOADER;
1542
1543 return 0;
1544 }
1545
1546 dev_info(&client->dev,
1547 "Family ID: %d Variant ID: %d Version: %d.%d "
1548 "Build: 0x%02X Object Num: %d\n",
1549 info->family_id, info->variant_id,
1550 info->version >> 4, info->version & 0xf,
1551 info->build, info->object_num);
1552
1553 data->state = APPMODE;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001554
1555 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001556 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001557 GFP_KERNEL);
1558 if (!data->object_table) {
1559 dev_err(&client->dev, "Failed to allocate memory\n");
1560 return -ENOMEM;
1561 }
1562
1563 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001564 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001565 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001566 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001567
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301568 error = mxt_update_cfg(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001569 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001570 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001571 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001572 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001573 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001574 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001575 info->matrix_xsize = val;
1576
Iiro Valkonen7686b102011-02-02 23:21:58 -08001577 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001578 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001579 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001580 info->matrix_ysize = val;
1581
1582 dev_info(&client->dev,
Nick Dyer0a4016c2012-01-18 15:17:59 +05301583 "Matrix X Size: %d Matrix Y Size: %d\n",
1584 info->matrix_xsize, info->matrix_ysize);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001585
1586 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001587
Jing Lin32c72532011-11-03 12:02:33 -07001588free_object_table:
1589 kfree(data->object_table);
1590 return error;
Joonyoung Shim910d8052011-04-12 23:14:38 -07001591}
1592
Iiro Valkonen7686b102011-02-02 23:21:58 -08001593static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001594 struct device_attribute *attr, char *buf)
1595{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001596 struct mxt_data *data = dev_get_drvdata(dev);
1597 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001598 int count = 0;
1599 int i, j;
1600 int error;
1601 u8 val;
1602
1603 for (i = 0; i < data->info.object_num; i++) {
1604 object = data->object_table + i;
1605
Daniel Kurtz626af862011-10-06 15:43:20 -07001606 count += snprintf(buf + count, PAGE_SIZE - count,
1607 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001608 i + 1, object->type);
Daniel Kurtz626af862011-10-06 15:43:20 -07001609 if (count >= PAGE_SIZE)
1610 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001611
Iiro Valkonen7686b102011-02-02 23:21:58 -08001612 if (!mxt_object_readable(object->type)) {
Daniel Kurtz626af862011-10-06 15:43:20 -07001613 count += snprintf(buf + count, PAGE_SIZE - count,
1614 "\n");
1615 if (count >= PAGE_SIZE)
1616 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001617 continue;
1618 }
1619
1620 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001621 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001622 object->type, j, &val);
1623 if (error)
1624 return error;
1625
Daniel Kurtz626af862011-10-06 15:43:20 -07001626 count += snprintf(buf + count, PAGE_SIZE - count,
1627 "\t[%2d]: %02x (%d)\n", j, val, val);
1628 if (count >= PAGE_SIZE)
1629 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001630 }
1631
Daniel Kurtz626af862011-10-06 15:43:20 -07001632 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1633 if (count >= PAGE_SIZE)
1634 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001635 }
1636
1637 return count;
1638}
1639
Jing Lincc974cb2012-02-01 23:13:14 -08001640static int strtobyte(const char *data, u8 *value)
1641{
1642 char str[3];
1643
1644 str[0] = data[0];
1645 str[1] = data[1];
1646 str[2] = '\0';
1647
1648 return kstrtou8(str, 16, value);
1649}
1650
Iiro Valkonen7686b102011-02-02 23:21:58 -08001651static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001652{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001653 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001654 struct i2c_client *client = data->client;
1655 const struct firmware *fw = NULL;
1656 unsigned int frame_size;
Nick Dyer0a4016c2012-01-18 15:17:59 +05301657 unsigned int retry = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001658 unsigned int pos = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001659 int ret, i, max_frame_size;
1660 u8 *frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001661
Jing Lincc974cb2012-02-01 23:13:14 -08001662 switch (data->info.family_id) {
1663 case MXT224_ID:
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301664 case MXT224E_ID:
Jing Lincc974cb2012-02-01 23:13:14 -08001665 max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
1666 break;
1667 case MXT1386_ID:
1668 max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
1669 break;
1670 default:
1671 return -EINVAL;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001672 }
1673
Jing Lincc974cb2012-02-01 23:13:14 -08001674 frame = kmalloc(max_frame_size, GFP_KERNEL);
1675 if (!frame) {
1676 dev_err(dev, "Unable to allocate memory for frame data\n");
1677 return -ENOMEM;
1678 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001679
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001680 ret = request_firmware(&fw, fn, dev);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301681 if (ret < 0) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001682 dev_err(dev, "Unable to open firmware %s\n", fn);
Jing Lincc974cb2012-02-01 23:13:14 -08001683 goto free_frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001684 }
1685
Nick Dyer0a4016c2012-01-18 15:17:59 +05301686 if (data->state != BOOTLOADER) {
1687 /* Change to the bootloader mode */
1688 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1689 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1690 mxt_reset_delay(data);
Amy Maloche7e447432011-09-14 11:36:30 -07001691
Nick Dyer0a4016c2012-01-18 15:17:59 +05301692 ret = mxt_switch_to_bootloader_address(data);
1693 if (ret)
1694 goto release_firmware;
1695 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001696
Iiro Valkonen7686b102011-02-02 23:21:58 -08001697 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301698 if (ret) {
1699 /* Bootloader may still be unlocked from previous update
1700 * attempt */
1701 ret = mxt_check_bootloader(client,
1702 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001703
Nick Dyer0a4016c2012-01-18 15:17:59 +05301704 if (ret)
1705 goto return_to_app_mode;
1706 } else {
1707 dev_info(dev, "Unlocking bootloader\n");
1708 /* Unlock bootloader */
1709 mxt_unlock_bootloader(client);
1710 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001711
1712 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001713 ret = mxt_check_bootloader(client,
1714 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001715 if (ret)
Nick Dyer0a4016c2012-01-18 15:17:59 +05301716 goto release_firmware;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001717
Jing Lincc974cb2012-02-01 23:13:14 -08001718 /* Get frame length MSB */
1719 ret = strtobyte(fw->data + pos, frame);
1720 if (ret)
1721 goto release_firmware;
1722
1723 /* Get frame length LSB */
1724 ret = strtobyte(fw->data + pos + 2, frame + 1);
1725 if (ret)
1726 goto release_firmware;
1727
1728 frame_size = ((*frame << 8) | *(frame + 1));
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001729
1730 /* We should add 2 at frame size as the the firmware data is not
1731 * included the CRC bytes.
1732 */
1733 frame_size += 2;
1734
Jing Lincc974cb2012-02-01 23:13:14 -08001735 if (frame_size > max_frame_size) {
1736 dev_err(dev, "Invalid frame size - %d\n", frame_size);
1737 ret = -EINVAL;
1738 goto release_firmware;
1739 }
1740
1741 /* Convert frame data and CRC from hex to binary */
1742 for (i = 2; i < frame_size; i++) {
1743 ret = strtobyte(fw->data + pos + i * 2, frame + i);
1744 if (ret)
1745 goto release_firmware;
1746 }
1747
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001748 /* Write one frame to device */
Jing Lincc974cb2012-02-01 23:13:14 -08001749 mxt_fw_write(client, frame, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001750
Iiro Valkonen7686b102011-02-02 23:21:58 -08001751 ret = mxt_check_bootloader(client,
1752 MXT_FRAME_CRC_PASS);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301753 if (ret) {
1754 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001755
Nick Dyer0a4016c2012-01-18 15:17:59 +05301756 /* Back off by 20ms per retry */
1757 msleep(retry * 20);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001758
Nick Dyer0a4016c2012-01-18 15:17:59 +05301759 if (retry > 20)
1760 goto release_firmware;
1761 } else {
1762 retry = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001763 pos += frame_size * 2;
1764 dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301765 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001766 }
1767
Nick Dyer0a4016c2012-01-18 15:17:59 +05301768return_to_app_mode:
1769 mxt_switch_to_appmode_address(data);
1770release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001771 release_firmware(fw);
Jing Lincc974cb2012-02-01 23:13:14 -08001772free_frame:
1773 kfree(frame);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001774
1775 return ret;
1776}
1777
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001778static const char *
1779mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
1780{
1781 const struct mxt_platform_data *pdata = data->pdata;
1782 const struct mxt_config_info *cfg_info;
1783 const char *fw_name = NULL;
1784 int i;
1785
1786 for (i = 0; i < pdata->config_array_size; i++) {
1787 cfg_info = &pdata->config_array[i];
1788 if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
1789 data->config_info = cfg_info;
1790 data->info.family_id = cfg_info->family_id;
1791 fw_name = cfg_info->fw_name;
1792 }
1793 }
1794
1795 return fw_name;
1796}
1797
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301798static ssize_t mxt_force_cfg_update_store(struct device *dev,
1799 struct device_attribute *attr,
1800 const char *buf, size_t count)
1801{
1802 struct mxt_data *data = dev_get_drvdata(dev);
1803 int flag = buf[0]-'0';
1804 int error;
1805 data->no_force_update = !flag;
1806
1807 if (data->state == APPMODE) {
1808 disable_irq(data->irq);
1809 error = mxt_update_cfg(data);
1810 enable_irq(data->irq);
1811 if (error)
1812 return error;
1813 } else {
1814 dev_err(dev,
1815 "Not in APPMODE, Unable to force cfg update\n");
1816 return -EINVAL;
1817 }
1818
1819 return count;
1820}
1821
Iiro Valkonen7686b102011-02-02 23:21:58 -08001822static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001823 struct device_attribute *attr,
1824 const char *buf, size_t count)
1825{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001826 struct mxt_data *data = dev_get_drvdata(dev);
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301827 int error, address;
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001828 const char *fw_name;
1829 u8 bootldr_id;
Jing Lin8a9472d2012-03-21 15:43:45 -07001830 u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001831
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301832 data->no_force_update = false;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001833 /* If fw_name is set, then the existing firmware has an upgrade */
1834 if (!data->fw_name) {
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001835 /*
1836 * If the device boots up in the bootloader mode, check if
1837 * there is a firmware to upgrade.
1838 */
1839 if (data->state == BOOTLOADER) {
1840 bootldr_id = mxt_get_bootloader_id(data->client);
1841 if (bootldr_id <= 0) {
1842 dev_err(dev,
1843 "Unable to retrieve bootloader id\n");
1844 return -EINVAL;
1845 }
1846 fw_name = mxt_search_fw_name(data, bootldr_id);
1847 if (fw_name == NULL) {
1848 dev_err(dev,
1849 "Unable to find fw from bootloader id\n");
1850 return -EINVAL;
1851 }
1852 } else {
1853 /* In APPMODE, if the f/w name does not exist, quit */
1854 dev_err(dev,
1855 "Firmware name not specified in platform data\n");
1856 return -EINVAL;
1857 }
1858 } else {
1859 fw_name = data->fw_name;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001860 }
1861
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001862 dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001863
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001864 disable_irq(data->irq);
1865
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001866 error = mxt_load_fw(dev, fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001867 if (error) {
1868 dev_err(dev, "The firmware update failed(%d)\n", error);
1869 count = error;
1870 } else {
Nick Dyer0a4016c2012-01-18 15:17:59 +05301871 dev_info(dev, "The firmware update succeeded\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001872
1873 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001874 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001875
Nick Dyer0a4016c2012-01-18 15:17:59 +05301876 data->state = INIT;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001877 kfree(data->object_table);
1878 data->object_table = NULL;
Jing Lincc974cb2012-02-01 23:13:14 -08001879 data->cfg_version_idx = 0;
Jing Lina962ba32012-12-03 09:46:33 -08001880 data->config_info = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001881 data->update_cfg = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001882
Mohan Pallaka78fe53c2012-07-09 14:32:28 +05301883 /* T38 object address might have changed, read it from
1884 touch controller */
1885 address = mxt_get_object_address(dev, MXT_SPT_USERDATA_T38);
1886 if (address < 0) {
1887 dev_err(dev, "T38 required for touch operation\n");
1888 return -EINVAL;
1889 }
1890
1891 data->t38_start_addr = address;
1892
Jing Lin8a9472d2012-03-21 15:43:45 -07001893 error = __mxt_write_reg(data->client, data->t38_start_addr,
1894 sizeof(cfg_version), cfg_version);
1895 if (error)
1896 dev_err(dev,
1897 "Unable to zero out config version after fw upgrade\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001898
Iiro Valkonen7686b102011-02-02 23:21:58 -08001899 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001900 }
1901
Nick Dyer0a4016c2012-01-18 15:17:59 +05301902 if (data->state == APPMODE) {
1903 enable_irq(data->irq);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001904
Nick Dyer0a4016c2012-01-18 15:17:59 +05301905 error = mxt_make_highchg(data);
1906 if (error)
1907 return error;
1908 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07001909
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001910 return count;
1911}
1912
Iiro Valkonen7686b102011-02-02 23:21:58 -08001913static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
1914static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301915static DEVICE_ATTR(force_cfg_update, 0664, NULL, mxt_force_cfg_update_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001916
Iiro Valkonen7686b102011-02-02 23:21:58 -08001917static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001918 &dev_attr_object.attr,
1919 &dev_attr_update_fw.attr,
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05301920 &dev_attr_force_cfg_update.attr,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001921 NULL
1922};
1923
Iiro Valkonen7686b102011-02-02 23:21:58 -08001924static const struct attribute_group mxt_attr_group = {
1925 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001926};
1927
Amy Maloche52262212011-09-15 16:46:57 -07001928static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001929{
Jing Lin36aee812011-10-17 17:17:28 -07001930 int error;
1931
Amy Maloche52262212011-09-15 16:46:57 -07001932 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07001933 error = __mxt_write_reg(data->client, data->t7_start_addr,
1934 T7_DATA_SIZE, data->t7_data);
1935 if (error < 0) {
1936 dev_err(&data->client->dev,
1937 "failed to restore old power state\n");
1938 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001939 }
Jing Lin36aee812011-10-17 17:17:28 -07001940
Amy Maloche52262212011-09-15 16:46:57 -07001941 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001942}
1943
Amy Maloche52262212011-09-15 16:46:57 -07001944static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001945{
Jing Lin36aee812011-10-17 17:17:28 -07001946 int error;
1947 u8 t7_data[T7_DATA_SIZE] = {0};
1948
Jing Lin36aee812011-10-17 17:17:28 -07001949 error = __mxt_write_reg(data->client, data->t7_start_addr,
1950 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07001951 if (error < 0) {
1952 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07001953 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07001954 return error;
1955 }
1956
1957 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001958}
1959
Iiro Valkonen7686b102011-02-02 23:21:58 -08001960static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001961{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001962 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001963 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001964
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001965 if (data->state == APPMODE) {
1966 error = mxt_start(data);
1967 if (error < 0) {
1968 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
1969 return error;
1970 }
Amy Maloche52262212011-09-15 16:46:57 -07001971 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001972
1973 return 0;
1974}
1975
Iiro Valkonen7686b102011-02-02 23:21:58 -08001976static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001977{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001978 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001979 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001980
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001981 if (data->state == APPMODE) {
1982 error = mxt_stop(data);
1983 if (error < 0)
1984 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
1985 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001986}
1987
Amy Malochec331f842012-01-24 10:33:47 -08001988static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
1989{
1990 return (regulator_count_voltages(reg) > 0) ?
1991 regulator_set_optimum_mode(reg, load_uA) : 0;
1992}
1993
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301994static int mxt_power_on(struct mxt_data *data, bool on)
1995{
1996 int rc;
1997
1998 if (on == false)
1999 goto power_off;
2000
Amy Malochec331f842012-01-24 10:33:47 -08002001 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302002 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07002003 dev_err(&data->client->dev,
2004 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302005 return rc;
2006 }
2007
Amy Maloche21115eb2011-11-02 09:04:37 -07002008 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302009 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07002010 dev_err(&data->client->dev,
2011 "Regulator vcc_ana enable failed rc=%d\n", rc);
2012 goto error_reg_en_vcc_ana;
2013 }
2014
2015 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002016 rc = reg_set_optimum_mode_check(data->vcc_dig,
2017 MXT_ACTIVE_LOAD_DIG_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002018 if (rc < 0) {
2019 dev_err(&data->client->dev,
2020 "Regulator vcc_dig set_opt failed rc=%d\n",
2021 rc);
2022 goto error_reg_opt_vcc_dig;
2023 }
2024
2025 rc = regulator_enable(data->vcc_dig);
2026 if (rc) {
2027 dev_err(&data->client->dev,
2028 "Regulator vcc_dig enable failed rc=%d\n", rc);
2029 goto error_reg_en_vcc_dig;
2030 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302031 }
2032
2033 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002034 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302035 if (rc < 0) {
2036 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002037 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302038 goto error_reg_opt_i2c;
2039 }
2040
2041 rc = regulator_enable(data->vcc_i2c);
2042 if (rc) {
2043 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002044 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302045 goto error_reg_en_vcc_i2c;
2046 }
2047 }
2048
Amy Malochef0d7b8d2011-10-17 12:10:51 -07002049 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302050
2051 return 0;
2052
2053error_reg_en_vcc_i2c:
2054 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002055 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302056error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07002057 if (data->pdata->digital_pwr_regulator)
2058 regulator_disable(data->vcc_dig);
2059error_reg_en_vcc_dig:
2060 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002061 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002062error_reg_opt_vcc_dig:
2063 regulator_disable(data->vcc_ana);
2064error_reg_en_vcc_ana:
Amy Malochec331f842012-01-24 10:33:47 -08002065 reg_set_optimum_mode_check(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302066 return rc;
2067
2068power_off:
Amy Malochec331f842012-01-24 10:33:47 -08002069 reg_set_optimum_mode_check(data->vcc_ana, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002070 regulator_disable(data->vcc_ana);
2071 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002072 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07002073 regulator_disable(data->vcc_dig);
2074 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302075 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002076 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302077 regulator_disable(data->vcc_i2c);
2078 }
2079 msleep(50);
2080 return 0;
2081}
2082
2083static int mxt_regulator_configure(struct mxt_data *data, bool on)
2084{
2085 int rc;
2086
2087 if (on == false)
2088 goto hw_shutdown;
2089
Amy Maloche21115eb2011-11-02 09:04:37 -07002090 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
2091 if (IS_ERR(data->vcc_ana)) {
2092 rc = PTR_ERR(data->vcc_ana);
2093 dev_err(&data->client->dev,
2094 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302095 return rc;
2096 }
2097
Amy Maloche21115eb2011-11-02 09:04:37 -07002098 if (regulator_count_voltages(data->vcc_ana) > 0) {
2099 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302100 MXT_VTG_MAX_UV);
2101 if (rc) {
2102 dev_err(&data->client->dev,
2103 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07002104 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302105 }
2106 }
Amy Maloche21115eb2011-11-02 09:04:37 -07002107 if (data->pdata->digital_pwr_regulator) {
2108 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
2109 if (IS_ERR(data->vcc_dig)) {
2110 rc = PTR_ERR(data->vcc_dig);
2111 dev_err(&data->client->dev,
2112 "Regulator get dig failed rc=%d\n", rc);
2113 goto error_get_vtg_vcc_dig;
2114 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302115
Amy Maloche21115eb2011-11-02 09:04:37 -07002116 if (regulator_count_voltages(data->vcc_dig) > 0) {
2117 rc = regulator_set_voltage(data->vcc_dig,
2118 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
2119 if (rc) {
2120 dev_err(&data->client->dev,
2121 "regulator set_vtg failed rc=%d\n", rc);
2122 goto error_set_vtg_vcc_dig;
2123 }
2124 }
2125 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302126 if (data->pdata->i2c_pull_up) {
2127 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
2128 if (IS_ERR(data->vcc_i2c)) {
2129 rc = PTR_ERR(data->vcc_i2c);
2130 dev_err(&data->client->dev,
2131 "Regulator get failed rc=%d\n", rc);
2132 goto error_get_vtg_i2c;
2133 }
2134 if (regulator_count_voltages(data->vcc_i2c) > 0) {
2135 rc = regulator_set_voltage(data->vcc_i2c,
2136 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
2137 if (rc) {
2138 dev_err(&data->client->dev,
2139 "regulator set_vtg failed rc=%d\n", rc);
2140 goto error_set_vtg_i2c;
2141 }
2142 }
2143 }
2144
2145 return 0;
2146
2147error_set_vtg_i2c:
2148 regulator_put(data->vcc_i2c);
2149error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07002150 if (data->pdata->digital_pwr_regulator)
2151 if (regulator_count_voltages(data->vcc_dig) > 0)
2152 regulator_set_voltage(data->vcc_dig, 0,
2153 MXT_VTG_DIG_MAX_UV);
2154error_set_vtg_vcc_dig:
2155 if (data->pdata->digital_pwr_regulator)
2156 regulator_put(data->vcc_dig);
2157error_get_vtg_vcc_dig:
2158 if (regulator_count_voltages(data->vcc_ana) > 0)
2159 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2160error_set_vtg_vcc_ana:
2161 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302162 return rc;
2163
2164hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07002165 if (regulator_count_voltages(data->vcc_ana) > 0)
2166 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2167 regulator_put(data->vcc_ana);
2168 if (data->pdata->digital_pwr_regulator) {
2169 if (regulator_count_voltages(data->vcc_dig) > 0)
2170 regulator_set_voltage(data->vcc_dig, 0,
2171 MXT_VTG_DIG_MAX_UV);
2172 regulator_put(data->vcc_dig);
2173 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302174 if (data->pdata->i2c_pull_up) {
2175 if (regulator_count_voltages(data->vcc_i2c) > 0)
2176 regulator_set_voltage(data->vcc_i2c, 0,
2177 MXT_I2C_VTG_MAX_UV);
2178 regulator_put(data->vcc_i2c);
2179 }
2180 return 0;
2181}
2182
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302183#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07002184static int mxt_regulator_lpm(struct mxt_data *data, bool on)
2185{
2186
2187 int rc;
2188
2189 if (on == false)
2190 goto regulator_hpm;
2191
Amy Malochec331f842012-01-24 10:33:47 -08002192 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002193 if (rc < 0) {
2194 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002195 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002196 goto fail_regulator_lpm;
2197 }
2198
Amy Maloche21115eb2011-11-02 09:04:37 -07002199 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002200 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002201 MXT_LPM_LOAD_DIG_UA);
2202 if (rc < 0) {
2203 dev_err(&data->client->dev,
2204 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2205 goto fail_regulator_lpm;
2206 }
2207 }
2208
Jing Linbace50b2011-10-18 22:55:47 -07002209 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002210 rc = reg_set_optimum_mode_check(data->vcc_i2c,
Jing Linbace50b2011-10-18 22:55:47 -07002211 MXT_I2C_LPM_LOAD_UA);
2212 if (rc < 0) {
2213 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002214 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002215 goto fail_regulator_lpm;
2216 }
2217 }
2218
2219 return 0;
2220
2221regulator_hpm:
2222
Amy Malochec331f842012-01-24 10:33:47 -08002223 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002224 if (rc < 0) {
2225 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002226 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002227 goto fail_regulator_hpm;
2228 }
2229
Amy Maloche21115eb2011-11-02 09:04:37 -07002230 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002231 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002232 MXT_ACTIVE_LOAD_DIG_UA);
2233 if (rc < 0) {
2234 dev_err(&data->client->dev,
2235 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2236 goto fail_regulator_hpm;
2237 }
2238 }
2239
Jing Linbace50b2011-10-18 22:55:47 -07002240 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002241 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002242 if (rc < 0) {
2243 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002244 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002245 goto fail_regulator_hpm;
2246 }
2247 }
2248
2249 return 0;
2250
2251fail_regulator_lpm:
Amy Malochec331f842012-01-24 10:33:47 -08002252 reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002253 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002254 reg_set_optimum_mode_check(data->vcc_dig,
2255 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002256 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002257 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002258
2259 return rc;
2260
2261fail_regulator_hpm:
Amy Malochec331f842012-01-24 10:33:47 -08002262 reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002263 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002264 reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002265 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002266 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002267
2268 return rc;
2269}
2270
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302271static int mxt_suspend(struct device *dev)
2272{
2273 struct i2c_client *client = to_i2c_client(dev);
2274 struct mxt_data *data = i2c_get_clientdata(client);
2275 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002276 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302277
2278 mutex_lock(&input_dev->mutex);
2279
Amy Maloche52262212011-09-15 16:46:57 -07002280 if (input_dev->users) {
2281 error = mxt_stop(data);
2282 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002283 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07002284 mutex_unlock(&input_dev->mutex);
2285 return error;
2286 }
2287
2288 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302289
2290 mutex_unlock(&input_dev->mutex);
2291
Jing Linbace50b2011-10-18 22:55:47 -07002292 /* put regulators in low power mode */
2293 error = mxt_regulator_lpm(data, true);
2294 if (error < 0) {
2295 dev_err(dev, "failed to enter low power mode\n");
2296 return error;
2297 }
2298
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302299 return 0;
2300}
2301
2302static int mxt_resume(struct device *dev)
2303{
2304 struct i2c_client *client = to_i2c_client(dev);
2305 struct mxt_data *data = i2c_get_clientdata(client);
2306 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002307 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302308
Jing Linbace50b2011-10-18 22:55:47 -07002309 /* put regulators in high power mode */
2310 error = mxt_regulator_lpm(data, false);
2311 if (error < 0) {
2312 dev_err(dev, "failed to enter high power mode\n");
2313 return error;
2314 }
2315
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302316 mutex_lock(&input_dev->mutex);
2317
Amy Maloche52262212011-09-15 16:46:57 -07002318 if (input_dev->users) {
2319 error = mxt_start(data);
2320 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002321 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07002322 mutex_unlock(&input_dev->mutex);
2323 return error;
2324 }
2325 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302326
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302327 /* calibrate */
2328 if (data->pdata->need_calibration) {
2329 error = mxt_write_object(data, MXT_GEN_COMMAND_T6,
2330 MXT_COMMAND_CALIBRATE, 1);
2331 if (error < 0)
2332 dev_dbg(dev, "sending calibration command failed\n");
2333 }
2334
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302335 mutex_unlock(&input_dev->mutex);
2336
2337 return 0;
2338}
2339
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302340static const struct dev_pm_ops mxt_pm_ops = {
Anurag Singh49d76132013-01-29 12:07:00 -08002341#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302342 .suspend = mxt_suspend,
2343 .resume = mxt_resume,
2344#endif
2345};
2346#endif
2347
Jing Lin6cfc00e2011-11-02 15:15:30 -07002348static int mxt_debugfs_object_show(struct seq_file *m, void *v)
2349{
2350 struct mxt_data *data = m->private;
2351 struct mxt_object *object;
2352 struct device *dev = &data->client->dev;
2353 int i, j, k;
2354 int error;
2355 int obj_size;
2356 u8 val;
2357
2358 for (i = 0; i < data->info.object_num; i++) {
2359 object = data->object_table + i;
2360 obj_size = object->size + 1;
2361
2362 seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
2363
2364 for (j = 0; j < object->instances + 1; j++) {
2365 seq_printf(m, "[Instance %d]\n", j);
2366
2367 for (k = 0; k < obj_size; k++) {
2368 error = mxt_read_object(data, object->type,
2369 j * obj_size + k, &val);
2370 if (error) {
2371 dev_err(dev,
2372 "Failed to read object %d "
2373 "instance %d at offset %d\n",
2374 object->type, j, k);
2375 return error;
2376 }
2377
2378 seq_printf(m, "Byte %d: 0x%02x (%d)\n",
2379 k, val, val);
2380 }
2381 }
2382 }
2383
2384 return 0;
2385}
2386
2387static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
2388{
2389 return single_open(file, mxt_debugfs_object_show, inode->i_private);
2390}
2391
2392static const struct file_operations mxt_object_fops = {
2393 .owner = THIS_MODULE,
2394 .open = mxt_debugfs_object_open,
2395 .read = seq_read,
2396 .release = single_release,
2397};
2398
Stephen Boyd0d578692012-04-25 11:49:18 -07002399static void __devinit mxt_debugfs_init(struct mxt_data *data)
Jing Lin6cfc00e2011-11-02 15:15:30 -07002400{
2401 debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
2402 if (IS_ERR_OR_NULL(debug_base))
2403 pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
2404 if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
2405 0444,
2406 debug_base,
2407 data,
2408 &mxt_object_fops))) {
2409 pr_err("atmel_mxt_ts: Failed to create object file\n");
2410 debugfs_remove_recursive(debug_base);
2411 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002412}
2413
Mohan Pallakad96f5032012-06-18 22:49:10 +05302414#ifdef CONFIG_OF
2415static int mxt_get_dt_coords(struct device *dev, char *name,
2416 struct mxt_platform_data *pdata)
2417{
2418 u32 coords[MXT_COORDS_ARR_SIZE];
2419 struct property *prop;
2420 struct device_node *np = dev->of_node;
2421 int coords_size, rc;
2422
2423 prop = of_find_property(np, name, NULL);
2424 if (!prop)
2425 return -EINVAL;
2426 if (!prop->value)
2427 return -ENODATA;
2428
2429 coords_size = prop->length / sizeof(u32);
2430 if (coords_size != MXT_COORDS_ARR_SIZE) {
2431 dev_err(dev, "invalid %s\n", name);
2432 return -EINVAL;
2433 }
2434
2435 rc = of_property_read_u32_array(np, name, coords, coords_size);
2436 if (rc && (rc != -EINVAL)) {
2437 dev_err(dev, "Unable to read %s\n", name);
2438 return rc;
2439 }
2440
2441 if (strncmp(name, "atmel,panel-coords",
2442 sizeof("atmel,panel-coords")) == 0) {
2443 pdata->panel_minx = coords[0];
2444 pdata->panel_miny = coords[1];
2445 pdata->panel_maxx = coords[2];
2446 pdata->panel_maxy = coords[3];
2447 } else if (strncmp(name, "atmel,display-coords",
2448 sizeof("atmel,display-coords")) == 0) {
2449 pdata->disp_minx = coords[0];
2450 pdata->disp_miny = coords[1];
2451 pdata->disp_maxx = coords[2];
2452 pdata->disp_maxy = coords[3];
2453 } else {
2454 dev_err(dev, "unsupported property %s\n", name);
2455 return -EINVAL;
2456 }
2457
2458 return 0;
2459}
2460
2461static int mxt_parse_config(struct device *dev, struct device_node *np,
2462 struct mxt_config_info *info)
2463{
2464 struct property *prop;
2465 u8 *temp_cfg;
2466
2467 prop = of_find_property(np, "atmel,config", &info->config_length);
2468 if (!prop) {
2469 dev_err(dev, "Looking up %s property in node %s failed",
2470 "atmel,config", np->full_name);
2471 return -ENODEV;
2472 } else if (!info->config_length) {
2473 dev_err(dev, "Invalid length of configuration data\n");
2474 return -EINVAL;
2475 }
2476
2477 temp_cfg = devm_kzalloc(dev,
2478 info->config_length * sizeof(u8), GFP_KERNEL);
2479 if (!temp_cfg) {
2480 dev_err(dev, "Unable to allocate memory to store cfg\n");
2481 return -ENOMEM;
2482 }
2483
2484 memcpy(temp_cfg, prop->value, info->config_length);
2485 info->config = temp_cfg;
2486
2487 return 0;
2488}
2489
2490static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
2491{
2492 int rc;
2493 struct mxt_config_info *info;
2494 struct device_node *temp, *np = dev->of_node;
2495 struct property *prop;
2496 u32 temp_val;
2497
2498 rc = mxt_get_dt_coords(dev, "atmel,panel-coords", pdata);
2499 if (rc)
2500 return rc;
2501
2502 rc = mxt_get_dt_coords(dev, "atmel,display-coords", pdata);
2503 if (rc)
2504 return rc;
2505
2506 /* regulator info */
2507 pdata->i2c_pull_up = of_property_read_bool(np, "atmel,i2c-pull-up");
2508 pdata->digital_pwr_regulator = of_property_read_bool(np,
2509 "atmel,dig-reg-support");
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302510
2511 pdata->no_force_update = of_property_read_bool(np,
2512 "atmel,no-force-update");
2513
Mohan Pallakad96f5032012-06-18 22:49:10 +05302514 /* reset, irq gpio info */
2515 pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
2516 0, &pdata->reset_gpio_flags);
2517 pdata->irq_gpio = of_get_named_gpio_flags(np, "atmel,irq-gpio",
2518 0, &pdata->irq_gpio_flags);
2519
2520 /* keycodes for keyarray object*/
2521 prop = of_find_property(np, "atmel,key-codes", NULL);
2522 if (prop) {
2523 pdata->key_codes = devm_kzalloc(dev,
2524 sizeof(int) * MXT_KEYARRAY_MAX_KEYS,
2525 GFP_KERNEL);
2526 if (!pdata->key_codes)
2527 return -ENOMEM;
2528 if ((prop->length/sizeof(u32)) == MXT_KEYARRAY_MAX_KEYS) {
2529 rc = of_property_read_u32_array(np, "atmel,key-codes",
2530 pdata->key_codes, MXT_KEYARRAY_MAX_KEYS);
2531 if (rc) {
2532 dev_err(dev, "Unable to read key codes\n");
2533 return rc;
2534 }
2535 } else
2536 return -EINVAL;
2537 }
2538
Mohan Pallaka63a5f652012-09-21 16:51:44 +05302539 /* need calibration during wakeup? */
2540 pdata->need_calibration = of_property_read_bool(np,
2541 "atmel,need-calibration");
Mohan Pallakad96f5032012-06-18 22:49:10 +05302542 /* config array size */
2543 pdata->config_array_size = 0;
2544 temp = NULL;
2545 while ((temp = of_get_next_child(np, temp)))
2546 pdata->config_array_size++;
2547
2548 if (!pdata->config_array_size)
2549 return 0;
2550
2551 info = devm_kzalloc(dev, pdata->config_array_size *
2552 sizeof(struct mxt_config_info), GFP_KERNEL);
2553 if (!info) {
2554 dev_err(dev, "Unable to allocate memory\n");
2555 return -ENOMEM;
2556 }
2557
2558 pdata->config_array = info;
2559
2560 for_each_child_of_node(np, temp) {
2561 rc = of_property_read_string(temp, "atmel,fw-name",
2562 &info->fw_name);
2563 if (rc && (rc != -EINVAL)) {
2564 dev_err(dev, "Unable to read fw name\n");
2565 return rc;
2566 }
2567
2568 rc = of_property_read_u32(temp, "atmel,family-id", &temp_val);
2569 if (rc) {
2570 dev_err(dev, "Unable to read family id\n");
2571 return rc;
2572 } else
2573 info->family_id = (u8) temp_val;
2574
2575 rc = of_property_read_u32(temp, "atmel,variant-id", &temp_val);
2576 if (rc) {
2577 dev_err(dev, "Unable to read variant id\n");
2578 return rc;
2579 } else
2580 info->variant_id = (u8) temp_val;
2581
2582 rc = of_property_read_u32(temp, "atmel,version", &temp_val);
2583 if (rc) {
2584 dev_err(dev, "Unable to read controller version\n");
2585 return rc;
2586 } else
2587 info->version = (u8) temp_val;
2588
2589 rc = of_property_read_u32(temp, "atmel,build", &temp_val);
2590 if (rc) {
2591 dev_err(dev, "Unable to read build id\n");
2592 return rc;
2593 } else
2594 info->build = (u8) temp_val;
2595
Steve Mucklee1533542013-02-13 15:03:16 -08002596 info->bootldr_id = of_property_read_u32(temp,
Mohan Pallakad96f5032012-06-18 22:49:10 +05302597 "atmel,bootldr-id", &temp_val);
2598 if (rc) {
2599 dev_err(dev, "Unable to read bootldr-id\n");
2600 return rc;
2601 } else
2602 info->bootldr_id = (u8) temp_val;
2603
2604 rc = mxt_parse_config(dev, temp, info);
2605 if (rc) {
2606 dev_err(dev, "Unable to parse config data\n");
2607 return rc;
2608 }
2609 info++;
2610 }
2611
2612 return 0;
2613}
2614#else
2615static int mxt_parse_dt(struct device *dev, struct mxt_platform_data *pdata)
2616{
2617 return -ENODEV;
2618}
2619#endif
2620
Anurag Singh49d76132013-01-29 12:07:00 -08002621#if defined(CONFIG_FB)
2622static int fb_notifier_callback(struct notifier_block *self,
2623 unsigned long event, void *data)
2624{
2625 struct fb_event *evdata = data;
2626 int *blank;
2627 struct mxt_data *mxt_dev_data =
2628 container_of(self, struct mxt_data, fb_notif);
2629
2630 if (evdata && evdata->data && event == FB_EVENT_BLANK && mxt_dev_data &&
2631 mxt_dev_data->client) {
2632 blank = evdata->data;
2633 if (*blank == FB_BLANK_UNBLANK)
2634 mxt_resume(&mxt_dev_data->client->dev);
2635 else if (*blank == FB_BLANK_POWERDOWN)
2636 mxt_suspend(&mxt_dev_data->client->dev);
2637 }
2638
2639 return 0;
2640}
2641#elif defined(CONFIG_HAS_EARLYSUSPEND)
2642static void mxt_early_suspend(struct early_suspend *h)
2643{
2644 struct mxt_data *data = container_of(h, struct mxt_data,
2645 early_suspend);
2646 mxt_suspend(&data->client->dev);
2647}
2648
2649static void mxt_late_resume(struct early_suspend *h)
2650{
2651 struct mxt_data *data = container_of(h, struct mxt_data,
2652 early_suspend);
2653 mxt_resume(&data->client->dev);
2654}
2655
2656#endif
2657
Iiro Valkonen7686b102011-02-02 23:21:58 -08002658static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002659 const struct i2c_device_id *id)
2660{
Mohan Pallakad96f5032012-06-18 22:49:10 +05302661 struct mxt_platform_data *pdata;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002662 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002663 struct input_dev *input_dev;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002664 int error, i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002665
Mohan Pallakad96f5032012-06-18 22:49:10 +05302666 if (client->dev.of_node) {
2667 pdata = devm_kzalloc(&client->dev,
2668 sizeof(struct mxt_platform_data), GFP_KERNEL);
2669 if (!pdata) {
2670 dev_err(&client->dev, "Failed to allocate memory\n");
2671 return -ENOMEM;
2672 }
2673
2674 error = mxt_parse_dt(&client->dev, pdata);
2675 if (error)
2676 return error;
2677 } else
2678 pdata = client->dev.platform_data;
2679
Iiro Valkonen919ed892011-02-15 13:36:52 -08002680 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002681 return -EINVAL;
2682
Iiro Valkonen7686b102011-02-02 23:21:58 -08002683 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002684 input_dev = input_allocate_device();
2685 if (!data || !input_dev) {
2686 dev_err(&client->dev, "Failed to allocate memory\n");
2687 error = -ENOMEM;
2688 goto err_free_mem;
2689 }
2690
Nick Dyer0a4016c2012-01-18 15:17:59 +05302691 data->state = INIT;
Amy Maloche83c385a2012-02-01 10:32:03 +05302692 input_dev->name = "atmel_mxt_ts";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002693 input_dev->id.bustype = BUS_I2C;
2694 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002695 input_dev->open = mxt_input_open;
2696 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002697
Joonyoung Shim910d8052011-04-12 23:14:38 -07002698 data->client = client;
2699 data->input_dev = input_dev;
2700 data->pdata = pdata;
Sreenivasulu Chalam Charlaa339ef72012-09-20 08:25:04 +05302701 data->no_force_update = pdata->no_force_update;
Joonyoung Shim910d8052011-04-12 23:14:38 -07002702
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002703 __set_bit(EV_ABS, input_dev->evbit);
2704 __set_bit(EV_KEY, input_dev->evbit);
2705 __set_bit(BTN_TOUCH, input_dev->keybit);
Amy Maloche9d0faa02012-06-19 12:37:39 -07002706 __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002707
2708 /* For single touch */
2709 input_set_abs_params(input_dev, ABS_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002710 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002711 input_set_abs_params(input_dev, ABS_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002712 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002713 input_set_abs_params(input_dev, ABS_PRESSURE,
2714 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002715
2716 /* For multi touch */
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -07002717 input_mt_init_slots(input_dev, MXT_MAX_FINGER);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002718 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08002719 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002720 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002721 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002722 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002723 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002724 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2725 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002726
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002727 /* set key array supported keys */
2728 if (pdata->key_codes) {
2729 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
2730 if (pdata->key_codes[i])
2731 input_set_capability(input_dev, EV_KEY,
2732 pdata->key_codes[i]);
2733 }
2734 }
2735
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002736 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002737 i2c_set_clientdata(client, data);
2738
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302739 if (pdata->init_hw)
2740 error = pdata->init_hw(true);
2741 else
2742 error = mxt_regulator_configure(data, true);
2743 if (error) {
2744 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07002745 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302746 }
2747
2748 if (pdata->power_on)
2749 error = pdata->power_on(true);
2750 else
2751 error = mxt_power_on(data, true);
2752 if (error) {
2753 dev_err(&client->dev, "Failed to power on hardware\n");
2754 goto err_regulator_on;
2755 }
2756
Amy Maloche08266db2011-11-04 11:07:16 -07002757 if (gpio_is_valid(pdata->irq_gpio)) {
2758 /* configure touchscreen irq gpio */
Mohan Pallakad96f5032012-06-18 22:49:10 +05302759 error = gpio_request(pdata->irq_gpio, "mxt_irq_gpio");
Amy Maloche08266db2011-11-04 11:07:16 -07002760 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302761 dev_err(&client->dev, "unable to request gpio [%d]\n",
Amy Maloche08266db2011-11-04 11:07:16 -07002762 pdata->irq_gpio);
2763 goto err_power_on;
2764 }
2765 error = gpio_direction_input(pdata->irq_gpio);
2766 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302767 dev_err(&client->dev,
2768 "unable to set direction for gpio [%d]\n",
2769 pdata->irq_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002770 goto err_irq_gpio_req;
2771 }
Mohan Pallakad96f5032012-06-18 22:49:10 +05302772 data->irq = client->irq = gpio_to_irq(pdata->irq_gpio);
2773 } else {
2774 dev_err(&client->dev, "irq gpio not provided\n");
2775 goto err_power_on;
Amy Maloche08266db2011-11-04 11:07:16 -07002776 }
2777
2778 if (gpio_is_valid(pdata->reset_gpio)) {
2779 /* configure touchscreen reset out gpio */
Mohan Pallakad96f5032012-06-18 22:49:10 +05302780 error = gpio_request(pdata->reset_gpio, "mxt_reset_gpio");
Amy Maloche08266db2011-11-04 11:07:16 -07002781 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302782 dev_err(&client->dev, "unable to request gpio [%d]\n",
2783 pdata->reset_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002784 goto err_irq_gpio_req;
2785 }
2786
Mohan Pallakad96f5032012-06-18 22:49:10 +05302787 error = gpio_direction_output(pdata->reset_gpio, 1);
Amy Maloche08266db2011-11-04 11:07:16 -07002788 if (error) {
Mohan Pallakad96f5032012-06-18 22:49:10 +05302789 dev_err(&client->dev,
2790 "unable to set direction for gpio [%d]\n",
2791 pdata->reset_gpio);
Amy Maloche08266db2011-11-04 11:07:16 -07002792 goto err_reset_gpio_req;
2793 }
2794 }
2795
Jing Lin64fdd1f2012-12-20 17:08:28 -08002796 mxt_power_on_delay(data);
2797
Iiro Valkonen7686b102011-02-02 23:21:58 -08002798 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002799 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07002800 goto err_reset_gpio_req;
Jing Lin64fdd1f2012-12-20 17:08:28 -08002801
Iiro Valkonen7686b102011-02-02 23:21:58 -08002802 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08002803 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002804 if (error) {
2805 dev_err(&client->dev, "Failed to register interrupt\n");
2806 goto err_free_object;
2807 }
2808
Nick Dyer0a4016c2012-01-18 15:17:59 +05302809 if (data->state == APPMODE) {
2810 error = mxt_make_highchg(data);
2811 if (error) {
2812 dev_err(&client->dev, "Failed to make high CHG\n");
2813 goto err_free_irq;
2814 }
2815 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07002816
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002817 error = input_register_device(input_dev);
2818 if (error)
2819 goto err_free_irq;
2820
Iiro Valkonen7686b102011-02-02 23:21:58 -08002821 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002822 if (error)
2823 goto err_unregister_device;
2824
Anurag Singh49d76132013-01-29 12:07:00 -08002825#if defined(CONFIG_FB)
2826 data->fb_notif.notifier_call = fb_notifier_callback;
2827
2828 error = fb_register_client(&data->fb_notif);
2829
2830 if (error)
2831 dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
2832 error);
2833#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302834 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
2835 MXT_SUSPEND_LEVEL;
2836 data->early_suspend.suspend = mxt_early_suspend;
2837 data->early_suspend.resume = mxt_late_resume;
2838 register_early_suspend(&data->early_suspend);
2839#endif
2840
Jing Lin6cfc00e2011-11-02 15:15:30 -07002841 mxt_debugfs_init(data);
2842
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002843 return 0;
2844
2845err_unregister_device:
2846 input_unregister_device(input_dev);
2847 input_dev = NULL;
2848err_free_irq:
2849 free_irq(client->irq, data);
2850err_free_object:
2851 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07002852err_reset_gpio_req:
2853 if (gpio_is_valid(pdata->reset_gpio))
2854 gpio_free(pdata->reset_gpio);
2855err_irq_gpio_req:
2856 if (gpio_is_valid(pdata->irq_gpio))
2857 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302858err_power_on:
2859 if (pdata->power_on)
2860 pdata->power_on(false);
2861 else
2862 mxt_power_on(data, false);
2863err_regulator_on:
2864 if (pdata->init_hw)
2865 pdata->init_hw(false);
2866 else
2867 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002868err_free_mem:
2869 input_free_device(input_dev);
2870 kfree(data);
2871 return error;
2872}
2873
Iiro Valkonen7686b102011-02-02 23:21:58 -08002874static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002875{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002876 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002877
Iiro Valkonen7686b102011-02-02 23:21:58 -08002878 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002879 free_irq(data->irq, data);
2880 input_unregister_device(data->input_dev);
Anurag Singh49d76132013-01-29 12:07:00 -08002881#if defined(CONFIG_FB)
2882 if (fb_unregister_client(&data->fb_notif))
2883 dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
2884#elif defined(CONFIG_HAS_EARLYSUSPEND)
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302885 unregister_early_suspend(&data->early_suspend);
2886#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302887
2888 if (data->pdata->power_on)
2889 data->pdata->power_on(false);
2890 else
2891 mxt_power_on(data, false);
2892
2893 if (data->pdata->init_hw)
2894 data->pdata->init_hw(false);
2895 else
2896 mxt_regulator_configure(data, false);
2897
Mohan Pallakabfe8f302012-01-02 18:32:08 +08002898 if (gpio_is_valid(data->pdata->reset_gpio))
2899 gpio_free(data->pdata->reset_gpio);
2900
2901 if (gpio_is_valid(data->pdata->irq_gpio))
2902 gpio_free(data->pdata->irq_gpio);
2903
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002904 kfree(data->object_table);
2905 kfree(data);
2906
Jing Lin6cfc00e2011-11-02 15:15:30 -07002907 debugfs_remove_recursive(debug_base);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002908
2909 return 0;
2910}
2911
Iiro Valkonen7686b102011-02-02 23:21:58 -08002912static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002913 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002914 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08002915 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002916 { }
2917};
Iiro Valkonen7686b102011-02-02 23:21:58 -08002918MODULE_DEVICE_TABLE(i2c, mxt_id);
Amy Maloche56cb58c2012-08-23 13:21:03 -07002919#ifdef CONFIG_OF
Mohan Pallakad96f5032012-06-18 22:49:10 +05302920static struct of_device_id mxt_match_table[] = {
2921 { .compatible = "atmel,mxt-ts",},
2922 { },
2923};
2924#else
2925#define mxt_match_table NULL
2926#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002927
Iiro Valkonen7686b102011-02-02 23:21:58 -08002928static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002929 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08002930 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002931 .owner = THIS_MODULE,
Mohan Pallakad96f5032012-06-18 22:49:10 +05302932 .of_match_table = mxt_match_table,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002933#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08002934 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002935#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002936 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002937 .probe = mxt_probe,
2938 .remove = __devexit_p(mxt_remove),
2939 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002940};
2941
Axel Lin1b92c1c2012-03-16 23:05:41 -07002942module_i2c_driver(mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002943
2944/* Module information */
2945MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08002946MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002947MODULE_LICENSE("GPL");