blob: 3238d33a1b21bff566111a69154874763cc6353d [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>
Mohan Pallaka5e7343f2012-01-02 18:30:16 +08006 * Copyright (c) 2011-2012, Code Aurora Forum. 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 Shimcd473222012-02-14 18:32:48 -080021#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>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070029
Anirudh Ghayal253ce122011-08-09 19:32:57 +053030#if defined(CONFIG_HAS_EARLYSUSPEND)
31#include <linux/earlysuspend.h>
32/* Early-suspend level */
33#define MXT_SUSPEND_LEVEL 1
34#endif
35
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070036/* Family ID */
37#define MXT224_ID 0x80
Amy Maloche380cc0b2011-11-03 12:55:04 -070038#define MXT224E_ID 0x81
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070039#define MXT1386_ID 0xA0
40
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070041/* Version */
Iiro Valkonen7686b102011-02-02 23:21:58 -080042#define MXT_VER_20 20
43#define MXT_VER_21 21
44#define MXT_VER_22 22
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070045
Nick Dyer0a4016c2012-01-18 15:17:59 +053046/* I2C slave address pairs */
47struct mxt_address_pair {
48 int bootloader;
49 int application;
50};
51
52static const struct mxt_address_pair mxt_slave_addresses[] = {
53 { 0x24, 0x4a },
54 { 0x25, 0x4b },
55 { 0x25, 0x4b },
56 { 0x26, 0x4c },
57 { 0x27, 0x4d },
58 { 0x34, 0x5a },
59 { 0x35, 0x5b },
60 { 0 },
61};
62
63enum mxt_device_state { INIT, APPMODE, BOOTLOADER };
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070064
65/* Firmware */
Iiro Valkonen7686b102011-02-02 23:21:58 -080066#define MXT_FW_NAME "maxtouch.fw"
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070067
Jing Lincc974cb2012-02-01 23:13:14 -080068/* Firmware frame size including frame data and CRC */
69#define MXT_SINGLE_FW_MAX_FRAME_SIZE 278
70#define MXT_CHIPSET_FW_MAX_FRAME_SIZE 534
71
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070072/* Registers */
Iiro Valkonen7686b102011-02-02 23:21:58 -080073#define MXT_FAMILY_ID 0x00
74#define MXT_VARIANT_ID 0x01
75#define MXT_VERSION 0x02
76#define MXT_BUILD 0x03
77#define MXT_MATRIX_X_SIZE 0x04
78#define MXT_MATRIX_Y_SIZE 0x05
79#define MXT_OBJECT_NUM 0x06
80#define MXT_OBJECT_START 0x07
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070081
Iiro Valkonen7686b102011-02-02 23:21:58 -080082#define MXT_OBJECT_SIZE 6
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070083
84/* Object types */
Iiro Valkonene8645592011-11-18 12:56:19 -080085#define MXT_DEBUG_DIAGNOSTIC_T37 37
86#define MXT_GEN_MESSAGE_T5 5
87#define MXT_GEN_COMMAND_T6 6
88#define MXT_GEN_POWER_T7 7
89#define MXT_GEN_ACQUIRE_T8 8
90#define MXT_GEN_DATASOURCE_T53 53
91#define MXT_TOUCH_MULTI_T9 9
92#define MXT_TOUCH_KEYARRAY_T15 15
93#define MXT_TOUCH_PROXIMITY_T23 23
94#define MXT_TOUCH_PROXKEY_T52 52
95#define MXT_PROCI_GRIPFACE_T20 20
96#define MXT_PROCG_NOISE_T22 22
97#define MXT_PROCI_ONETOUCH_T24 24
98#define MXT_PROCI_TWOTOUCH_T27 27
99#define MXT_PROCI_GRIP_T40 40
100#define MXT_PROCI_PALM_T41 41
101#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
102#define MXT_PROCI_STYLUS_T47 47
Jing Linc7fc4052011-12-21 16:16:19 -0800103#define MXT_PROCI_SHIELDLESS_T56 56
Iiro Valkonene8645592011-11-18 12:56:19 -0800104#define MXT_PROCG_NOISESUPPRESSION_T48 48
105#define MXT_SPT_COMMSCONFIG_T18 18
106#define MXT_SPT_GPIOPWM_T19 19
107#define MXT_SPT_SELFTEST_T25 25
108#define MXT_SPT_CTECONFIG_T28 28
109#define MXT_SPT_USERDATA_T38 38
110#define MXT_SPT_DIGITIZER_T43 43
111#define MXT_SPT_MESSAGECOUNT_T44 44
112#define MXT_SPT_CTECONFIG_T46 46
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700113
Iiro Valkonene8645592011-11-18 12:56:19 -0800114/* MXT_GEN_COMMAND_T6 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800115#define MXT_COMMAND_RESET 0
116#define MXT_COMMAND_BACKUPNV 1
117#define MXT_COMMAND_CALIBRATE 2
118#define MXT_COMMAND_REPORTALL 3
119#define MXT_COMMAND_DIAGNOSTIC 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700120
Iiro Valkonene8645592011-11-18 12:56:19 -0800121/* MXT_GEN_POWER_T7 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800122#define MXT_POWER_IDLEACQINT 0
123#define MXT_POWER_ACTVACQINT 1
124#define MXT_POWER_ACTV2IDLETO 2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700125
Iiro Valkonene8645592011-11-18 12:56:19 -0800126/* MXT_GEN_ACQUIRE_T8 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800127#define MXT_ACQUIRE_CHRGTIME 0
128#define MXT_ACQUIRE_TCHDRIFT 2
129#define MXT_ACQUIRE_DRIFTST 3
130#define MXT_ACQUIRE_TCHAUTOCAL 4
131#define MXT_ACQUIRE_SYNC 5
132#define MXT_ACQUIRE_ATCHCALST 6
133#define MXT_ACQUIRE_ATCHCALSTHR 7
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700134
Iiro Valkonene8645592011-11-18 12:56:19 -0800135/* MXT_TOUCH_MULT_T9 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800136#define MXT_TOUCH_CTRL 0
137#define MXT_TOUCH_XORIGIN 1
138#define MXT_TOUCH_YORIGIN 2
139#define MXT_TOUCH_XSIZE 3
140#define MXT_TOUCH_YSIZE 4
141#define MXT_TOUCH_BLEN 6
142#define MXT_TOUCH_TCHTHR 7
143#define MXT_TOUCH_TCHDI 8
144#define MXT_TOUCH_ORIENT 9
145#define MXT_TOUCH_MOVHYSTI 11
146#define MXT_TOUCH_MOVHYSTN 12
147#define MXT_TOUCH_NUMTOUCH 14
148#define MXT_TOUCH_MRGHYST 15
149#define MXT_TOUCH_MRGTHR 16
150#define MXT_TOUCH_AMPHYST 17
151#define MXT_TOUCH_XRANGE_LSB 18
152#define MXT_TOUCH_XRANGE_MSB 19
153#define MXT_TOUCH_YRANGE_LSB 20
154#define MXT_TOUCH_YRANGE_MSB 21
155#define MXT_TOUCH_XLOCLIP 22
156#define MXT_TOUCH_XHICLIP 23
157#define MXT_TOUCH_YLOCLIP 24
158#define MXT_TOUCH_YHICLIP 25
159#define MXT_TOUCH_XEDGECTRL 26
160#define MXT_TOUCH_XEDGEDIST 27
161#define MXT_TOUCH_YEDGECTRL 28
162#define MXT_TOUCH_YEDGEDIST 29
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700163#define MXT_TOUCH_JUMPLIMIT 30
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700164
Iiro Valkonene8645592011-11-18 12:56:19 -0800165/* MXT_PROCI_GRIPFACE_T20 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800166#define MXT_GRIPFACE_CTRL 0
167#define MXT_GRIPFACE_XLOGRIP 1
168#define MXT_GRIPFACE_XHIGRIP 2
169#define MXT_GRIPFACE_YLOGRIP 3
170#define MXT_GRIPFACE_YHIGRIP 4
171#define MXT_GRIPFACE_MAXTCHS 5
172#define MXT_GRIPFACE_SZTHR1 7
173#define MXT_GRIPFACE_SZTHR2 8
174#define MXT_GRIPFACE_SHPTHR1 9
175#define MXT_GRIPFACE_SHPTHR2 10
176#define MXT_GRIPFACE_SUPEXTTO 11
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700177
Iiro Valkonen7686b102011-02-02 23:21:58 -0800178/* MXT_PROCI_NOISE field */
179#define MXT_NOISE_CTRL 0
180#define MXT_NOISE_OUTFLEN 1
181#define MXT_NOISE_GCAFUL_LSB 3
182#define MXT_NOISE_GCAFUL_MSB 4
183#define MXT_NOISE_GCAFLL_LSB 5
184#define MXT_NOISE_GCAFLL_MSB 6
185#define MXT_NOISE_ACTVGCAFVALID 7
186#define MXT_NOISE_NOISETHR 8
187#define MXT_NOISE_FREQHOPSCALE 10
188#define MXT_NOISE_FREQ0 11
189#define MXT_NOISE_FREQ1 12
190#define MXT_NOISE_FREQ2 13
191#define MXT_NOISE_FREQ3 14
192#define MXT_NOISE_FREQ4 15
193#define MXT_NOISE_IDLEGCAFVALID 16
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700194
Iiro Valkonene8645592011-11-18 12:56:19 -0800195/* MXT_SPT_COMMSCONFIG_T18 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800196#define MXT_COMMS_CTRL 0
197#define MXT_COMMS_CMD 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700198
Iiro Valkonene8645592011-11-18 12:56:19 -0800199/* MXT_SPT_CTECONFIG_T28 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800200#define MXT_CTE_CTRL 0
201#define MXT_CTE_CMD 1
202#define MXT_CTE_MODE 2
203#define MXT_CTE_IDLEGCAFDEPTH 3
204#define MXT_CTE_ACTVGCAFDEPTH 4
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700205#define MXT_CTE_VOLTAGE 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700206
Iiro Valkonen7686b102011-02-02 23:21:58 -0800207#define MXT_VOLTAGE_DEFAULT 2700000
208#define MXT_VOLTAGE_STEP 10000
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700209
Amy Maloche21115eb2011-11-02 09:04:37 -0700210/* Analog voltage @2.7 V */
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530211#define MXT_VTG_MIN_UV 2700000
212#define MXT_VTG_MAX_UV 3300000
213#define MXT_ACTIVE_LOAD_UA 15000
Jing Linbace50b2011-10-18 22:55:47 -0700214#define MXT_LPM_LOAD_UA 10
Amy Maloche21115eb2011-11-02 09:04:37 -0700215/* Digital voltage @1.8 V */
216#define MXT_VTG_DIG_MIN_UV 1800000
217#define MXT_VTG_DIG_MAX_UV 1800000
218#define MXT_ACTIVE_LOAD_DIG_UA 10000
219#define MXT_LPM_LOAD_DIG_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530220
221#define MXT_I2C_VTG_MIN_UV 1800000
222#define MXT_I2C_VTG_MAX_UV 1800000
223#define MXT_I2C_LOAD_UA 10000
Jing Linbace50b2011-10-18 22:55:47 -0700224#define MXT_I2C_LPM_LOAD_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530225
Iiro Valkonene8645592011-11-18 12:56:19 -0800226/* Define for MXT_GEN_COMMAND_T6 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800227#define MXT_BOOT_VALUE 0xa5
228#define MXT_BACKUP_VALUE 0x55
229#define MXT_BACKUP_TIME 25 /* msec */
Jing Linc7fc4052011-12-21 16:16:19 -0800230#define MXT224_RESET_TIME 65 /* msec */
231#define MXT224E_RESET_TIME 22 /* msec */
232#define MXT1386_RESET_TIME 250 /* msec */
Amy Maloche7e447432011-09-14 11:36:30 -0700233#define MXT_RESET_TIME 250 /* msec */
Jing Linc7fc4052011-12-21 16:16:19 -0800234#define MXT_RESET_NOCHGREAD 400 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700235
Nick Dyer0a4016c2012-01-18 15:17:59 +0530236#define MXT_FWRESET_TIME 1000 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700237
Jing Lin36aee812011-10-17 17:17:28 -0700238#define MXT_WAKE_TIME 25
239
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700240/* Command to unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800241#define MXT_UNLOCK_CMD_MSB 0xaa
242#define MXT_UNLOCK_CMD_LSB 0xdc
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700243
244/* Bootloader mode status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800245#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
246#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
247#define MXT_FRAME_CRC_CHECK 0x02
248#define MXT_FRAME_CRC_FAIL 0x03
249#define MXT_FRAME_CRC_PASS 0x04
250#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
251#define MXT_BOOT_STATUS_MASK 0x3f
Nick Dyer0a4016c2012-01-18 15:17:59 +0530252#define MXT_BOOT_EXTENDED_ID (1 << 5)
253#define MXT_BOOT_ID_MASK 0x1f
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700254
255/* Touch status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800256#define MXT_SUPPRESS (1 << 1)
257#define MXT_AMP (1 << 2)
258#define MXT_VECTOR (1 << 3)
259#define MXT_MOVE (1 << 4)
260#define MXT_RELEASE (1 << 5)
261#define MXT_PRESS (1 << 6)
262#define MXT_DETECT (1 << 7)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700263
Joonyoung Shim910d8052011-04-12 23:14:38 -0700264/* Touch orient bits */
265#define MXT_XY_SWITCH (1 << 0)
266#define MXT_X_INVERT (1 << 1)
267#define MXT_Y_INVERT (1 << 2)
268
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700269/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800270#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700271
Iiro Valkonen7686b102011-02-02 23:21:58 -0800272#define MXT_MAX_FINGER 10
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700273
Jing Lin36aee812011-10-17 17:17:28 -0700274#define T7_DATA_SIZE 3
275#define MXT_MAX_RW_TRIES 3
276#define MXT_BLOCK_SIZE 256
Jing Lin8fadad72012-02-24 10:10:50 -0800277#define MXT_CFG_VERSION_LEN 3
278#define MXT_CFG_VERSION_EQUAL 0
279#define MXT_CFG_VERSION_LESS 1
280#define MXT_CFG_VERSION_GREATER 2
Mohan Pallakaab51f2b2011-09-29 18:17:35 +0530281
Jing Lin6cfc00e2011-11-02 15:15:30 -0700282#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
283#define MXT_DEBUGFS_FILE "object"
284
Iiro Valkonen7686b102011-02-02 23:21:58 -0800285struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700286 u8 family_id;
287 u8 variant_id;
288 u8 version;
289 u8 build;
290 u8 matrix_xsize;
291 u8 matrix_ysize;
292 u8 object_num;
293};
294
Iiro Valkonen7686b102011-02-02 23:21:58 -0800295struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700296 u8 type;
297 u16 start_address;
298 u8 size;
299 u8 instances;
300 u8 num_report_ids;
301
302 /* to map object and message */
303 u8 max_reportid;
304};
305
Iiro Valkonen7686b102011-02-02 23:21:58 -0800306struct mxt_message {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700307 u8 reportid;
308 u8 message[7];
309 u8 checksum;
310};
311
Iiro Valkonen7686b102011-02-02 23:21:58 -0800312struct mxt_finger {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700313 int status;
314 int x;
315 int y;
316 int area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700317 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700318};
319
320/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800321struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700322 struct i2c_client *client;
323 struct input_dev *input_dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800324 const struct mxt_platform_data *pdata;
Jing Lindc4413c2012-01-16 15:22:52 -0800325 const struct mxt_config_info *config_info;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530326 enum mxt_device_state state;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800327 struct mxt_object *object_table;
328 struct mxt_info info;
329 struct mxt_finger finger[MXT_MAX_FINGER];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700330 unsigned int irq;
Amy Maloche21115eb2011-11-02 09:04:37 -0700331 struct regulator *vcc_ana;
332 struct regulator *vcc_dig;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530333 struct regulator *vcc_i2c;
Anirudh Ghayal253ce122011-08-09 19:32:57 +0530334#if defined(CONFIG_HAS_EARLYSUSPEND)
335 struct early_suspend early_suspend;
336#endif
Jing Lin36aee812011-10-17 17:17:28 -0700337
Amy Maloche52262212011-09-15 16:46:57 -0700338 u8 t7_data[T7_DATA_SIZE];
Jing Lin36aee812011-10-17 17:17:28 -0700339 u16 t7_start_addr;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800340 u32 keyarray_old;
341 u32 keyarray_new;
342 u8 t9_max_reportid;
343 u8 t9_min_reportid;
344 u8 t15_max_reportid;
345 u8 t15_min_reportid;
Jing Lin8fadad72012-02-24 10:10:50 -0800346 u8 cfg_version[MXT_CFG_VERSION_LEN];
Jing Lindc4413c2012-01-16 15:22:52 -0800347 int cfg_version_idx;
Jing Lin8a9472d2012-03-21 15:43:45 -0700348 int t38_start_addr;
Jing Lin8fadad72012-02-24 10:10:50 -0800349 bool update_cfg;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -0800350 const char *fw_name;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700351};
352
Jing Lin6cfc00e2011-11-02 15:15:30 -0700353static struct dentry *debug_base;
354
Iiro Valkonen7686b102011-02-02 23:21:58 -0800355static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700356{
357 switch (type) {
Iiro Valkonene8645592011-11-18 12:56:19 -0800358 case MXT_GEN_MESSAGE_T5:
359 case MXT_GEN_COMMAND_T6:
360 case MXT_GEN_POWER_T7:
361 case MXT_GEN_ACQUIRE_T8:
362 case MXT_GEN_DATASOURCE_T53:
363 case MXT_TOUCH_MULTI_T9:
364 case MXT_TOUCH_KEYARRAY_T15:
365 case MXT_TOUCH_PROXIMITY_T23:
366 case MXT_TOUCH_PROXKEY_T52:
367 case MXT_PROCI_GRIPFACE_T20:
368 case MXT_PROCG_NOISE_T22:
369 case MXT_PROCI_ONETOUCH_T24:
370 case MXT_PROCI_TWOTOUCH_T27:
371 case MXT_PROCI_GRIP_T40:
372 case MXT_PROCI_PALM_T41:
373 case MXT_PROCI_TOUCHSUPPRESSION_T42:
374 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800375 case MXT_PROCI_SHIELDLESS_T56:
Iiro Valkonene8645592011-11-18 12:56:19 -0800376 case MXT_PROCG_NOISESUPPRESSION_T48:
377 case MXT_SPT_COMMSCONFIG_T18:
378 case MXT_SPT_GPIOPWM_T19:
379 case MXT_SPT_SELFTEST_T25:
380 case MXT_SPT_CTECONFIG_T28:
381 case MXT_SPT_USERDATA_T38:
382 case MXT_SPT_DIGITIZER_T43:
383 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700384 return true;
385 default:
386 return false;
387 }
388}
389
Iiro Valkonen7686b102011-02-02 23:21:58 -0800390static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700391{
392 switch (type) {
Iiro Valkonene8645592011-11-18 12:56:19 -0800393 case MXT_GEN_COMMAND_T6:
394 case MXT_GEN_POWER_T7:
395 case MXT_GEN_ACQUIRE_T8:
396 case MXT_TOUCH_MULTI_T9:
397 case MXT_TOUCH_KEYARRAY_T15:
398 case MXT_TOUCH_PROXIMITY_T23:
399 case MXT_TOUCH_PROXKEY_T52:
400 case MXT_PROCI_GRIPFACE_T20:
401 case MXT_PROCG_NOISE_T22:
402 case MXT_PROCI_ONETOUCH_T24:
403 case MXT_PROCI_TWOTOUCH_T27:
404 case MXT_PROCI_GRIP_T40:
405 case MXT_PROCI_PALM_T41:
406 case MXT_PROCI_TOUCHSUPPRESSION_T42:
407 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800408 case MXT_PROCI_SHIELDLESS_T56:
Iiro Valkonene8645592011-11-18 12:56:19 -0800409 case MXT_PROCG_NOISESUPPRESSION_T48:
410 case MXT_SPT_COMMSCONFIG_T18:
411 case MXT_SPT_GPIOPWM_T19:
412 case MXT_SPT_SELFTEST_T25:
413 case MXT_SPT_CTECONFIG_T28:
414 case MXT_SPT_USERDATA_T38:
415 case MXT_SPT_DIGITIZER_T43:
416 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700417 return true;
418 default:
419 return false;
420 }
421}
422
Iiro Valkonen7686b102011-02-02 23:21:58 -0800423static void mxt_dump_message(struct device *dev,
424 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700425{
426 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
427 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
428 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
429 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
430 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
431 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
432 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
433 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
434 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
435}
436
Nick Dyer0a4016c2012-01-18 15:17:59 +0530437static int mxt_switch_to_bootloader_address(struct mxt_data *data)
438{
439 int i;
440 struct i2c_client *client = data->client;
441
442 if (data->state == BOOTLOADER) {
443 dev_err(&client->dev, "Already in BOOTLOADER state\n");
444 return -EINVAL;
445 }
446
447 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
448 if (mxt_slave_addresses[i].application == client->addr) {
449 dev_info(&client->dev, "Changing to bootloader address: "
450 "%02x -> %02x",
451 client->addr,
452 mxt_slave_addresses[i].bootloader);
453
454 client->addr = mxt_slave_addresses[i].bootloader;
455 data->state = BOOTLOADER;
456 return 0;
457 }
458 }
459
460 dev_err(&client->dev, "Address 0x%02x not found in address table",
461 client->addr);
462 return -EINVAL;
463}
464
465static int mxt_switch_to_appmode_address(struct mxt_data *data)
466{
467 int i;
468 struct i2c_client *client = data->client;
469
470 if (data->state == APPMODE) {
471 dev_err(&client->dev, "Already in APPMODE state\n");
472 return -EINVAL;
473 }
474
475 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
476 if (mxt_slave_addresses[i].bootloader == client->addr) {
477 dev_info(&client->dev,
478 "Changing to application mode address: "
479 "0x%02x -> 0x%02x",
480 client->addr,
481 mxt_slave_addresses[i].application);
482
483 client->addr = mxt_slave_addresses[i].application;
484 data->state = APPMODE;
485 return 0;
486 }
487 }
488
489 dev_err(&client->dev, "Address 0x%02x not found in address table",
490 client->addr);
491 return -EINVAL;
492}
493
494static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
495{
496 u8 buf[3];
497
498 if (val | MXT_BOOT_EXTENDED_ID) {
499 dev_dbg(&client->dev,
500 "Retrieving extended mode ID information");
501
502 if (i2c_master_recv(client, &buf[0], 3) != 3) {
503 dev_err(&client->dev, "%s: i2c recv failed\n",
504 __func__);
505 return -EIO;
506 }
507
508 dev_info(&client->dev, "Bootloader ID:%d Version:%d",
509 buf[1], buf[2]);
510
511 return buf[0];
512 } else {
513 dev_info(&client->dev, "Bootloader ID:%d",
514 val & MXT_BOOT_ID_MASK);
515
516 return val;
517 }
518}
519
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -0800520static int mxt_get_bootloader_id(struct i2c_client *client)
521{
522 u8 val;
523 u8 buf[3];
524
525 if (i2c_master_recv(client, &val, 1) != 1) {
526 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
527 return -EIO;
528 }
529
530 if (val | MXT_BOOT_EXTENDED_ID) {
531 if (i2c_master_recv(client, &buf[0], 3) != 3) {
532 dev_err(&client->dev, "%s: i2c recv failed\n",
533 __func__);
534 return -EIO;
535 }
536 return buf[1];
537 } else {
538 dev_info(&client->dev, "Bootloader ID:%d",
539 val & MXT_BOOT_ID_MASK);
540
541 return val & MXT_BOOT_ID_MASK;
542 }
543}
544
Iiro Valkonen7686b102011-02-02 23:21:58 -0800545static int mxt_check_bootloader(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530546 unsigned int state)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700547{
548 u8 val;
549
550recheck:
551 if (i2c_master_recv(client, &val, 1) != 1) {
552 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
553 return -EIO;
554 }
555
556 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800557 case MXT_WAITING_BOOTLOAD_CMD:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530558 val = mxt_get_bootloader_version(client, val);
559 val &= ~MXT_BOOT_STATUS_MASK;
560 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800561 case MXT_WAITING_FRAME_DATA:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530562 case MXT_APP_CRC_FAIL:
Iiro Valkonen7686b102011-02-02 23:21:58 -0800563 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700564 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800565 case MXT_FRAME_CRC_PASS:
566 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700567 goto recheck;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530568 if (val == MXT_FRAME_CRC_FAIL) {
569 dev_err(&client->dev, "Bootloader CRC fail\n");
570 return -EINVAL;
571 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700572 break;
573 default:
574 return -EINVAL;
575 }
576
577 if (val != state) {
Nick Dyer0a4016c2012-01-18 15:17:59 +0530578 dev_err(&client->dev, "Invalid bootloader mode state %X\n",
579 val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700580 return -EINVAL;
581 }
582
583 return 0;
584}
585
Iiro Valkonen7686b102011-02-02 23:21:58 -0800586static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700587{
588 u8 buf[2];
589
Iiro Valkonen7686b102011-02-02 23:21:58 -0800590 buf[0] = MXT_UNLOCK_CMD_LSB;
591 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700592
593 if (i2c_master_send(client, buf, 2) != 2) {
594 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
595 return -EIO;
596 }
597
598 return 0;
599}
600
Iiro Valkonen7686b102011-02-02 23:21:58 -0800601static int mxt_fw_write(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530602 const u8 *data, unsigned int frame_size)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700603{
604 if (i2c_master_send(client, data, frame_size) != frame_size) {
605 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
606 return -EIO;
607 }
608
609 return 0;
610}
611
Iiro Valkonen7686b102011-02-02 23:21:58 -0800612static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700613 u16 reg, u16 len, void *val)
614{
615 struct i2c_msg xfer[2];
616 u8 buf[2];
Jing Lin36aee812011-10-17 17:17:28 -0700617 int i = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700618
619 buf[0] = reg & 0xff;
620 buf[1] = (reg >> 8) & 0xff;
621
622 /* Write register */
623 xfer[0].addr = client->addr;
624 xfer[0].flags = 0;
625 xfer[0].len = 2;
626 xfer[0].buf = buf;
627
628 /* Read data */
629 xfer[1].addr = client->addr;
630 xfer[1].flags = I2C_M_RD;
631 xfer[1].len = len;
632 xfer[1].buf = val;
633
Jing Lin36aee812011-10-17 17:17:28 -0700634 do {
635 if (i2c_transfer(client->adapter, xfer, 2) == 2)
636 return 0;
637 msleep(MXT_WAKE_TIME);
638 } while (++i < MXT_MAX_RW_TRIES);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700639
Jing Lin36aee812011-10-17 17:17:28 -0700640 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
641 return -EIO;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700642}
643
Iiro Valkonen7686b102011-02-02 23:21:58 -0800644static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700645{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800646 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700647}
648
Jing Lin36aee812011-10-17 17:17:28 -0700649static int __mxt_write_reg(struct i2c_client *client,
650 u16 addr, u16 length, u8 *value)
651{
652 u8 buf[MXT_BLOCK_SIZE + 2];
653 int i, tries = 0;
654
655 if (length > MXT_BLOCK_SIZE)
656 return -EINVAL;
657
658 buf[0] = addr & 0xff;
659 buf[1] = (addr >> 8) & 0xff;
660 for (i = 0; i < length; i++)
661 buf[i + 2] = *value++;
662
663 do {
664 if (i2c_master_send(client, buf, length + 2) == (length + 2))
665 return 0;
666 msleep(MXT_WAKE_TIME);
667 } while (++tries < MXT_MAX_RW_TRIES);
668
669 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
670 return -EIO;
671}
672
Iiro Valkonen7686b102011-02-02 23:21:58 -0800673static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700674{
Jing Lin36aee812011-10-17 17:17:28 -0700675 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700676}
677
Iiro Valkonen7686b102011-02-02 23:21:58 -0800678static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700679 u16 reg, u8 *object_buf)
680{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800681 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700682 object_buf);
683}
684
Iiro Valkonen7686b102011-02-02 23:21:58 -0800685static struct mxt_object *
686mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700687{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800688 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700689 int i;
690
691 for (i = 0; i < data->info.object_num; i++) {
692 object = data->object_table + i;
693 if (object->type == type)
694 return object;
695 }
696
697 dev_err(&data->client->dev, "Invalid object type\n");
698 return NULL;
699}
700
Iiro Valkonen7686b102011-02-02 23:21:58 -0800701static int mxt_read_message(struct mxt_data *data,
702 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700703{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800704 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700705 u16 reg;
706
Iiro Valkonene8645592011-11-18 12:56:19 -0800707 object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700708 if (!object)
709 return -EINVAL;
710
711 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800712 return __mxt_read_reg(data->client, reg,
713 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700714}
715
Iiro Valkonen7686b102011-02-02 23:21:58 -0800716static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700717 u8 type, u8 offset, u8 *val)
718{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800719 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700720 u16 reg;
721
Iiro Valkonen7686b102011-02-02 23:21:58 -0800722 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700723 if (!object)
724 return -EINVAL;
725
726 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800727 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700728}
729
Iiro Valkonen7686b102011-02-02 23:21:58 -0800730static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700731 u8 type, u8 offset, u8 val)
732{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800733 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700734 u16 reg;
735
Iiro Valkonen7686b102011-02-02 23:21:58 -0800736 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700737 if (!object)
738 return -EINVAL;
739
740 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800741 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700742}
743
Iiro Valkonen7686b102011-02-02 23:21:58 -0800744static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700745{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800746 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700747 struct input_dev *input_dev = data->input_dev;
748 int status = finger[single_id].status;
749 int finger_num = 0;
750 int id;
751
Iiro Valkonen7686b102011-02-02 23:21:58 -0800752 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700753 if (!finger[id].status)
754 continue;
755
Joonyoung Shimcd473222012-02-14 18:32:48 -0800756 input_mt_slot(input_dev, id);
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800757 /* Firmware reports min/max values when the touch is
758 * outside screen area. Send a release event in
759 * such cases to avoid unwanted touches.
760 */
761 if (finger[id].x <= data->pdata->panel_minx ||
762 finger[id].x >= data->pdata->panel_maxx ||
763 finger[id].y <= data->pdata->panel_miny ||
764 finger[id].y >= data->pdata->panel_maxy) {
765 finger[id].status = MXT_RELEASE;
766 }
767
Joonyoung Shimcd473222012-02-14 18:32:48 -0800768 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
769 finger[id].status != MXT_RELEASE);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700770
Joonyoung Shimcd473222012-02-14 18:32:48 -0800771 if (finger[id].status != MXT_RELEASE) {
Amy Maloche2b59bab2011-10-13 16:08:16 -0700772 finger_num++;
Joonyoung Shimcd473222012-02-14 18:32:48 -0800773 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
774 finger[id].area);
775 input_report_abs(input_dev, ABS_MT_POSITION_X,
776 finger[id].x);
777 input_report_abs(input_dev, ABS_MT_POSITION_Y,
778 finger[id].y);
779 input_report_abs(input_dev, ABS_MT_PRESSURE,
780 finger[id].area);
781 } else {
782 finger[id].status = 0;
783 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700784 }
785
786 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
787
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800788 if (finger[single_id].x <= data->pdata->panel_minx ||
789 finger[single_id].x >= data->pdata->panel_maxx ||
790 finger[single_id].y <= data->pdata->panel_miny ||
791 finger[single_id].y >= data->pdata->panel_maxy) {
792 status = MXT_RELEASE;
793 }
794
Iiro Valkonen7686b102011-02-02 23:21:58 -0800795 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700796 input_report_abs(input_dev, ABS_X, finger[single_id].x);
797 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700798 input_report_abs(input_dev,
799 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700800 }
801
802 input_sync(input_dev);
803}
804
Iiro Valkonen7686b102011-02-02 23:21:58 -0800805static void mxt_input_touchevent(struct mxt_data *data,
806 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700807{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800808 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700809 struct device *dev = &data->client->dev;
810 u8 status = message->message[0];
811 int x;
812 int y;
813 int area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700814 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700815
816 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800817 if (!(status & MXT_DETECT)) {
818 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700819 dev_dbg(dev, "[%d] released\n", id);
820
Iiro Valkonen7686b102011-02-02 23:21:58 -0800821 finger[id].status = MXT_RELEASE;
822 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700823 }
824 return;
825 }
826
827 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800828 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700829 return;
830
Joonyoung Shim910d8052011-04-12 23:14:38 -0700831 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
832 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800833 if (data->pdata->panel_maxx < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700834 x = x >> 2;
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800835 if (data->pdata->panel_maxy < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700836 y = y >> 2;
837
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700838 area = message->message[4];
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700839 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700840
841 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800842 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700843 x, y, area);
844
Iiro Valkonen7686b102011-02-02 23:21:58 -0800845 finger[id].status = status & MXT_MOVE ?
846 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700847 finger[id].x = x;
848 finger[id].y = y;
849 finger[id].area = area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700850 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700851
Iiro Valkonen7686b102011-02-02 23:21:58 -0800852 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700853}
854
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800855static void mxt_handle_key_array(struct mxt_data *data,
856 struct mxt_message *message)
857{
858 u32 keys_changed;
859 int i;
860
861 if (!data->pdata->key_codes) {
862 dev_err(&data->client->dev, "keyarray is not supported\n");
863 return;
864 }
865
866 data->keyarray_new = message->message[1] |
867 (message->message[2] << 8) |
868 (message->message[3] << 16) |
869 (message->message[4] << 24);
870
871 keys_changed = data->keyarray_old ^ data->keyarray_new;
872
873 if (!keys_changed) {
874 dev_dbg(&data->client->dev, "no keys changed\n");
875 return;
876 }
877
878 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
879 if (!(keys_changed & (1 << i)))
880 continue;
881
882 input_report_key(data->input_dev, data->pdata->key_codes[i],
883 (data->keyarray_new & (1 << i)));
884 input_sync(data->input_dev);
885 }
886
887 data->keyarray_old = data->keyarray_new;
888}
889
Iiro Valkonen7686b102011-02-02 23:21:58 -0800890static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700891{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800892 struct mxt_data *data = dev_id;
893 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700894 struct device *dev = &data->client->dev;
895 int id;
896 u8 reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700897
Nick Dyer0a4016c2012-01-18 15:17:59 +0530898 if (data->state != APPMODE) {
899 dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
900 return IRQ_HANDLED;
901 }
902
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700903 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800904 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700905 dev_err(dev, "Failed to read message\n");
906 goto end;
907 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700908 reportid = message.reportid;
909
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800910 if (!reportid) {
911 dev_dbg(dev, "Report id 0 is reserved\n");
912 continue;
913 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700914
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800915 /* check whether report id is part of T9 or T15 */
916 id = reportid - data->t9_min_reportid;
917
918 if (reportid >= data->t9_min_reportid &&
919 reportid <= data->t9_max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -0800920 mxt_input_touchevent(data, &message, id);
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800921 else if (reportid >= data->t15_min_reportid &&
922 reportid <= data->t15_max_reportid)
923 mxt_handle_key_array(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700924 else
Iiro Valkonen7686b102011-02-02 23:21:58 -0800925 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700926 } while (reportid != 0xff);
927
928end:
929 return IRQ_HANDLED;
930}
931
Iiro Valkonen7686b102011-02-02 23:21:58 -0800932static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700933{
Jing Lindc4413c2012-01-16 15:22:52 -0800934 const struct mxt_config_info *config_info = data->config_info;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800935 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700936 struct device *dev = &data->client->dev;
937 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -0800938 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700939
Jing Lindc4413c2012-01-16 15:22:52 -0800940 if (!config_info) {
Iiro Valkonen71749f52011-02-15 13:36:52 -0800941 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
942 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700943 }
944
945 for (i = 0; i < data->info.object_num; i++) {
946 object = data->object_table + i;
947
Iiro Valkonen7686b102011-02-02 23:21:58 -0800948 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700949 continue;
950
Iiro Valkonen71749f52011-02-15 13:36:52 -0800951 for (j = 0; j < object->size + 1; j++) {
952 config_offset = index + j;
Jing Lindc4413c2012-01-16 15:22:52 -0800953 if (config_offset > config_info->config_length) {
Iiro Valkonen71749f52011-02-15 13:36:52 -0800954 dev_err(dev, "Not enough config data!\n");
955 return -EINVAL;
956 }
Iiro Valkonen7686b102011-02-02 23:21:58 -0800957 mxt_write_object(data, object->type, j,
Jing Lindc4413c2012-01-16 15:22:52 -0800958 config_info->config[config_offset]);
Iiro Valkonen71749f52011-02-15 13:36:52 -0800959 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700960 index += object->size + 1;
961 }
962
963 return 0;
964}
965
Iiro Valkonen7686b102011-02-02 23:21:58 -0800966static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700967{
968 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800969 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700970 int count = 10;
971 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700972
973 /* Read dummy message to make high CHG pin */
974 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800975 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700976 if (error)
977 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800978 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700979
980 if (!count) {
981 dev_err(dev, "CHG pin isn't cleared\n");
982 return -EBUSY;
983 }
984
985 return 0;
986}
987
Iiro Valkonen7686b102011-02-02 23:21:58 -0800988static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700989{
990 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800991 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700992 int error;
993 u8 val;
994
Iiro Valkonen7686b102011-02-02 23:21:58 -0800995 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700996 if (error)
997 return error;
998 info->family_id = val;
999
Iiro Valkonen7686b102011-02-02 23:21:58 -08001000 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001001 if (error)
1002 return error;
1003 info->variant_id = val;
1004
Iiro Valkonen7686b102011-02-02 23:21:58 -08001005 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001006 if (error)
1007 return error;
1008 info->version = val;
1009
Iiro Valkonen7686b102011-02-02 23:21:58 -08001010 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001011 if (error)
1012 return error;
1013 info->build = val;
1014
Iiro Valkonen7686b102011-02-02 23:21:58 -08001015 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001016 if (error)
1017 return error;
1018 info->object_num = val;
1019
1020 return 0;
1021}
1022
Iiro Valkonen7686b102011-02-02 23:21:58 -08001023static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001024{
1025 int error;
1026 int i;
1027 u16 reg;
1028 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001029 u8 buf[MXT_OBJECT_SIZE];
Jing Lindc4413c2012-01-16 15:22:52 -08001030 bool found_t38 = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001031
1032 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001033 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001034
Iiro Valkonen7686b102011-02-02 23:21:58 -08001035 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
1036 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001037 if (error)
1038 return error;
1039
1040 object->type = buf[0];
1041 object->start_address = (buf[2] << 8) | buf[1];
1042 object->size = buf[3];
1043 object->instances = buf[4];
1044 object->num_report_ids = buf[5];
1045
1046 if (object->num_report_ids) {
1047 reportid += object->num_report_ids *
1048 (object->instances + 1);
1049 object->max_reportid = reportid;
1050 }
Jing Lindc4413c2012-01-16 15:22:52 -08001051
1052 /* Calculate index for config major version in config array.
1053 * Major version is the first byte in object T38.
1054 */
Jing Lin8a9472d2012-03-21 15:43:45 -07001055 if (object->type == MXT_SPT_USERDATA_T38) {
1056 data->t38_start_addr = object->start_address;
Jing Lindc4413c2012-01-16 15:22:52 -08001057 found_t38 = true;
Jing Lin8a9472d2012-03-21 15:43:45 -07001058 }
Jing Lindc4413c2012-01-16 15:22:52 -08001059 if (!found_t38 && mxt_object_writable(object->type))
1060 data->cfg_version_idx += object->size + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001061 }
1062
1063 return 0;
1064}
1065
Jing Lin8fadad72012-02-24 10:10:50 -08001066static int compare_versions(const u8 *v1, const u8 *v2)
1067{
1068 int i;
1069
1070 if (!v1 || !v2)
1071 return -EINVAL;
1072
1073 /* The major version number stays the same across different versions for
1074 * a particular controller on a target. The minor and sub-minor version
1075 * numbers indicate which version is newer.
1076 */
1077 if (v1[0] != v2[0])
1078 return -EINVAL;
1079
1080 for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
1081 if (v1[i] > v2[i])
1082 return MXT_CFG_VERSION_LESS; /* v2 is older */
1083
1084 if (v1[i] < v2[i])
1085 return MXT_CFG_VERSION_GREATER; /* v2 is newer */
1086 }
1087
1088 return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
1089}
1090
1091static void mxt_check_config_version(struct mxt_data *data,
1092 const struct mxt_config_info *cfg_info,
1093 bool match_major,
1094 const u8 **cfg_version_found,
1095 bool *found_cfg_major_match)
1096{
1097 const u8 *cfg_version;
1098 int result = -EINVAL;
1099
1100 cfg_version = cfg_info->config + data->cfg_version_idx;
1101
1102 if (*cfg_version_found)
1103 result = compare_versions(*cfg_version_found, cfg_version);
1104
1105 if (match_major) {
1106 if (result >= MXT_CFG_VERSION_EQUAL)
1107 *found_cfg_major_match = true;
1108
1109 if (result == MXT_CFG_VERSION_EQUAL ||
1110 result == MXT_CFG_VERSION_GREATER) {
1111 data->config_info = cfg_info;
1112 data->fw_name = cfg_info->fw_name;
1113 *cfg_version_found = cfg_version;
1114 }
1115
1116 if (result == MXT_CFG_VERSION_GREATER)
1117 data->update_cfg = true;
1118 } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
1119 data->config_info = cfg_info;
1120 data->fw_name = cfg_info->fw_name;
1121 data->update_cfg = true;
1122 *cfg_version_found = cfg_version;
1123 }
1124}
1125
1126/* If the controller's config version has a non-zero major number, call this
1127 * function with match_major = true to look for the latest config present in
1128 * the pdata based on matching family id, variant id, f/w version, build, and
1129 * config major number. If the controller is programmed with wrong config data
1130 * previously, call this function with match_major = false to look for latest
1131 * config based on based on matching family id, variant id, f/w version and
1132 * build only.
1133 */
1134static int mxt_search_config_array(struct mxt_data *data, bool match_major)
Jing Lindc4413c2012-01-16 15:22:52 -08001135{
1136
1137 const struct mxt_platform_data *pdata = data->pdata;
1138 const struct mxt_config_info *cfg_info;
Jing Lin8fadad72012-02-24 10:10:50 -08001139 const struct mxt_info *info = &data->info;
1140 const u8 *cfg_version_found;
1141 bool found_cfg_major_match = false;
Jing Lindc4413c2012-01-16 15:22:52 -08001142 int i;
Jing Lin8fadad72012-02-24 10:10:50 -08001143
1144 cfg_version_found = match_major ? data->cfg_version : NULL;
Jing Lindc4413c2012-01-16 15:22:52 -08001145
1146 for (i = 0; i < pdata->config_array_size; i++) {
1147
1148 cfg_info = &pdata->config_array[i];
1149
1150 if (!cfg_info->config || !cfg_info->config_length)
1151 continue;
1152
1153 if (info->family_id == cfg_info->family_id &&
1154 info->variant_id == cfg_info->variant_id &&
1155 info->version == cfg_info->version &&
1156 info->build == cfg_info->build) {
1157
Jing Lin8fadad72012-02-24 10:10:50 -08001158 mxt_check_config_version(data, cfg_info, match_major,
1159 &cfg_version_found, &found_cfg_major_match);
Jing Lindc4413c2012-01-16 15:22:52 -08001160 }
1161 }
1162
Jing Lin8fadad72012-02-24 10:10:50 -08001163 if (data->config_info || found_cfg_major_match)
1164 return 0;
1165
1166 data->config_info = NULL;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001167 data->fw_name = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001168
Jing Lindc4413c2012-01-16 15:22:52 -08001169 return -EINVAL;
1170}
1171
1172static int mxt_get_config(struct mxt_data *data)
1173{
1174 const struct mxt_platform_data *pdata = data->pdata;
1175 struct device *dev = &data->client->dev;
1176 struct mxt_object *object;
1177 int error;
1178
1179 if (!pdata->config_array || !pdata->config_array_size) {
1180 dev_dbg(dev, "No cfg data provided by platform data\n");
1181 return 0;
1182 }
1183
1184 /* Get current config version */
1185 object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
1186 if (!object) {
1187 dev_err(dev, "Unable to obtain USERDATA object\n");
1188 return -EINVAL;
1189 }
1190
Jing Lin8fadad72012-02-24 10:10:50 -08001191 error = __mxt_read_reg(data->client, object->start_address,
1192 sizeof(data->cfg_version), data->cfg_version);
Jing Lindc4413c2012-01-16 15:22:52 -08001193 if (error) {
1194 dev_err(dev, "Unable to read config version\n");
1195 return error;
1196 }
Jing Lin8fadad72012-02-24 10:10:50 -08001197 dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
1198 data->cfg_version[0], data->cfg_version[1],
1199 data->cfg_version[2]);
Jing Lindc4413c2012-01-16 15:22:52 -08001200
1201 /* It is possible that the config data on the controller is not
1202 * versioned and the version number returns 0. In this case,
1203 * find a match without the config version checking.
1204 */
1205 error = mxt_search_config_array(data,
Jing Lin8fadad72012-02-24 10:10:50 -08001206 data->cfg_version[0] != 0 ? true : false);
1207 if (error) {
1208 /* If a match wasn't found for a non-zero config version,
1209 * it means the controller has the wrong config data. Search
1210 * for a best match based on controller and firmware version,
1211 * but not config version.
1212 */
1213 if (data->cfg_version[0])
1214 error = mxt_search_config_array(data, false);
1215 if (error) {
1216 dev_err(dev,
1217 "Unable to find matching config in pdata\n");
1218 return error;
1219 }
1220 }
Jing Lindc4413c2012-01-16 15:22:52 -08001221
1222 return 0;
1223}
Jing Lin8fadad72012-02-24 10:10:50 -08001224
Amy Maloche7e447432011-09-14 11:36:30 -07001225static void mxt_reset_delay(struct mxt_data *data)
1226{
1227 struct mxt_info *info = &data->info;
1228
1229 switch (info->family_id) {
1230 case MXT224_ID:
1231 msleep(MXT224_RESET_TIME);
1232 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -07001233 case MXT224E_ID:
1234 msleep(MXT224E_RESET_TIME);
1235 break;
Amy Maloche7e447432011-09-14 11:36:30 -07001236 case MXT1386_ID:
1237 msleep(MXT1386_RESET_TIME);
1238 break;
1239 default:
1240 msleep(MXT_RESET_TIME);
1241 }
1242}
1243
Jing Lin8fadad72012-02-24 10:10:50 -08001244static int mxt_backup_nv(struct mxt_data *data)
1245{
1246 int error;
1247 u8 command_register;
1248 int timeout_counter = 0;
1249
1250 /* Backup to memory */
1251 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1252 MXT_COMMAND_BACKUPNV,
1253 MXT_BACKUP_VALUE);
1254 msleep(MXT_BACKUP_TIME);
1255
1256 do {
1257 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
1258 MXT_COMMAND_BACKUPNV,
1259 &command_register);
1260 if (error)
1261 return error;
1262
1263 usleep_range(1000, 2000);
1264
1265 } while ((command_register != 0) && (++timeout_counter <= 100));
1266
1267 if (timeout_counter > 100) {
1268 dev_err(&data->client->dev, "No response after backup!\n");
1269 return -EIO;
1270 }
1271
1272 /* Soft reset */
1273 mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
1274
1275 mxt_reset_delay(data);
1276
1277 return 0;
1278}
1279
Jing Lin412aedc2012-02-28 13:57:19 -08001280static int mxt_save_objects(struct mxt_data *data)
1281{
1282 struct i2c_client *client = data->client;
1283 struct mxt_object *t7_object;
1284 struct mxt_object *t9_object;
1285 struct mxt_object *t15_object;
1286 int error;
1287
1288 /* Store T7 and T9 locally, used in suspend/resume operations */
1289 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
1290 if (!t7_object) {
1291 dev_err(&client->dev, "Failed to get T7 object\n");
1292 return -EINVAL;
1293 }
1294
1295 data->t7_start_addr = t7_object->start_address;
1296 error = __mxt_read_reg(client, data->t7_start_addr,
1297 T7_DATA_SIZE, data->t7_data);
1298 if (error < 0) {
1299 dev_err(&client->dev,
1300 "Failed to save current power state\n");
1301 return error;
1302 }
1303
Jing Lin412aedc2012-02-28 13:57:19 -08001304 /* Store T9, T15's min and max report ids */
1305 t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1306 if (!t9_object) {
1307 dev_err(&client->dev, "Failed to get T9 object\n");
1308 return -EINVAL;
1309 }
1310 data->t9_max_reportid = t9_object->max_reportid;
1311 data->t9_min_reportid = t9_object->max_reportid -
1312 t9_object->num_report_ids + 1;
1313
1314 if (data->pdata->key_codes) {
1315 t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
1316 if (!t15_object)
1317 dev_dbg(&client->dev, "T15 object is not available\n");
1318 else {
1319 data->t15_max_reportid = t15_object->max_reportid;
1320 data->t15_min_reportid = t15_object->max_reportid -
1321 t15_object->num_report_ids + 1;
1322 }
1323 }
1324
1325 return 0;
1326}
1327
Iiro Valkonen7686b102011-02-02 23:21:58 -08001328static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001329{
1330 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001331 struct mxt_info *info = &data->info;
Jing Lin36aee812011-10-17 17:17:28 -07001332 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001333 u8 val;
Jing Lin8fadad72012-02-24 10:10:50 -08001334 const u8 *cfg_ver;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001335
Iiro Valkonen7686b102011-02-02 23:21:58 -08001336 error = mxt_get_info(data);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301337 if (error) {
1338 /* Try bootloader mode */
1339 error = mxt_switch_to_bootloader_address(data);
1340 if (error)
1341 return error;
1342
1343 error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
1344 if (error)
1345 return error;
1346
1347 dev_err(&client->dev, "Application CRC failure\n");
1348 data->state = BOOTLOADER;
1349
1350 return 0;
1351 }
1352
1353 dev_info(&client->dev,
1354 "Family ID: %d Variant ID: %d Version: %d.%d "
1355 "Build: 0x%02X Object Num: %d\n",
1356 info->family_id, info->variant_id,
1357 info->version >> 4, info->version & 0xf,
1358 info->build, info->object_num);
1359
1360 data->state = APPMODE;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001361
1362 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001363 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001364 GFP_KERNEL);
1365 if (!data->object_table) {
1366 dev_err(&client->dev, "Failed to allocate memory\n");
1367 return -ENOMEM;
1368 }
1369
1370 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001371 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001372 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001373 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001374
Jing Lindc4413c2012-01-16 15:22:52 -08001375 /* Get config data from platform data */
1376 error = mxt_get_config(data);
1377 if (error)
1378 dev_dbg(&client->dev, "Config info not found.\n");
1379
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001380 /* Check register init values */
Jing Lin8fadad72012-02-24 10:10:50 -08001381 if (data->config_info && data->config_info->config) {
1382 if (data->update_cfg) {
1383 error = mxt_check_reg_init(data);
1384 if (error) {
1385 dev_err(&client->dev,
1386 "Failed to check reg init value\n");
1387 goto free_object_table;
1388 }
1389
1390 error = mxt_backup_nv(data);
1391 if (error) {
1392 dev_err(&client->dev, "Failed to back up NV\n");
1393 goto free_object_table;
1394 }
1395
1396 cfg_ver = data->config_info->config +
1397 data->cfg_version_idx;
1398 dev_info(&client->dev,
1399 "Config updated from %d.%d.%d to %d.%d.%d\n",
1400 data->cfg_version[0], data->cfg_version[1],
1401 data->cfg_version[2],
1402 cfg_ver[0], cfg_ver[1], cfg_ver[2]);
1403
1404 memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
1405 }
1406 } else {
1407 dev_info(&client->dev,
1408 "No cfg data defined, skipping check reg init\n");
1409 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001410
Jing Lin412aedc2012-02-28 13:57:19 -08001411 error = mxt_save_objects(data);
1412 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001413 goto free_object_table;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001414
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001415 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001416 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001417 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001418 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001419 info->matrix_xsize = val;
1420
Iiro Valkonen7686b102011-02-02 23:21:58 -08001421 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001422 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001423 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001424 info->matrix_ysize = val;
1425
1426 dev_info(&client->dev,
Nick Dyer0a4016c2012-01-18 15:17:59 +05301427 "Matrix X Size: %d Matrix Y Size: %d\n",
1428 info->matrix_xsize, info->matrix_ysize);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001429
1430 return 0;
Jing Lin32c72532011-11-03 12:02:33 -07001431
1432free_object_table:
1433 kfree(data->object_table);
1434 return error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001435}
1436
Iiro Valkonen7686b102011-02-02 23:21:58 -08001437static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001438 struct device_attribute *attr, char *buf)
1439{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001440 struct mxt_data *data = dev_get_drvdata(dev);
1441 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001442 int count = 0;
1443 int i, j;
1444 int error;
1445 u8 val;
1446
1447 for (i = 0; i < data->info.object_num; i++) {
1448 object = data->object_table + i;
1449
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001450 count += snprintf(buf + count, PAGE_SIZE - count,
1451 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001452 i + 1, object->type);
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001453 if (count >= PAGE_SIZE)
1454 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001455
Iiro Valkonen7686b102011-02-02 23:21:58 -08001456 if (!mxt_object_readable(object->type)) {
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001457 count += snprintf(buf + count, PAGE_SIZE - count,
1458 "\n");
1459 if (count >= PAGE_SIZE)
1460 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001461 continue;
1462 }
1463
1464 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001465 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001466 object->type, j, &val);
1467 if (error)
1468 return error;
1469
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001470 count += snprintf(buf + count, PAGE_SIZE - count,
1471 "\t[%2d]: %02x (%d)\n", j, val, val);
1472 if (count >= PAGE_SIZE)
1473 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001474 }
1475
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001476 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1477 if (count >= PAGE_SIZE)
1478 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001479 }
1480
1481 return count;
1482}
1483
Jing Lincc974cb2012-02-01 23:13:14 -08001484static int strtobyte(const char *data, u8 *value)
1485{
1486 char str[3];
1487
1488 str[0] = data[0];
1489 str[1] = data[1];
1490 str[2] = '\0';
1491
1492 return kstrtou8(str, 16, value);
1493}
1494
Iiro Valkonen7686b102011-02-02 23:21:58 -08001495static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001496{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001497 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001498 struct i2c_client *client = data->client;
1499 const struct firmware *fw = NULL;
1500 unsigned int frame_size;
Nick Dyer0a4016c2012-01-18 15:17:59 +05301501 unsigned int retry = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001502 unsigned int pos = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001503 int ret, i, max_frame_size;
1504 u8 *frame;
1505
1506 switch (data->info.family_id) {
1507 case MXT224_ID:
1508 max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
1509 break;
1510 case MXT1386_ID:
1511 max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
1512 break;
1513 default:
1514 return -EINVAL;
1515 }
1516
1517 frame = kmalloc(max_frame_size, GFP_KERNEL);
1518 if (!frame) {
1519 dev_err(dev, "Unable to allocate memory for frame data\n");
1520 return -ENOMEM;
1521 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001522
1523 ret = request_firmware(&fw, fn, dev);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301524 if (ret < 0) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001525 dev_err(dev, "Unable to open firmware %s\n", fn);
Jing Lincc974cb2012-02-01 23:13:14 -08001526 goto free_frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001527 }
1528
Nick Dyer0a4016c2012-01-18 15:17:59 +05301529 if (data->state != BOOTLOADER) {
1530 /* Change to the bootloader mode */
1531 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1532 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1533 mxt_reset_delay(data);
Amy Maloche7e447432011-09-14 11:36:30 -07001534
Nick Dyer0a4016c2012-01-18 15:17:59 +05301535 ret = mxt_switch_to_bootloader_address(data);
1536 if (ret)
1537 goto release_firmware;
1538 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001539
Iiro Valkonen7686b102011-02-02 23:21:58 -08001540 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301541 if (ret) {
1542 /* Bootloader may still be unlocked from previous update
1543 * attempt */
1544 ret = mxt_check_bootloader(client,
1545 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001546
Nick Dyer0a4016c2012-01-18 15:17:59 +05301547 if (ret)
1548 goto return_to_app_mode;
1549 } else {
1550 dev_info(dev, "Unlocking bootloader\n");
1551 /* Unlock bootloader */
1552 mxt_unlock_bootloader(client);
1553 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001554
1555 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001556 ret = mxt_check_bootloader(client,
1557 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001558 if (ret)
Nick Dyer0a4016c2012-01-18 15:17:59 +05301559 goto release_firmware;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001560
Jing Lincc974cb2012-02-01 23:13:14 -08001561 /* Get frame length MSB */
1562 ret = strtobyte(fw->data + pos, frame);
1563 if (ret)
1564 goto release_firmware;
1565
1566 /* Get frame length LSB */
1567 ret = strtobyte(fw->data + pos + 2, frame + 1);
1568 if (ret)
1569 goto release_firmware;
1570
1571 frame_size = ((*frame << 8) | *(frame + 1));
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001572
1573 /* We should add 2 at frame size as the the firmware data is not
1574 * included the CRC bytes.
1575 */
1576 frame_size += 2;
1577
Jing Lincc974cb2012-02-01 23:13:14 -08001578 if (frame_size > max_frame_size) {
1579 dev_err(dev, "Invalid frame size - %d\n", frame_size);
1580 ret = -EINVAL;
1581 goto release_firmware;
1582 }
1583
1584 /* Convert frame data and CRC from hex to binary */
1585 for (i = 2; i < frame_size; i++) {
1586 ret = strtobyte(fw->data + pos + i * 2, frame + i);
1587 if (ret)
1588 goto release_firmware;
1589 }
1590
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001591 /* Write one frame to device */
Jing Lincc974cb2012-02-01 23:13:14 -08001592 mxt_fw_write(client, frame, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001593
Iiro Valkonen7686b102011-02-02 23:21:58 -08001594 ret = mxt_check_bootloader(client,
1595 MXT_FRAME_CRC_PASS);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301596 if (ret) {
1597 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001598
Nick Dyer0a4016c2012-01-18 15:17:59 +05301599 /* Back off by 20ms per retry */
1600 msleep(retry * 20);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001601
Nick Dyer0a4016c2012-01-18 15:17:59 +05301602 if (retry > 20)
1603 goto release_firmware;
1604 } else {
1605 retry = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001606 pos += frame_size * 2;
1607 dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301608 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001609 }
1610
Nick Dyer0a4016c2012-01-18 15:17:59 +05301611return_to_app_mode:
1612 mxt_switch_to_appmode_address(data);
1613release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001614 release_firmware(fw);
Jing Lincc974cb2012-02-01 23:13:14 -08001615free_frame:
1616 kfree(frame);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001617
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001618 return ret;
1619}
1620
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001621static const char *
1622mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
1623{
1624 const struct mxt_platform_data *pdata = data->pdata;
1625 const struct mxt_config_info *cfg_info;
1626 const char *fw_name = NULL;
1627 int i;
1628
1629 for (i = 0; i < pdata->config_array_size; i++) {
1630 cfg_info = &pdata->config_array[i];
1631 if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
1632 data->config_info = cfg_info;
1633 data->info.family_id = cfg_info->family_id;
1634 fw_name = cfg_info->fw_name;
1635 }
1636 }
1637
1638 return fw_name;
1639}
1640
Iiro Valkonen7686b102011-02-02 23:21:58 -08001641static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001642 struct device_attribute *attr,
1643 const char *buf, size_t count)
1644{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001645 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001646 int error;
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001647 const char *fw_name;
1648 u8 bootldr_id;
Jing Lin8a9472d2012-03-21 15:43:45 -07001649 u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001650
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001651 /* If fw_name is set, then the existing firmware has an upgrade */
1652 if (!data->fw_name) {
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001653 /*
1654 * If the device boots up in the bootloader mode, check if
1655 * there is a firmware to upgrade.
1656 */
1657 if (data->state == BOOTLOADER) {
1658 bootldr_id = mxt_get_bootloader_id(data->client);
1659 if (bootldr_id <= 0) {
1660 dev_err(dev,
1661 "Unable to retrieve bootloader id\n");
1662 return -EINVAL;
1663 }
1664 fw_name = mxt_search_fw_name(data, bootldr_id);
1665 if (fw_name == NULL) {
1666 dev_err(dev,
1667 "Unable to find fw from bootloader id\n");
1668 return -EINVAL;
1669 }
1670 } else {
1671 /* In APPMODE, if the f/w name does not exist, quit */
1672 dev_err(dev,
1673 "Firmware name not specified in platform data\n");
1674 return -EINVAL;
1675 }
1676 } else {
1677 fw_name = data->fw_name;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001678 }
1679
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001680 dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001681
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001682 disable_irq(data->irq);
1683
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001684 error = mxt_load_fw(dev, fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001685 if (error) {
1686 dev_err(dev, "The firmware update failed(%d)\n", error);
1687 count = error;
1688 } else {
Nick Dyer0a4016c2012-01-18 15:17:59 +05301689 dev_info(dev, "The firmware update succeeded\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001690
1691 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001692 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001693
Nick Dyer0a4016c2012-01-18 15:17:59 +05301694 data->state = INIT;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001695 kfree(data->object_table);
1696 data->object_table = NULL;
Jing Lincc974cb2012-02-01 23:13:14 -08001697 data->cfg_version_idx = 0;
Jing Lin8fadad72012-02-24 10:10:50 -08001698 data->update_cfg = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001699
Jing Lin8a9472d2012-03-21 15:43:45 -07001700 error = __mxt_write_reg(data->client, data->t38_start_addr,
1701 sizeof(cfg_version), cfg_version);
1702 if (error)
1703 dev_err(dev,
1704 "Unable to zero out config version after fw upgrade\n");
1705
Iiro Valkonen7686b102011-02-02 23:21:58 -08001706 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001707 }
1708
Nick Dyer0a4016c2012-01-18 15:17:59 +05301709 if (data->state == APPMODE) {
1710 enable_irq(data->irq);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001711
Nick Dyer0a4016c2012-01-18 15:17:59 +05301712 error = mxt_make_highchg(data);
1713 if (error)
1714 return error;
1715 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07001716
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001717 return count;
1718}
1719
Iiro Valkonen7686b102011-02-02 23:21:58 -08001720static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
1721static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001722
Iiro Valkonen7686b102011-02-02 23:21:58 -08001723static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001724 &dev_attr_object.attr,
1725 &dev_attr_update_fw.attr,
1726 NULL
1727};
1728
Iiro Valkonen7686b102011-02-02 23:21:58 -08001729static const struct attribute_group mxt_attr_group = {
1730 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001731};
1732
Amy Maloche52262212011-09-15 16:46:57 -07001733static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001734{
Jing Lin36aee812011-10-17 17:17:28 -07001735 int error;
1736
Amy Maloche52262212011-09-15 16:46:57 -07001737 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07001738 error = __mxt_write_reg(data->client, data->t7_start_addr,
1739 T7_DATA_SIZE, data->t7_data);
1740 if (error < 0) {
1741 dev_err(&data->client->dev,
1742 "failed to restore old power state\n");
1743 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001744 }
Jing Lin36aee812011-10-17 17:17:28 -07001745
Amy Maloche52262212011-09-15 16:46:57 -07001746 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001747}
1748
Amy Maloche52262212011-09-15 16:46:57 -07001749static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001750{
Jing Lin36aee812011-10-17 17:17:28 -07001751 int error;
1752 u8 t7_data[T7_DATA_SIZE] = {0};
1753
Jing Lin36aee812011-10-17 17:17:28 -07001754 error = __mxt_write_reg(data->client, data->t7_start_addr,
1755 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07001756 if (error < 0) {
1757 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07001758 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07001759 return error;
1760 }
1761
1762 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001763}
1764
Iiro Valkonen7686b102011-02-02 23:21:58 -08001765static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001766{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001767 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001768 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001769
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001770 if (data->state == APPMODE) {
1771 error = mxt_start(data);
1772 if (error < 0) {
1773 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
1774 return error;
1775 }
Amy Maloche52262212011-09-15 16:46:57 -07001776 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001777
1778 return 0;
1779}
1780
Iiro Valkonen7686b102011-02-02 23:21:58 -08001781static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001782{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001783 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001784 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001785
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001786 if (data->state == APPMODE) {
1787 error = mxt_stop(data);
1788 if (error < 0)
1789 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
1790 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001791}
1792
Amy Malochec331f842012-01-24 10:33:47 -08001793static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
1794{
1795 return (regulator_count_voltages(reg) > 0) ?
1796 regulator_set_optimum_mode(reg, load_uA) : 0;
1797}
1798
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301799static int mxt_power_on(struct mxt_data *data, bool on)
1800{
1801 int rc;
1802
1803 if (on == false)
1804 goto power_off;
1805
Amy Malochec331f842012-01-24 10:33:47 -08001806 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301807 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001808 dev_err(&data->client->dev,
1809 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301810 return rc;
1811 }
1812
Amy Maloche21115eb2011-11-02 09:04:37 -07001813 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301814 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001815 dev_err(&data->client->dev,
1816 "Regulator vcc_ana enable failed rc=%d\n", rc);
1817 goto error_reg_en_vcc_ana;
1818 }
1819
1820 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001821 rc = reg_set_optimum_mode_check(data->vcc_dig,
1822 MXT_ACTIVE_LOAD_DIG_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07001823 if (rc < 0) {
1824 dev_err(&data->client->dev,
1825 "Regulator vcc_dig set_opt failed rc=%d\n",
1826 rc);
1827 goto error_reg_opt_vcc_dig;
1828 }
1829
1830 rc = regulator_enable(data->vcc_dig);
1831 if (rc) {
1832 dev_err(&data->client->dev,
1833 "Regulator vcc_dig enable failed rc=%d\n", rc);
1834 goto error_reg_en_vcc_dig;
1835 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301836 }
1837
1838 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001839 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301840 if (rc < 0) {
1841 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001842 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301843 goto error_reg_opt_i2c;
1844 }
1845
1846 rc = regulator_enable(data->vcc_i2c);
1847 if (rc) {
1848 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001849 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301850 goto error_reg_en_vcc_i2c;
1851 }
1852 }
1853
Amy Malochef0d7b8d2011-10-17 12:10:51 -07001854 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301855
1856 return 0;
1857
1858error_reg_en_vcc_i2c:
1859 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08001860 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301861error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001862 if (data->pdata->digital_pwr_regulator)
1863 regulator_disable(data->vcc_dig);
1864error_reg_en_vcc_dig:
1865 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08001866 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001867error_reg_opt_vcc_dig:
1868 regulator_disable(data->vcc_ana);
1869error_reg_en_vcc_ana:
Amy Malochec331f842012-01-24 10:33:47 -08001870 reg_set_optimum_mode_check(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301871 return rc;
1872
1873power_off:
Amy Malochec331f842012-01-24 10:33:47 -08001874 reg_set_optimum_mode_check(data->vcc_ana, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001875 regulator_disable(data->vcc_ana);
1876 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001877 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001878 regulator_disable(data->vcc_dig);
1879 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301880 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001881 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301882 regulator_disable(data->vcc_i2c);
1883 }
1884 msleep(50);
1885 return 0;
1886}
1887
1888static int mxt_regulator_configure(struct mxt_data *data, bool on)
1889{
1890 int rc;
1891
1892 if (on == false)
1893 goto hw_shutdown;
1894
Amy Maloche21115eb2011-11-02 09:04:37 -07001895 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
1896 if (IS_ERR(data->vcc_ana)) {
1897 rc = PTR_ERR(data->vcc_ana);
1898 dev_err(&data->client->dev,
1899 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301900 return rc;
1901 }
1902
Amy Maloche21115eb2011-11-02 09:04:37 -07001903 if (regulator_count_voltages(data->vcc_ana) > 0) {
1904 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301905 MXT_VTG_MAX_UV);
1906 if (rc) {
1907 dev_err(&data->client->dev,
1908 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07001909 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301910 }
1911 }
Amy Maloche21115eb2011-11-02 09:04:37 -07001912 if (data->pdata->digital_pwr_regulator) {
1913 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
1914 if (IS_ERR(data->vcc_dig)) {
1915 rc = PTR_ERR(data->vcc_dig);
1916 dev_err(&data->client->dev,
1917 "Regulator get dig failed rc=%d\n", rc);
1918 goto error_get_vtg_vcc_dig;
1919 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301920
Amy Maloche21115eb2011-11-02 09:04:37 -07001921 if (regulator_count_voltages(data->vcc_dig) > 0) {
1922 rc = regulator_set_voltage(data->vcc_dig,
1923 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
1924 if (rc) {
1925 dev_err(&data->client->dev,
1926 "regulator set_vtg failed rc=%d\n", rc);
1927 goto error_set_vtg_vcc_dig;
1928 }
1929 }
1930 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301931 if (data->pdata->i2c_pull_up) {
1932 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
1933 if (IS_ERR(data->vcc_i2c)) {
1934 rc = PTR_ERR(data->vcc_i2c);
1935 dev_err(&data->client->dev,
1936 "Regulator get failed rc=%d\n", rc);
1937 goto error_get_vtg_i2c;
1938 }
1939 if (regulator_count_voltages(data->vcc_i2c) > 0) {
1940 rc = regulator_set_voltage(data->vcc_i2c,
1941 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
1942 if (rc) {
1943 dev_err(&data->client->dev,
1944 "regulator set_vtg failed rc=%d\n", rc);
1945 goto error_set_vtg_i2c;
1946 }
1947 }
1948 }
1949
1950 return 0;
1951
1952error_set_vtg_i2c:
1953 regulator_put(data->vcc_i2c);
1954error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001955 if (data->pdata->digital_pwr_regulator)
1956 if (regulator_count_voltages(data->vcc_dig) > 0)
1957 regulator_set_voltage(data->vcc_dig, 0,
1958 MXT_VTG_DIG_MAX_UV);
1959error_set_vtg_vcc_dig:
1960 if (data->pdata->digital_pwr_regulator)
1961 regulator_put(data->vcc_dig);
1962error_get_vtg_vcc_dig:
1963 if (regulator_count_voltages(data->vcc_ana) > 0)
1964 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1965error_set_vtg_vcc_ana:
1966 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301967 return rc;
1968
1969hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07001970 if (regulator_count_voltages(data->vcc_ana) > 0)
1971 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1972 regulator_put(data->vcc_ana);
1973 if (data->pdata->digital_pwr_regulator) {
1974 if (regulator_count_voltages(data->vcc_dig) > 0)
1975 regulator_set_voltage(data->vcc_dig, 0,
1976 MXT_VTG_DIG_MAX_UV);
1977 regulator_put(data->vcc_dig);
1978 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301979 if (data->pdata->i2c_pull_up) {
1980 if (regulator_count_voltages(data->vcc_i2c) > 0)
1981 regulator_set_voltage(data->vcc_i2c, 0,
1982 MXT_I2C_VTG_MAX_UV);
1983 regulator_put(data->vcc_i2c);
1984 }
1985 return 0;
1986}
1987
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301988#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07001989static int mxt_regulator_lpm(struct mxt_data *data, bool on)
1990{
1991
1992 int rc;
1993
1994 if (on == false)
1995 goto regulator_hpm;
1996
Amy Malochec331f842012-01-24 10:33:47 -08001997 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001998 if (rc < 0) {
1999 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002000 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002001 goto fail_regulator_lpm;
2002 }
2003
Amy Maloche21115eb2011-11-02 09:04:37 -07002004 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002005 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002006 MXT_LPM_LOAD_DIG_UA);
2007 if (rc < 0) {
2008 dev_err(&data->client->dev,
2009 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2010 goto fail_regulator_lpm;
2011 }
2012 }
2013
Jing Linbace50b2011-10-18 22:55:47 -07002014 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002015 rc = reg_set_optimum_mode_check(data->vcc_i2c,
Jing Linbace50b2011-10-18 22:55:47 -07002016 MXT_I2C_LPM_LOAD_UA);
2017 if (rc < 0) {
2018 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002019 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002020 goto fail_regulator_lpm;
2021 }
2022 }
2023
2024 return 0;
2025
2026regulator_hpm:
2027
Amy Malochec331f842012-01-24 10:33:47 -08002028 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002029 if (rc < 0) {
2030 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002031 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002032 goto fail_regulator_hpm;
2033 }
2034
Amy Maloche21115eb2011-11-02 09:04:37 -07002035 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002036 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002037 MXT_ACTIVE_LOAD_DIG_UA);
2038 if (rc < 0) {
2039 dev_err(&data->client->dev,
2040 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2041 goto fail_regulator_hpm;
2042 }
2043 }
2044
Jing Linbace50b2011-10-18 22:55:47 -07002045 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002046 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002047 if (rc < 0) {
2048 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002049 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002050 goto fail_regulator_hpm;
2051 }
2052 }
2053
2054 return 0;
2055
2056fail_regulator_lpm:
Amy Malochec331f842012-01-24 10:33:47 -08002057 reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002058 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002059 reg_set_optimum_mode_check(data->vcc_dig,
2060 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002061 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002062 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002063
2064 return rc;
2065
2066fail_regulator_hpm:
Amy Malochec331f842012-01-24 10:33:47 -08002067 reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002068 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002069 reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002070 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002071 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002072
2073 return rc;
2074}
2075
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302076static int mxt_suspend(struct device *dev)
2077{
2078 struct i2c_client *client = to_i2c_client(dev);
2079 struct mxt_data *data = i2c_get_clientdata(client);
2080 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002081 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302082
2083 mutex_lock(&input_dev->mutex);
2084
Amy Maloche52262212011-09-15 16:46:57 -07002085 if (input_dev->users) {
2086 error = mxt_stop(data);
2087 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002088 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07002089 mutex_unlock(&input_dev->mutex);
2090 return error;
2091 }
2092
2093 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302094
2095 mutex_unlock(&input_dev->mutex);
2096
Jing Linbace50b2011-10-18 22:55:47 -07002097 /* put regulators in low power mode */
2098 error = mxt_regulator_lpm(data, true);
2099 if (error < 0) {
2100 dev_err(dev, "failed to enter low power mode\n");
2101 return error;
2102 }
2103
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302104 return 0;
2105}
2106
2107static int mxt_resume(struct device *dev)
2108{
2109 struct i2c_client *client = to_i2c_client(dev);
2110 struct mxt_data *data = i2c_get_clientdata(client);
2111 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002112 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302113
Jing Linbace50b2011-10-18 22:55:47 -07002114 /* put regulators in high power mode */
2115 error = mxt_regulator_lpm(data, false);
2116 if (error < 0) {
2117 dev_err(dev, "failed to enter high power mode\n");
2118 return error;
2119 }
2120
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302121 mutex_lock(&input_dev->mutex);
2122
Amy Maloche52262212011-09-15 16:46:57 -07002123 if (input_dev->users) {
2124 error = mxt_start(data);
2125 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002126 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07002127 mutex_unlock(&input_dev->mutex);
2128 return error;
2129 }
2130 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302131
2132 mutex_unlock(&input_dev->mutex);
2133
2134 return 0;
2135}
2136
2137#if defined(CONFIG_HAS_EARLYSUSPEND)
2138static void mxt_early_suspend(struct early_suspend *h)
2139{
2140 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2141
2142 mxt_suspend(&data->client->dev);
2143}
2144
2145static void mxt_late_resume(struct early_suspend *h)
2146{
2147 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2148
2149 mxt_resume(&data->client->dev);
2150}
2151#endif
2152
2153static const struct dev_pm_ops mxt_pm_ops = {
2154#ifndef CONFIG_HAS_EARLYSUSPEND
2155 .suspend = mxt_suspend,
2156 .resume = mxt_resume,
2157#endif
2158};
2159#endif
2160
Jing Lin6cfc00e2011-11-02 15:15:30 -07002161static int mxt_debugfs_object_show(struct seq_file *m, void *v)
2162{
2163 struct mxt_data *data = m->private;
2164 struct mxt_object *object;
2165 struct device *dev = &data->client->dev;
2166 int i, j, k;
2167 int error;
2168 int obj_size;
2169 u8 val;
2170
2171 for (i = 0; i < data->info.object_num; i++) {
2172 object = data->object_table + i;
2173 obj_size = object->size + 1;
2174
2175 seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
2176
2177 for (j = 0; j < object->instances + 1; j++) {
2178 seq_printf(m, "[Instance %d]\n", j);
2179
2180 for (k = 0; k < obj_size; k++) {
2181 error = mxt_read_object(data, object->type,
2182 j * obj_size + k, &val);
2183 if (error) {
2184 dev_err(dev,
2185 "Failed to read object %d "
2186 "instance %d at offset %d\n",
2187 object->type, j, k);
2188 return error;
2189 }
2190
2191 seq_printf(m, "Byte %d: 0x%02x (%d)\n",
2192 k, val, val);
2193 }
2194 }
2195 }
2196
2197 return 0;
2198}
2199
2200static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
2201{
2202 return single_open(file, mxt_debugfs_object_show, inode->i_private);
2203}
2204
2205static const struct file_operations mxt_object_fops = {
2206 .owner = THIS_MODULE,
2207 .open = mxt_debugfs_object_open,
2208 .read = seq_read,
2209 .release = single_release,
2210};
2211
Stephen Boyd0d578692012-04-25 11:49:18 -07002212static void __devinit mxt_debugfs_init(struct mxt_data *data)
Jing Lin6cfc00e2011-11-02 15:15:30 -07002213{
2214 debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
2215 if (IS_ERR_OR_NULL(debug_base))
2216 pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
2217 if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
2218 0444,
2219 debug_base,
2220 data,
2221 &mxt_object_fops))) {
2222 pr_err("atmel_mxt_ts: Failed to create object file\n");
2223 debugfs_remove_recursive(debug_base);
2224 }
2225}
2226
Iiro Valkonen7686b102011-02-02 23:21:58 -08002227static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002228 const struct i2c_device_id *id)
2229{
Iiro Valkonen919ed892011-02-15 13:36:52 -08002230 const struct mxt_platform_data *pdata = client->dev.platform_data;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002231 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002232 struct input_dev *input_dev;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002233 int error, i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002234
Iiro Valkonen919ed892011-02-15 13:36:52 -08002235 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002236 return -EINVAL;
2237
Iiro Valkonen7686b102011-02-02 23:21:58 -08002238 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002239 input_dev = input_allocate_device();
2240 if (!data || !input_dev) {
2241 dev_err(&client->dev, "Failed to allocate memory\n");
2242 error = -ENOMEM;
2243 goto err_free_mem;
2244 }
2245
Nick Dyer0a4016c2012-01-18 15:17:59 +05302246 data->state = INIT;
Amy Maloche83c385a2012-02-01 10:32:03 +05302247 input_dev->name = "atmel_mxt_ts";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002248 input_dev->id.bustype = BUS_I2C;
2249 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002250 input_dev->open = mxt_input_open;
2251 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002252
Joonyoung Shim910d8052011-04-12 23:14:38 -07002253 data->client = client;
2254 data->input_dev = input_dev;
2255 data->pdata = pdata;
2256 data->irq = client->irq;
2257
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002258 __set_bit(EV_ABS, input_dev->evbit);
2259 __set_bit(EV_KEY, input_dev->evbit);
2260 __set_bit(BTN_TOUCH, input_dev->keybit);
2261
2262 /* For single touch */
2263 input_set_abs_params(input_dev, ABS_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002264 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002265 input_set_abs_params(input_dev, ABS_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002266 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07002267 input_set_abs_params(input_dev, ABS_PRESSURE,
2268 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002269
2270 /* For multi touch */
Joonyoung Shimcd473222012-02-14 18:32:48 -08002271 input_mt_init_slots(input_dev, MXT_MAX_FINGER);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002272 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08002273 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002274 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002275 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002276 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002277 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07002278 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2279 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002280
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002281 /* set key array supported keys */
2282 if (pdata->key_codes) {
2283 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
2284 if (pdata->key_codes[i])
2285 input_set_capability(input_dev, EV_KEY,
2286 pdata->key_codes[i]);
2287 }
2288 }
2289
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002290 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002291 i2c_set_clientdata(client, data);
2292
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302293 if (pdata->init_hw)
2294 error = pdata->init_hw(true);
2295 else
2296 error = mxt_regulator_configure(data, true);
2297 if (error) {
2298 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07002299 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302300 }
2301
2302 if (pdata->power_on)
2303 error = pdata->power_on(true);
2304 else
2305 error = mxt_power_on(data, true);
2306 if (error) {
2307 dev_err(&client->dev, "Failed to power on hardware\n");
2308 goto err_regulator_on;
2309 }
2310
Amy Maloche08266db2011-11-04 11:07:16 -07002311 if (gpio_is_valid(pdata->irq_gpio)) {
2312 /* configure touchscreen irq gpio */
2313 error = gpio_request(pdata->irq_gpio,
2314 "mxt_irq_gpio");
2315 if (error) {
2316 pr_err("%s: unable to request gpio [%d]\n", __func__,
2317 pdata->irq_gpio);
2318 goto err_power_on;
2319 }
2320 error = gpio_direction_input(pdata->irq_gpio);
2321 if (error) {
2322 pr_err("%s: unable to set_direction for gpio [%d]\n",
2323 __func__, pdata->irq_gpio);
2324 goto err_irq_gpio_req;
2325 }
2326 }
2327
2328 if (gpio_is_valid(pdata->reset_gpio)) {
2329 /* configure touchscreen reset out gpio */
2330 error = gpio_request(pdata->reset_gpio,
2331 "mxt_reset_gpio");
2332 if (error) {
2333 pr_err("%s: unable to request reset gpio %d\n",
2334 __func__, pdata->reset_gpio);
2335 goto err_irq_gpio_req;
2336 }
2337
2338 error = gpio_direction_output(
2339 pdata->reset_gpio, 1);
2340 if (error) {
2341 pr_err("%s: unable to set direction for gpio %d\n",
2342 __func__, pdata->reset_gpio);
2343 goto err_reset_gpio_req;
2344 }
2345 }
2346
2347 mxt_reset_delay(data);
2348
Iiro Valkonen7686b102011-02-02 23:21:58 -08002349 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002350 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07002351 goto err_reset_gpio_req;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002352
Iiro Valkonen7686b102011-02-02 23:21:58 -08002353 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08002354 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002355 if (error) {
2356 dev_err(&client->dev, "Failed to register interrupt\n");
Jing Lin32c72532011-11-03 12:02:33 -07002357 goto err_free_object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002358 }
2359
Nick Dyer0a4016c2012-01-18 15:17:59 +05302360 if (data->state == APPMODE) {
2361 error = mxt_make_highchg(data);
2362 if (error) {
2363 dev_err(&client->dev, "Failed to make high CHG\n");
2364 goto err_free_irq;
2365 }
2366 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07002367
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002368 error = input_register_device(input_dev);
2369 if (error)
2370 goto err_free_irq;
2371
Iiro Valkonen7686b102011-02-02 23:21:58 -08002372 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002373 if (error)
2374 goto err_unregister_device;
2375
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302376#if defined(CONFIG_HAS_EARLYSUSPEND)
2377 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
2378 MXT_SUSPEND_LEVEL;
2379 data->early_suspend.suspend = mxt_early_suspend;
2380 data->early_suspend.resume = mxt_late_resume;
2381 register_early_suspend(&data->early_suspend);
2382#endif
2383
Jing Lin6cfc00e2011-11-02 15:15:30 -07002384 mxt_debugfs_init(data);
2385
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002386 return 0;
2387
2388err_unregister_device:
2389 input_unregister_device(input_dev);
2390 input_dev = NULL;
2391err_free_irq:
2392 free_irq(client->irq, data);
Jing Lin32c72532011-11-03 12:02:33 -07002393err_free_object:
2394 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07002395err_reset_gpio_req:
2396 if (gpio_is_valid(pdata->reset_gpio))
2397 gpio_free(pdata->reset_gpio);
2398err_irq_gpio_req:
2399 if (gpio_is_valid(pdata->irq_gpio))
2400 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302401err_power_on:
2402 if (pdata->power_on)
2403 pdata->power_on(false);
2404 else
2405 mxt_power_on(data, false);
2406err_regulator_on:
2407 if (pdata->init_hw)
2408 pdata->init_hw(false);
2409 else
2410 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002411err_free_mem:
2412 input_free_device(input_dev);
2413 kfree(data);
2414 return error;
2415}
2416
Iiro Valkonen7686b102011-02-02 23:21:58 -08002417static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002418{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002419 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002420
Iiro Valkonen7686b102011-02-02 23:21:58 -08002421 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002422 free_irq(data->irq, data);
2423 input_unregister_device(data->input_dev);
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302424#if defined(CONFIG_HAS_EARLYSUSPEND)
2425 unregister_early_suspend(&data->early_suspend);
2426#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302427
2428 if (data->pdata->power_on)
2429 data->pdata->power_on(false);
2430 else
2431 mxt_power_on(data, false);
2432
2433 if (data->pdata->init_hw)
2434 data->pdata->init_hw(false);
2435 else
2436 mxt_regulator_configure(data, false);
2437
Mohan Pallakabfe8f302012-01-02 18:32:08 +08002438 if (gpio_is_valid(data->pdata->reset_gpio))
2439 gpio_free(data->pdata->reset_gpio);
2440
2441 if (gpio_is_valid(data->pdata->irq_gpio))
2442 gpio_free(data->pdata->irq_gpio);
2443
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002444 kfree(data->object_table);
2445 kfree(data);
2446
Jing Lin6cfc00e2011-11-02 15:15:30 -07002447 debugfs_remove_recursive(debug_base);
2448
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002449 return 0;
2450}
2451
Iiro Valkonen7686b102011-02-02 23:21:58 -08002452static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002453 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002454 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08002455 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002456 { }
2457};
Iiro Valkonen7686b102011-02-02 23:21:58 -08002458MODULE_DEVICE_TABLE(i2c, mxt_id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002459
Iiro Valkonen7686b102011-02-02 23:21:58 -08002460static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002461 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08002462 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002463 .owner = THIS_MODULE,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002464#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08002465 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002466#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002467 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002468 .probe = mxt_probe,
2469 .remove = __devexit_p(mxt_remove),
2470 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002471};
2472
Iiro Valkonen7686b102011-02-02 23:21:58 -08002473static int __init mxt_init(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002474{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002475 return i2c_add_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002476}
2477
Iiro Valkonen7686b102011-02-02 23:21:58 -08002478static void __exit mxt_exit(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002479{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002480 i2c_del_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002481}
2482
Iiro Valkonen7686b102011-02-02 23:21:58 -08002483module_init(mxt_init);
2484module_exit(mxt_exit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002485
2486/* Module information */
2487MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08002488MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002489MODULE_LICENSE("GPL");