blob: 10bf66ae23dea48fb45c2debc54ce55cdac40593 [file] [log] [blame]
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001/*
Iiro Valkonen7686b102011-02-02 23:21:58 -08002 * Atmel maXTouch Touchscreen driver
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003 *
4 * Copyright (C) 2010 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
Mohan Pallaka5e7343f2012-01-02 18:30:16 +08006 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07007 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/firmware.h>
19#include <linux/i2c.h>
Dmitry Torokhov964de522011-02-02 23:21:58 -080020#include <linux/i2c/atmel_mxt_ts.h>
Joonyoung Shimcd473222012-02-14 18:32:48 -080021#include <linux/input/mt.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070022#include <linux/interrupt.h>
23#include <linux/slab.h>
Amy Maloche08266db2011-11-04 11:07:16 -070024#include <linux/gpio.h>
Jing Lin6cfc00e2011-11-02 15:15:30 -070025#include <linux/debugfs.h>
26#include <linux/seq_file.h>
Anirudh Ghayala498e4d2011-08-09 19:10:12 +053027#include <linux/regulator/consumer.h>
Jing Lincc974cb2012-02-01 23:13:14 -080028#include <linux/string.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070029
Anirudh Ghayal253ce122011-08-09 19:32:57 +053030#if defined(CONFIG_HAS_EARLYSUSPEND)
31#include <linux/earlysuspend.h>
32/* Early-suspend level */
33#define MXT_SUSPEND_LEVEL 1
34#endif
35
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070036/* Family ID */
37#define MXT224_ID 0x80
Amy Maloche380cc0b2011-11-03 12:55:04 -070038#define MXT224E_ID 0x81
Iiro Valkonen4ac053c2011-09-08 11:10:52 -070039#define MXT1386_ID 0xA0
40
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070041/* Version */
Iiro Valkonen7686b102011-02-02 23:21:58 -080042#define MXT_VER_20 20
43#define MXT_VER_21 21
44#define MXT_VER_22 22
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070045
Nick Dyer0a4016c2012-01-18 15:17:59 +053046/* I2C slave address pairs */
47struct mxt_address_pair {
48 int bootloader;
49 int application;
50};
51
52static const struct mxt_address_pair mxt_slave_addresses[] = {
53 { 0x24, 0x4a },
54 { 0x25, 0x4b },
55 { 0x25, 0x4b },
56 { 0x26, 0x4c },
57 { 0x27, 0x4d },
58 { 0x34, 0x5a },
59 { 0x35, 0x5b },
60 { 0 },
61};
62
63enum mxt_device_state { INIT, APPMODE, BOOTLOADER };
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070064
65/* Firmware */
Iiro Valkonen7686b102011-02-02 23:21:58 -080066#define MXT_FW_NAME "maxtouch.fw"
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070067
Jing Lincc974cb2012-02-01 23:13:14 -080068/* Firmware frame size including frame data and CRC */
69#define MXT_SINGLE_FW_MAX_FRAME_SIZE 278
70#define MXT_CHIPSET_FW_MAX_FRAME_SIZE 534
71
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070072/* Registers */
Iiro Valkonen7686b102011-02-02 23:21:58 -080073#define MXT_FAMILY_ID 0x00
74#define MXT_VARIANT_ID 0x01
75#define MXT_VERSION 0x02
76#define MXT_BUILD 0x03
77#define MXT_MATRIX_X_SIZE 0x04
78#define MXT_MATRIX_Y_SIZE 0x05
79#define MXT_OBJECT_NUM 0x06
80#define MXT_OBJECT_START 0x07
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070081
Iiro Valkonen7686b102011-02-02 23:21:58 -080082#define MXT_OBJECT_SIZE 6
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070083
84/* Object types */
Iiro Valkonene8645592011-11-18 12:56:19 -080085#define MXT_DEBUG_DIAGNOSTIC_T37 37
86#define MXT_GEN_MESSAGE_T5 5
87#define MXT_GEN_COMMAND_T6 6
88#define MXT_GEN_POWER_T7 7
89#define MXT_GEN_ACQUIRE_T8 8
90#define MXT_GEN_DATASOURCE_T53 53
91#define MXT_TOUCH_MULTI_T9 9
92#define MXT_TOUCH_KEYARRAY_T15 15
93#define MXT_TOUCH_PROXIMITY_T23 23
94#define MXT_TOUCH_PROXKEY_T52 52
95#define MXT_PROCI_GRIPFACE_T20 20
96#define MXT_PROCG_NOISE_T22 22
97#define MXT_PROCI_ONETOUCH_T24 24
98#define MXT_PROCI_TWOTOUCH_T27 27
99#define MXT_PROCI_GRIP_T40 40
100#define MXT_PROCI_PALM_T41 41
101#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
102#define MXT_PROCI_STYLUS_T47 47
Jing Linc7fc4052011-12-21 16:16:19 -0800103#define MXT_PROCI_SHIELDLESS_T56 56
Iiro Valkonene8645592011-11-18 12:56:19 -0800104#define MXT_PROCG_NOISESUPPRESSION_T48 48
105#define MXT_SPT_COMMSCONFIG_T18 18
106#define MXT_SPT_GPIOPWM_T19 19
107#define MXT_SPT_SELFTEST_T25 25
108#define MXT_SPT_CTECONFIG_T28 28
109#define MXT_SPT_USERDATA_T38 38
110#define MXT_SPT_DIGITIZER_T43 43
111#define MXT_SPT_MESSAGECOUNT_T44 44
112#define MXT_SPT_CTECONFIG_T46 46
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700113
Iiro Valkonene8645592011-11-18 12:56:19 -0800114/* MXT_GEN_COMMAND_T6 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800115#define MXT_COMMAND_RESET 0
116#define MXT_COMMAND_BACKUPNV 1
117#define MXT_COMMAND_CALIBRATE 2
118#define MXT_COMMAND_REPORTALL 3
119#define MXT_COMMAND_DIAGNOSTIC 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700120
Iiro Valkonene8645592011-11-18 12:56:19 -0800121/* MXT_GEN_POWER_T7 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800122#define MXT_POWER_IDLEACQINT 0
123#define MXT_POWER_ACTVACQINT 1
124#define MXT_POWER_ACTV2IDLETO 2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700125
Iiro Valkonene8645592011-11-18 12:56:19 -0800126/* MXT_GEN_ACQUIRE_T8 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800127#define MXT_ACQUIRE_CHRGTIME 0
128#define MXT_ACQUIRE_TCHDRIFT 2
129#define MXT_ACQUIRE_DRIFTST 3
130#define MXT_ACQUIRE_TCHAUTOCAL 4
131#define MXT_ACQUIRE_SYNC 5
132#define MXT_ACQUIRE_ATCHCALST 6
133#define MXT_ACQUIRE_ATCHCALSTHR 7
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700134
Iiro Valkonene8645592011-11-18 12:56:19 -0800135/* MXT_TOUCH_MULT_T9 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800136#define MXT_TOUCH_CTRL 0
137#define MXT_TOUCH_XORIGIN 1
138#define MXT_TOUCH_YORIGIN 2
139#define MXT_TOUCH_XSIZE 3
140#define MXT_TOUCH_YSIZE 4
141#define MXT_TOUCH_BLEN 6
142#define MXT_TOUCH_TCHTHR 7
143#define MXT_TOUCH_TCHDI 8
144#define MXT_TOUCH_ORIENT 9
145#define MXT_TOUCH_MOVHYSTI 11
146#define MXT_TOUCH_MOVHYSTN 12
147#define MXT_TOUCH_NUMTOUCH 14
148#define MXT_TOUCH_MRGHYST 15
149#define MXT_TOUCH_MRGTHR 16
150#define MXT_TOUCH_AMPHYST 17
151#define MXT_TOUCH_XRANGE_LSB 18
152#define MXT_TOUCH_XRANGE_MSB 19
153#define MXT_TOUCH_YRANGE_LSB 20
154#define MXT_TOUCH_YRANGE_MSB 21
155#define MXT_TOUCH_XLOCLIP 22
156#define MXT_TOUCH_XHICLIP 23
157#define MXT_TOUCH_YLOCLIP 24
158#define MXT_TOUCH_YHICLIP 25
159#define MXT_TOUCH_XEDGECTRL 26
160#define MXT_TOUCH_XEDGEDIST 27
161#define MXT_TOUCH_YEDGECTRL 28
162#define MXT_TOUCH_YEDGEDIST 29
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700163#define MXT_TOUCH_JUMPLIMIT 30
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700164
Iiro Valkonene8645592011-11-18 12:56:19 -0800165/* MXT_PROCI_GRIPFACE_T20 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800166#define MXT_GRIPFACE_CTRL 0
167#define MXT_GRIPFACE_XLOGRIP 1
168#define MXT_GRIPFACE_XHIGRIP 2
169#define MXT_GRIPFACE_YLOGRIP 3
170#define MXT_GRIPFACE_YHIGRIP 4
171#define MXT_GRIPFACE_MAXTCHS 5
172#define MXT_GRIPFACE_SZTHR1 7
173#define MXT_GRIPFACE_SZTHR2 8
174#define MXT_GRIPFACE_SHPTHR1 9
175#define MXT_GRIPFACE_SHPTHR2 10
176#define MXT_GRIPFACE_SUPEXTTO 11
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700177
Iiro Valkonen7686b102011-02-02 23:21:58 -0800178/* MXT_PROCI_NOISE field */
179#define MXT_NOISE_CTRL 0
180#define MXT_NOISE_OUTFLEN 1
181#define MXT_NOISE_GCAFUL_LSB 3
182#define MXT_NOISE_GCAFUL_MSB 4
183#define MXT_NOISE_GCAFLL_LSB 5
184#define MXT_NOISE_GCAFLL_MSB 6
185#define MXT_NOISE_ACTVGCAFVALID 7
186#define MXT_NOISE_NOISETHR 8
187#define MXT_NOISE_FREQHOPSCALE 10
188#define MXT_NOISE_FREQ0 11
189#define MXT_NOISE_FREQ1 12
190#define MXT_NOISE_FREQ2 13
191#define MXT_NOISE_FREQ3 14
192#define MXT_NOISE_FREQ4 15
193#define MXT_NOISE_IDLEGCAFVALID 16
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700194
Iiro Valkonene8645592011-11-18 12:56:19 -0800195/* MXT_SPT_COMMSCONFIG_T18 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800196#define MXT_COMMS_CTRL 0
197#define MXT_COMMS_CMD 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700198
Iiro Valkonene8645592011-11-18 12:56:19 -0800199/* MXT_SPT_CTECONFIG_T28 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800200#define MXT_CTE_CTRL 0
201#define MXT_CTE_CMD 1
202#define MXT_CTE_MODE 2
203#define MXT_CTE_IDLEGCAFDEPTH 3
204#define MXT_CTE_ACTVGCAFDEPTH 4
Joonyoung Shim979a72d2011-03-14 21:41:34 -0700205#define MXT_CTE_VOLTAGE 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700206
Iiro Valkonen7686b102011-02-02 23:21:58 -0800207#define MXT_VOLTAGE_DEFAULT 2700000
208#define MXT_VOLTAGE_STEP 10000
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700209
Amy Maloche21115eb2011-11-02 09:04:37 -0700210/* Analog voltage @2.7 V */
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530211#define MXT_VTG_MIN_UV 2700000
212#define MXT_VTG_MAX_UV 3300000
213#define MXT_ACTIVE_LOAD_UA 15000
Jing Linbace50b2011-10-18 22:55:47 -0700214#define MXT_LPM_LOAD_UA 10
Amy Maloche21115eb2011-11-02 09:04:37 -0700215/* Digital voltage @1.8 V */
216#define MXT_VTG_DIG_MIN_UV 1800000
217#define MXT_VTG_DIG_MAX_UV 1800000
218#define MXT_ACTIVE_LOAD_DIG_UA 10000
219#define MXT_LPM_LOAD_DIG_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530220
221#define MXT_I2C_VTG_MIN_UV 1800000
222#define MXT_I2C_VTG_MAX_UV 1800000
223#define MXT_I2C_LOAD_UA 10000
Jing Linbace50b2011-10-18 22:55:47 -0700224#define MXT_I2C_LPM_LOAD_UA 10
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530225
Iiro Valkonene8645592011-11-18 12:56:19 -0800226/* Define for MXT_GEN_COMMAND_T6 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800227#define MXT_BOOT_VALUE 0xa5
228#define MXT_BACKUP_VALUE 0x55
229#define MXT_BACKUP_TIME 25 /* msec */
Jing Linc7fc4052011-12-21 16:16:19 -0800230#define MXT224_RESET_TIME 65 /* msec */
231#define MXT224E_RESET_TIME 22 /* msec */
232#define MXT1386_RESET_TIME 250 /* msec */
Amy Maloche7e447432011-09-14 11:36:30 -0700233#define MXT_RESET_TIME 250 /* msec */
Jing Linc7fc4052011-12-21 16:16:19 -0800234#define MXT_RESET_NOCHGREAD 400 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700235
Nick Dyer0a4016c2012-01-18 15:17:59 +0530236#define MXT_FWRESET_TIME 1000 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700237
Jing Lin36aee812011-10-17 17:17:28 -0700238#define MXT_WAKE_TIME 25
239
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700240/* Command to unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800241#define MXT_UNLOCK_CMD_MSB 0xaa
242#define MXT_UNLOCK_CMD_LSB 0xdc
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700243
244/* Bootloader mode status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800245#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
246#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
247#define MXT_FRAME_CRC_CHECK 0x02
248#define MXT_FRAME_CRC_FAIL 0x03
249#define MXT_FRAME_CRC_PASS 0x04
250#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
251#define MXT_BOOT_STATUS_MASK 0x3f
Nick Dyer0a4016c2012-01-18 15:17:59 +0530252#define MXT_BOOT_EXTENDED_ID (1 << 5)
253#define MXT_BOOT_ID_MASK 0x1f
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700254
255/* Touch status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800256#define MXT_SUPPRESS (1 << 1)
257#define MXT_AMP (1 << 2)
258#define MXT_VECTOR (1 << 3)
259#define MXT_MOVE (1 << 4)
260#define MXT_RELEASE (1 << 5)
261#define MXT_PRESS (1 << 6)
262#define MXT_DETECT (1 << 7)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700263
Joonyoung Shim910d8052011-04-12 23:14:38 -0700264/* Touch orient bits */
265#define MXT_XY_SWITCH (1 << 0)
266#define MXT_X_INVERT (1 << 1)
267#define MXT_Y_INVERT (1 << 2)
268
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700269/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800270#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700271
Iiro Valkonen7686b102011-02-02 23:21:58 -0800272#define MXT_MAX_FINGER 10
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700273
Jing Lin36aee812011-10-17 17:17:28 -0700274#define T7_DATA_SIZE 3
275#define MXT_MAX_RW_TRIES 3
276#define MXT_BLOCK_SIZE 256
Jing Lin8fadad72012-02-24 10:10:50 -0800277#define MXT_CFG_VERSION_LEN 3
278#define MXT_CFG_VERSION_EQUAL 0
279#define MXT_CFG_VERSION_LESS 1
280#define MXT_CFG_VERSION_GREATER 2
Mohan Pallakaab51f2b2011-09-29 18:17:35 +0530281
Jing Lin6cfc00e2011-11-02 15:15:30 -0700282#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
283#define MXT_DEBUGFS_FILE "object"
284
Iiro Valkonen7686b102011-02-02 23:21:58 -0800285struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700286 u8 family_id;
287 u8 variant_id;
288 u8 version;
289 u8 build;
290 u8 matrix_xsize;
291 u8 matrix_ysize;
292 u8 object_num;
293};
294
Iiro Valkonen7686b102011-02-02 23:21:58 -0800295struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700296 u8 type;
297 u16 start_address;
298 u8 size;
299 u8 instances;
300 u8 num_report_ids;
301
302 /* to map object and message */
303 u8 max_reportid;
304};
305
Iiro Valkonen7686b102011-02-02 23:21:58 -0800306struct mxt_message {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700307 u8 reportid;
308 u8 message[7];
309 u8 checksum;
310};
311
Iiro Valkonen7686b102011-02-02 23:21:58 -0800312struct mxt_finger {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700313 int status;
314 int x;
315 int y;
316 int area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700317 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700318};
319
320/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800321struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700322 struct i2c_client *client;
323 struct input_dev *input_dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800324 const struct mxt_platform_data *pdata;
Jing Lindc4413c2012-01-16 15:22:52 -0800325 const struct mxt_config_info *config_info;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530326 enum mxt_device_state state;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800327 struct mxt_object *object_table;
328 struct mxt_info info;
329 struct mxt_finger finger[MXT_MAX_FINGER];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700330 unsigned int irq;
Amy Maloche21115eb2011-11-02 09:04:37 -0700331 struct regulator *vcc_ana;
332 struct regulator *vcc_dig;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530333 struct regulator *vcc_i2c;
Anirudh Ghayal253ce122011-08-09 19:32:57 +0530334#if defined(CONFIG_HAS_EARLYSUSPEND)
335 struct early_suspend early_suspend;
336#endif
Jing Lin36aee812011-10-17 17:17:28 -0700337
Amy Maloche52262212011-09-15 16:46:57 -0700338 u8 t7_data[T7_DATA_SIZE];
Jing Lin36aee812011-10-17 17:17:28 -0700339 u16 t7_start_addr;
Amy Maloche52262212011-09-15 16:46:57 -0700340 u8 t9_ctrl;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800341 u32 keyarray_old;
342 u32 keyarray_new;
343 u8 t9_max_reportid;
344 u8 t9_min_reportid;
345 u8 t15_max_reportid;
346 u8 t15_min_reportid;
Jing Lin8fadad72012-02-24 10:10:50 -0800347 u8 cfg_version[MXT_CFG_VERSION_LEN];
Jing Lindc4413c2012-01-16 15:22:52 -0800348 int cfg_version_idx;
Jing Lin8fadad72012-02-24 10:10:50 -0800349 bool update_cfg;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -0800350 const char *fw_name;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700351};
352
Jing Lin6cfc00e2011-11-02 15:15:30 -0700353static struct dentry *debug_base;
354
Iiro Valkonen7686b102011-02-02 23:21:58 -0800355static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700356{
357 switch (type) {
Iiro Valkonene8645592011-11-18 12:56:19 -0800358 case MXT_GEN_MESSAGE_T5:
359 case MXT_GEN_COMMAND_T6:
360 case MXT_GEN_POWER_T7:
361 case MXT_GEN_ACQUIRE_T8:
362 case MXT_GEN_DATASOURCE_T53:
363 case MXT_TOUCH_MULTI_T9:
364 case MXT_TOUCH_KEYARRAY_T15:
365 case MXT_TOUCH_PROXIMITY_T23:
366 case MXT_TOUCH_PROXKEY_T52:
367 case MXT_PROCI_GRIPFACE_T20:
368 case MXT_PROCG_NOISE_T22:
369 case MXT_PROCI_ONETOUCH_T24:
370 case MXT_PROCI_TWOTOUCH_T27:
371 case MXT_PROCI_GRIP_T40:
372 case MXT_PROCI_PALM_T41:
373 case MXT_PROCI_TOUCHSUPPRESSION_T42:
374 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800375 case MXT_PROCI_SHIELDLESS_T56:
Iiro Valkonene8645592011-11-18 12:56:19 -0800376 case MXT_PROCG_NOISESUPPRESSION_T48:
377 case MXT_SPT_COMMSCONFIG_T18:
378 case MXT_SPT_GPIOPWM_T19:
379 case MXT_SPT_SELFTEST_T25:
380 case MXT_SPT_CTECONFIG_T28:
381 case MXT_SPT_USERDATA_T38:
382 case MXT_SPT_DIGITIZER_T43:
383 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700384 return true;
385 default:
386 return false;
387 }
388}
389
Iiro Valkonen7686b102011-02-02 23:21:58 -0800390static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700391{
392 switch (type) {
Iiro Valkonene8645592011-11-18 12:56:19 -0800393 case MXT_GEN_COMMAND_T6:
394 case MXT_GEN_POWER_T7:
395 case MXT_GEN_ACQUIRE_T8:
396 case MXT_TOUCH_MULTI_T9:
397 case MXT_TOUCH_KEYARRAY_T15:
398 case MXT_TOUCH_PROXIMITY_T23:
399 case MXT_TOUCH_PROXKEY_T52:
400 case MXT_PROCI_GRIPFACE_T20:
401 case MXT_PROCG_NOISE_T22:
402 case MXT_PROCI_ONETOUCH_T24:
403 case MXT_PROCI_TWOTOUCH_T27:
404 case MXT_PROCI_GRIP_T40:
405 case MXT_PROCI_PALM_T41:
406 case MXT_PROCI_TOUCHSUPPRESSION_T42:
407 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800408 case MXT_PROCI_SHIELDLESS_T56:
Iiro Valkonene8645592011-11-18 12:56:19 -0800409 case MXT_PROCG_NOISESUPPRESSION_T48:
410 case MXT_SPT_COMMSCONFIG_T18:
411 case MXT_SPT_GPIOPWM_T19:
412 case MXT_SPT_SELFTEST_T25:
413 case MXT_SPT_CTECONFIG_T28:
414 case MXT_SPT_USERDATA_T38:
415 case MXT_SPT_DIGITIZER_T43:
416 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700417 return true;
418 default:
419 return false;
420 }
421}
422
Iiro Valkonen7686b102011-02-02 23:21:58 -0800423static void mxt_dump_message(struct device *dev,
424 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700425{
426 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
427 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
428 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
429 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
430 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
431 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
432 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
433 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
434 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
435}
436
Nick Dyer0a4016c2012-01-18 15:17:59 +0530437static int mxt_switch_to_bootloader_address(struct mxt_data *data)
438{
439 int i;
440 struct i2c_client *client = data->client;
441
442 if (data->state == BOOTLOADER) {
443 dev_err(&client->dev, "Already in BOOTLOADER state\n");
444 return -EINVAL;
445 }
446
447 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
448 if (mxt_slave_addresses[i].application == client->addr) {
449 dev_info(&client->dev, "Changing to bootloader address: "
450 "%02x -> %02x",
451 client->addr,
452 mxt_slave_addresses[i].bootloader);
453
454 client->addr = mxt_slave_addresses[i].bootloader;
455 data->state = BOOTLOADER;
456 return 0;
457 }
458 }
459
460 dev_err(&client->dev, "Address 0x%02x not found in address table",
461 client->addr);
462 return -EINVAL;
463}
464
465static int mxt_switch_to_appmode_address(struct mxt_data *data)
466{
467 int i;
468 struct i2c_client *client = data->client;
469
470 if (data->state == APPMODE) {
471 dev_err(&client->dev, "Already in APPMODE state\n");
472 return -EINVAL;
473 }
474
475 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
476 if (mxt_slave_addresses[i].bootloader == client->addr) {
477 dev_info(&client->dev,
478 "Changing to application mode address: "
479 "0x%02x -> 0x%02x",
480 client->addr,
481 mxt_slave_addresses[i].application);
482
483 client->addr = mxt_slave_addresses[i].application;
484 data->state = APPMODE;
485 return 0;
486 }
487 }
488
489 dev_err(&client->dev, "Address 0x%02x not found in address table",
490 client->addr);
491 return -EINVAL;
492}
493
494static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
495{
496 u8 buf[3];
497
498 if (val | MXT_BOOT_EXTENDED_ID) {
499 dev_dbg(&client->dev,
500 "Retrieving extended mode ID information");
501
502 if (i2c_master_recv(client, &buf[0], 3) != 3) {
503 dev_err(&client->dev, "%s: i2c recv failed\n",
504 __func__);
505 return -EIO;
506 }
507
508 dev_info(&client->dev, "Bootloader ID:%d Version:%d",
509 buf[1], buf[2]);
510
511 return buf[0];
512 } else {
513 dev_info(&client->dev, "Bootloader ID:%d",
514 val & MXT_BOOT_ID_MASK);
515
516 return val;
517 }
518}
519
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -0800520static int mxt_get_bootloader_id(struct i2c_client *client)
521{
522 u8 val;
523 u8 buf[3];
524
525 if (i2c_master_recv(client, &val, 1) != 1) {
526 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
527 return -EIO;
528 }
529
530 if (val | MXT_BOOT_EXTENDED_ID) {
531 if (i2c_master_recv(client, &buf[0], 3) != 3) {
532 dev_err(&client->dev, "%s: i2c recv failed\n",
533 __func__);
534 return -EIO;
535 }
536 return buf[1];
537 } else {
538 dev_info(&client->dev, "Bootloader ID:%d",
539 val & MXT_BOOT_ID_MASK);
540
541 return val & MXT_BOOT_ID_MASK;
542 }
543}
544
Iiro Valkonen7686b102011-02-02 23:21:58 -0800545static int mxt_check_bootloader(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530546 unsigned int state)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700547{
548 u8 val;
549
550recheck:
551 if (i2c_master_recv(client, &val, 1) != 1) {
552 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
553 return -EIO;
554 }
555
556 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800557 case MXT_WAITING_BOOTLOAD_CMD:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530558 val = mxt_get_bootloader_version(client, val);
559 val &= ~MXT_BOOT_STATUS_MASK;
560 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800561 case MXT_WAITING_FRAME_DATA:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530562 case MXT_APP_CRC_FAIL:
Iiro Valkonen7686b102011-02-02 23:21:58 -0800563 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700564 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800565 case MXT_FRAME_CRC_PASS:
566 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700567 goto recheck;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530568 if (val == MXT_FRAME_CRC_FAIL) {
569 dev_err(&client->dev, "Bootloader CRC fail\n");
570 return -EINVAL;
571 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700572 break;
573 default:
574 return -EINVAL;
575 }
576
577 if (val != state) {
Nick Dyer0a4016c2012-01-18 15:17:59 +0530578 dev_err(&client->dev, "Invalid bootloader mode state %X\n",
579 val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700580 return -EINVAL;
581 }
582
583 return 0;
584}
585
Iiro Valkonen7686b102011-02-02 23:21:58 -0800586static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700587{
588 u8 buf[2];
589
Iiro Valkonen7686b102011-02-02 23:21:58 -0800590 buf[0] = MXT_UNLOCK_CMD_LSB;
591 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700592
593 if (i2c_master_send(client, buf, 2) != 2) {
594 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
595 return -EIO;
596 }
597
598 return 0;
599}
600
Iiro Valkonen7686b102011-02-02 23:21:58 -0800601static int mxt_fw_write(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530602 const u8 *data, unsigned int frame_size)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700603{
604 if (i2c_master_send(client, data, frame_size) != frame_size) {
605 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
606 return -EIO;
607 }
608
609 return 0;
610}
611
Iiro Valkonen7686b102011-02-02 23:21:58 -0800612static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700613 u16 reg, u16 len, void *val)
614{
615 struct i2c_msg xfer[2];
616 u8 buf[2];
Jing Lin36aee812011-10-17 17:17:28 -0700617 int i = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700618
619 buf[0] = reg & 0xff;
620 buf[1] = (reg >> 8) & 0xff;
621
622 /* Write register */
623 xfer[0].addr = client->addr;
624 xfer[0].flags = 0;
625 xfer[0].len = 2;
626 xfer[0].buf = buf;
627
628 /* Read data */
629 xfer[1].addr = client->addr;
630 xfer[1].flags = I2C_M_RD;
631 xfer[1].len = len;
632 xfer[1].buf = val;
633
Jing Lin36aee812011-10-17 17:17:28 -0700634 do {
635 if (i2c_transfer(client->adapter, xfer, 2) == 2)
636 return 0;
637 msleep(MXT_WAKE_TIME);
638 } while (++i < MXT_MAX_RW_TRIES);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700639
Jing Lin36aee812011-10-17 17:17:28 -0700640 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
641 return -EIO;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700642}
643
Iiro Valkonen7686b102011-02-02 23:21:58 -0800644static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700645{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800646 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700647}
648
Jing Lin36aee812011-10-17 17:17:28 -0700649static int __mxt_write_reg(struct i2c_client *client,
650 u16 addr, u16 length, u8 *value)
651{
652 u8 buf[MXT_BLOCK_SIZE + 2];
653 int i, tries = 0;
654
655 if (length > MXT_BLOCK_SIZE)
656 return -EINVAL;
657
658 buf[0] = addr & 0xff;
659 buf[1] = (addr >> 8) & 0xff;
660 for (i = 0; i < length; i++)
661 buf[i + 2] = *value++;
662
663 do {
664 if (i2c_master_send(client, buf, length + 2) == (length + 2))
665 return 0;
666 msleep(MXT_WAKE_TIME);
667 } while (++tries < MXT_MAX_RW_TRIES);
668
669 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
670 return -EIO;
671}
672
Iiro Valkonen7686b102011-02-02 23:21:58 -0800673static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700674{
Jing Lin36aee812011-10-17 17:17:28 -0700675 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700676}
677
Iiro Valkonen7686b102011-02-02 23:21:58 -0800678static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700679 u16 reg, u8 *object_buf)
680{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800681 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700682 object_buf);
683}
684
Iiro Valkonen7686b102011-02-02 23:21:58 -0800685static struct mxt_object *
686mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700687{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800688 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700689 int i;
690
691 for (i = 0; i < data->info.object_num; i++) {
692 object = data->object_table + i;
693 if (object->type == type)
694 return object;
695 }
696
697 dev_err(&data->client->dev, "Invalid object type\n");
698 return NULL;
699}
700
Iiro Valkonen7686b102011-02-02 23:21:58 -0800701static int mxt_read_message(struct mxt_data *data,
702 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700703{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800704 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700705 u16 reg;
706
Iiro Valkonene8645592011-11-18 12:56:19 -0800707 object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700708 if (!object)
709 return -EINVAL;
710
711 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800712 return __mxt_read_reg(data->client, reg,
713 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700714}
715
Iiro Valkonen7686b102011-02-02 23:21:58 -0800716static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700717 u8 type, u8 offset, u8 *val)
718{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800719 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700720 u16 reg;
721
Iiro Valkonen7686b102011-02-02 23:21:58 -0800722 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700723 if (!object)
724 return -EINVAL;
725
726 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800727 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700728}
729
Iiro Valkonen7686b102011-02-02 23:21:58 -0800730static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700731 u8 type, u8 offset, u8 val)
732{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800733 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700734 u16 reg;
735
Iiro Valkonen7686b102011-02-02 23:21:58 -0800736 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700737 if (!object)
738 return -EINVAL;
739
740 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800741 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700742}
743
Iiro Valkonen7686b102011-02-02 23:21:58 -0800744static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700745{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800746 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700747 struct input_dev *input_dev = data->input_dev;
748 int status = finger[single_id].status;
749 int finger_num = 0;
750 int id;
751
Iiro Valkonen7686b102011-02-02 23:21:58 -0800752 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700753 if (!finger[id].status)
754 continue;
755
Joonyoung Shimcd473222012-02-14 18:32:48 -0800756 input_mt_slot(input_dev, id);
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800757 /* Firmware reports min/max values when the touch is
758 * outside screen area. Send a release event in
759 * such cases to avoid unwanted touches.
760 */
761 if (finger[id].x <= data->pdata->panel_minx ||
762 finger[id].x >= data->pdata->panel_maxx ||
763 finger[id].y <= data->pdata->panel_miny ||
764 finger[id].y >= data->pdata->panel_maxy) {
765 finger[id].status = MXT_RELEASE;
766 }
767
Joonyoung Shimcd473222012-02-14 18:32:48 -0800768 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
769 finger[id].status != MXT_RELEASE);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700770
Joonyoung Shimcd473222012-02-14 18:32:48 -0800771 if (finger[id].status != MXT_RELEASE) {
Amy Maloche2b59bab2011-10-13 16:08:16 -0700772 finger_num++;
Joonyoung Shimcd473222012-02-14 18:32:48 -0800773 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
774 finger[id].area);
775 input_report_abs(input_dev, ABS_MT_POSITION_X,
776 finger[id].x);
777 input_report_abs(input_dev, ABS_MT_POSITION_Y,
778 finger[id].y);
779 input_report_abs(input_dev, ABS_MT_PRESSURE,
780 finger[id].area);
781 } else {
782 finger[id].status = 0;
783 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700784 }
785
786 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
787
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800788 if (finger[single_id].x <= data->pdata->panel_minx ||
789 finger[single_id].x >= data->pdata->panel_maxx ||
790 finger[single_id].y <= data->pdata->panel_miny ||
791 finger[single_id].y >= data->pdata->panel_maxy) {
792 status = MXT_RELEASE;
793 }
794
Iiro Valkonen7686b102011-02-02 23:21:58 -0800795 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700796 input_report_abs(input_dev, ABS_X, finger[single_id].x);
797 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700798 input_report_abs(input_dev,
799 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700800 }
801
802 input_sync(input_dev);
803}
804
Iiro Valkonen7686b102011-02-02 23:21:58 -0800805static void mxt_input_touchevent(struct mxt_data *data,
806 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700807{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800808 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700809 struct device *dev = &data->client->dev;
810 u8 status = message->message[0];
811 int x;
812 int y;
813 int area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700814 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700815
816 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800817 if (!(status & MXT_DETECT)) {
818 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700819 dev_dbg(dev, "[%d] released\n", id);
820
Iiro Valkonen7686b102011-02-02 23:21:58 -0800821 finger[id].status = MXT_RELEASE;
822 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700823 }
824 return;
825 }
826
827 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800828 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700829 return;
830
Joonyoung Shim910d8052011-04-12 23:14:38 -0700831 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
832 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800833 if (data->pdata->panel_maxx < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700834 x = x >> 2;
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800835 if (data->pdata->panel_maxy < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700836 y = y >> 2;
837
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700838 area = message->message[4];
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700839 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700840
841 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800842 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700843 x, y, area);
844
Iiro Valkonen7686b102011-02-02 23:21:58 -0800845 finger[id].status = status & MXT_MOVE ?
846 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700847 finger[id].x = x;
848 finger[id].y = y;
849 finger[id].area = area;
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700850 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700851
Iiro Valkonen7686b102011-02-02 23:21:58 -0800852 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700853}
854
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800855static void mxt_handle_key_array(struct mxt_data *data,
856 struct mxt_message *message)
857{
858 u32 keys_changed;
859 int i;
860
861 if (!data->pdata->key_codes) {
862 dev_err(&data->client->dev, "keyarray is not supported\n");
863 return;
864 }
865
866 data->keyarray_new = message->message[1] |
867 (message->message[2] << 8) |
868 (message->message[3] << 16) |
869 (message->message[4] << 24);
870
871 keys_changed = data->keyarray_old ^ data->keyarray_new;
872
873 if (!keys_changed) {
874 dev_dbg(&data->client->dev, "no keys changed\n");
875 return;
876 }
877
878 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
879 if (!(keys_changed & (1 << i)))
880 continue;
881
882 input_report_key(data->input_dev, data->pdata->key_codes[i],
883 (data->keyarray_new & (1 << i)));
884 input_sync(data->input_dev);
885 }
886
887 data->keyarray_old = data->keyarray_new;
888}
889
Iiro Valkonen7686b102011-02-02 23:21:58 -0800890static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700891{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800892 struct mxt_data *data = dev_id;
893 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700894 struct device *dev = &data->client->dev;
895 int id;
896 u8 reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700897
Nick Dyer0a4016c2012-01-18 15:17:59 +0530898 if (data->state != APPMODE) {
899 dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
900 return IRQ_HANDLED;
901 }
902
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700903 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800904 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700905 dev_err(dev, "Failed to read message\n");
906 goto end;
907 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700908 reportid = message.reportid;
909
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800910 if (!reportid) {
911 dev_dbg(dev, "Report id 0 is reserved\n");
912 continue;
913 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700914
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800915 /* check whether report id is part of T9 or T15 */
916 id = reportid - data->t9_min_reportid;
917
918 if (reportid >= data->t9_min_reportid &&
919 reportid <= data->t9_max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -0800920 mxt_input_touchevent(data, &message, id);
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800921 else if (reportid >= data->t15_min_reportid &&
922 reportid <= data->t15_max_reportid)
923 mxt_handle_key_array(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700924 else
Iiro Valkonen7686b102011-02-02 23:21:58 -0800925 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700926 } while (reportid != 0xff);
927
928end:
929 return IRQ_HANDLED;
930}
931
Iiro Valkonen7686b102011-02-02 23:21:58 -0800932static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700933{
Jing Lindc4413c2012-01-16 15:22:52 -0800934 const struct mxt_config_info *config_info = data->config_info;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800935 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700936 struct device *dev = &data->client->dev;
937 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -0800938 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700939
Jing Lindc4413c2012-01-16 15:22:52 -0800940 if (!config_info) {
Iiro Valkonen71749f52011-02-15 13:36:52 -0800941 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
942 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700943 }
944
945 for (i = 0; i < data->info.object_num; i++) {
946 object = data->object_table + i;
947
Iiro Valkonen7686b102011-02-02 23:21:58 -0800948 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700949 continue;
950
Iiro Valkonen71749f52011-02-15 13:36:52 -0800951 for (j = 0; j < object->size + 1; j++) {
952 config_offset = index + j;
Jing Lindc4413c2012-01-16 15:22:52 -0800953 if (config_offset > config_info->config_length) {
Iiro Valkonen71749f52011-02-15 13:36:52 -0800954 dev_err(dev, "Not enough config data!\n");
955 return -EINVAL;
956 }
Iiro Valkonen7686b102011-02-02 23:21:58 -0800957 mxt_write_object(data, object->type, j,
Jing Lindc4413c2012-01-16 15:22:52 -0800958 config_info->config[config_offset]);
Iiro Valkonen71749f52011-02-15 13:36:52 -0800959 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700960 index += object->size + 1;
961 }
962
963 return 0;
964}
965
Iiro Valkonen7686b102011-02-02 23:21:58 -0800966static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700967{
968 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800969 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700970 int count = 10;
971 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700972
973 /* Read dummy message to make high CHG pin */
974 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800975 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700976 if (error)
977 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800978 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700979
980 if (!count) {
981 dev_err(dev, "CHG pin isn't cleared\n");
982 return -EBUSY;
983 }
984
985 return 0;
986}
987
Iiro Valkonen7686b102011-02-02 23:21:58 -0800988static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700989{
990 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800991 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700992 int error;
993 u8 val;
994
Iiro Valkonen7686b102011-02-02 23:21:58 -0800995 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700996 if (error)
997 return error;
998 info->family_id = val;
999
Iiro Valkonen7686b102011-02-02 23:21:58 -08001000 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001001 if (error)
1002 return error;
1003 info->variant_id = val;
1004
Iiro Valkonen7686b102011-02-02 23:21:58 -08001005 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001006 if (error)
1007 return error;
1008 info->version = val;
1009
Iiro Valkonen7686b102011-02-02 23:21:58 -08001010 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001011 if (error)
1012 return error;
1013 info->build = val;
1014
Iiro Valkonen7686b102011-02-02 23:21:58 -08001015 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001016 if (error)
1017 return error;
1018 info->object_num = val;
1019
1020 return 0;
1021}
1022
Iiro Valkonen7686b102011-02-02 23:21:58 -08001023static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001024{
1025 int error;
1026 int i;
1027 u16 reg;
1028 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001029 u8 buf[MXT_OBJECT_SIZE];
Jing Lindc4413c2012-01-16 15:22:52 -08001030 bool found_t38 = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001031
1032 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001033 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001034
Iiro Valkonen7686b102011-02-02 23:21:58 -08001035 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
1036 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001037 if (error)
1038 return error;
1039
1040 object->type = buf[0];
1041 object->start_address = (buf[2] << 8) | buf[1];
1042 object->size = buf[3];
1043 object->instances = buf[4];
1044 object->num_report_ids = buf[5];
1045
1046 if (object->num_report_ids) {
1047 reportid += object->num_report_ids *
1048 (object->instances + 1);
1049 object->max_reportid = reportid;
1050 }
Jing Lindc4413c2012-01-16 15:22:52 -08001051
1052 /* Calculate index for config major version in config array.
1053 * Major version is the first byte in object T38.
1054 */
1055 if (object->type == MXT_SPT_USERDATA_T38)
1056 found_t38 = true;
1057 if (!found_t38 && mxt_object_writable(object->type))
1058 data->cfg_version_idx += object->size + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001059 }
1060
1061 return 0;
1062}
1063
Jing Lin8fadad72012-02-24 10:10:50 -08001064static int compare_versions(const u8 *v1, const u8 *v2)
1065{
1066 int i;
1067
1068 if (!v1 || !v2)
1069 return -EINVAL;
1070
1071 /* The major version number stays the same across different versions for
1072 * a particular controller on a target. The minor and sub-minor version
1073 * numbers indicate which version is newer.
1074 */
1075 if (v1[0] != v2[0])
1076 return -EINVAL;
1077
1078 for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
1079 if (v1[i] > v2[i])
1080 return MXT_CFG_VERSION_LESS; /* v2 is older */
1081
1082 if (v1[i] < v2[i])
1083 return MXT_CFG_VERSION_GREATER; /* v2 is newer */
1084 }
1085
1086 return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
1087}
1088
1089static void mxt_check_config_version(struct mxt_data *data,
1090 const struct mxt_config_info *cfg_info,
1091 bool match_major,
1092 const u8 **cfg_version_found,
1093 bool *found_cfg_major_match)
1094{
1095 const u8 *cfg_version;
1096 int result = -EINVAL;
1097
1098 cfg_version = cfg_info->config + data->cfg_version_idx;
1099
1100 if (*cfg_version_found)
1101 result = compare_versions(*cfg_version_found, cfg_version);
1102
1103 if (match_major) {
1104 if (result >= MXT_CFG_VERSION_EQUAL)
1105 *found_cfg_major_match = true;
1106
1107 if (result == MXT_CFG_VERSION_EQUAL ||
1108 result == MXT_CFG_VERSION_GREATER) {
1109 data->config_info = cfg_info;
1110 data->fw_name = cfg_info->fw_name;
1111 *cfg_version_found = cfg_version;
1112 }
1113
1114 if (result == MXT_CFG_VERSION_GREATER)
1115 data->update_cfg = true;
1116 } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
1117 data->config_info = cfg_info;
1118 data->fw_name = cfg_info->fw_name;
1119 data->update_cfg = true;
1120 *cfg_version_found = cfg_version;
1121 }
1122}
1123
1124/* If the controller's config version has a non-zero major number, call this
1125 * function with match_major = true to look for the latest config present in
1126 * the pdata based on matching family id, variant id, f/w version, build, and
1127 * config major number. If the controller is programmed with wrong config data
1128 * previously, call this function with match_major = false to look for latest
1129 * config based on based on matching family id, variant id, f/w version and
1130 * build only.
1131 */
1132static int mxt_search_config_array(struct mxt_data *data, bool match_major)
Jing Lindc4413c2012-01-16 15:22:52 -08001133{
1134
1135 const struct mxt_platform_data *pdata = data->pdata;
1136 const struct mxt_config_info *cfg_info;
Jing Lin8fadad72012-02-24 10:10:50 -08001137 const struct mxt_info *info = &data->info;
1138 const u8 *cfg_version_found;
1139 bool found_cfg_major_match = false;
Jing Lindc4413c2012-01-16 15:22:52 -08001140 int i;
Jing Lin8fadad72012-02-24 10:10:50 -08001141
1142 cfg_version_found = match_major ? data->cfg_version : NULL;
Jing Lindc4413c2012-01-16 15:22:52 -08001143
1144 for (i = 0; i < pdata->config_array_size; i++) {
1145
1146 cfg_info = &pdata->config_array[i];
1147
1148 if (!cfg_info->config || !cfg_info->config_length)
1149 continue;
1150
1151 if (info->family_id == cfg_info->family_id &&
1152 info->variant_id == cfg_info->variant_id &&
1153 info->version == cfg_info->version &&
1154 info->build == cfg_info->build) {
1155
Jing Lin8fadad72012-02-24 10:10:50 -08001156 mxt_check_config_version(data, cfg_info, match_major,
1157 &cfg_version_found, &found_cfg_major_match);
Jing Lindc4413c2012-01-16 15:22:52 -08001158 }
1159 }
1160
Jing Lin8fadad72012-02-24 10:10:50 -08001161 if (data->config_info || found_cfg_major_match)
1162 return 0;
1163
1164 data->config_info = NULL;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001165 data->fw_name = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001166
Jing Lindc4413c2012-01-16 15:22:52 -08001167 return -EINVAL;
1168}
1169
1170static int mxt_get_config(struct mxt_data *data)
1171{
1172 const struct mxt_platform_data *pdata = data->pdata;
1173 struct device *dev = &data->client->dev;
1174 struct mxt_object *object;
1175 int error;
1176
1177 if (!pdata->config_array || !pdata->config_array_size) {
1178 dev_dbg(dev, "No cfg data provided by platform data\n");
1179 return 0;
1180 }
1181
1182 /* Get current config version */
1183 object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
1184 if (!object) {
1185 dev_err(dev, "Unable to obtain USERDATA object\n");
1186 return -EINVAL;
1187 }
1188
Jing Lin8fadad72012-02-24 10:10:50 -08001189 error = __mxt_read_reg(data->client, object->start_address,
1190 sizeof(data->cfg_version), data->cfg_version);
Jing Lindc4413c2012-01-16 15:22:52 -08001191 if (error) {
1192 dev_err(dev, "Unable to read config version\n");
1193 return error;
1194 }
Jing Lin8fadad72012-02-24 10:10:50 -08001195 dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
1196 data->cfg_version[0], data->cfg_version[1],
1197 data->cfg_version[2]);
Jing Lindc4413c2012-01-16 15:22:52 -08001198
1199 /* It is possible that the config data on the controller is not
1200 * versioned and the version number returns 0. In this case,
1201 * find a match without the config version checking.
1202 */
1203 error = mxt_search_config_array(data,
Jing Lin8fadad72012-02-24 10:10:50 -08001204 data->cfg_version[0] != 0 ? true : false);
1205 if (error) {
1206 /* If a match wasn't found for a non-zero config version,
1207 * it means the controller has the wrong config data. Search
1208 * for a best match based on controller and firmware version,
1209 * but not config version.
1210 */
1211 if (data->cfg_version[0])
1212 error = mxt_search_config_array(data, false);
1213 if (error) {
1214 dev_err(dev,
1215 "Unable to find matching config in pdata\n");
1216 return error;
1217 }
1218 }
Jing Lindc4413c2012-01-16 15:22:52 -08001219
1220 return 0;
1221}
Jing Lin8fadad72012-02-24 10:10:50 -08001222
Amy Maloche7e447432011-09-14 11:36:30 -07001223static void mxt_reset_delay(struct mxt_data *data)
1224{
1225 struct mxt_info *info = &data->info;
1226
1227 switch (info->family_id) {
1228 case MXT224_ID:
1229 msleep(MXT224_RESET_TIME);
1230 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -07001231 case MXT224E_ID:
1232 msleep(MXT224E_RESET_TIME);
1233 break;
Amy Maloche7e447432011-09-14 11:36:30 -07001234 case MXT1386_ID:
1235 msleep(MXT1386_RESET_TIME);
1236 break;
1237 default:
1238 msleep(MXT_RESET_TIME);
1239 }
1240}
1241
Jing Lin8fadad72012-02-24 10:10:50 -08001242static int mxt_backup_nv(struct mxt_data *data)
1243{
1244 int error;
1245 u8 command_register;
1246 int timeout_counter = 0;
1247
1248 /* Backup to memory */
1249 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1250 MXT_COMMAND_BACKUPNV,
1251 MXT_BACKUP_VALUE);
1252 msleep(MXT_BACKUP_TIME);
1253
1254 do {
1255 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
1256 MXT_COMMAND_BACKUPNV,
1257 &command_register);
1258 if (error)
1259 return error;
1260
1261 usleep_range(1000, 2000);
1262
1263 } while ((command_register != 0) && (++timeout_counter <= 100));
1264
1265 if (timeout_counter > 100) {
1266 dev_err(&data->client->dev, "No response after backup!\n");
1267 return -EIO;
1268 }
1269
1270 /* Soft reset */
1271 mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
1272
1273 mxt_reset_delay(data);
1274
1275 return 0;
1276}
1277
Iiro Valkonen7686b102011-02-02 23:21:58 -08001278static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001279{
1280 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001281 struct mxt_info *info = &data->info;
Jing Lin36aee812011-10-17 17:17:28 -07001282 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001283 u8 val;
Jing Lin8fadad72012-02-24 10:10:50 -08001284 const u8 *cfg_ver;
Jing Lin36aee812011-10-17 17:17:28 -07001285 struct mxt_object *t7_object;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001286 struct mxt_object *t9_object;
1287 struct mxt_object *t15_object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001288
Iiro Valkonen7686b102011-02-02 23:21:58 -08001289 error = mxt_get_info(data);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301290 if (error) {
1291 /* Try bootloader mode */
1292 error = mxt_switch_to_bootloader_address(data);
1293 if (error)
1294 return error;
1295
1296 error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
1297 if (error)
1298 return error;
1299
1300 dev_err(&client->dev, "Application CRC failure\n");
1301 data->state = BOOTLOADER;
1302
1303 return 0;
1304 }
1305
1306 dev_info(&client->dev,
1307 "Family ID: %d Variant ID: %d Version: %d.%d "
1308 "Build: 0x%02X Object Num: %d\n",
1309 info->family_id, info->variant_id,
1310 info->version >> 4, info->version & 0xf,
1311 info->build, info->object_num);
1312
1313 data->state = APPMODE;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001314
1315 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001316 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001317 GFP_KERNEL);
1318 if (!data->object_table) {
1319 dev_err(&client->dev, "Failed to allocate memory\n");
1320 return -ENOMEM;
1321 }
1322
1323 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001324 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001325 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001326 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001327
Jing Lindc4413c2012-01-16 15:22:52 -08001328 /* Get config data from platform data */
1329 error = mxt_get_config(data);
1330 if (error)
1331 dev_dbg(&client->dev, "Config info not found.\n");
1332
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001333 /* Check register init values */
Jing Lin8fadad72012-02-24 10:10:50 -08001334 if (data->config_info && data->config_info->config) {
1335 if (data->update_cfg) {
1336 error = mxt_check_reg_init(data);
1337 if (error) {
1338 dev_err(&client->dev,
1339 "Failed to check reg init value\n");
1340 goto free_object_table;
1341 }
1342
1343 error = mxt_backup_nv(data);
1344 if (error) {
1345 dev_err(&client->dev, "Failed to back up NV\n");
1346 goto free_object_table;
1347 }
1348
1349 cfg_ver = data->config_info->config +
1350 data->cfg_version_idx;
1351 dev_info(&client->dev,
1352 "Config updated from %d.%d.%d to %d.%d.%d\n",
1353 data->cfg_version[0], data->cfg_version[1],
1354 data->cfg_version[2],
1355 cfg_ver[0], cfg_ver[1], cfg_ver[2]);
1356
1357 memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
1358 }
1359 } else {
1360 dev_info(&client->dev,
1361 "No cfg data defined, skipping check reg init\n");
1362 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001363
Amy Maloche52262212011-09-15 16:46:57 -07001364 /* Store T7 and T9 locally, used in suspend/resume operations */
Iiro Valkonene8645592011-11-18 12:56:19 -08001365 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
Jing Lin36aee812011-10-17 17:17:28 -07001366 if (!t7_object) {
1367 dev_err(&client->dev, "Failed to get T7 object\n");
Jing Lin32c72532011-11-03 12:02:33 -07001368 error = -EINVAL;
1369 goto free_object_table;
Jing Lin36aee812011-10-17 17:17:28 -07001370 }
1371
1372 data->t7_start_addr = t7_object->start_address;
1373 error = __mxt_read_reg(client, data->t7_start_addr,
1374 T7_DATA_SIZE, data->t7_data);
1375 if (error < 0) {
1376 dev_err(&client->dev,
Jing Lin32c72532011-11-03 12:02:33 -07001377 "Failed to save current power state\n");
1378 goto free_object_table;
Amy Maloche52262212011-09-15 16:46:57 -07001379 }
Iiro Valkonene8645592011-11-18 12:56:19 -08001380 error = mxt_read_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL,
Amy Maloche52262212011-09-15 16:46:57 -07001381 &data->t9_ctrl);
1382 if (error < 0) {
Jing Lin32c72532011-11-03 12:02:33 -07001383 dev_err(&client->dev, "Failed to save current touch object\n");
1384 goto free_object_table;
Amy Maloche52262212011-09-15 16:46:57 -07001385 }
1386
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08001387 /* Store T9, T15's min and max report ids */
1388 t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1389 if (!t9_object) {
1390 dev_err(&client->dev, "Failed to get T9 object\n");
1391 error = -EINVAL;
1392 goto free_object_table;
1393 }
1394 data->t9_max_reportid = t9_object->max_reportid;
1395 data->t9_min_reportid = t9_object->max_reportid -
1396 t9_object->num_report_ids + 1;
1397
1398 if (data->pdata->key_codes) {
1399 t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
1400 if (!t15_object)
1401 dev_dbg(&client->dev, "T15 object is not available\n");
1402 else {
1403 data->t15_max_reportid = t15_object->max_reportid;
1404 data->t15_min_reportid = t15_object->max_reportid -
1405 t15_object->num_report_ids + 1;
1406 }
1407 }
1408
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001409 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001410 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001411 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001412 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001413 info->matrix_xsize = val;
1414
Iiro Valkonen7686b102011-02-02 23:21:58 -08001415 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001416 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001417 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001418 info->matrix_ysize = val;
1419
1420 dev_info(&client->dev,
Nick Dyer0a4016c2012-01-18 15:17:59 +05301421 "Matrix X Size: %d Matrix Y Size: %d\n",
1422 info->matrix_xsize, info->matrix_ysize);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001423
1424 return 0;
Jing Lin32c72532011-11-03 12:02:33 -07001425
1426free_object_table:
1427 kfree(data->object_table);
1428 return error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001429}
1430
Iiro Valkonen7686b102011-02-02 23:21:58 -08001431static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001432 struct device_attribute *attr, char *buf)
1433{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001434 struct mxt_data *data = dev_get_drvdata(dev);
1435 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001436 int count = 0;
1437 int i, j;
1438 int error;
1439 u8 val;
1440
1441 for (i = 0; i < data->info.object_num; i++) {
1442 object = data->object_table + i;
1443
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001444 count += snprintf(buf + count, PAGE_SIZE - count,
1445 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001446 i + 1, object->type);
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001447 if (count >= PAGE_SIZE)
1448 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001449
Iiro Valkonen7686b102011-02-02 23:21:58 -08001450 if (!mxt_object_readable(object->type)) {
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001451 count += snprintf(buf + count, PAGE_SIZE - count,
1452 "\n");
1453 if (count >= PAGE_SIZE)
1454 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001455 continue;
1456 }
1457
1458 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001459 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001460 object->type, j, &val);
1461 if (error)
1462 return error;
1463
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001464 count += snprintf(buf + count, PAGE_SIZE - count,
1465 "\t[%2d]: %02x (%d)\n", j, val, val);
1466 if (count >= PAGE_SIZE)
1467 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001468 }
1469
Daniel Kurtz4ef11a82011-11-02 10:43:08 -07001470 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1471 if (count >= PAGE_SIZE)
1472 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001473 }
1474
1475 return count;
1476}
1477
Jing Lincc974cb2012-02-01 23:13:14 -08001478static int strtobyte(const char *data, u8 *value)
1479{
1480 char str[3];
1481
1482 str[0] = data[0];
1483 str[1] = data[1];
1484 str[2] = '\0';
1485
1486 return kstrtou8(str, 16, value);
1487}
1488
Iiro Valkonen7686b102011-02-02 23:21:58 -08001489static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001490{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001491 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001492 struct i2c_client *client = data->client;
1493 const struct firmware *fw = NULL;
1494 unsigned int frame_size;
Nick Dyer0a4016c2012-01-18 15:17:59 +05301495 unsigned int retry = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001496 unsigned int pos = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001497 int ret, i, max_frame_size;
1498 u8 *frame;
1499
1500 switch (data->info.family_id) {
1501 case MXT224_ID:
1502 max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
1503 break;
1504 case MXT1386_ID:
1505 max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
1506 break;
1507 default:
1508 return -EINVAL;
1509 }
1510
1511 frame = kmalloc(max_frame_size, GFP_KERNEL);
1512 if (!frame) {
1513 dev_err(dev, "Unable to allocate memory for frame data\n");
1514 return -ENOMEM;
1515 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001516
1517 ret = request_firmware(&fw, fn, dev);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301518 if (ret < 0) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001519 dev_err(dev, "Unable to open firmware %s\n", fn);
Jing Lincc974cb2012-02-01 23:13:14 -08001520 goto free_frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001521 }
1522
Nick Dyer0a4016c2012-01-18 15:17:59 +05301523 if (data->state != BOOTLOADER) {
1524 /* Change to the bootloader mode */
1525 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1526 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1527 mxt_reset_delay(data);
Amy Maloche7e447432011-09-14 11:36:30 -07001528
Nick Dyer0a4016c2012-01-18 15:17:59 +05301529 ret = mxt_switch_to_bootloader_address(data);
1530 if (ret)
1531 goto release_firmware;
1532 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001533
Iiro Valkonen7686b102011-02-02 23:21:58 -08001534 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301535 if (ret) {
1536 /* Bootloader may still be unlocked from previous update
1537 * attempt */
1538 ret = mxt_check_bootloader(client,
1539 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001540
Nick Dyer0a4016c2012-01-18 15:17:59 +05301541 if (ret)
1542 goto return_to_app_mode;
1543 } else {
1544 dev_info(dev, "Unlocking bootloader\n");
1545 /* Unlock bootloader */
1546 mxt_unlock_bootloader(client);
1547 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001548
1549 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001550 ret = mxt_check_bootloader(client,
1551 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001552 if (ret)
Nick Dyer0a4016c2012-01-18 15:17:59 +05301553 goto release_firmware;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001554
Jing Lincc974cb2012-02-01 23:13:14 -08001555 /* Get frame length MSB */
1556 ret = strtobyte(fw->data + pos, frame);
1557 if (ret)
1558 goto release_firmware;
1559
1560 /* Get frame length LSB */
1561 ret = strtobyte(fw->data + pos + 2, frame + 1);
1562 if (ret)
1563 goto release_firmware;
1564
1565 frame_size = ((*frame << 8) | *(frame + 1));
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001566
1567 /* We should add 2 at frame size as the the firmware data is not
1568 * included the CRC bytes.
1569 */
1570 frame_size += 2;
1571
Jing Lincc974cb2012-02-01 23:13:14 -08001572 if (frame_size > max_frame_size) {
1573 dev_err(dev, "Invalid frame size - %d\n", frame_size);
1574 ret = -EINVAL;
1575 goto release_firmware;
1576 }
1577
1578 /* Convert frame data and CRC from hex to binary */
1579 for (i = 2; i < frame_size; i++) {
1580 ret = strtobyte(fw->data + pos + i * 2, frame + i);
1581 if (ret)
1582 goto release_firmware;
1583 }
1584
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001585 /* Write one frame to device */
Jing Lincc974cb2012-02-01 23:13:14 -08001586 mxt_fw_write(client, frame, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001587
Iiro Valkonen7686b102011-02-02 23:21:58 -08001588 ret = mxt_check_bootloader(client,
1589 MXT_FRAME_CRC_PASS);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301590 if (ret) {
1591 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001592
Nick Dyer0a4016c2012-01-18 15:17:59 +05301593 /* Back off by 20ms per retry */
1594 msleep(retry * 20);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001595
Nick Dyer0a4016c2012-01-18 15:17:59 +05301596 if (retry > 20)
1597 goto release_firmware;
1598 } else {
1599 retry = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001600 pos += frame_size * 2;
1601 dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301602 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001603 }
1604
Nick Dyer0a4016c2012-01-18 15:17:59 +05301605return_to_app_mode:
1606 mxt_switch_to_appmode_address(data);
1607release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001608 release_firmware(fw);
Jing Lincc974cb2012-02-01 23:13:14 -08001609free_frame:
1610 kfree(frame);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001611
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001612 return ret;
1613}
1614
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001615static const char *
1616mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
1617{
1618 const struct mxt_platform_data *pdata = data->pdata;
1619 const struct mxt_config_info *cfg_info;
1620 const char *fw_name = NULL;
1621 int i;
1622
1623 for (i = 0; i < pdata->config_array_size; i++) {
1624 cfg_info = &pdata->config_array[i];
1625 if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
1626 data->config_info = cfg_info;
1627 data->info.family_id = cfg_info->family_id;
1628 fw_name = cfg_info->fw_name;
1629 }
1630 }
1631
1632 return fw_name;
1633}
1634
Iiro Valkonen7686b102011-02-02 23:21:58 -08001635static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001636 struct device_attribute *attr,
1637 const char *buf, size_t count)
1638{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001639 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001640 int error;
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001641 const char *fw_name;
1642 u8 bootldr_id;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001643
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001644 /* If fw_name is set, then the existing firmware has an upgrade */
1645 if (!data->fw_name) {
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001646 /*
1647 * If the device boots up in the bootloader mode, check if
1648 * there is a firmware to upgrade.
1649 */
1650 if (data->state == BOOTLOADER) {
1651 bootldr_id = mxt_get_bootloader_id(data->client);
1652 if (bootldr_id <= 0) {
1653 dev_err(dev,
1654 "Unable to retrieve bootloader id\n");
1655 return -EINVAL;
1656 }
1657 fw_name = mxt_search_fw_name(data, bootldr_id);
1658 if (fw_name == NULL) {
1659 dev_err(dev,
1660 "Unable to find fw from bootloader id\n");
1661 return -EINVAL;
1662 }
1663 } else {
1664 /* In APPMODE, if the f/w name does not exist, quit */
1665 dev_err(dev,
1666 "Firmware name not specified in platform data\n");
1667 return -EINVAL;
1668 }
1669 } else {
1670 fw_name = data->fw_name;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001671 }
1672
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001673 dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001674
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001675 disable_irq(data->irq);
1676
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001677 error = mxt_load_fw(dev, fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001678 if (error) {
1679 dev_err(dev, "The firmware update failed(%d)\n", error);
1680 count = error;
1681 } else {
Nick Dyer0a4016c2012-01-18 15:17:59 +05301682 dev_info(dev, "The firmware update succeeded\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001683
1684 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001685 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001686
Nick Dyer0a4016c2012-01-18 15:17:59 +05301687 data->state = INIT;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001688 kfree(data->object_table);
1689 data->object_table = NULL;
Jing Lincc974cb2012-02-01 23:13:14 -08001690 data->cfg_version_idx = 0;
Jing Lin8fadad72012-02-24 10:10:50 -08001691 data->update_cfg = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001692
Iiro Valkonen7686b102011-02-02 23:21:58 -08001693 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001694 }
1695
Nick Dyer0a4016c2012-01-18 15:17:59 +05301696 if (data->state == APPMODE) {
1697 enable_irq(data->irq);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001698
Nick Dyer0a4016c2012-01-18 15:17:59 +05301699 error = mxt_make_highchg(data);
1700 if (error)
1701 return error;
1702 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07001703
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001704 return count;
1705}
1706
Iiro Valkonen7686b102011-02-02 23:21:58 -08001707static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
1708static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001709
Iiro Valkonen7686b102011-02-02 23:21:58 -08001710static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001711 &dev_attr_object.attr,
1712 &dev_attr_update_fw.attr,
1713 NULL
1714};
1715
Iiro Valkonen7686b102011-02-02 23:21:58 -08001716static const struct attribute_group mxt_attr_group = {
1717 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001718};
1719
Amy Maloche52262212011-09-15 16:46:57 -07001720static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001721{
Jing Lin36aee812011-10-17 17:17:28 -07001722 int error;
1723
Amy Maloche52262212011-09-15 16:46:57 -07001724 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07001725 error = __mxt_write_reg(data->client, data->t7_start_addr,
1726 T7_DATA_SIZE, data->t7_data);
1727 if (error < 0) {
1728 dev_err(&data->client->dev,
1729 "failed to restore old power state\n");
1730 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001731 }
Jing Lin36aee812011-10-17 17:17:28 -07001732
Amy Maloche52262212011-09-15 16:46:57 -07001733 error = mxt_write_object(data,
Iiro Valkonene8645592011-11-18 12:56:19 -08001734 MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, data->t9_ctrl);
Amy Maloche52262212011-09-15 16:46:57 -07001735 if (error < 0) {
1736 dev_err(&data->client->dev, "failed to restore touch\n");
1737 return error;
1738 }
1739
1740 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001741}
1742
Amy Maloche52262212011-09-15 16:46:57 -07001743static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001744{
Jing Lin36aee812011-10-17 17:17:28 -07001745 int error;
1746 u8 t7_data[T7_DATA_SIZE] = {0};
1747
1748 /* disable touch and configure deep sleep mode */
Iiro Valkonene8645592011-11-18 12:56:19 -08001749 error = mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
Jing Lin36aee812011-10-17 17:17:28 -07001750 if (error < 0) {
1751 dev_err(&data->client->dev, "failed to disable touch\n");
1752 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001753 }
1754
Jing Lin36aee812011-10-17 17:17:28 -07001755 error = __mxt_write_reg(data->client, data->t7_start_addr,
1756 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07001757 if (error < 0) {
1758 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07001759 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07001760 return error;
1761 }
1762
1763 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001764}
1765
Iiro Valkonen7686b102011-02-02 23:21:58 -08001766static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001767{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001768 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001769 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001770
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001771 if (data->state == APPMODE) {
1772 error = mxt_start(data);
1773 if (error < 0) {
1774 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
1775 return error;
1776 }
Amy Maloche52262212011-09-15 16:46:57 -07001777 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001778
1779 return 0;
1780}
1781
Iiro Valkonen7686b102011-02-02 23:21:58 -08001782static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001783{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001784 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001785 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001786
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001787 if (data->state == APPMODE) {
1788 error = mxt_stop(data);
1789 if (error < 0)
1790 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
1791 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001792}
1793
Amy Malochec331f842012-01-24 10:33:47 -08001794static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
1795{
1796 return (regulator_count_voltages(reg) > 0) ?
1797 regulator_set_optimum_mode(reg, load_uA) : 0;
1798}
1799
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301800static int mxt_power_on(struct mxt_data *data, bool on)
1801{
1802 int rc;
1803
1804 if (on == false)
1805 goto power_off;
1806
Amy Malochec331f842012-01-24 10:33:47 -08001807 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301808 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001809 dev_err(&data->client->dev,
1810 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301811 return rc;
1812 }
1813
Amy Maloche21115eb2011-11-02 09:04:37 -07001814 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301815 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001816 dev_err(&data->client->dev,
1817 "Regulator vcc_ana enable failed rc=%d\n", rc);
1818 goto error_reg_en_vcc_ana;
1819 }
1820
1821 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001822 rc = reg_set_optimum_mode_check(data->vcc_dig,
1823 MXT_ACTIVE_LOAD_DIG_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07001824 if (rc < 0) {
1825 dev_err(&data->client->dev,
1826 "Regulator vcc_dig set_opt failed rc=%d\n",
1827 rc);
1828 goto error_reg_opt_vcc_dig;
1829 }
1830
1831 rc = regulator_enable(data->vcc_dig);
1832 if (rc) {
1833 dev_err(&data->client->dev,
1834 "Regulator vcc_dig enable failed rc=%d\n", rc);
1835 goto error_reg_en_vcc_dig;
1836 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301837 }
1838
1839 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001840 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301841 if (rc < 0) {
1842 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001843 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301844 goto error_reg_opt_i2c;
1845 }
1846
1847 rc = regulator_enable(data->vcc_i2c);
1848 if (rc) {
1849 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001850 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301851 goto error_reg_en_vcc_i2c;
1852 }
1853 }
1854
Amy Malochef0d7b8d2011-10-17 12:10:51 -07001855 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301856
1857 return 0;
1858
1859error_reg_en_vcc_i2c:
1860 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08001861 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301862error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001863 if (data->pdata->digital_pwr_regulator)
1864 regulator_disable(data->vcc_dig);
1865error_reg_en_vcc_dig:
1866 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08001867 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001868error_reg_opt_vcc_dig:
1869 regulator_disable(data->vcc_ana);
1870error_reg_en_vcc_ana:
Amy Malochec331f842012-01-24 10:33:47 -08001871 reg_set_optimum_mode_check(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301872 return rc;
1873
1874power_off:
Amy Malochec331f842012-01-24 10:33:47 -08001875 reg_set_optimum_mode_check(data->vcc_ana, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001876 regulator_disable(data->vcc_ana);
1877 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001878 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001879 regulator_disable(data->vcc_dig);
1880 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301881 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 +05301883 regulator_disable(data->vcc_i2c);
1884 }
1885 msleep(50);
1886 return 0;
1887}
1888
1889static int mxt_regulator_configure(struct mxt_data *data, bool on)
1890{
1891 int rc;
1892
1893 if (on == false)
1894 goto hw_shutdown;
1895
Amy Maloche21115eb2011-11-02 09:04:37 -07001896 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
1897 if (IS_ERR(data->vcc_ana)) {
1898 rc = PTR_ERR(data->vcc_ana);
1899 dev_err(&data->client->dev,
1900 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301901 return rc;
1902 }
1903
Amy Maloche21115eb2011-11-02 09:04:37 -07001904 if (regulator_count_voltages(data->vcc_ana) > 0) {
1905 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301906 MXT_VTG_MAX_UV);
1907 if (rc) {
1908 dev_err(&data->client->dev,
1909 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07001910 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301911 }
1912 }
Amy Maloche21115eb2011-11-02 09:04:37 -07001913 if (data->pdata->digital_pwr_regulator) {
1914 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
1915 if (IS_ERR(data->vcc_dig)) {
1916 rc = PTR_ERR(data->vcc_dig);
1917 dev_err(&data->client->dev,
1918 "Regulator get dig failed rc=%d\n", rc);
1919 goto error_get_vtg_vcc_dig;
1920 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301921
Amy Maloche21115eb2011-11-02 09:04:37 -07001922 if (regulator_count_voltages(data->vcc_dig) > 0) {
1923 rc = regulator_set_voltage(data->vcc_dig,
1924 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
1925 if (rc) {
1926 dev_err(&data->client->dev,
1927 "regulator set_vtg failed rc=%d\n", rc);
1928 goto error_set_vtg_vcc_dig;
1929 }
1930 }
1931 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301932 if (data->pdata->i2c_pull_up) {
1933 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
1934 if (IS_ERR(data->vcc_i2c)) {
1935 rc = PTR_ERR(data->vcc_i2c);
1936 dev_err(&data->client->dev,
1937 "Regulator get failed rc=%d\n", rc);
1938 goto error_get_vtg_i2c;
1939 }
1940 if (regulator_count_voltages(data->vcc_i2c) > 0) {
1941 rc = regulator_set_voltage(data->vcc_i2c,
1942 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
1943 if (rc) {
1944 dev_err(&data->client->dev,
1945 "regulator set_vtg failed rc=%d\n", rc);
1946 goto error_set_vtg_i2c;
1947 }
1948 }
1949 }
1950
1951 return 0;
1952
1953error_set_vtg_i2c:
1954 regulator_put(data->vcc_i2c);
1955error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001956 if (data->pdata->digital_pwr_regulator)
1957 if (regulator_count_voltages(data->vcc_dig) > 0)
1958 regulator_set_voltage(data->vcc_dig, 0,
1959 MXT_VTG_DIG_MAX_UV);
1960error_set_vtg_vcc_dig:
1961 if (data->pdata->digital_pwr_regulator)
1962 regulator_put(data->vcc_dig);
1963error_get_vtg_vcc_dig:
1964 if (regulator_count_voltages(data->vcc_ana) > 0)
1965 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1966error_set_vtg_vcc_ana:
1967 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301968 return rc;
1969
1970hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07001971 if (regulator_count_voltages(data->vcc_ana) > 0)
1972 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
1973 regulator_put(data->vcc_ana);
1974 if (data->pdata->digital_pwr_regulator) {
1975 if (regulator_count_voltages(data->vcc_dig) > 0)
1976 regulator_set_voltage(data->vcc_dig, 0,
1977 MXT_VTG_DIG_MAX_UV);
1978 regulator_put(data->vcc_dig);
1979 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301980 if (data->pdata->i2c_pull_up) {
1981 if (regulator_count_voltages(data->vcc_i2c) > 0)
1982 regulator_set_voltage(data->vcc_i2c, 0,
1983 MXT_I2C_VTG_MAX_UV);
1984 regulator_put(data->vcc_i2c);
1985 }
1986 return 0;
1987}
1988
Anirudh Ghayal253ce122011-08-09 19:32:57 +05301989#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07001990static int mxt_regulator_lpm(struct mxt_data *data, bool on)
1991{
1992
1993 int rc;
1994
1995 if (on == false)
1996 goto regulator_hpm;
1997
Amy Malochec331f842012-01-24 10:33:47 -08001998 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07001999 if (rc < 0) {
2000 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002001 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002002 goto fail_regulator_lpm;
2003 }
2004
Amy Maloche21115eb2011-11-02 09:04:37 -07002005 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002006 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002007 MXT_LPM_LOAD_DIG_UA);
2008 if (rc < 0) {
2009 dev_err(&data->client->dev,
2010 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2011 goto fail_regulator_lpm;
2012 }
2013 }
2014
Jing Linbace50b2011-10-18 22:55:47 -07002015 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002016 rc = reg_set_optimum_mode_check(data->vcc_i2c,
Jing Linbace50b2011-10-18 22:55:47 -07002017 MXT_I2C_LPM_LOAD_UA);
2018 if (rc < 0) {
2019 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002020 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002021 goto fail_regulator_lpm;
2022 }
2023 }
2024
2025 return 0;
2026
2027regulator_hpm:
2028
Amy Malochec331f842012-01-24 10:33:47 -08002029 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002030 if (rc < 0) {
2031 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002032 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002033 goto fail_regulator_hpm;
2034 }
2035
Amy Maloche21115eb2011-11-02 09:04:37 -07002036 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002037 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002038 MXT_ACTIVE_LOAD_DIG_UA);
2039 if (rc < 0) {
2040 dev_err(&data->client->dev,
2041 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2042 goto fail_regulator_hpm;
2043 }
2044 }
2045
Jing Linbace50b2011-10-18 22:55:47 -07002046 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002047 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002048 if (rc < 0) {
2049 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002050 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002051 goto fail_regulator_hpm;
2052 }
2053 }
2054
2055 return 0;
2056
2057fail_regulator_lpm:
Amy Malochec331f842012-01-24 10:33:47 -08002058 reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002059 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002060 reg_set_optimum_mode_check(data->vcc_dig,
2061 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002062 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002063 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002064
2065 return rc;
2066
2067fail_regulator_hpm:
Amy Malochec331f842012-01-24 10:33:47 -08002068 reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002069 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002070 reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002071 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002072 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002073
2074 return rc;
2075}
2076
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302077static int mxt_suspend(struct device *dev)
2078{
2079 struct i2c_client *client = to_i2c_client(dev);
2080 struct mxt_data *data = i2c_get_clientdata(client);
2081 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002082 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302083
2084 mutex_lock(&input_dev->mutex);
2085
Amy Maloche52262212011-09-15 16:46:57 -07002086 if (input_dev->users) {
2087 error = mxt_stop(data);
2088 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002089 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07002090 mutex_unlock(&input_dev->mutex);
2091 return error;
2092 }
2093
2094 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302095
2096 mutex_unlock(&input_dev->mutex);
2097
Jing Linbace50b2011-10-18 22:55:47 -07002098 /* put regulators in low power mode */
2099 error = mxt_regulator_lpm(data, true);
2100 if (error < 0) {
2101 dev_err(dev, "failed to enter low power mode\n");
2102 return error;
2103 }
2104
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302105 return 0;
2106}
2107
2108static int mxt_resume(struct device *dev)
2109{
2110 struct i2c_client *client = to_i2c_client(dev);
2111 struct mxt_data *data = i2c_get_clientdata(client);
2112 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002113 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302114
Jing Linbace50b2011-10-18 22:55:47 -07002115 /* put regulators in high power mode */
2116 error = mxt_regulator_lpm(data, false);
2117 if (error < 0) {
2118 dev_err(dev, "failed to enter high power mode\n");
2119 return error;
2120 }
2121
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302122 mutex_lock(&input_dev->mutex);
2123
Amy Maloche52262212011-09-15 16:46:57 -07002124 if (input_dev->users) {
2125 error = mxt_start(data);
2126 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002127 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07002128 mutex_unlock(&input_dev->mutex);
2129 return error;
2130 }
2131 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302132
2133 mutex_unlock(&input_dev->mutex);
2134
2135 return 0;
2136}
2137
2138#if defined(CONFIG_HAS_EARLYSUSPEND)
2139static void mxt_early_suspend(struct early_suspend *h)
2140{
2141 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2142
2143 mxt_suspend(&data->client->dev);
2144}
2145
2146static void mxt_late_resume(struct early_suspend *h)
2147{
2148 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2149
2150 mxt_resume(&data->client->dev);
2151}
2152#endif
2153
2154static const struct dev_pm_ops mxt_pm_ops = {
2155#ifndef CONFIG_HAS_EARLYSUSPEND
2156 .suspend = mxt_suspend,
2157 .resume = mxt_resume,
2158#endif
2159};
2160#endif
2161
Jing Lin6cfc00e2011-11-02 15:15:30 -07002162static int mxt_debugfs_object_show(struct seq_file *m, void *v)
2163{
2164 struct mxt_data *data = m->private;
2165 struct mxt_object *object;
2166 struct device *dev = &data->client->dev;
2167 int i, j, k;
2168 int error;
2169 int obj_size;
2170 u8 val;
2171
2172 for (i = 0; i < data->info.object_num; i++) {
2173 object = data->object_table + i;
2174 obj_size = object->size + 1;
2175
2176 seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
2177
2178 for (j = 0; j < object->instances + 1; j++) {
2179 seq_printf(m, "[Instance %d]\n", j);
2180
2181 for (k = 0; k < obj_size; k++) {
2182 error = mxt_read_object(data, object->type,
2183 j * obj_size + k, &val);
2184 if (error) {
2185 dev_err(dev,
2186 "Failed to read object %d "
2187 "instance %d at offset %d\n",
2188 object->type, j, k);
2189 return error;
2190 }
2191
2192 seq_printf(m, "Byte %d: 0x%02x (%d)\n",
2193 k, val, val);
2194 }
2195 }
2196 }
2197
2198 return 0;
2199}
2200
2201static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
2202{
2203 return single_open(file, mxt_debugfs_object_show, inode->i_private);
2204}
2205
2206static const struct file_operations mxt_object_fops = {
2207 .owner = THIS_MODULE,
2208 .open = mxt_debugfs_object_open,
2209 .read = seq_read,
2210 .release = single_release,
2211};
2212
2213static void __init mxt_debugfs_init(struct mxt_data *data)
2214{
2215 debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
2216 if (IS_ERR_OR_NULL(debug_base))
2217 pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
2218 if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
2219 0444,
2220 debug_base,
2221 data,
2222 &mxt_object_fops))) {
2223 pr_err("atmel_mxt_ts: Failed to create object file\n");
2224 debugfs_remove_recursive(debug_base);
2225 }
2226}
2227
Iiro Valkonen7686b102011-02-02 23:21:58 -08002228static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002229 const struct i2c_device_id *id)
2230{
Iiro Valkonen919ed892011-02-15 13:36:52 -08002231 const struct mxt_platform_data *pdata = client->dev.platform_data;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002232 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002233 struct input_dev *input_dev;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002234 int error, i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002235
Iiro Valkonen919ed892011-02-15 13:36:52 -08002236 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002237 return -EINVAL;
2238
Iiro Valkonen7686b102011-02-02 23:21:58 -08002239 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002240 input_dev = input_allocate_device();
2241 if (!data || !input_dev) {
2242 dev_err(&client->dev, "Failed to allocate memory\n");
2243 error = -ENOMEM;
2244 goto err_free_mem;
2245 }
2246
Nick Dyer0a4016c2012-01-18 15:17:59 +05302247 data->state = INIT;
Amy Maloche83c385a2012-02-01 10:32:03 +05302248 input_dev->name = "atmel_mxt_ts";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002249 input_dev->id.bustype = BUS_I2C;
2250 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002251 input_dev->open = mxt_input_open;
2252 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002253
Joonyoung Shim910d8052011-04-12 23:14:38 -07002254 data->client = client;
2255 data->input_dev = input_dev;
2256 data->pdata = pdata;
2257 data->irq = client->irq;
2258
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002259 __set_bit(EV_ABS, input_dev->evbit);
2260 __set_bit(EV_KEY, input_dev->evbit);
2261 __set_bit(BTN_TOUCH, input_dev->keybit);
2262
2263 /* For single touch */
2264 input_set_abs_params(input_dev, ABS_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002265 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002266 input_set_abs_params(input_dev, ABS_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002267 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07002268 input_set_abs_params(input_dev, ABS_PRESSURE,
2269 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002270
2271 /* For multi touch */
Joonyoung Shimcd473222012-02-14 18:32:48 -08002272 input_mt_init_slots(input_dev, MXT_MAX_FINGER);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002273 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08002274 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002275 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002276 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002277 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002278 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shene6eb36a2011-10-11 12:28:21 -07002279 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2280 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002281
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002282 /* set key array supported keys */
2283 if (pdata->key_codes) {
2284 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
2285 if (pdata->key_codes[i])
2286 input_set_capability(input_dev, EV_KEY,
2287 pdata->key_codes[i]);
2288 }
2289 }
2290
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002291 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002292 i2c_set_clientdata(client, data);
2293
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302294 if (pdata->init_hw)
2295 error = pdata->init_hw(true);
2296 else
2297 error = mxt_regulator_configure(data, true);
2298 if (error) {
2299 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07002300 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302301 }
2302
2303 if (pdata->power_on)
2304 error = pdata->power_on(true);
2305 else
2306 error = mxt_power_on(data, true);
2307 if (error) {
2308 dev_err(&client->dev, "Failed to power on hardware\n");
2309 goto err_regulator_on;
2310 }
2311
Amy Maloche08266db2011-11-04 11:07:16 -07002312 if (gpio_is_valid(pdata->irq_gpio)) {
2313 /* configure touchscreen irq gpio */
2314 error = gpio_request(pdata->irq_gpio,
2315 "mxt_irq_gpio");
2316 if (error) {
2317 pr_err("%s: unable to request gpio [%d]\n", __func__,
2318 pdata->irq_gpio);
2319 goto err_power_on;
2320 }
2321 error = gpio_direction_input(pdata->irq_gpio);
2322 if (error) {
2323 pr_err("%s: unable to set_direction for gpio [%d]\n",
2324 __func__, pdata->irq_gpio);
2325 goto err_irq_gpio_req;
2326 }
2327 }
2328
2329 if (gpio_is_valid(pdata->reset_gpio)) {
2330 /* configure touchscreen reset out gpio */
2331 error = gpio_request(pdata->reset_gpio,
2332 "mxt_reset_gpio");
2333 if (error) {
2334 pr_err("%s: unable to request reset gpio %d\n",
2335 __func__, pdata->reset_gpio);
2336 goto err_irq_gpio_req;
2337 }
2338
2339 error = gpio_direction_output(
2340 pdata->reset_gpio, 1);
2341 if (error) {
2342 pr_err("%s: unable to set direction for gpio %d\n",
2343 __func__, pdata->reset_gpio);
2344 goto err_reset_gpio_req;
2345 }
2346 }
2347
2348 mxt_reset_delay(data);
2349
Iiro Valkonen7686b102011-02-02 23:21:58 -08002350 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002351 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07002352 goto err_reset_gpio_req;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002353
Iiro Valkonen7686b102011-02-02 23:21:58 -08002354 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08002355 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002356 if (error) {
2357 dev_err(&client->dev, "Failed to register interrupt\n");
Jing Lin32c72532011-11-03 12:02:33 -07002358 goto err_free_object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002359 }
2360
Nick Dyer0a4016c2012-01-18 15:17:59 +05302361 if (data->state == APPMODE) {
2362 error = mxt_make_highchg(data);
2363 if (error) {
2364 dev_err(&client->dev, "Failed to make high CHG\n");
2365 goto err_free_irq;
2366 }
2367 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07002368
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002369 error = input_register_device(input_dev);
2370 if (error)
2371 goto err_free_irq;
2372
Iiro Valkonen7686b102011-02-02 23:21:58 -08002373 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002374 if (error)
2375 goto err_unregister_device;
2376
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302377#if defined(CONFIG_HAS_EARLYSUSPEND)
2378 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
2379 MXT_SUSPEND_LEVEL;
2380 data->early_suspend.suspend = mxt_early_suspend;
2381 data->early_suspend.resume = mxt_late_resume;
2382 register_early_suspend(&data->early_suspend);
2383#endif
2384
Jing Lin6cfc00e2011-11-02 15:15:30 -07002385 mxt_debugfs_init(data);
2386
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002387 return 0;
2388
2389err_unregister_device:
2390 input_unregister_device(input_dev);
2391 input_dev = NULL;
2392err_free_irq:
2393 free_irq(client->irq, data);
Jing Lin32c72532011-11-03 12:02:33 -07002394err_free_object:
2395 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07002396err_reset_gpio_req:
2397 if (gpio_is_valid(pdata->reset_gpio))
2398 gpio_free(pdata->reset_gpio);
2399err_irq_gpio_req:
2400 if (gpio_is_valid(pdata->irq_gpio))
2401 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302402err_power_on:
2403 if (pdata->power_on)
2404 pdata->power_on(false);
2405 else
2406 mxt_power_on(data, false);
2407err_regulator_on:
2408 if (pdata->init_hw)
2409 pdata->init_hw(false);
2410 else
2411 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002412err_free_mem:
2413 input_free_device(input_dev);
2414 kfree(data);
2415 return error;
2416}
2417
Iiro Valkonen7686b102011-02-02 23:21:58 -08002418static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002419{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002420 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002421
Iiro Valkonen7686b102011-02-02 23:21:58 -08002422 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002423 free_irq(data->irq, data);
2424 input_unregister_device(data->input_dev);
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302425#if defined(CONFIG_HAS_EARLYSUSPEND)
2426 unregister_early_suspend(&data->early_suspend);
2427#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302428
2429 if (data->pdata->power_on)
2430 data->pdata->power_on(false);
2431 else
2432 mxt_power_on(data, false);
2433
2434 if (data->pdata->init_hw)
2435 data->pdata->init_hw(false);
2436 else
2437 mxt_regulator_configure(data, false);
2438
Mohan Pallakabfe8f302012-01-02 18:32:08 +08002439 if (gpio_is_valid(data->pdata->reset_gpio))
2440 gpio_free(data->pdata->reset_gpio);
2441
2442 if (gpio_is_valid(data->pdata->irq_gpio))
2443 gpio_free(data->pdata->irq_gpio);
2444
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002445 kfree(data->object_table);
2446 kfree(data);
2447
Jing Lin6cfc00e2011-11-02 15:15:30 -07002448 debugfs_remove_recursive(debug_base);
2449
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002450 return 0;
2451}
2452
Iiro Valkonen7686b102011-02-02 23:21:58 -08002453static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002454 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002455 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08002456 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002457 { }
2458};
Iiro Valkonen7686b102011-02-02 23:21:58 -08002459MODULE_DEVICE_TABLE(i2c, mxt_id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002460
Iiro Valkonen7686b102011-02-02 23:21:58 -08002461static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002462 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08002463 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002464 .owner = THIS_MODULE,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002465#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08002466 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002467#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002468 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002469 .probe = mxt_probe,
2470 .remove = __devexit_p(mxt_remove),
2471 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002472};
2473
Iiro Valkonen7686b102011-02-02 23:21:58 -08002474static int __init mxt_init(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002475{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002476 return i2c_add_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002477}
2478
Iiro Valkonen7686b102011-02-02 23:21:58 -08002479static void __exit mxt_exit(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002480{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002481 i2c_del_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002482}
2483
Iiro Valkonen7686b102011-02-02 23:21:58 -08002484module_init(mxt_init);
2485module_exit(mxt_exit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002486
2487/* Module information */
2488MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08002489MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002490MODULE_LICENSE("GPL");