blob: 4049614193b49c2bd567234b3a025d2a6c4b06af [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;
Amy Maloche52262212011-09-15 16:46:57 -0700340 u8 t9_ctrl;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800341 u32 keyarray_old;
342 u32 keyarray_new;
343 u8 t9_max_reportid;
344 u8 t9_min_reportid;
345 u8 t15_max_reportid;
346 u8 t15_min_reportid;
Jing Lin8fadad72012-02-24 10:10:50 -0800347 u8 cfg_version[MXT_CFG_VERSION_LEN];
Jing Lindc4413c2012-01-16 15:22:52 -0800348 int cfg_version_idx;
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 */
1055 if (object->type == MXT_SPT_USERDATA_T38)
1056 found_t38 = true;
1057 if (!found_t38 && mxt_object_writable(object->type))
1058 data->cfg_version_idx += object->size + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001059 }
1060
1061 return 0;
1062}
1063
Jing Lin8fadad72012-02-24 10:10:50 -08001064static int compare_versions(const u8 *v1, const u8 *v2)
1065{
1066 int i;
1067
1068 if (!v1 || !v2)
1069 return -EINVAL;
1070
1071 /* The major version number stays the same across different versions for
1072 * a particular controller on a target. The minor and sub-minor version
1073 * numbers indicate which version is newer.
1074 */
1075 if (v1[0] != v2[0])
1076 return -EINVAL;
1077
1078 for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
1079 if (v1[i] > v2[i])
1080 return MXT_CFG_VERSION_LESS; /* v2 is older */
1081
1082 if (v1[i] < v2[i])
1083 return MXT_CFG_VERSION_GREATER; /* v2 is newer */
1084 }
1085
1086 return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
1087}
1088
1089static void mxt_check_config_version(struct mxt_data *data,
1090 const struct mxt_config_info *cfg_info,
1091 bool match_major,
1092 const u8 **cfg_version_found,
1093 bool *found_cfg_major_match)
1094{
1095 const u8 *cfg_version;
1096 int result = -EINVAL;
1097
1098 cfg_version = cfg_info->config + data->cfg_version_idx;
1099
1100 if (*cfg_version_found)
1101 result = compare_versions(*cfg_version_found, cfg_version);
1102
1103 if (match_major) {
1104 if (result >= MXT_CFG_VERSION_EQUAL)
1105 *found_cfg_major_match = true;
1106
1107 if (result == MXT_CFG_VERSION_EQUAL ||
1108 result == MXT_CFG_VERSION_GREATER) {
1109 data->config_info = cfg_info;
1110 data->fw_name = cfg_info->fw_name;
1111 *cfg_version_found = cfg_version;
1112 }
1113
1114 if (result == MXT_CFG_VERSION_GREATER)
1115 data->update_cfg = true;
1116 } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
1117 data->config_info = cfg_info;
1118 data->fw_name = cfg_info->fw_name;
1119 data->update_cfg = true;
1120 *cfg_version_found = cfg_version;
1121 }
1122}
1123
1124/* If the controller's config version has a non-zero major number, call this
1125 * function with match_major = true to look for the latest config present in
1126 * the pdata based on matching family id, variant id, f/w version, build, and
1127 * config major number. If the controller is programmed with wrong config data
1128 * previously, call this function with match_major = false to look for latest
1129 * config based on based on matching family id, variant id, f/w version and
1130 * build only.
1131 */
1132static int mxt_search_config_array(struct mxt_data *data, bool match_major)
Jing Lindc4413c2012-01-16 15:22:52 -08001133{
1134
1135 const struct mxt_platform_data *pdata = data->pdata;
1136 const struct mxt_config_info *cfg_info;
Jing Lin8fadad72012-02-24 10:10:50 -08001137 const struct mxt_info *info = &data->info;
1138 const u8 *cfg_version_found;
1139 bool found_cfg_major_match = false;
Jing Lindc4413c2012-01-16 15:22:52 -08001140 int i;
Jing Lin8fadad72012-02-24 10:10:50 -08001141
1142 cfg_version_found = match_major ? data->cfg_version : NULL;
Jing Lindc4413c2012-01-16 15:22:52 -08001143
1144 for (i = 0; i < pdata->config_array_size; i++) {
1145
1146 cfg_info = &pdata->config_array[i];
1147
1148 if (!cfg_info->config || !cfg_info->config_length)
1149 continue;
1150
1151 if (info->family_id == cfg_info->family_id &&
1152 info->variant_id == cfg_info->variant_id &&
1153 info->version == cfg_info->version &&
1154 info->build == cfg_info->build) {
1155
Jing Lin8fadad72012-02-24 10:10:50 -08001156 mxt_check_config_version(data, cfg_info, match_major,
1157 &cfg_version_found, &found_cfg_major_match);
Jing Lindc4413c2012-01-16 15:22:52 -08001158 }
1159 }
1160
Jing Lin8fadad72012-02-24 10:10:50 -08001161 if (data->config_info || found_cfg_major_match)
1162 return 0;
1163
1164 data->config_info = NULL;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001165 data->fw_name = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001166
Jing Lindc4413c2012-01-16 15:22:52 -08001167 return -EINVAL;
1168}
1169
1170static int mxt_get_config(struct mxt_data *data)
1171{
1172 const struct mxt_platform_data *pdata = data->pdata;
1173 struct device *dev = &data->client->dev;
1174 struct mxt_object *object;
1175 int error;
1176
1177 if (!pdata->config_array || !pdata->config_array_size) {
1178 dev_dbg(dev, "No cfg data provided by platform data\n");
1179 return 0;
1180 }
1181
1182 /* Get current config version */
1183 object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
1184 if (!object) {
1185 dev_err(dev, "Unable to obtain USERDATA object\n");
1186 return -EINVAL;
1187 }
1188
Jing Lin8fadad72012-02-24 10:10:50 -08001189 error = __mxt_read_reg(data->client, object->start_address,
1190 sizeof(data->cfg_version), data->cfg_version);
Jing Lindc4413c2012-01-16 15:22:52 -08001191 if (error) {
1192 dev_err(dev, "Unable to read config version\n");
1193 return error;
1194 }
Jing Lin8fadad72012-02-24 10:10:50 -08001195 dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
1196 data->cfg_version[0], data->cfg_version[1],
1197 data->cfg_version[2]);
Jing Lindc4413c2012-01-16 15:22:52 -08001198
1199 /* It is possible that the config data on the controller is not
1200 * versioned and the version number returns 0. In this case,
1201 * find a match without the config version checking.
1202 */
1203 error = mxt_search_config_array(data,
Jing Lin8fadad72012-02-24 10:10:50 -08001204 data->cfg_version[0] != 0 ? true : false);
1205 if (error) {
1206 /* If a match wasn't found for a non-zero config version,
1207 * it means the controller has the wrong config data. Search
1208 * for a best match based on controller and firmware version,
1209 * but not config version.
1210 */
1211 if (data->cfg_version[0])
1212 error = mxt_search_config_array(data, false);
1213 if (error) {
1214 dev_err(dev,
1215 "Unable to find matching config in pdata\n");
1216 return error;
1217 }
1218 }
Jing Lindc4413c2012-01-16 15:22:52 -08001219
1220 return 0;
1221}
Jing Lin8fadad72012-02-24 10:10:50 -08001222
Amy Maloche7e447432011-09-14 11:36:30 -07001223static void mxt_reset_delay(struct mxt_data *data)
1224{
1225 struct mxt_info *info = &data->info;
1226
1227 switch (info->family_id) {
1228 case MXT224_ID:
1229 msleep(MXT224_RESET_TIME);
1230 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -07001231 case MXT224E_ID:
1232 msleep(MXT224E_RESET_TIME);
1233 break;
Amy Maloche7e447432011-09-14 11:36:30 -07001234 case MXT1386_ID:
1235 msleep(MXT1386_RESET_TIME);
1236 break;
1237 default:
1238 msleep(MXT_RESET_TIME);
1239 }
1240}
1241
Jing Lin8fadad72012-02-24 10:10:50 -08001242static int mxt_backup_nv(struct mxt_data *data)
1243{
1244 int error;
1245 u8 command_register;
1246 int timeout_counter = 0;
1247
1248 /* Backup to memory */
1249 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1250 MXT_COMMAND_BACKUPNV,
1251 MXT_BACKUP_VALUE);
1252 msleep(MXT_BACKUP_TIME);
1253
1254 do {
1255 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
1256 MXT_COMMAND_BACKUPNV,
1257 &command_register);
1258 if (error)
1259 return error;
1260
1261 usleep_range(1000, 2000);
1262
1263 } while ((command_register != 0) && (++timeout_counter <= 100));
1264
1265 if (timeout_counter > 100) {
1266 dev_err(&data->client->dev, "No response after backup!\n");
1267 return -EIO;
1268 }
1269
1270 /* Soft reset */
1271 mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
1272
1273 mxt_reset_delay(data);
1274
1275 return 0;
1276}
1277
Jing Lin412aedc2012-02-28 13:57:19 -08001278static int mxt_save_objects(struct mxt_data *data)
1279{
1280 struct i2c_client *client = data->client;
1281 struct mxt_object *t7_object;
1282 struct mxt_object *t9_object;
1283 struct mxt_object *t15_object;
1284 int error;
1285
1286 /* Store T7 and T9 locally, used in suspend/resume operations */
1287 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
1288 if (!t7_object) {
1289 dev_err(&client->dev, "Failed to get T7 object\n");
1290 return -EINVAL;
1291 }
1292
1293 data->t7_start_addr = t7_object->start_address;
1294 error = __mxt_read_reg(client, data->t7_start_addr,
1295 T7_DATA_SIZE, data->t7_data);
1296 if (error < 0) {
1297 dev_err(&client->dev,
1298 "Failed to save current power state\n");
1299 return error;
1300 }
1301
1302 error = mxt_read_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
1303 &data->t9_ctrl);
1304 if (error < 0) {
1305 dev_err(&client->dev, "Failed to save current touch object\n");
1306 return error;
1307 }
1308
1309 /* Store T9, T15's min and max report ids */
1310 t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1311 if (!t9_object) {
1312 dev_err(&client->dev, "Failed to get T9 object\n");
1313 return -EINVAL;
1314 }
1315 data->t9_max_reportid = t9_object->max_reportid;
1316 data->t9_min_reportid = t9_object->max_reportid -
1317 t9_object->num_report_ids + 1;
1318
1319 if (data->pdata->key_codes) {
1320 t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
1321 if (!t15_object)
1322 dev_dbg(&client->dev, "T15 object is not available\n");
1323 else {
1324 data->t15_max_reportid = t15_object->max_reportid;
1325 data->t15_min_reportid = t15_object->max_reportid -
1326 t15_object->num_report_ids + 1;
1327 }
1328 }
1329
1330 return 0;
1331}
1332
Iiro Valkonen7686b102011-02-02 23:21:58 -08001333static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001334{
1335 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001336 struct mxt_info *info = &data->info;
Jing Lin36aee812011-10-17 17:17:28 -07001337 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001338 u8 val;
Jing Lin8fadad72012-02-24 10:10:50 -08001339 const u8 *cfg_ver;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001340
Iiro Valkonen7686b102011-02-02 23:21:58 -08001341 error = mxt_get_info(data);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301342 if (error) {
1343 /* Try bootloader mode */
1344 error = mxt_switch_to_bootloader_address(data);
1345 if (error)
1346 return error;
1347
1348 error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
1349 if (error)
1350 return error;
1351
1352 dev_err(&client->dev, "Application CRC failure\n");
1353 data->state = BOOTLOADER;
1354
1355 return 0;
1356 }
1357
1358 dev_info(&client->dev,
1359 "Family ID: %d Variant ID: %d Version: %d.%d "
1360 "Build: 0x%02X Object Num: %d\n",
1361 info->family_id, info->variant_id,
1362 info->version >> 4, info->version & 0xf,
1363 info->build, info->object_num);
1364
1365 data->state = APPMODE;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001366
1367 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001368 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001369 GFP_KERNEL);
1370 if (!data->object_table) {
1371 dev_err(&client->dev, "Failed to allocate memory\n");
1372 return -ENOMEM;
1373 }
1374
1375 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001376 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001377 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001378 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001379
Jing Lindc4413c2012-01-16 15:22:52 -08001380 /* Get config data from platform data */
1381 error = mxt_get_config(data);
1382 if (error)
1383 dev_dbg(&client->dev, "Config info not found.\n");
1384
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001385 /* Check register init values */
Jing Lin8fadad72012-02-24 10:10:50 -08001386 if (data->config_info && data->config_info->config) {
1387 if (data->update_cfg) {
1388 error = mxt_check_reg_init(data);
1389 if (error) {
1390 dev_err(&client->dev,
1391 "Failed to check reg init value\n");
1392 goto free_object_table;
1393 }
1394
1395 error = mxt_backup_nv(data);
1396 if (error) {
1397 dev_err(&client->dev, "Failed to back up NV\n");
1398 goto free_object_table;
1399 }
1400
1401 cfg_ver = data->config_info->config +
1402 data->cfg_version_idx;
1403 dev_info(&client->dev,
1404 "Config updated from %d.%d.%d to %d.%d.%d\n",
1405 data->cfg_version[0], data->cfg_version[1],
1406 data->cfg_version[2],
1407 cfg_ver[0], cfg_ver[1], cfg_ver[2]);
1408
1409 memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
1410 }
1411 } else {
1412 dev_info(&client->dev,
1413 "No cfg data defined, skipping check reg init\n");
1414 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001415
Jing Lin412aedc2012-02-28 13:57:19 -08001416 error = mxt_save_objects(data);
1417 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001418 goto free_object_table;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001419
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001420 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001421 error = mxt_read_reg(client, MXT_MATRIX_X_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_xsize = val;
1425
Iiro Valkonen7686b102011-02-02 23:21:58 -08001426 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001427 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001428 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001429 info->matrix_ysize = val;
1430
1431 dev_info(&client->dev,
Nick Dyer0a4016c2012-01-18 15:17:59 +05301432 "Matrix X Size: %d Matrix Y Size: %d\n",
1433 info->matrix_xsize, info->matrix_ysize);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001434
1435 return 0;
Jing Lin32c72532011-11-03 12:02:33 -07001436
1437free_object_table:
1438 kfree(data->object_table);
1439 return error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001440}
1441
Iiro Valkonen7686b102011-02-02 23:21:58 -08001442static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001443 struct device_attribute *attr, char *buf)
1444{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001445 struct mxt_data *data = dev_get_drvdata(dev);
1446 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001447 int count = 0;
1448 int i, j;
1449 int error;
1450 u8 val;
1451
1452 for (i = 0; i < data->info.object_num; i++) {
1453 object = data->object_table + i;
1454
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001455 count += snprintf(buf + count, PAGE_SIZE - count,
1456 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001457 i + 1, object->type);
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001458 if (count >= PAGE_SIZE)
1459 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001460
Iiro Valkonen7686b102011-02-02 23:21:58 -08001461 if (!mxt_object_readable(object->type)) {
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001462 count += snprintf(buf + count, PAGE_SIZE - count,
1463 "\n");
1464 if (count >= PAGE_SIZE)
1465 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001466 continue;
1467 }
1468
1469 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001470 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001471 object->type, j, &val);
1472 if (error)
1473 return error;
1474
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001475 count += snprintf(buf + count, PAGE_SIZE - count,
1476 "\t[%2d]: %02x (%d)\n", j, val, val);
1477 if (count >= PAGE_SIZE)
1478 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001479 }
1480
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001481 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1482 if (count >= PAGE_SIZE)
1483 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001484 }
1485
1486 return count;
1487}
1488
Jing Lincc974cb2012-02-01 23:13:14 -08001489static int strtobyte(const char *data, u8 *value)
1490{
1491 char str[3];
1492
1493 str[0] = data[0];
1494 str[1] = data[1];
1495 str[2] = '\0';
1496
1497 return kstrtou8(str, 16, value);
1498}
1499
Iiro Valkonen7686b102011-02-02 23:21:58 -08001500static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001501{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001502 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001503 struct i2c_client *client = data->client;
1504 const struct firmware *fw = NULL;
1505 unsigned int frame_size;
Nick Dyer0a4016c2012-01-18 15:17:59 +05301506 unsigned int retry = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001507 unsigned int pos = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001508 int ret, i, max_frame_size;
1509 u8 *frame;
1510
1511 switch (data->info.family_id) {
1512 case MXT224_ID:
1513 max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
1514 break;
1515 case MXT1386_ID:
1516 max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
1517 break;
1518 default:
1519 return -EINVAL;
1520 }
1521
1522 frame = kmalloc(max_frame_size, GFP_KERNEL);
1523 if (!frame) {
1524 dev_err(dev, "Unable to allocate memory for frame data\n");
1525 return -ENOMEM;
1526 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001527
1528 ret = request_firmware(&fw, fn, dev);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301529 if (ret < 0) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001530 dev_err(dev, "Unable to open firmware %s\n", fn);
Jing Lincc974cb2012-02-01 23:13:14 -08001531 goto free_frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001532 }
1533
Nick Dyer0a4016c2012-01-18 15:17:59 +05301534 if (data->state != BOOTLOADER) {
1535 /* Change to the bootloader mode */
1536 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1537 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1538 mxt_reset_delay(data);
Amy Maloche7e447432011-09-14 11:36:30 -07001539
Nick Dyer0a4016c2012-01-18 15:17:59 +05301540 ret = mxt_switch_to_bootloader_address(data);
1541 if (ret)
1542 goto release_firmware;
1543 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001544
Iiro Valkonen7686b102011-02-02 23:21:58 -08001545 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301546 if (ret) {
1547 /* Bootloader may still be unlocked from previous update
1548 * attempt */
1549 ret = mxt_check_bootloader(client,
1550 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001551
Nick Dyer0a4016c2012-01-18 15:17:59 +05301552 if (ret)
1553 goto return_to_app_mode;
1554 } else {
1555 dev_info(dev, "Unlocking bootloader\n");
1556 /* Unlock bootloader */
1557 mxt_unlock_bootloader(client);
1558 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001559
1560 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001561 ret = mxt_check_bootloader(client,
1562 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001563 if (ret)
Nick Dyer0a4016c2012-01-18 15:17:59 +05301564 goto release_firmware;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001565
Jing Lincc974cb2012-02-01 23:13:14 -08001566 /* Get frame length MSB */
1567 ret = strtobyte(fw->data + pos, frame);
1568 if (ret)
1569 goto release_firmware;
1570
1571 /* Get frame length LSB */
1572 ret = strtobyte(fw->data + pos + 2, frame + 1);
1573 if (ret)
1574 goto release_firmware;
1575
1576 frame_size = ((*frame << 8) | *(frame + 1));
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001577
1578 /* We should add 2 at frame size as the the firmware data is not
1579 * included the CRC bytes.
1580 */
1581 frame_size += 2;
1582
Jing Lincc974cb2012-02-01 23:13:14 -08001583 if (frame_size > max_frame_size) {
1584 dev_err(dev, "Invalid frame size - %d\n", frame_size);
1585 ret = -EINVAL;
1586 goto release_firmware;
1587 }
1588
1589 /* Convert frame data and CRC from hex to binary */
1590 for (i = 2; i < frame_size; i++) {
1591 ret = strtobyte(fw->data + pos + i * 2, frame + i);
1592 if (ret)
1593 goto release_firmware;
1594 }
1595
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001596 /* Write one frame to device */
Jing Lincc974cb2012-02-01 23:13:14 -08001597 mxt_fw_write(client, frame, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001598
Iiro Valkonen7686b102011-02-02 23:21:58 -08001599 ret = mxt_check_bootloader(client,
1600 MXT_FRAME_CRC_PASS);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301601 if (ret) {
1602 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001603
Nick Dyer0a4016c2012-01-18 15:17:59 +05301604 /* Back off by 20ms per retry */
1605 msleep(retry * 20);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001606
Nick Dyer0a4016c2012-01-18 15:17:59 +05301607 if (retry > 20)
1608 goto release_firmware;
1609 } else {
1610 retry = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001611 pos += frame_size * 2;
1612 dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301613 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001614 }
1615
Nick Dyer0a4016c2012-01-18 15:17:59 +05301616return_to_app_mode:
1617 mxt_switch_to_appmode_address(data);
1618release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001619 release_firmware(fw);
Jing Lincc974cb2012-02-01 23:13:14 -08001620free_frame:
1621 kfree(frame);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001622
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001623 return ret;
1624}
1625
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001626static const char *
1627mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
1628{
1629 const struct mxt_platform_data *pdata = data->pdata;
1630 const struct mxt_config_info *cfg_info;
1631 const char *fw_name = NULL;
1632 int i;
1633
1634 for (i = 0; i < pdata->config_array_size; i++) {
1635 cfg_info = &pdata->config_array[i];
1636 if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
1637 data->config_info = cfg_info;
1638 data->info.family_id = cfg_info->family_id;
1639 fw_name = cfg_info->fw_name;
1640 }
1641 }
1642
1643 return fw_name;
1644}
1645
Iiro Valkonen7686b102011-02-02 23:21:58 -08001646static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001647 struct device_attribute *attr,
1648 const char *buf, size_t count)
1649{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001650 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001651 int error;
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001652 const char *fw_name;
1653 u8 bootldr_id;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001654
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001655 /* If fw_name is set, then the existing firmware has an upgrade */
1656 if (!data->fw_name) {
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001657 /*
1658 * If the device boots up in the bootloader mode, check if
1659 * there is a firmware to upgrade.
1660 */
1661 if (data->state == BOOTLOADER) {
1662 bootldr_id = mxt_get_bootloader_id(data->client);
1663 if (bootldr_id <= 0) {
1664 dev_err(dev,
1665 "Unable to retrieve bootloader id\n");
1666 return -EINVAL;
1667 }
1668 fw_name = mxt_search_fw_name(data, bootldr_id);
1669 if (fw_name == NULL) {
1670 dev_err(dev,
1671 "Unable to find fw from bootloader id\n");
1672 return -EINVAL;
1673 }
1674 } else {
1675 /* In APPMODE, if the f/w name does not exist, quit */
1676 dev_err(dev,
1677 "Firmware name not specified in platform data\n");
1678 return -EINVAL;
1679 }
1680 } else {
1681 fw_name = data->fw_name;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001682 }
1683
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001684 dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001685
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001686 disable_irq(data->irq);
1687
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001688 error = mxt_load_fw(dev, fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001689 if (error) {
1690 dev_err(dev, "The firmware update failed(%d)\n", error);
1691 count = error;
1692 } else {
Nick Dyer0a4016c2012-01-18 15:17:59 +05301693 dev_info(dev, "The firmware update succeeded\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001694
1695 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001696 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001697
Nick Dyer0a4016c2012-01-18 15:17:59 +05301698 data->state = INIT;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001699 kfree(data->object_table);
1700 data->object_table = NULL;
Jing Lincc974cb2012-02-01 23:13:14 -08001701 data->cfg_version_idx = 0;
Jing Lin8fadad72012-02-24 10:10:50 -08001702 data->update_cfg = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001703
Iiro Valkonen7686b102011-02-02 23:21:58 -08001704 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001705 }
1706
Nick Dyer0a4016c2012-01-18 15:17:59 +05301707 if (data->state == APPMODE) {
1708 enable_irq(data->irq);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001709
Nick Dyer0a4016c2012-01-18 15:17:59 +05301710 error = mxt_make_highchg(data);
1711 if (error)
1712 return error;
1713 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07001714
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001715 return count;
1716}
1717
Iiro Valkonen7686b102011-02-02 23:21:58 -08001718static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
1719static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001720
Iiro Valkonen7686b102011-02-02 23:21:58 -08001721static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001722 &dev_attr_object.attr,
1723 &dev_attr_update_fw.attr,
1724 NULL
1725};
1726
Iiro Valkonen7686b102011-02-02 23:21:58 -08001727static const struct attribute_group mxt_attr_group = {
1728 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001729};
1730
Amy Maloche52262212011-09-15 16:46:57 -07001731static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001732{
Jing Lin36aee812011-10-17 17:17:28 -07001733 int error;
1734
Amy Maloche52262212011-09-15 16:46:57 -07001735 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07001736 error = __mxt_write_reg(data->client, data->t7_start_addr,
1737 T7_DATA_SIZE, data->t7_data);
1738 if (error < 0) {
1739 dev_err(&data->client->dev,
1740 "failed to restore old power state\n");
1741 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001742 }
Jing Lin36aee812011-10-17 17:17:28 -07001743
Amy Maloche52262212011-09-15 16:46:57 -07001744 error = mxt_write_object(data,
Iiro Valkonene8645592011-11-18 12:56:19 -08001745 MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, data->t9_ctrl);
Amy Maloche52262212011-09-15 16:46:57 -07001746 if (error < 0) {
1747 dev_err(&data->client->dev, "failed to restore touch\n");
1748 return error;
1749 }
1750
1751 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001752}
1753
Amy Maloche52262212011-09-15 16:46:57 -07001754static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001755{
Jing Lin36aee812011-10-17 17:17:28 -07001756 int error;
1757 u8 t7_data[T7_DATA_SIZE] = {0};
1758
1759 /* disable touch and configure deep sleep mode */
Iiro Valkonene8645592011-11-18 12:56:19 -08001760 error = mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
Jing Lin36aee812011-10-17 17:17:28 -07001761 if (error < 0) {
1762 dev_err(&data->client->dev, "failed to disable touch\n");
1763 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001764 }
1765
Jing Lin36aee812011-10-17 17:17:28 -07001766 error = __mxt_write_reg(data->client, data->t7_start_addr,
1767 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07001768 if (error < 0) {
1769 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07001770 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07001771 return error;
1772 }
1773
1774 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001775}
1776
Iiro Valkonen7686b102011-02-02 23:21:58 -08001777static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001778{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001779 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001780 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001781
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001782 if (data->state == APPMODE) {
1783 error = mxt_start(data);
1784 if (error < 0) {
1785 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
1786 return error;
1787 }
Amy Maloche52262212011-09-15 16:46:57 -07001788 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001789
1790 return 0;
1791}
1792
Iiro Valkonen7686b102011-02-02 23:21:58 -08001793static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001794{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001795 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001796 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001797
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001798 if (data->state == APPMODE) {
1799 error = mxt_stop(data);
1800 if (error < 0)
1801 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
1802 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001803}
1804
Amy Malochec331f842012-01-24 10:33:47 -08001805static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
1806{
1807 return (regulator_count_voltages(reg) > 0) ?
1808 regulator_set_optimum_mode(reg, load_uA) : 0;
1809}
1810
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301811static int mxt_power_on(struct mxt_data *data, bool on)
1812{
1813 int rc;
1814
1815 if (on == false)
1816 goto power_off;
1817
Amy Malochec331f842012-01-24 10:33:47 -08001818 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301819 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001820 dev_err(&data->client->dev,
1821 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301822 return rc;
1823 }
1824
Amy Maloche21115eb2011-11-02 09:04:37 -07001825 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301826 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001827 dev_err(&data->client->dev,
1828 "Regulator vcc_ana enable failed rc=%d\n", rc);
1829 goto error_reg_en_vcc_ana;
1830 }
1831
1832 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001833 rc = reg_set_optimum_mode_check(data->vcc_dig,
1834 MXT_ACTIVE_LOAD_DIG_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07001835 if (rc < 0) {
1836 dev_err(&data->client->dev,
1837 "Regulator vcc_dig set_opt failed rc=%d\n",
1838 rc);
1839 goto error_reg_opt_vcc_dig;
1840 }
1841
1842 rc = regulator_enable(data->vcc_dig);
1843 if (rc) {
1844 dev_err(&data->client->dev,
1845 "Regulator vcc_dig enable failed rc=%d\n", rc);
1846 goto error_reg_en_vcc_dig;
1847 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301848 }
1849
1850 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001851 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301852 if (rc < 0) {
1853 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001854 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301855 goto error_reg_opt_i2c;
1856 }
1857
1858 rc = regulator_enable(data->vcc_i2c);
1859 if (rc) {
1860 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001861 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301862 goto error_reg_en_vcc_i2c;
1863 }
1864 }
1865
Amy Malochef0d7b8d2011-10-17 12:10:51 -07001866 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301867
1868 return 0;
1869
1870error_reg_en_vcc_i2c:
1871 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08001872 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301873error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001874 if (data->pdata->digital_pwr_regulator)
1875 regulator_disable(data->vcc_dig);
1876error_reg_en_vcc_dig:
1877 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08001878 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001879error_reg_opt_vcc_dig:
1880 regulator_disable(data->vcc_ana);
1881error_reg_en_vcc_ana:
Amy Malochec331f842012-01-24 10:33:47 -08001882 reg_set_optimum_mode_check(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301883 return rc;
1884
1885power_off:
Amy Malochec331f842012-01-24 10:33:47 -08001886 reg_set_optimum_mode_check(data->vcc_ana, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001887 regulator_disable(data->vcc_ana);
1888 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001889 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001890 regulator_disable(data->vcc_dig);
1891 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301892 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001893 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301894 regulator_disable(data->vcc_i2c);
1895 }
1896 msleep(50);
1897 return 0;
1898}
1899
1900static int mxt_regulator_configure(struct mxt_data *data, bool on)
1901{
1902 int rc;
1903
1904 if (on == false)
1905 goto hw_shutdown;
1906
Amy Maloche21115eb2011-11-02 09:04:37 -07001907 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
1908 if (IS_ERR(data->vcc_ana)) {
1909 rc = PTR_ERR(data->vcc_ana);
1910 dev_err(&data->client->dev,
1911 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301912 return rc;
1913 }
1914
Amy Maloche21115eb2011-11-02 09:04:37 -07001915 if (regulator_count_voltages(data->vcc_ana) > 0) {
1916 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301917 MXT_VTG_MAX_UV);
1918 if (rc) {
1919 dev_err(&data->client->dev,
1920 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07001921 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301922 }
1923 }
Amy Maloche21115eb2011-11-02 09:04:37 -07001924 if (data->pdata->digital_pwr_regulator) {
1925 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
1926 if (IS_ERR(data->vcc_dig)) {
1927 rc = PTR_ERR(data->vcc_dig);
1928 dev_err(&data->client->dev,
1929 "Regulator get dig failed rc=%d\n", rc);
1930 goto error_get_vtg_vcc_dig;
1931 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301932
Amy Maloche21115eb2011-11-02 09:04:37 -07001933 if (regulator_count_voltages(data->vcc_dig) > 0) {
1934 rc = regulator_set_voltage(data->vcc_dig,
1935 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
1936 if (rc) {
1937 dev_err(&data->client->dev,
1938 "regulator set_vtg failed rc=%d\n", rc);
1939 goto error_set_vtg_vcc_dig;
1940 }
1941 }
1942 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301943 if (data->pdata->i2c_pull_up) {
1944 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
1945 if (IS_ERR(data->vcc_i2c)) {
1946 rc = PTR_ERR(data->vcc_i2c);
1947 dev_err(&data->client->dev,
1948 "Regulator get failed rc=%d\n", rc);
1949 goto error_get_vtg_i2c;
1950 }
1951 if (regulator_count_voltages(data->vcc_i2c) > 0) {
1952 rc = regulator_set_voltage(data->vcc_i2c,
1953 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
1954 if (rc) {
1955 dev_err(&data->client->dev,
1956 "regulator set_vtg failed rc=%d\n", rc);
1957 goto error_set_vtg_i2c;
1958 }
1959 }
1960 }
1961
1962 return 0;
1963
1964error_set_vtg_i2c:
1965 regulator_put(data->vcc_i2c);
1966error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001967 if (data->pdata->digital_pwr_regulator)
1968 if (regulator_count_voltages(data->vcc_dig) > 0)
1969 regulator_set_voltage(data->vcc_dig, 0,
1970 MXT_VTG_DIG_MAX_UV);
1971error_set_vtg_vcc_dig:
1972 if (data->pdata->digital_pwr_regulator)
1973 regulator_put(data->vcc_dig);
1974error_get_vtg_vcc_dig:
1975 if (regulator_count_voltages(data->vcc_ana) > 0)
1976 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1977error_set_vtg_vcc_ana:
1978 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301979 return rc;
1980
1981hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07001982 if (regulator_count_voltages(data->vcc_ana) > 0)
1983 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1984 regulator_put(data->vcc_ana);
1985 if (data->pdata->digital_pwr_regulator) {
1986 if (regulator_count_voltages(data->vcc_dig) > 0)
1987 regulator_set_voltage(data->vcc_dig, 0,
1988 MXT_VTG_DIG_MAX_UV);
1989 regulator_put(data->vcc_dig);
1990 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301991 if (data->pdata->i2c_pull_up) {
1992 if (regulator_count_voltages(data->vcc_i2c) > 0)
1993 regulator_set_voltage(data->vcc_i2c, 0,
1994 MXT_I2C_VTG_MAX_UV);
1995 regulator_put(data->vcc_i2c);
1996 }
1997 return 0;
1998}
1999
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302000#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07002001static int mxt_regulator_lpm(struct mxt_data *data, bool on)
2002{
2003
2004 int rc;
2005
2006 if (on == false)
2007 goto regulator_hpm;
2008
Amy Malochec331f842012-01-24 10:33:47 -08002009 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002010 if (rc < 0) {
2011 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002012 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002013 goto fail_regulator_lpm;
2014 }
2015
Amy Maloche21115eb2011-11-02 09:04:37 -07002016 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002017 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002018 MXT_LPM_LOAD_DIG_UA);
2019 if (rc < 0) {
2020 dev_err(&data->client->dev,
2021 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2022 goto fail_regulator_lpm;
2023 }
2024 }
2025
Jing Linbace50b2011-10-18 22:55:47 -07002026 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002027 rc = reg_set_optimum_mode_check(data->vcc_i2c,
Jing Linbace50b2011-10-18 22:55:47 -07002028 MXT_I2C_LPM_LOAD_UA);
2029 if (rc < 0) {
2030 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002031 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002032 goto fail_regulator_lpm;
2033 }
2034 }
2035
2036 return 0;
2037
2038regulator_hpm:
2039
Amy Malochec331f842012-01-24 10:33:47 -08002040 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002041 if (rc < 0) {
2042 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002043 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002044 goto fail_regulator_hpm;
2045 }
2046
Amy Maloche21115eb2011-11-02 09:04:37 -07002047 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002048 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002049 MXT_ACTIVE_LOAD_DIG_UA);
2050 if (rc < 0) {
2051 dev_err(&data->client->dev,
2052 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2053 goto fail_regulator_hpm;
2054 }
2055 }
2056
Jing Linbace50b2011-10-18 22:55:47 -07002057 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002058 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002059 if (rc < 0) {
2060 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002061 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002062 goto fail_regulator_hpm;
2063 }
2064 }
2065
2066 return 0;
2067
2068fail_regulator_lpm:
Amy Malochec331f842012-01-24 10:33:47 -08002069 reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002070 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002071 reg_set_optimum_mode_check(data->vcc_dig,
2072 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002073 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002074 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002075
2076 return rc;
2077
2078fail_regulator_hpm:
Amy Malochec331f842012-01-24 10:33:47 -08002079 reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002080 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002081 reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002082 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002083 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002084
2085 return rc;
2086}
2087
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302088static int mxt_suspend(struct device *dev)
2089{
2090 struct i2c_client *client = to_i2c_client(dev);
2091 struct mxt_data *data = i2c_get_clientdata(client);
2092 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002093 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302094
2095 mutex_lock(&input_dev->mutex);
2096
Amy Maloche52262212011-09-15 16:46:57 -07002097 if (input_dev->users) {
2098 error = mxt_stop(data);
2099 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002100 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07002101 mutex_unlock(&input_dev->mutex);
2102 return error;
2103 }
2104
2105 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302106
2107 mutex_unlock(&input_dev->mutex);
2108
Jing Linbace50b2011-10-18 22:55:47 -07002109 /* put regulators in low power mode */
2110 error = mxt_regulator_lpm(data, true);
2111 if (error < 0) {
2112 dev_err(dev, "failed to enter low power mode\n");
2113 return error;
2114 }
2115
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302116 return 0;
2117}
2118
2119static int mxt_resume(struct device *dev)
2120{
2121 struct i2c_client *client = to_i2c_client(dev);
2122 struct mxt_data *data = i2c_get_clientdata(client);
2123 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002124 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302125
Jing Linbace50b2011-10-18 22:55:47 -07002126 /* put regulators in high power mode */
2127 error = mxt_regulator_lpm(data, false);
2128 if (error < 0) {
2129 dev_err(dev, "failed to enter high power mode\n");
2130 return error;
2131 }
2132
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302133 mutex_lock(&input_dev->mutex);
2134
Amy Maloche52262212011-09-15 16:46:57 -07002135 if (input_dev->users) {
2136 error = mxt_start(data);
2137 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002138 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07002139 mutex_unlock(&input_dev->mutex);
2140 return error;
2141 }
2142 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302143
2144 mutex_unlock(&input_dev->mutex);
2145
2146 return 0;
2147}
2148
2149#if defined(CONFIG_HAS_EARLYSUSPEND)
2150static void mxt_early_suspend(struct early_suspend *h)
2151{
2152 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2153
2154 mxt_suspend(&data->client->dev);
2155}
2156
2157static void mxt_late_resume(struct early_suspend *h)
2158{
2159 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2160
2161 mxt_resume(&data->client->dev);
2162}
2163#endif
2164
2165static const struct dev_pm_ops mxt_pm_ops = {
2166#ifndef CONFIG_HAS_EARLYSUSPEND
2167 .suspend = mxt_suspend,
2168 .resume = mxt_resume,
2169#endif
2170};
2171#endif
2172
Jing Lin6cfc00e2011-11-02 15:15:30 -07002173static int mxt_debugfs_object_show(struct seq_file *m, void *v)
2174{
2175 struct mxt_data *data = m->private;
2176 struct mxt_object *object;
2177 struct device *dev = &data->client->dev;
2178 int i, j, k;
2179 int error;
2180 int obj_size;
2181 u8 val;
2182
2183 for (i = 0; i < data->info.object_num; i++) {
2184 object = data->object_table + i;
2185 obj_size = object->size + 1;
2186
2187 seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
2188
2189 for (j = 0; j < object->instances + 1; j++) {
2190 seq_printf(m, "[Instance %d]\n", j);
2191
2192 for (k = 0; k < obj_size; k++) {
2193 error = mxt_read_object(data, object->type,
2194 j * obj_size + k, &val);
2195 if (error) {
2196 dev_err(dev,
2197 "Failed to read object %d "
2198 "instance %d at offset %d\n",
2199 object->type, j, k);
2200 return error;
2201 }
2202
2203 seq_printf(m, "Byte %d: 0x%02x (%d)\n",
2204 k, val, val);
2205 }
2206 }
2207 }
2208
2209 return 0;
2210}
2211
2212static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
2213{
2214 return single_open(file, mxt_debugfs_object_show, inode->i_private);
2215}
2216
2217static const struct file_operations mxt_object_fops = {
2218 .owner = THIS_MODULE,
2219 .open = mxt_debugfs_object_open,
2220 .read = seq_read,
2221 .release = single_release,
2222};
2223
2224static void __init mxt_debugfs_init(struct mxt_data *data)
2225{
2226 debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
2227 if (IS_ERR_OR_NULL(debug_base))
2228 pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
2229 if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
2230 0444,
2231 debug_base,
2232 data,
2233 &mxt_object_fops))) {
2234 pr_err("atmel_mxt_ts: Failed to create object file\n");
2235 debugfs_remove_recursive(debug_base);
2236 }
2237}
2238
Iiro Valkonen7686b102011-02-02 23:21:58 -08002239static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002240 const struct i2c_device_id *id)
2241{
Iiro Valkonen919ed892011-02-15 13:36:52 -08002242 const struct mxt_platform_data *pdata = client->dev.platform_data;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002243 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002244 struct input_dev *input_dev;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002245 int error, i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002246
Iiro Valkonen919ed892011-02-15 13:36:52 -08002247 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002248 return -EINVAL;
2249
Iiro Valkonen7686b102011-02-02 23:21:58 -08002250 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002251 input_dev = input_allocate_device();
2252 if (!data || !input_dev) {
2253 dev_err(&client->dev, "Failed to allocate memory\n");
2254 error = -ENOMEM;
2255 goto err_free_mem;
2256 }
2257
Nick Dyer0a4016c2012-01-18 15:17:59 +05302258 data->state = INIT;
Amy Maloche83c385a2012-02-01 10:32:03 +05302259 input_dev->name = "atmel_mxt_ts";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002260 input_dev->id.bustype = BUS_I2C;
2261 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002262 input_dev->open = mxt_input_open;
2263 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002264
Joonyoung Shim910d8052011-04-12 23:14:38 -07002265 data->client = client;
2266 data->input_dev = input_dev;
2267 data->pdata = pdata;
2268 data->irq = client->irq;
2269
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002270 __set_bit(EV_ABS, input_dev->evbit);
2271 __set_bit(EV_KEY, input_dev->evbit);
2272 __set_bit(BTN_TOUCH, input_dev->keybit);
2273
2274 /* For single touch */
2275 input_set_abs_params(input_dev, ABS_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002276 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002277 input_set_abs_params(input_dev, ABS_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002278 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07002279 input_set_abs_params(input_dev, ABS_PRESSURE,
2280 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002281
2282 /* For multi touch */
Joonyoung Shimcd473222012-02-14 18:32:48 -08002283 input_mt_init_slots(input_dev, MXT_MAX_FINGER);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002284 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08002285 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002286 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002287 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002288 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002289 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07002290 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2291 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002292
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002293 /* set key array supported keys */
2294 if (pdata->key_codes) {
2295 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
2296 if (pdata->key_codes[i])
2297 input_set_capability(input_dev, EV_KEY,
2298 pdata->key_codes[i]);
2299 }
2300 }
2301
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002302 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002303 i2c_set_clientdata(client, data);
2304
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302305 if (pdata->init_hw)
2306 error = pdata->init_hw(true);
2307 else
2308 error = mxt_regulator_configure(data, true);
2309 if (error) {
2310 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07002311 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302312 }
2313
2314 if (pdata->power_on)
2315 error = pdata->power_on(true);
2316 else
2317 error = mxt_power_on(data, true);
2318 if (error) {
2319 dev_err(&client->dev, "Failed to power on hardware\n");
2320 goto err_regulator_on;
2321 }
2322
Amy Maloche08266db2011-11-04 11:07:16 -07002323 if (gpio_is_valid(pdata->irq_gpio)) {
2324 /* configure touchscreen irq gpio */
2325 error = gpio_request(pdata->irq_gpio,
2326 "mxt_irq_gpio");
2327 if (error) {
2328 pr_err("%s: unable to request gpio [%d]\n", __func__,
2329 pdata->irq_gpio);
2330 goto err_power_on;
2331 }
2332 error = gpio_direction_input(pdata->irq_gpio);
2333 if (error) {
2334 pr_err("%s: unable to set_direction for gpio [%d]\n",
2335 __func__, pdata->irq_gpio);
2336 goto err_irq_gpio_req;
2337 }
2338 }
2339
2340 if (gpio_is_valid(pdata->reset_gpio)) {
2341 /* configure touchscreen reset out gpio */
2342 error = gpio_request(pdata->reset_gpio,
2343 "mxt_reset_gpio");
2344 if (error) {
2345 pr_err("%s: unable to request reset gpio %d\n",
2346 __func__, pdata->reset_gpio);
2347 goto err_irq_gpio_req;
2348 }
2349
2350 error = gpio_direction_output(
2351 pdata->reset_gpio, 1);
2352 if (error) {
2353 pr_err("%s: unable to set direction for gpio %d\n",
2354 __func__, pdata->reset_gpio);
2355 goto err_reset_gpio_req;
2356 }
2357 }
2358
2359 mxt_reset_delay(data);
2360
Iiro Valkonen7686b102011-02-02 23:21:58 -08002361 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002362 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07002363 goto err_reset_gpio_req;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002364
Iiro Valkonen7686b102011-02-02 23:21:58 -08002365 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08002366 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002367 if (error) {
2368 dev_err(&client->dev, "Failed to register interrupt\n");
Jing Lin32c72532011-11-03 12:02:33 -07002369 goto err_free_object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002370 }
2371
Nick Dyer0a4016c2012-01-18 15:17:59 +05302372 if (data->state == APPMODE) {
2373 error = mxt_make_highchg(data);
2374 if (error) {
2375 dev_err(&client->dev, "Failed to make high CHG\n");
2376 goto err_free_irq;
2377 }
2378 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07002379
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002380 error = input_register_device(input_dev);
2381 if (error)
2382 goto err_free_irq;
2383
Iiro Valkonen7686b102011-02-02 23:21:58 -08002384 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002385 if (error)
2386 goto err_unregister_device;
2387
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302388#if defined(CONFIG_HAS_EARLYSUSPEND)
2389 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
2390 MXT_SUSPEND_LEVEL;
2391 data->early_suspend.suspend = mxt_early_suspend;
2392 data->early_suspend.resume = mxt_late_resume;
2393 register_early_suspend(&data->early_suspend);
2394#endif
2395
Jing Lin6cfc00e2011-11-02 15:15:30 -07002396 mxt_debugfs_init(data);
2397
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002398 return 0;
2399
2400err_unregister_device:
2401 input_unregister_device(input_dev);
2402 input_dev = NULL;
2403err_free_irq:
2404 free_irq(client->irq, data);
Jing Lin32c72532011-11-03 12:02:33 -07002405err_free_object:
2406 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07002407err_reset_gpio_req:
2408 if (gpio_is_valid(pdata->reset_gpio))
2409 gpio_free(pdata->reset_gpio);
2410err_irq_gpio_req:
2411 if (gpio_is_valid(pdata->irq_gpio))
2412 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302413err_power_on:
2414 if (pdata->power_on)
2415 pdata->power_on(false);
2416 else
2417 mxt_power_on(data, false);
2418err_regulator_on:
2419 if (pdata->init_hw)
2420 pdata->init_hw(false);
2421 else
2422 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002423err_free_mem:
2424 input_free_device(input_dev);
2425 kfree(data);
2426 return error;
2427}
2428
Iiro Valkonen7686b102011-02-02 23:21:58 -08002429static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002430{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002431 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002432
Iiro Valkonen7686b102011-02-02 23:21:58 -08002433 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002434 free_irq(data->irq, data);
2435 input_unregister_device(data->input_dev);
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302436#if defined(CONFIG_HAS_EARLYSUSPEND)
2437 unregister_early_suspend(&data->early_suspend);
2438#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302439
2440 if (data->pdata->power_on)
2441 data->pdata->power_on(false);
2442 else
2443 mxt_power_on(data, false);
2444
2445 if (data->pdata->init_hw)
2446 data->pdata->init_hw(false);
2447 else
2448 mxt_regulator_configure(data, false);
2449
Mohan Pallakabfe8f302012-01-02 18:32:08 +08002450 if (gpio_is_valid(data->pdata->reset_gpio))
2451 gpio_free(data->pdata->reset_gpio);
2452
2453 if (gpio_is_valid(data->pdata->irq_gpio))
2454 gpio_free(data->pdata->irq_gpio);
2455
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002456 kfree(data->object_table);
2457 kfree(data);
2458
Jing Lin6cfc00e2011-11-02 15:15:30 -07002459 debugfs_remove_recursive(debug_base);
2460
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002461 return 0;
2462}
2463
Iiro Valkonen7686b102011-02-02 23:21:58 -08002464static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002465 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002466 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08002467 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002468 { }
2469};
Iiro Valkonen7686b102011-02-02 23:21:58 -08002470MODULE_DEVICE_TABLE(i2c, mxt_id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002471
Iiro Valkonen7686b102011-02-02 23:21:58 -08002472static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002473 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08002474 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002475 .owner = THIS_MODULE,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002476#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08002477 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002478#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002479 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002480 .probe = mxt_probe,
2481 .remove = __devexit_p(mxt_remove),
2482 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002483};
2484
Iiro Valkonen7686b102011-02-02 23:21:58 -08002485static int __init mxt_init(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002486{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002487 return i2c_add_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002488}
2489
Iiro Valkonen7686b102011-02-02 23:21:58 -08002490static void __exit mxt_exit(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002491{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002492 i2c_del_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002493}
2494
Iiro Valkonen7686b102011-02-02 23:21:58 -08002495module_init(mxt_init);
2496module_exit(mxt_exit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002497
2498/* Module information */
2499MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08002500MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002501MODULE_LICENSE("GPL");