blob: bda7cb23cf93ba8bff475fcbd89f928b19fb55a1 [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 Lin8a9472d2012-03-21 15:43:45 -0700349 int t38_start_addr;
Jing Lin8fadad72012-02-24 10:10:50 -0800350 bool update_cfg;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -0800351 const char *fw_name;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700352};
353
Jing Lin6cfc00e2011-11-02 15:15:30 -0700354static struct dentry *debug_base;
355
Iiro Valkonen7686b102011-02-02 23:21:58 -0800356static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700357{
358 switch (type) {
Iiro Valkonene8645592011-11-18 12:56:19 -0800359 case MXT_GEN_MESSAGE_T5:
360 case MXT_GEN_COMMAND_T6:
361 case MXT_GEN_POWER_T7:
362 case MXT_GEN_ACQUIRE_T8:
363 case MXT_GEN_DATASOURCE_T53:
364 case MXT_TOUCH_MULTI_T9:
365 case MXT_TOUCH_KEYARRAY_T15:
366 case MXT_TOUCH_PROXIMITY_T23:
367 case MXT_TOUCH_PROXKEY_T52:
368 case MXT_PROCI_GRIPFACE_T20:
369 case MXT_PROCG_NOISE_T22:
370 case MXT_PROCI_ONETOUCH_T24:
371 case MXT_PROCI_TWOTOUCH_T27:
372 case MXT_PROCI_GRIP_T40:
373 case MXT_PROCI_PALM_T41:
374 case MXT_PROCI_TOUCHSUPPRESSION_T42:
375 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800376 case MXT_PROCI_SHIELDLESS_T56:
Iiro Valkonene8645592011-11-18 12:56:19 -0800377 case MXT_PROCG_NOISESUPPRESSION_T48:
378 case MXT_SPT_COMMSCONFIG_T18:
379 case MXT_SPT_GPIOPWM_T19:
380 case MXT_SPT_SELFTEST_T25:
381 case MXT_SPT_CTECONFIG_T28:
382 case MXT_SPT_USERDATA_T38:
383 case MXT_SPT_DIGITIZER_T43:
384 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700385 return true;
386 default:
387 return false;
388 }
389}
390
Iiro Valkonen7686b102011-02-02 23:21:58 -0800391static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700392{
393 switch (type) {
Iiro Valkonene8645592011-11-18 12:56:19 -0800394 case MXT_GEN_COMMAND_T6:
395 case MXT_GEN_POWER_T7:
396 case MXT_GEN_ACQUIRE_T8:
397 case MXT_TOUCH_MULTI_T9:
398 case MXT_TOUCH_KEYARRAY_T15:
399 case MXT_TOUCH_PROXIMITY_T23:
400 case MXT_TOUCH_PROXKEY_T52:
401 case MXT_PROCI_GRIPFACE_T20:
402 case MXT_PROCG_NOISE_T22:
403 case MXT_PROCI_ONETOUCH_T24:
404 case MXT_PROCI_TWOTOUCH_T27:
405 case MXT_PROCI_GRIP_T40:
406 case MXT_PROCI_PALM_T41:
407 case MXT_PROCI_TOUCHSUPPRESSION_T42:
408 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800409 case MXT_PROCI_SHIELDLESS_T56:
Iiro Valkonene8645592011-11-18 12:56:19 -0800410 case MXT_PROCG_NOISESUPPRESSION_T48:
411 case MXT_SPT_COMMSCONFIG_T18:
412 case MXT_SPT_GPIOPWM_T19:
413 case MXT_SPT_SELFTEST_T25:
414 case MXT_SPT_CTECONFIG_T28:
415 case MXT_SPT_USERDATA_T38:
416 case MXT_SPT_DIGITIZER_T43:
417 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700418 return true;
419 default:
420 return false;
421 }
422}
423
Iiro Valkonen7686b102011-02-02 23:21:58 -0800424static void mxt_dump_message(struct device *dev,
425 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700426{
427 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
428 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
429 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
430 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
431 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
432 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
433 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
434 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
435 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
436}
437
Nick Dyer0a4016c2012-01-18 15:17:59 +0530438static int mxt_switch_to_bootloader_address(struct mxt_data *data)
439{
440 int i;
441 struct i2c_client *client = data->client;
442
443 if (data->state == BOOTLOADER) {
444 dev_err(&client->dev, "Already in BOOTLOADER state\n");
445 return -EINVAL;
446 }
447
448 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
449 if (mxt_slave_addresses[i].application == client->addr) {
450 dev_info(&client->dev, "Changing to bootloader address: "
451 "%02x -> %02x",
452 client->addr,
453 mxt_slave_addresses[i].bootloader);
454
455 client->addr = mxt_slave_addresses[i].bootloader;
456 data->state = BOOTLOADER;
457 return 0;
458 }
459 }
460
461 dev_err(&client->dev, "Address 0x%02x not found in address table",
462 client->addr);
463 return -EINVAL;
464}
465
466static int mxt_switch_to_appmode_address(struct mxt_data *data)
467{
468 int i;
469 struct i2c_client *client = data->client;
470
471 if (data->state == APPMODE) {
472 dev_err(&client->dev, "Already in APPMODE state\n");
473 return -EINVAL;
474 }
475
476 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
477 if (mxt_slave_addresses[i].bootloader == client->addr) {
478 dev_info(&client->dev,
479 "Changing to application mode address: "
480 "0x%02x -> 0x%02x",
481 client->addr,
482 mxt_slave_addresses[i].application);
483
484 client->addr = mxt_slave_addresses[i].application;
485 data->state = APPMODE;
486 return 0;
487 }
488 }
489
490 dev_err(&client->dev, "Address 0x%02x not found in address table",
491 client->addr);
492 return -EINVAL;
493}
494
495static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
496{
497 u8 buf[3];
498
499 if (val | MXT_BOOT_EXTENDED_ID) {
500 dev_dbg(&client->dev,
501 "Retrieving extended mode ID information");
502
503 if (i2c_master_recv(client, &buf[0], 3) != 3) {
504 dev_err(&client->dev, "%s: i2c recv failed\n",
505 __func__);
506 return -EIO;
507 }
508
509 dev_info(&client->dev, "Bootloader ID:%d Version:%d",
510 buf[1], buf[2]);
511
512 return buf[0];
513 } else {
514 dev_info(&client->dev, "Bootloader ID:%d",
515 val & MXT_BOOT_ID_MASK);
516
517 return val;
518 }
519}
520
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -0800521static int mxt_get_bootloader_id(struct i2c_client *client)
522{
523 u8 val;
524 u8 buf[3];
525
526 if (i2c_master_recv(client, &val, 1) != 1) {
527 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
528 return -EIO;
529 }
530
531 if (val | MXT_BOOT_EXTENDED_ID) {
532 if (i2c_master_recv(client, &buf[0], 3) != 3) {
533 dev_err(&client->dev, "%s: i2c recv failed\n",
534 __func__);
535 return -EIO;
536 }
537 return buf[1];
538 } else {
539 dev_info(&client->dev, "Bootloader ID:%d",
540 val & MXT_BOOT_ID_MASK);
541
542 return val & MXT_BOOT_ID_MASK;
543 }
544}
545
Iiro Valkonen7686b102011-02-02 23:21:58 -0800546static int mxt_check_bootloader(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530547 unsigned int state)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700548{
549 u8 val;
550
551recheck:
552 if (i2c_master_recv(client, &val, 1) != 1) {
553 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
554 return -EIO;
555 }
556
557 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800558 case MXT_WAITING_BOOTLOAD_CMD:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530559 val = mxt_get_bootloader_version(client, val);
560 val &= ~MXT_BOOT_STATUS_MASK;
561 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800562 case MXT_WAITING_FRAME_DATA:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530563 case MXT_APP_CRC_FAIL:
Iiro Valkonen7686b102011-02-02 23:21:58 -0800564 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700565 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800566 case MXT_FRAME_CRC_PASS:
567 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700568 goto recheck;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530569 if (val == MXT_FRAME_CRC_FAIL) {
570 dev_err(&client->dev, "Bootloader CRC fail\n");
571 return -EINVAL;
572 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700573 break;
574 default:
575 return -EINVAL;
576 }
577
578 if (val != state) {
Nick Dyer0a4016c2012-01-18 15:17:59 +0530579 dev_err(&client->dev, "Invalid bootloader mode state %X\n",
580 val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700581 return -EINVAL;
582 }
583
584 return 0;
585}
586
Iiro Valkonen7686b102011-02-02 23:21:58 -0800587static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700588{
589 u8 buf[2];
590
Iiro Valkonen7686b102011-02-02 23:21:58 -0800591 buf[0] = MXT_UNLOCK_CMD_LSB;
592 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700593
594 if (i2c_master_send(client, buf, 2) != 2) {
595 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
596 return -EIO;
597 }
598
599 return 0;
600}
601
Iiro Valkonen7686b102011-02-02 23:21:58 -0800602static int mxt_fw_write(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530603 const u8 *data, unsigned int frame_size)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700604{
605 if (i2c_master_send(client, data, frame_size) != frame_size) {
606 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
607 return -EIO;
608 }
609
610 return 0;
611}
612
Iiro Valkonen7686b102011-02-02 23:21:58 -0800613static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700614 u16 reg, u16 len, void *val)
615{
616 struct i2c_msg xfer[2];
617 u8 buf[2];
Jing Lin36aee812011-10-17 17:17:28 -0700618 int i = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700619
620 buf[0] = reg & 0xff;
621 buf[1] = (reg >> 8) & 0xff;
622
623 /* Write register */
624 xfer[0].addr = client->addr;
625 xfer[0].flags = 0;
626 xfer[0].len = 2;
627 xfer[0].buf = buf;
628
629 /* Read data */
630 xfer[1].addr = client->addr;
631 xfer[1].flags = I2C_M_RD;
632 xfer[1].len = len;
633 xfer[1].buf = val;
634
Jing Lin36aee812011-10-17 17:17:28 -0700635 do {
636 if (i2c_transfer(client->adapter, xfer, 2) == 2)
637 return 0;
638 msleep(MXT_WAKE_TIME);
639 } while (++i < MXT_MAX_RW_TRIES);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700640
Jing Lin36aee812011-10-17 17:17:28 -0700641 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
642 return -EIO;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700643}
644
Iiro Valkonen7686b102011-02-02 23:21:58 -0800645static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700646{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800647 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700648}
649
Jing Lin36aee812011-10-17 17:17:28 -0700650static int __mxt_write_reg(struct i2c_client *client,
651 u16 addr, u16 length, u8 *value)
652{
653 u8 buf[MXT_BLOCK_SIZE + 2];
654 int i, tries = 0;
655
656 if (length > MXT_BLOCK_SIZE)
657 return -EINVAL;
658
659 buf[0] = addr & 0xff;
660 buf[1] = (addr >> 8) & 0xff;
661 for (i = 0; i < length; i++)
662 buf[i + 2] = *value++;
663
664 do {
665 if (i2c_master_send(client, buf, length + 2) == (length + 2))
666 return 0;
667 msleep(MXT_WAKE_TIME);
668 } while (++tries < MXT_MAX_RW_TRIES);
669
670 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
671 return -EIO;
672}
673
Iiro Valkonen7686b102011-02-02 23:21:58 -0800674static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700675{
Jing Lin36aee812011-10-17 17:17:28 -0700676 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700677}
678
Iiro Valkonen7686b102011-02-02 23:21:58 -0800679static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700680 u16 reg, u8 *object_buf)
681{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800682 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700683 object_buf);
684}
685
Iiro Valkonen7686b102011-02-02 23:21:58 -0800686static struct mxt_object *
687mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700688{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800689 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700690 int i;
691
692 for (i = 0; i < data->info.object_num; i++) {
693 object = data->object_table + i;
694 if (object->type == type)
695 return object;
696 }
697
698 dev_err(&data->client->dev, "Invalid object type\n");
699 return NULL;
700}
701
Iiro Valkonen7686b102011-02-02 23:21:58 -0800702static int mxt_read_message(struct mxt_data *data,
703 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700704{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800705 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700706 u16 reg;
707
Iiro Valkonene8645592011-11-18 12:56:19 -0800708 object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700709 if (!object)
710 return -EINVAL;
711
712 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800713 return __mxt_read_reg(data->client, reg,
714 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700715}
716
Iiro Valkonen7686b102011-02-02 23:21:58 -0800717static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700718 u8 type, u8 offset, u8 *val)
719{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800720 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700721 u16 reg;
722
Iiro Valkonen7686b102011-02-02 23:21:58 -0800723 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700724 if (!object)
725 return -EINVAL;
726
727 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800728 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700729}
730
Iiro Valkonen7686b102011-02-02 23:21:58 -0800731static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700732 u8 type, u8 offset, u8 val)
733{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800734 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700735 u16 reg;
736
Iiro Valkonen7686b102011-02-02 23:21:58 -0800737 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700738 if (!object)
739 return -EINVAL;
740
741 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800742 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700743}
744
Iiro Valkonen7686b102011-02-02 23:21:58 -0800745static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700746{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800747 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700748 struct input_dev *input_dev = data->input_dev;
749 int status = finger[single_id].status;
750 int finger_num = 0;
751 int id;
752
Iiro Valkonen7686b102011-02-02 23:21:58 -0800753 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700754 if (!finger[id].status)
755 continue;
756
Joonyoung Shimcd473222012-02-14 18:32:48 -0800757 input_mt_slot(input_dev, id);
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800758 /* Firmware reports min/max values when the touch is
759 * outside screen area. Send a release event in
760 * such cases to avoid unwanted touches.
761 */
762 if (finger[id].x <= data->pdata->panel_minx ||
763 finger[id].x >= data->pdata->panel_maxx ||
764 finger[id].y <= data->pdata->panel_miny ||
765 finger[id].y >= data->pdata->panel_maxy) {
766 finger[id].status = MXT_RELEASE;
767 }
768
Joonyoung Shimcd473222012-02-14 18:32:48 -0800769 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
770 finger[id].status != MXT_RELEASE);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700771
Joonyoung Shimcd473222012-02-14 18:32:48 -0800772 if (finger[id].status != MXT_RELEASE) {
Amy Maloche2b59bab2011-10-13 16:08:16 -0700773 finger_num++;
Joonyoung Shimcd473222012-02-14 18:32:48 -0800774 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
775 finger[id].area);
776 input_report_abs(input_dev, ABS_MT_POSITION_X,
777 finger[id].x);
778 input_report_abs(input_dev, ABS_MT_POSITION_Y,
779 finger[id].y);
780 input_report_abs(input_dev, ABS_MT_PRESSURE,
781 finger[id].area);
782 } else {
783 finger[id].status = 0;
784 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700785 }
786
787 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
788
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800789 if (finger[single_id].x <= data->pdata->panel_minx ||
790 finger[single_id].x >= data->pdata->panel_maxx ||
791 finger[single_id].y <= data->pdata->panel_miny ||
792 finger[single_id].y >= data->pdata->panel_maxy) {
793 status = MXT_RELEASE;
794 }
795
Iiro Valkonen7686b102011-02-02 23:21:58 -0800796 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700797 input_report_abs(input_dev, ABS_X, finger[single_id].x);
798 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700799 input_report_abs(input_dev,
800 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700801 }
802
803 input_sync(input_dev);
804}
805
Iiro Valkonen7686b102011-02-02 23:21:58 -0800806static void mxt_input_touchevent(struct mxt_data *data,
807 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700808{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800809 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700810 struct device *dev = &data->client->dev;
811 u8 status = message->message[0];
812 int x;
813 int y;
814 int area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700815 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700816
817 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800818 if (!(status & MXT_DETECT)) {
819 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700820 dev_dbg(dev, "[%d] released\n", id);
821
Iiro Valkonen7686b102011-02-02 23:21:58 -0800822 finger[id].status = MXT_RELEASE;
823 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700824 }
825 return;
826 }
827
828 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800829 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700830 return;
831
Joonyoung Shim910d8052011-04-12 23:14:38 -0700832 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
833 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800834 if (data->pdata->panel_maxx < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700835 x = x >> 2;
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800836 if (data->pdata->panel_maxy < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700837 y = y >> 2;
838
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700839 area = message->message[4];
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700840 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700841
842 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800843 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700844 x, y, area);
845
Iiro Valkonen7686b102011-02-02 23:21:58 -0800846 finger[id].status = status & MXT_MOVE ?
847 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700848 finger[id].x = x;
849 finger[id].y = y;
850 finger[id].area = area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700851 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700852
Iiro Valkonen7686b102011-02-02 23:21:58 -0800853 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700854}
855
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800856static void mxt_handle_key_array(struct mxt_data *data,
857 struct mxt_message *message)
858{
859 u32 keys_changed;
860 int i;
861
862 if (!data->pdata->key_codes) {
863 dev_err(&data->client->dev, "keyarray is not supported\n");
864 return;
865 }
866
867 data->keyarray_new = message->message[1] |
868 (message->message[2] << 8) |
869 (message->message[3] << 16) |
870 (message->message[4] << 24);
871
872 keys_changed = data->keyarray_old ^ data->keyarray_new;
873
874 if (!keys_changed) {
875 dev_dbg(&data->client->dev, "no keys changed\n");
876 return;
877 }
878
879 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
880 if (!(keys_changed & (1 << i)))
881 continue;
882
883 input_report_key(data->input_dev, data->pdata->key_codes[i],
884 (data->keyarray_new & (1 << i)));
885 input_sync(data->input_dev);
886 }
887
888 data->keyarray_old = data->keyarray_new;
889}
890
Iiro Valkonen7686b102011-02-02 23:21:58 -0800891static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700892{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800893 struct mxt_data *data = dev_id;
894 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700895 struct device *dev = &data->client->dev;
896 int id;
897 u8 reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700898
Nick Dyer0a4016c2012-01-18 15:17:59 +0530899 if (data->state != APPMODE) {
900 dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
901 return IRQ_HANDLED;
902 }
903
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700904 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800905 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700906 dev_err(dev, "Failed to read message\n");
907 goto end;
908 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700909 reportid = message.reportid;
910
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800911 if (!reportid) {
912 dev_dbg(dev, "Report id 0 is reserved\n");
913 continue;
914 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700915
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800916 /* check whether report id is part of T9 or T15 */
917 id = reportid - data->t9_min_reportid;
918
919 if (reportid >= data->t9_min_reportid &&
920 reportid <= data->t9_max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -0800921 mxt_input_touchevent(data, &message, id);
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800922 else if (reportid >= data->t15_min_reportid &&
923 reportid <= data->t15_max_reportid)
924 mxt_handle_key_array(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700925 else
Iiro Valkonen7686b102011-02-02 23:21:58 -0800926 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700927 } while (reportid != 0xff);
928
929end:
930 return IRQ_HANDLED;
931}
932
Iiro Valkonen7686b102011-02-02 23:21:58 -0800933static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700934{
Jing Lindc4413c2012-01-16 15:22:52 -0800935 const struct mxt_config_info *config_info = data->config_info;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800936 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700937 struct device *dev = &data->client->dev;
938 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -0800939 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700940
Jing Lindc4413c2012-01-16 15:22:52 -0800941 if (!config_info) {
Iiro Valkonen71749f52011-02-15 13:36:52 -0800942 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
943 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700944 }
945
946 for (i = 0; i < data->info.object_num; i++) {
947 object = data->object_table + i;
948
Iiro Valkonen7686b102011-02-02 23:21:58 -0800949 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700950 continue;
951
Iiro Valkonen71749f52011-02-15 13:36:52 -0800952 for (j = 0; j < object->size + 1; j++) {
953 config_offset = index + j;
Jing Lindc4413c2012-01-16 15:22:52 -0800954 if (config_offset > config_info->config_length) {
Iiro Valkonen71749f52011-02-15 13:36:52 -0800955 dev_err(dev, "Not enough config data!\n");
956 return -EINVAL;
957 }
Iiro Valkonen7686b102011-02-02 23:21:58 -0800958 mxt_write_object(data, object->type, j,
Jing Lindc4413c2012-01-16 15:22:52 -0800959 config_info->config[config_offset]);
Iiro Valkonen71749f52011-02-15 13:36:52 -0800960 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700961 index += object->size + 1;
962 }
963
964 return 0;
965}
966
Iiro Valkonen7686b102011-02-02 23:21:58 -0800967static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700968{
969 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800970 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700971 int count = 10;
972 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700973
974 /* Read dummy message to make high CHG pin */
975 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800976 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700977 if (error)
978 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800979 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700980
981 if (!count) {
982 dev_err(dev, "CHG pin isn't cleared\n");
983 return -EBUSY;
984 }
985
986 return 0;
987}
988
Iiro Valkonen7686b102011-02-02 23:21:58 -0800989static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700990{
991 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800992 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700993 int error;
994 u8 val;
995
Iiro Valkonen7686b102011-02-02 23:21:58 -0800996 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700997 if (error)
998 return error;
999 info->family_id = val;
1000
Iiro Valkonen7686b102011-02-02 23:21:58 -08001001 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001002 if (error)
1003 return error;
1004 info->variant_id = val;
1005
Iiro Valkonen7686b102011-02-02 23:21:58 -08001006 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001007 if (error)
1008 return error;
1009 info->version = val;
1010
Iiro Valkonen7686b102011-02-02 23:21:58 -08001011 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001012 if (error)
1013 return error;
1014 info->build = val;
1015
Iiro Valkonen7686b102011-02-02 23:21:58 -08001016 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001017 if (error)
1018 return error;
1019 info->object_num = val;
1020
1021 return 0;
1022}
1023
Iiro Valkonen7686b102011-02-02 23:21:58 -08001024static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001025{
1026 int error;
1027 int i;
1028 u16 reg;
1029 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001030 u8 buf[MXT_OBJECT_SIZE];
Jing Lindc4413c2012-01-16 15:22:52 -08001031 bool found_t38 = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001032
1033 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001034 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001035
Iiro Valkonen7686b102011-02-02 23:21:58 -08001036 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
1037 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001038 if (error)
1039 return error;
1040
1041 object->type = buf[0];
1042 object->start_address = (buf[2] << 8) | buf[1];
1043 object->size = buf[3];
1044 object->instances = buf[4];
1045 object->num_report_ids = buf[5];
1046
1047 if (object->num_report_ids) {
1048 reportid += object->num_report_ids *
1049 (object->instances + 1);
1050 object->max_reportid = reportid;
1051 }
Jing Lindc4413c2012-01-16 15:22:52 -08001052
1053 /* Calculate index for config major version in config array.
1054 * Major version is the first byte in object T38.
1055 */
Jing Lin8a9472d2012-03-21 15:43:45 -07001056 if (object->type == MXT_SPT_USERDATA_T38) {
1057 data->t38_start_addr = object->start_address;
Jing Lindc4413c2012-01-16 15:22:52 -08001058 found_t38 = true;
Jing Lin8a9472d2012-03-21 15:43:45 -07001059 }
Jing Lindc4413c2012-01-16 15:22:52 -08001060 if (!found_t38 && mxt_object_writable(object->type))
1061 data->cfg_version_idx += object->size + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001062 }
1063
1064 return 0;
1065}
1066
Jing Lin8fadad72012-02-24 10:10:50 -08001067static int compare_versions(const u8 *v1, const u8 *v2)
1068{
1069 int i;
1070
1071 if (!v1 || !v2)
1072 return -EINVAL;
1073
1074 /* The major version number stays the same across different versions for
1075 * a particular controller on a target. The minor and sub-minor version
1076 * numbers indicate which version is newer.
1077 */
1078 if (v1[0] != v2[0])
1079 return -EINVAL;
1080
1081 for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
1082 if (v1[i] > v2[i])
1083 return MXT_CFG_VERSION_LESS; /* v2 is older */
1084
1085 if (v1[i] < v2[i])
1086 return MXT_CFG_VERSION_GREATER; /* v2 is newer */
1087 }
1088
1089 return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
1090}
1091
1092static void mxt_check_config_version(struct mxt_data *data,
1093 const struct mxt_config_info *cfg_info,
1094 bool match_major,
1095 const u8 **cfg_version_found,
1096 bool *found_cfg_major_match)
1097{
1098 const u8 *cfg_version;
1099 int result = -EINVAL;
1100
1101 cfg_version = cfg_info->config + data->cfg_version_idx;
1102
1103 if (*cfg_version_found)
1104 result = compare_versions(*cfg_version_found, cfg_version);
1105
1106 if (match_major) {
1107 if (result >= MXT_CFG_VERSION_EQUAL)
1108 *found_cfg_major_match = true;
1109
1110 if (result == MXT_CFG_VERSION_EQUAL ||
1111 result == MXT_CFG_VERSION_GREATER) {
1112 data->config_info = cfg_info;
1113 data->fw_name = cfg_info->fw_name;
1114 *cfg_version_found = cfg_version;
1115 }
1116
1117 if (result == MXT_CFG_VERSION_GREATER)
1118 data->update_cfg = true;
1119 } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
1120 data->config_info = cfg_info;
1121 data->fw_name = cfg_info->fw_name;
1122 data->update_cfg = true;
1123 *cfg_version_found = cfg_version;
1124 }
1125}
1126
1127/* If the controller's config version has a non-zero major number, call this
1128 * function with match_major = true to look for the latest config present in
1129 * the pdata based on matching family id, variant id, f/w version, build, and
1130 * config major number. If the controller is programmed with wrong config data
1131 * previously, call this function with match_major = false to look for latest
1132 * config based on based on matching family id, variant id, f/w version and
1133 * build only.
1134 */
1135static int mxt_search_config_array(struct mxt_data *data, bool match_major)
Jing Lindc4413c2012-01-16 15:22:52 -08001136{
1137
1138 const struct mxt_platform_data *pdata = data->pdata;
1139 const struct mxt_config_info *cfg_info;
Jing Lin8fadad72012-02-24 10:10:50 -08001140 const struct mxt_info *info = &data->info;
1141 const u8 *cfg_version_found;
1142 bool found_cfg_major_match = false;
Jing Lindc4413c2012-01-16 15:22:52 -08001143 int i;
Jing Lin8fadad72012-02-24 10:10:50 -08001144
1145 cfg_version_found = match_major ? data->cfg_version : NULL;
Jing Lindc4413c2012-01-16 15:22:52 -08001146
1147 for (i = 0; i < pdata->config_array_size; i++) {
1148
1149 cfg_info = &pdata->config_array[i];
1150
1151 if (!cfg_info->config || !cfg_info->config_length)
1152 continue;
1153
1154 if (info->family_id == cfg_info->family_id &&
1155 info->variant_id == cfg_info->variant_id &&
1156 info->version == cfg_info->version &&
1157 info->build == cfg_info->build) {
1158
Jing Lin8fadad72012-02-24 10:10:50 -08001159 mxt_check_config_version(data, cfg_info, match_major,
1160 &cfg_version_found, &found_cfg_major_match);
Jing Lindc4413c2012-01-16 15:22:52 -08001161 }
1162 }
1163
Jing Lin8fadad72012-02-24 10:10:50 -08001164 if (data->config_info || found_cfg_major_match)
1165 return 0;
1166
1167 data->config_info = NULL;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001168 data->fw_name = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001169
Jing Lindc4413c2012-01-16 15:22:52 -08001170 return -EINVAL;
1171}
1172
1173static int mxt_get_config(struct mxt_data *data)
1174{
1175 const struct mxt_platform_data *pdata = data->pdata;
1176 struct device *dev = &data->client->dev;
1177 struct mxt_object *object;
1178 int error;
1179
1180 if (!pdata->config_array || !pdata->config_array_size) {
1181 dev_dbg(dev, "No cfg data provided by platform data\n");
1182 return 0;
1183 }
1184
1185 /* Get current config version */
1186 object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
1187 if (!object) {
1188 dev_err(dev, "Unable to obtain USERDATA object\n");
1189 return -EINVAL;
1190 }
1191
Jing Lin8fadad72012-02-24 10:10:50 -08001192 error = __mxt_read_reg(data->client, object->start_address,
1193 sizeof(data->cfg_version), data->cfg_version);
Jing Lindc4413c2012-01-16 15:22:52 -08001194 if (error) {
1195 dev_err(dev, "Unable to read config version\n");
1196 return error;
1197 }
Jing Lin8fadad72012-02-24 10:10:50 -08001198 dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
1199 data->cfg_version[0], data->cfg_version[1],
1200 data->cfg_version[2]);
Jing Lindc4413c2012-01-16 15:22:52 -08001201
1202 /* It is possible that the config data on the controller is not
1203 * versioned and the version number returns 0. In this case,
1204 * find a match without the config version checking.
1205 */
1206 error = mxt_search_config_array(data,
Jing Lin8fadad72012-02-24 10:10:50 -08001207 data->cfg_version[0] != 0 ? true : false);
1208 if (error) {
1209 /* If a match wasn't found for a non-zero config version,
1210 * it means the controller has the wrong config data. Search
1211 * for a best match based on controller and firmware version,
1212 * but not config version.
1213 */
1214 if (data->cfg_version[0])
1215 error = mxt_search_config_array(data, false);
1216 if (error) {
1217 dev_err(dev,
1218 "Unable to find matching config in pdata\n");
1219 return error;
1220 }
1221 }
Jing Lindc4413c2012-01-16 15:22:52 -08001222
1223 return 0;
1224}
Jing Lin8fadad72012-02-24 10:10:50 -08001225
Amy Maloche7e447432011-09-14 11:36:30 -07001226static void mxt_reset_delay(struct mxt_data *data)
1227{
1228 struct mxt_info *info = &data->info;
1229
1230 switch (info->family_id) {
1231 case MXT224_ID:
1232 msleep(MXT224_RESET_TIME);
1233 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -07001234 case MXT224E_ID:
1235 msleep(MXT224E_RESET_TIME);
1236 break;
Amy Maloche7e447432011-09-14 11:36:30 -07001237 case MXT1386_ID:
1238 msleep(MXT1386_RESET_TIME);
1239 break;
1240 default:
1241 msleep(MXT_RESET_TIME);
1242 }
1243}
1244
Jing Lin8fadad72012-02-24 10:10:50 -08001245static int mxt_backup_nv(struct mxt_data *data)
1246{
1247 int error;
1248 u8 command_register;
1249 int timeout_counter = 0;
1250
1251 /* Backup to memory */
1252 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1253 MXT_COMMAND_BACKUPNV,
1254 MXT_BACKUP_VALUE);
1255 msleep(MXT_BACKUP_TIME);
1256
1257 do {
1258 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
1259 MXT_COMMAND_BACKUPNV,
1260 &command_register);
1261 if (error)
1262 return error;
1263
1264 usleep_range(1000, 2000);
1265
1266 } while ((command_register != 0) && (++timeout_counter <= 100));
1267
1268 if (timeout_counter > 100) {
1269 dev_err(&data->client->dev, "No response after backup!\n");
1270 return -EIO;
1271 }
1272
1273 /* Soft reset */
1274 mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
1275
1276 mxt_reset_delay(data);
1277
1278 return 0;
1279}
1280
Jing Lin412aedc2012-02-28 13:57:19 -08001281static int mxt_save_objects(struct mxt_data *data)
1282{
1283 struct i2c_client *client = data->client;
1284 struct mxt_object *t7_object;
1285 struct mxt_object *t9_object;
1286 struct mxt_object *t15_object;
1287 int error;
1288
1289 /* Store T7 and T9 locally, used in suspend/resume operations */
1290 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
1291 if (!t7_object) {
1292 dev_err(&client->dev, "Failed to get T7 object\n");
1293 return -EINVAL;
1294 }
1295
1296 data->t7_start_addr = t7_object->start_address;
1297 error = __mxt_read_reg(client, data->t7_start_addr,
1298 T7_DATA_SIZE, data->t7_data);
1299 if (error < 0) {
1300 dev_err(&client->dev,
1301 "Failed to save current power state\n");
1302 return error;
1303 }
1304
1305 error = mxt_read_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
1306 &data->t9_ctrl);
1307 if (error < 0) {
1308 dev_err(&client->dev, "Failed to save current touch object\n");
1309 return error;
1310 }
1311
1312 /* Store T9, T15's min and max report ids */
1313 t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1314 if (!t9_object) {
1315 dev_err(&client->dev, "Failed to get T9 object\n");
1316 return -EINVAL;
1317 }
1318 data->t9_max_reportid = t9_object->max_reportid;
1319 data->t9_min_reportid = t9_object->max_reportid -
1320 t9_object->num_report_ids + 1;
1321
1322 if (data->pdata->key_codes) {
1323 t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
1324 if (!t15_object)
1325 dev_dbg(&client->dev, "T15 object is not available\n");
1326 else {
1327 data->t15_max_reportid = t15_object->max_reportid;
1328 data->t15_min_reportid = t15_object->max_reportid -
1329 t15_object->num_report_ids + 1;
1330 }
1331 }
1332
1333 return 0;
1334}
1335
Iiro Valkonen7686b102011-02-02 23:21:58 -08001336static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001337{
1338 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001339 struct mxt_info *info = &data->info;
Jing Lin36aee812011-10-17 17:17:28 -07001340 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001341 u8 val;
Jing Lin8fadad72012-02-24 10:10:50 -08001342 const u8 *cfg_ver;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001343
Iiro Valkonen7686b102011-02-02 23:21:58 -08001344 error = mxt_get_info(data);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301345 if (error) {
1346 /* Try bootloader mode */
1347 error = mxt_switch_to_bootloader_address(data);
1348 if (error)
1349 return error;
1350
1351 error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
1352 if (error)
1353 return error;
1354
1355 dev_err(&client->dev, "Application CRC failure\n");
1356 data->state = BOOTLOADER;
1357
1358 return 0;
1359 }
1360
1361 dev_info(&client->dev,
1362 "Family ID: %d Variant ID: %d Version: %d.%d "
1363 "Build: 0x%02X Object Num: %d\n",
1364 info->family_id, info->variant_id,
1365 info->version >> 4, info->version & 0xf,
1366 info->build, info->object_num);
1367
1368 data->state = APPMODE;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001369
1370 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001371 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001372 GFP_KERNEL);
1373 if (!data->object_table) {
1374 dev_err(&client->dev, "Failed to allocate memory\n");
1375 return -ENOMEM;
1376 }
1377
1378 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001379 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001380 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001381 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001382
Jing Lindc4413c2012-01-16 15:22:52 -08001383 /* Get config data from platform data */
1384 error = mxt_get_config(data);
1385 if (error)
1386 dev_dbg(&client->dev, "Config info not found.\n");
1387
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001388 /* Check register init values */
Jing Lin8fadad72012-02-24 10:10:50 -08001389 if (data->config_info && data->config_info->config) {
1390 if (data->update_cfg) {
1391 error = mxt_check_reg_init(data);
1392 if (error) {
1393 dev_err(&client->dev,
1394 "Failed to check reg init value\n");
1395 goto free_object_table;
1396 }
1397
1398 error = mxt_backup_nv(data);
1399 if (error) {
1400 dev_err(&client->dev, "Failed to back up NV\n");
1401 goto free_object_table;
1402 }
1403
1404 cfg_ver = data->config_info->config +
1405 data->cfg_version_idx;
1406 dev_info(&client->dev,
1407 "Config updated from %d.%d.%d to %d.%d.%d\n",
1408 data->cfg_version[0], data->cfg_version[1],
1409 data->cfg_version[2],
1410 cfg_ver[0], cfg_ver[1], cfg_ver[2]);
1411
1412 memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
1413 }
1414 } else {
1415 dev_info(&client->dev,
1416 "No cfg data defined, skipping check reg init\n");
1417 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001418
Jing Lin412aedc2012-02-28 13:57:19 -08001419 error = mxt_save_objects(data);
1420 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001421 goto free_object_table;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001422
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001423 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001424 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001425 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001426 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001427 info->matrix_xsize = val;
1428
Iiro Valkonen7686b102011-02-02 23:21:58 -08001429 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001430 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001431 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001432 info->matrix_ysize = val;
1433
1434 dev_info(&client->dev,
Nick Dyer0a4016c2012-01-18 15:17:59 +05301435 "Matrix X Size: %d Matrix Y Size: %d\n",
1436 info->matrix_xsize, info->matrix_ysize);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001437
1438 return 0;
Jing Lin32c72532011-11-03 12:02:33 -07001439
1440free_object_table:
1441 kfree(data->object_table);
1442 return error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001443}
1444
Iiro Valkonen7686b102011-02-02 23:21:58 -08001445static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001446 struct device_attribute *attr, char *buf)
1447{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001448 struct mxt_data *data = dev_get_drvdata(dev);
1449 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001450 int count = 0;
1451 int i, j;
1452 int error;
1453 u8 val;
1454
1455 for (i = 0; i < data->info.object_num; i++) {
1456 object = data->object_table + i;
1457
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001458 count += snprintf(buf + count, PAGE_SIZE - count,
1459 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001460 i + 1, object->type);
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001461 if (count >= PAGE_SIZE)
1462 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001463
Iiro Valkonen7686b102011-02-02 23:21:58 -08001464 if (!mxt_object_readable(object->type)) {
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001465 count += snprintf(buf + count, PAGE_SIZE - count,
1466 "\n");
1467 if (count >= PAGE_SIZE)
1468 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001469 continue;
1470 }
1471
1472 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001473 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001474 object->type, j, &val);
1475 if (error)
1476 return error;
1477
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001478 count += snprintf(buf + count, PAGE_SIZE - count,
1479 "\t[%2d]: %02x (%d)\n", j, val, val);
1480 if (count >= PAGE_SIZE)
1481 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001482 }
1483
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001484 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1485 if (count >= PAGE_SIZE)
1486 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001487 }
1488
1489 return count;
1490}
1491
Jing Lincc974cb2012-02-01 23:13:14 -08001492static int strtobyte(const char *data, u8 *value)
1493{
1494 char str[3];
1495
1496 str[0] = data[0];
1497 str[1] = data[1];
1498 str[2] = '\0';
1499
1500 return kstrtou8(str, 16, value);
1501}
1502
Iiro Valkonen7686b102011-02-02 23:21:58 -08001503static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001504{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001505 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001506 struct i2c_client *client = data->client;
1507 const struct firmware *fw = NULL;
1508 unsigned int frame_size;
Nick Dyer0a4016c2012-01-18 15:17:59 +05301509 unsigned int retry = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001510 unsigned int pos = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001511 int ret, i, max_frame_size;
1512 u8 *frame;
1513
1514 switch (data->info.family_id) {
1515 case MXT224_ID:
1516 max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
1517 break;
1518 case MXT1386_ID:
1519 max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
1520 break;
1521 default:
1522 return -EINVAL;
1523 }
1524
1525 frame = kmalloc(max_frame_size, GFP_KERNEL);
1526 if (!frame) {
1527 dev_err(dev, "Unable to allocate memory for frame data\n");
1528 return -ENOMEM;
1529 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001530
1531 ret = request_firmware(&fw, fn, dev);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301532 if (ret < 0) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001533 dev_err(dev, "Unable to open firmware %s\n", fn);
Jing Lincc974cb2012-02-01 23:13:14 -08001534 goto free_frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001535 }
1536
Nick Dyer0a4016c2012-01-18 15:17:59 +05301537 if (data->state != BOOTLOADER) {
1538 /* Change to the bootloader mode */
1539 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1540 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1541 mxt_reset_delay(data);
Amy Maloche7e447432011-09-14 11:36:30 -07001542
Nick Dyer0a4016c2012-01-18 15:17:59 +05301543 ret = mxt_switch_to_bootloader_address(data);
1544 if (ret)
1545 goto release_firmware;
1546 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001547
Iiro Valkonen7686b102011-02-02 23:21:58 -08001548 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301549 if (ret) {
1550 /* Bootloader may still be unlocked from previous update
1551 * attempt */
1552 ret = mxt_check_bootloader(client,
1553 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001554
Nick Dyer0a4016c2012-01-18 15:17:59 +05301555 if (ret)
1556 goto return_to_app_mode;
1557 } else {
1558 dev_info(dev, "Unlocking bootloader\n");
1559 /* Unlock bootloader */
1560 mxt_unlock_bootloader(client);
1561 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001562
1563 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001564 ret = mxt_check_bootloader(client,
1565 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001566 if (ret)
Nick Dyer0a4016c2012-01-18 15:17:59 +05301567 goto release_firmware;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001568
Jing Lincc974cb2012-02-01 23:13:14 -08001569 /* Get frame length MSB */
1570 ret = strtobyte(fw->data + pos, frame);
1571 if (ret)
1572 goto release_firmware;
1573
1574 /* Get frame length LSB */
1575 ret = strtobyte(fw->data + pos + 2, frame + 1);
1576 if (ret)
1577 goto release_firmware;
1578
1579 frame_size = ((*frame << 8) | *(frame + 1));
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001580
1581 /* We should add 2 at frame size as the the firmware data is not
1582 * included the CRC bytes.
1583 */
1584 frame_size += 2;
1585
Jing Lincc974cb2012-02-01 23:13:14 -08001586 if (frame_size > max_frame_size) {
1587 dev_err(dev, "Invalid frame size - %d\n", frame_size);
1588 ret = -EINVAL;
1589 goto release_firmware;
1590 }
1591
1592 /* Convert frame data and CRC from hex to binary */
1593 for (i = 2; i < frame_size; i++) {
1594 ret = strtobyte(fw->data + pos + i * 2, frame + i);
1595 if (ret)
1596 goto release_firmware;
1597 }
1598
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001599 /* Write one frame to device */
Jing Lincc974cb2012-02-01 23:13:14 -08001600 mxt_fw_write(client, frame, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001601
Iiro Valkonen7686b102011-02-02 23:21:58 -08001602 ret = mxt_check_bootloader(client,
1603 MXT_FRAME_CRC_PASS);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301604 if (ret) {
1605 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001606
Nick Dyer0a4016c2012-01-18 15:17:59 +05301607 /* Back off by 20ms per retry */
1608 msleep(retry * 20);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001609
Nick Dyer0a4016c2012-01-18 15:17:59 +05301610 if (retry > 20)
1611 goto release_firmware;
1612 } else {
1613 retry = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001614 pos += frame_size * 2;
1615 dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301616 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001617 }
1618
Nick Dyer0a4016c2012-01-18 15:17:59 +05301619return_to_app_mode:
1620 mxt_switch_to_appmode_address(data);
1621release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001622 release_firmware(fw);
Jing Lincc974cb2012-02-01 23:13:14 -08001623free_frame:
1624 kfree(frame);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001625
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001626 return ret;
1627}
1628
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001629static const char *
1630mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
1631{
1632 const struct mxt_platform_data *pdata = data->pdata;
1633 const struct mxt_config_info *cfg_info;
1634 const char *fw_name = NULL;
1635 int i;
1636
1637 for (i = 0; i < pdata->config_array_size; i++) {
1638 cfg_info = &pdata->config_array[i];
1639 if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
1640 data->config_info = cfg_info;
1641 data->info.family_id = cfg_info->family_id;
1642 fw_name = cfg_info->fw_name;
1643 }
1644 }
1645
1646 return fw_name;
1647}
1648
Iiro Valkonen7686b102011-02-02 23:21:58 -08001649static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001650 struct device_attribute *attr,
1651 const char *buf, size_t count)
1652{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001653 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001654 int error;
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001655 const char *fw_name;
1656 u8 bootldr_id;
Jing Lin8a9472d2012-03-21 15:43:45 -07001657 u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001658
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001659 /* If fw_name is set, then the existing firmware has an upgrade */
1660 if (!data->fw_name) {
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001661 /*
1662 * If the device boots up in the bootloader mode, check if
1663 * there is a firmware to upgrade.
1664 */
1665 if (data->state == BOOTLOADER) {
1666 bootldr_id = mxt_get_bootloader_id(data->client);
1667 if (bootldr_id <= 0) {
1668 dev_err(dev,
1669 "Unable to retrieve bootloader id\n");
1670 return -EINVAL;
1671 }
1672 fw_name = mxt_search_fw_name(data, bootldr_id);
1673 if (fw_name == NULL) {
1674 dev_err(dev,
1675 "Unable to find fw from bootloader id\n");
1676 return -EINVAL;
1677 }
1678 } else {
1679 /* In APPMODE, if the f/w name does not exist, quit */
1680 dev_err(dev,
1681 "Firmware name not specified in platform data\n");
1682 return -EINVAL;
1683 }
1684 } else {
1685 fw_name = data->fw_name;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001686 }
1687
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001688 dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001689
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001690 disable_irq(data->irq);
1691
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001692 error = mxt_load_fw(dev, fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001693 if (error) {
1694 dev_err(dev, "The firmware update failed(%d)\n", error);
1695 count = error;
1696 } else {
Nick Dyer0a4016c2012-01-18 15:17:59 +05301697 dev_info(dev, "The firmware update succeeded\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001698
1699 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001700 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001701
Nick Dyer0a4016c2012-01-18 15:17:59 +05301702 data->state = INIT;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001703 kfree(data->object_table);
1704 data->object_table = NULL;
Jing Lincc974cb2012-02-01 23:13:14 -08001705 data->cfg_version_idx = 0;
Jing Lin8fadad72012-02-24 10:10:50 -08001706 data->update_cfg = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001707
Jing Lin8a9472d2012-03-21 15:43:45 -07001708 error = __mxt_write_reg(data->client, data->t38_start_addr,
1709 sizeof(cfg_version), cfg_version);
1710 if (error)
1711 dev_err(dev,
1712 "Unable to zero out config version after fw upgrade\n");
1713
Iiro Valkonen7686b102011-02-02 23:21:58 -08001714 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001715 }
1716
Nick Dyer0a4016c2012-01-18 15:17:59 +05301717 if (data->state == APPMODE) {
1718 enable_irq(data->irq);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001719
Nick Dyer0a4016c2012-01-18 15:17:59 +05301720 error = mxt_make_highchg(data);
1721 if (error)
1722 return error;
1723 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07001724
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001725 return count;
1726}
1727
Iiro Valkonen7686b102011-02-02 23:21:58 -08001728static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
1729static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001730
Iiro Valkonen7686b102011-02-02 23:21:58 -08001731static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001732 &dev_attr_object.attr,
1733 &dev_attr_update_fw.attr,
1734 NULL
1735};
1736
Iiro Valkonen7686b102011-02-02 23:21:58 -08001737static const struct attribute_group mxt_attr_group = {
1738 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001739};
1740
Amy Maloche52262212011-09-15 16:46:57 -07001741static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001742{
Jing Lin36aee812011-10-17 17:17:28 -07001743 int error;
1744
Amy Maloche52262212011-09-15 16:46:57 -07001745 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07001746 error = __mxt_write_reg(data->client, data->t7_start_addr,
1747 T7_DATA_SIZE, data->t7_data);
1748 if (error < 0) {
1749 dev_err(&data->client->dev,
1750 "failed to restore old power state\n");
1751 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001752 }
Jing Lin36aee812011-10-17 17:17:28 -07001753
Amy Maloche52262212011-09-15 16:46:57 -07001754 error = mxt_write_object(data,
Iiro Valkonene8645592011-11-18 12:56:19 -08001755 MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, data->t9_ctrl);
Amy Maloche52262212011-09-15 16:46:57 -07001756 if (error < 0) {
1757 dev_err(&data->client->dev, "failed to restore touch\n");
1758 return error;
1759 }
1760
1761 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001762}
1763
Amy Maloche52262212011-09-15 16:46:57 -07001764static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001765{
Jing Lin36aee812011-10-17 17:17:28 -07001766 int error;
1767 u8 t7_data[T7_DATA_SIZE] = {0};
1768
1769 /* disable touch and configure deep sleep mode */
Iiro Valkonene8645592011-11-18 12:56:19 -08001770 error = mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
Jing Lin36aee812011-10-17 17:17:28 -07001771 if (error < 0) {
1772 dev_err(&data->client->dev, "failed to disable touch\n");
1773 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001774 }
1775
Jing Lin36aee812011-10-17 17:17:28 -07001776 error = __mxt_write_reg(data->client, data->t7_start_addr,
1777 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07001778 if (error < 0) {
1779 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07001780 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07001781 return error;
1782 }
1783
1784 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001785}
1786
Iiro Valkonen7686b102011-02-02 23:21:58 -08001787static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001788{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001789 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001790 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001791
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001792 if (data->state == APPMODE) {
1793 error = mxt_start(data);
1794 if (error < 0) {
1795 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
1796 return error;
1797 }
Amy Maloche52262212011-09-15 16:46:57 -07001798 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001799
1800 return 0;
1801}
1802
Iiro Valkonen7686b102011-02-02 23:21:58 -08001803static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001804{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001805 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001806 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001807
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001808 if (data->state == APPMODE) {
1809 error = mxt_stop(data);
1810 if (error < 0)
1811 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
1812 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001813}
1814
Amy Malochec331f842012-01-24 10:33:47 -08001815static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
1816{
1817 return (regulator_count_voltages(reg) > 0) ?
1818 regulator_set_optimum_mode(reg, load_uA) : 0;
1819}
1820
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301821static int mxt_power_on(struct mxt_data *data, bool on)
1822{
1823 int rc;
1824
1825 if (on == false)
1826 goto power_off;
1827
Amy Malochec331f842012-01-24 10:33:47 -08001828 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301829 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001830 dev_err(&data->client->dev,
1831 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301832 return rc;
1833 }
1834
Amy Maloche21115eb2011-11-02 09:04:37 -07001835 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301836 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001837 dev_err(&data->client->dev,
1838 "Regulator vcc_ana enable failed rc=%d\n", rc);
1839 goto error_reg_en_vcc_ana;
1840 }
1841
1842 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001843 rc = reg_set_optimum_mode_check(data->vcc_dig,
1844 MXT_ACTIVE_LOAD_DIG_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07001845 if (rc < 0) {
1846 dev_err(&data->client->dev,
1847 "Regulator vcc_dig set_opt failed rc=%d\n",
1848 rc);
1849 goto error_reg_opt_vcc_dig;
1850 }
1851
1852 rc = regulator_enable(data->vcc_dig);
1853 if (rc) {
1854 dev_err(&data->client->dev,
1855 "Regulator vcc_dig enable failed rc=%d\n", rc);
1856 goto error_reg_en_vcc_dig;
1857 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301858 }
1859
1860 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001861 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301862 if (rc < 0) {
1863 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001864 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301865 goto error_reg_opt_i2c;
1866 }
1867
1868 rc = regulator_enable(data->vcc_i2c);
1869 if (rc) {
1870 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001871 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301872 goto error_reg_en_vcc_i2c;
1873 }
1874 }
1875
Amy Malochef0d7b8d2011-10-17 12:10:51 -07001876 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301877
1878 return 0;
1879
1880error_reg_en_vcc_i2c:
1881 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08001882 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301883error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001884 if (data->pdata->digital_pwr_regulator)
1885 regulator_disable(data->vcc_dig);
1886error_reg_en_vcc_dig:
1887 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08001888 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001889error_reg_opt_vcc_dig:
1890 regulator_disable(data->vcc_ana);
1891error_reg_en_vcc_ana:
Amy Malochec331f842012-01-24 10:33:47 -08001892 reg_set_optimum_mode_check(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301893 return rc;
1894
1895power_off:
Amy Malochec331f842012-01-24 10:33:47 -08001896 reg_set_optimum_mode_check(data->vcc_ana, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001897 regulator_disable(data->vcc_ana);
1898 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001899 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001900 regulator_disable(data->vcc_dig);
1901 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301902 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001903 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301904 regulator_disable(data->vcc_i2c);
1905 }
1906 msleep(50);
1907 return 0;
1908}
1909
1910static int mxt_regulator_configure(struct mxt_data *data, bool on)
1911{
1912 int rc;
1913
1914 if (on == false)
1915 goto hw_shutdown;
1916
Amy Maloche21115eb2011-11-02 09:04:37 -07001917 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
1918 if (IS_ERR(data->vcc_ana)) {
1919 rc = PTR_ERR(data->vcc_ana);
1920 dev_err(&data->client->dev,
1921 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301922 return rc;
1923 }
1924
Amy Maloche21115eb2011-11-02 09:04:37 -07001925 if (regulator_count_voltages(data->vcc_ana) > 0) {
1926 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301927 MXT_VTG_MAX_UV);
1928 if (rc) {
1929 dev_err(&data->client->dev,
1930 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07001931 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301932 }
1933 }
Amy Maloche21115eb2011-11-02 09:04:37 -07001934 if (data->pdata->digital_pwr_regulator) {
1935 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
1936 if (IS_ERR(data->vcc_dig)) {
1937 rc = PTR_ERR(data->vcc_dig);
1938 dev_err(&data->client->dev,
1939 "Regulator get dig failed rc=%d\n", rc);
1940 goto error_get_vtg_vcc_dig;
1941 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301942
Amy Maloche21115eb2011-11-02 09:04:37 -07001943 if (regulator_count_voltages(data->vcc_dig) > 0) {
1944 rc = regulator_set_voltage(data->vcc_dig,
1945 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
1946 if (rc) {
1947 dev_err(&data->client->dev,
1948 "regulator set_vtg failed rc=%d\n", rc);
1949 goto error_set_vtg_vcc_dig;
1950 }
1951 }
1952 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301953 if (data->pdata->i2c_pull_up) {
1954 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
1955 if (IS_ERR(data->vcc_i2c)) {
1956 rc = PTR_ERR(data->vcc_i2c);
1957 dev_err(&data->client->dev,
1958 "Regulator get failed rc=%d\n", rc);
1959 goto error_get_vtg_i2c;
1960 }
1961 if (regulator_count_voltages(data->vcc_i2c) > 0) {
1962 rc = regulator_set_voltage(data->vcc_i2c,
1963 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
1964 if (rc) {
1965 dev_err(&data->client->dev,
1966 "regulator set_vtg failed rc=%d\n", rc);
1967 goto error_set_vtg_i2c;
1968 }
1969 }
1970 }
1971
1972 return 0;
1973
1974error_set_vtg_i2c:
1975 regulator_put(data->vcc_i2c);
1976error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001977 if (data->pdata->digital_pwr_regulator)
1978 if (regulator_count_voltages(data->vcc_dig) > 0)
1979 regulator_set_voltage(data->vcc_dig, 0,
1980 MXT_VTG_DIG_MAX_UV);
1981error_set_vtg_vcc_dig:
1982 if (data->pdata->digital_pwr_regulator)
1983 regulator_put(data->vcc_dig);
1984error_get_vtg_vcc_dig:
1985 if (regulator_count_voltages(data->vcc_ana) > 0)
1986 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1987error_set_vtg_vcc_ana:
1988 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301989 return rc;
1990
1991hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07001992 if (regulator_count_voltages(data->vcc_ana) > 0)
1993 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1994 regulator_put(data->vcc_ana);
1995 if (data->pdata->digital_pwr_regulator) {
1996 if (regulator_count_voltages(data->vcc_dig) > 0)
1997 regulator_set_voltage(data->vcc_dig, 0,
1998 MXT_VTG_DIG_MAX_UV);
1999 regulator_put(data->vcc_dig);
2000 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302001 if (data->pdata->i2c_pull_up) {
2002 if (regulator_count_voltages(data->vcc_i2c) > 0)
2003 regulator_set_voltage(data->vcc_i2c, 0,
2004 MXT_I2C_VTG_MAX_UV);
2005 regulator_put(data->vcc_i2c);
2006 }
2007 return 0;
2008}
2009
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302010#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07002011static int mxt_regulator_lpm(struct mxt_data *data, bool on)
2012{
2013
2014 int rc;
2015
2016 if (on == false)
2017 goto regulator_hpm;
2018
Amy Malochec331f842012-01-24 10:33:47 -08002019 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002020 if (rc < 0) {
2021 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002022 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002023 goto fail_regulator_lpm;
2024 }
2025
Amy Maloche21115eb2011-11-02 09:04:37 -07002026 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002027 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002028 MXT_LPM_LOAD_DIG_UA);
2029 if (rc < 0) {
2030 dev_err(&data->client->dev,
2031 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2032 goto fail_regulator_lpm;
2033 }
2034 }
2035
Jing Linbace50b2011-10-18 22:55:47 -07002036 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002037 rc = reg_set_optimum_mode_check(data->vcc_i2c,
Jing Linbace50b2011-10-18 22:55:47 -07002038 MXT_I2C_LPM_LOAD_UA);
2039 if (rc < 0) {
2040 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002041 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002042 goto fail_regulator_lpm;
2043 }
2044 }
2045
2046 return 0;
2047
2048regulator_hpm:
2049
Amy Malochec331f842012-01-24 10:33:47 -08002050 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002051 if (rc < 0) {
2052 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002053 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002054 goto fail_regulator_hpm;
2055 }
2056
Amy Maloche21115eb2011-11-02 09:04:37 -07002057 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002058 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002059 MXT_ACTIVE_LOAD_DIG_UA);
2060 if (rc < 0) {
2061 dev_err(&data->client->dev,
2062 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2063 goto fail_regulator_hpm;
2064 }
2065 }
2066
Jing Linbace50b2011-10-18 22:55:47 -07002067 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002068 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002069 if (rc < 0) {
2070 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002071 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002072 goto fail_regulator_hpm;
2073 }
2074 }
2075
2076 return 0;
2077
2078fail_regulator_lpm:
Amy Malochec331f842012-01-24 10:33:47 -08002079 reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_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,
2082 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002083 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002084 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002085
2086 return rc;
2087
2088fail_regulator_hpm:
Amy Malochec331f842012-01-24 10:33:47 -08002089 reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002090 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002091 reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002092 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002093 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002094
2095 return rc;
2096}
2097
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302098static int mxt_suspend(struct device *dev)
2099{
2100 struct i2c_client *client = to_i2c_client(dev);
2101 struct mxt_data *data = i2c_get_clientdata(client);
2102 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002103 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302104
2105 mutex_lock(&input_dev->mutex);
2106
Amy Maloche52262212011-09-15 16:46:57 -07002107 if (input_dev->users) {
2108 error = mxt_stop(data);
2109 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002110 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07002111 mutex_unlock(&input_dev->mutex);
2112 return error;
2113 }
2114
2115 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302116
2117 mutex_unlock(&input_dev->mutex);
2118
Jing Linbace50b2011-10-18 22:55:47 -07002119 /* put regulators in low power mode */
2120 error = mxt_regulator_lpm(data, true);
2121 if (error < 0) {
2122 dev_err(dev, "failed to enter low power mode\n");
2123 return error;
2124 }
2125
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302126 return 0;
2127}
2128
2129static int mxt_resume(struct device *dev)
2130{
2131 struct i2c_client *client = to_i2c_client(dev);
2132 struct mxt_data *data = i2c_get_clientdata(client);
2133 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002134 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302135
Jing Linbace50b2011-10-18 22:55:47 -07002136 /* put regulators in high power mode */
2137 error = mxt_regulator_lpm(data, false);
2138 if (error < 0) {
2139 dev_err(dev, "failed to enter high power mode\n");
2140 return error;
2141 }
2142
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302143 mutex_lock(&input_dev->mutex);
2144
Amy Maloche52262212011-09-15 16:46:57 -07002145 if (input_dev->users) {
2146 error = mxt_start(data);
2147 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002148 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07002149 mutex_unlock(&input_dev->mutex);
2150 return error;
2151 }
2152 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302153
2154 mutex_unlock(&input_dev->mutex);
2155
2156 return 0;
2157}
2158
2159#if defined(CONFIG_HAS_EARLYSUSPEND)
2160static void mxt_early_suspend(struct early_suspend *h)
2161{
2162 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2163
2164 mxt_suspend(&data->client->dev);
2165}
2166
2167static void mxt_late_resume(struct early_suspend *h)
2168{
2169 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2170
2171 mxt_resume(&data->client->dev);
2172}
2173#endif
2174
2175static const struct dev_pm_ops mxt_pm_ops = {
2176#ifndef CONFIG_HAS_EARLYSUSPEND
2177 .suspend = mxt_suspend,
2178 .resume = mxt_resume,
2179#endif
2180};
2181#endif
2182
Jing Lin6cfc00e2011-11-02 15:15:30 -07002183static int mxt_debugfs_object_show(struct seq_file *m, void *v)
2184{
2185 struct mxt_data *data = m->private;
2186 struct mxt_object *object;
2187 struct device *dev = &data->client->dev;
2188 int i, j, k;
2189 int error;
2190 int obj_size;
2191 u8 val;
2192
2193 for (i = 0; i < data->info.object_num; i++) {
2194 object = data->object_table + i;
2195 obj_size = object->size + 1;
2196
2197 seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
2198
2199 for (j = 0; j < object->instances + 1; j++) {
2200 seq_printf(m, "[Instance %d]\n", j);
2201
2202 for (k = 0; k < obj_size; k++) {
2203 error = mxt_read_object(data, object->type,
2204 j * obj_size + k, &val);
2205 if (error) {
2206 dev_err(dev,
2207 "Failed to read object %d "
2208 "instance %d at offset %d\n",
2209 object->type, j, k);
2210 return error;
2211 }
2212
2213 seq_printf(m, "Byte %d: 0x%02x (%d)\n",
2214 k, val, val);
2215 }
2216 }
2217 }
2218
2219 return 0;
2220}
2221
2222static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
2223{
2224 return single_open(file, mxt_debugfs_object_show, inode->i_private);
2225}
2226
2227static const struct file_operations mxt_object_fops = {
2228 .owner = THIS_MODULE,
2229 .open = mxt_debugfs_object_open,
2230 .read = seq_read,
2231 .release = single_release,
2232};
2233
2234static void __init mxt_debugfs_init(struct mxt_data *data)
2235{
2236 debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
2237 if (IS_ERR_OR_NULL(debug_base))
2238 pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
2239 if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
2240 0444,
2241 debug_base,
2242 data,
2243 &mxt_object_fops))) {
2244 pr_err("atmel_mxt_ts: Failed to create object file\n");
2245 debugfs_remove_recursive(debug_base);
2246 }
2247}
2248
Iiro Valkonen7686b102011-02-02 23:21:58 -08002249static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002250 const struct i2c_device_id *id)
2251{
Iiro Valkonen919ed892011-02-15 13:36:52 -08002252 const struct mxt_platform_data *pdata = client->dev.platform_data;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002253 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002254 struct input_dev *input_dev;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002255 int error, i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002256
Iiro Valkonen919ed892011-02-15 13:36:52 -08002257 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002258 return -EINVAL;
2259
Iiro Valkonen7686b102011-02-02 23:21:58 -08002260 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002261 input_dev = input_allocate_device();
2262 if (!data || !input_dev) {
2263 dev_err(&client->dev, "Failed to allocate memory\n");
2264 error = -ENOMEM;
2265 goto err_free_mem;
2266 }
2267
Nick Dyer0a4016c2012-01-18 15:17:59 +05302268 data->state = INIT;
Amy Maloche83c385a2012-02-01 10:32:03 +05302269 input_dev->name = "atmel_mxt_ts";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002270 input_dev->id.bustype = BUS_I2C;
2271 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002272 input_dev->open = mxt_input_open;
2273 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002274
Joonyoung Shim910d8052011-04-12 23:14:38 -07002275 data->client = client;
2276 data->input_dev = input_dev;
2277 data->pdata = pdata;
2278 data->irq = client->irq;
2279
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002280 __set_bit(EV_ABS, input_dev->evbit);
2281 __set_bit(EV_KEY, input_dev->evbit);
2282 __set_bit(BTN_TOUCH, input_dev->keybit);
2283
2284 /* For single touch */
2285 input_set_abs_params(input_dev, ABS_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002286 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002287 input_set_abs_params(input_dev, ABS_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002288 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07002289 input_set_abs_params(input_dev, ABS_PRESSURE,
2290 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002291
2292 /* For multi touch */
Joonyoung Shimcd473222012-02-14 18:32:48 -08002293 input_mt_init_slots(input_dev, MXT_MAX_FINGER);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002294 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08002295 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002296 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002297 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002298 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002299 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07002300 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2301 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002302
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002303 /* set key array supported keys */
2304 if (pdata->key_codes) {
2305 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
2306 if (pdata->key_codes[i])
2307 input_set_capability(input_dev, EV_KEY,
2308 pdata->key_codes[i]);
2309 }
2310 }
2311
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002312 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002313 i2c_set_clientdata(client, data);
2314
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302315 if (pdata->init_hw)
2316 error = pdata->init_hw(true);
2317 else
2318 error = mxt_regulator_configure(data, true);
2319 if (error) {
2320 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07002321 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302322 }
2323
2324 if (pdata->power_on)
2325 error = pdata->power_on(true);
2326 else
2327 error = mxt_power_on(data, true);
2328 if (error) {
2329 dev_err(&client->dev, "Failed to power on hardware\n");
2330 goto err_regulator_on;
2331 }
2332
Amy Maloche08266db2011-11-04 11:07:16 -07002333 if (gpio_is_valid(pdata->irq_gpio)) {
2334 /* configure touchscreen irq gpio */
2335 error = gpio_request(pdata->irq_gpio,
2336 "mxt_irq_gpio");
2337 if (error) {
2338 pr_err("%s: unable to request gpio [%d]\n", __func__,
2339 pdata->irq_gpio);
2340 goto err_power_on;
2341 }
2342 error = gpio_direction_input(pdata->irq_gpio);
2343 if (error) {
2344 pr_err("%s: unable to set_direction for gpio [%d]\n",
2345 __func__, pdata->irq_gpio);
2346 goto err_irq_gpio_req;
2347 }
2348 }
2349
2350 if (gpio_is_valid(pdata->reset_gpio)) {
2351 /* configure touchscreen reset out gpio */
2352 error = gpio_request(pdata->reset_gpio,
2353 "mxt_reset_gpio");
2354 if (error) {
2355 pr_err("%s: unable to request reset gpio %d\n",
2356 __func__, pdata->reset_gpio);
2357 goto err_irq_gpio_req;
2358 }
2359
2360 error = gpio_direction_output(
2361 pdata->reset_gpio, 1);
2362 if (error) {
2363 pr_err("%s: unable to set direction for gpio %d\n",
2364 __func__, pdata->reset_gpio);
2365 goto err_reset_gpio_req;
2366 }
2367 }
2368
2369 mxt_reset_delay(data);
2370
Iiro Valkonen7686b102011-02-02 23:21:58 -08002371 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002372 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07002373 goto err_reset_gpio_req;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002374
Iiro Valkonen7686b102011-02-02 23:21:58 -08002375 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08002376 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002377 if (error) {
2378 dev_err(&client->dev, "Failed to register interrupt\n");
Jing Lin32c72532011-11-03 12:02:33 -07002379 goto err_free_object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002380 }
2381
Nick Dyer0a4016c2012-01-18 15:17:59 +05302382 if (data->state == APPMODE) {
2383 error = mxt_make_highchg(data);
2384 if (error) {
2385 dev_err(&client->dev, "Failed to make high CHG\n");
2386 goto err_free_irq;
2387 }
2388 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07002389
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002390 error = input_register_device(input_dev);
2391 if (error)
2392 goto err_free_irq;
2393
Iiro Valkonen7686b102011-02-02 23:21:58 -08002394 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002395 if (error)
2396 goto err_unregister_device;
2397
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302398#if defined(CONFIG_HAS_EARLYSUSPEND)
2399 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
2400 MXT_SUSPEND_LEVEL;
2401 data->early_suspend.suspend = mxt_early_suspend;
2402 data->early_suspend.resume = mxt_late_resume;
2403 register_early_suspend(&data->early_suspend);
2404#endif
2405
Jing Lin6cfc00e2011-11-02 15:15:30 -07002406 mxt_debugfs_init(data);
2407
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002408 return 0;
2409
2410err_unregister_device:
2411 input_unregister_device(input_dev);
2412 input_dev = NULL;
2413err_free_irq:
2414 free_irq(client->irq, data);
Jing Lin32c72532011-11-03 12:02:33 -07002415err_free_object:
2416 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07002417err_reset_gpio_req:
2418 if (gpio_is_valid(pdata->reset_gpio))
2419 gpio_free(pdata->reset_gpio);
2420err_irq_gpio_req:
2421 if (gpio_is_valid(pdata->irq_gpio))
2422 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302423err_power_on:
2424 if (pdata->power_on)
2425 pdata->power_on(false);
2426 else
2427 mxt_power_on(data, false);
2428err_regulator_on:
2429 if (pdata->init_hw)
2430 pdata->init_hw(false);
2431 else
2432 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002433err_free_mem:
2434 input_free_device(input_dev);
2435 kfree(data);
2436 return error;
2437}
2438
Iiro Valkonen7686b102011-02-02 23:21:58 -08002439static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002440{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002441 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002442
Iiro Valkonen7686b102011-02-02 23:21:58 -08002443 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002444 free_irq(data->irq, data);
2445 input_unregister_device(data->input_dev);
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302446#if defined(CONFIG_HAS_EARLYSUSPEND)
2447 unregister_early_suspend(&data->early_suspend);
2448#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302449
2450 if (data->pdata->power_on)
2451 data->pdata->power_on(false);
2452 else
2453 mxt_power_on(data, false);
2454
2455 if (data->pdata->init_hw)
2456 data->pdata->init_hw(false);
2457 else
2458 mxt_regulator_configure(data, false);
2459
Mohan Pallakabfe8f302012-01-02 18:32:08 +08002460 if (gpio_is_valid(data->pdata->reset_gpio))
2461 gpio_free(data->pdata->reset_gpio);
2462
2463 if (gpio_is_valid(data->pdata->irq_gpio))
2464 gpio_free(data->pdata->irq_gpio);
2465
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002466 kfree(data->object_table);
2467 kfree(data);
2468
Jing Lin6cfc00e2011-11-02 15:15:30 -07002469 debugfs_remove_recursive(debug_base);
2470
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002471 return 0;
2472}
2473
Iiro Valkonen7686b102011-02-02 23:21:58 -08002474static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002475 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002476 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08002477 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002478 { }
2479};
Iiro Valkonen7686b102011-02-02 23:21:58 -08002480MODULE_DEVICE_TABLE(i2c, mxt_id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002481
Iiro Valkonen7686b102011-02-02 23:21:58 -08002482static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002483 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08002484 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002485 .owner = THIS_MODULE,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002486#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08002487 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002488#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002489 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002490 .probe = mxt_probe,
2491 .remove = __devexit_p(mxt_remove),
2492 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002493};
2494
Iiro Valkonen7686b102011-02-02 23:21:58 -08002495static int __init mxt_init(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002496{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002497 return i2c_add_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002498}
2499
Iiro Valkonen7686b102011-02-02 23:21:58 -08002500static void __exit mxt_exit(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002501{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002502 i2c_del_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002503}
2504
Iiro Valkonen7686b102011-02-02 23:21:58 -08002505module_init(mxt_init);
2506module_exit(mxt_exit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002507
2508/* Module information */
2509MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08002510MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002511MODULE_LICENSE("GPL");