blob: 09ff05d7dacce08412b1458eb0ba2ba6c55aaec9 [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 Shim8b86c1c2011-04-12 23:18:59 -070021#include <linux/input/mt.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070022#include <linux/interrupt.h>
23#include <linux/slab.h>
Amy Maloche08266db2011-11-04 11:07:16 -070024#include <linux/gpio.h>
Jing Lin6cfc00e2011-11-02 15:15:30 -070025#include <linux/debugfs.h>
26#include <linux/seq_file.h>
Anirudh Ghayala498e4d2011-08-09 19:10:12 +053027#include <linux/regulator/consumer.h>
Jing Lincc974cb2012-02-01 23:13:14 -080028#include <linux/string.h>
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
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070040
41/* 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 Valkonen81c88a72011-07-04 03:08:25 -070085#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 Valkonen81c88a72011-07-04 03:08:25 -0700104#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 Valkonen81c88a72011-07-04 03:08:25 -0700114/* 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 Valkonen81c88a72011-07-04 03:08:25 -0700121/* 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 Valkonen81c88a72011-07-04 03:08:25 -0700126/* 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 Valkonen81c88a72011-07-04 03:08:25 -0700165/* 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 Valkonen81c88a72011-07-04 03:08:25 -0700195/* 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 Valkonen81c88a72011-07-04 03:08:25 -0700199/* 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 Valkonen81c88a72011-07-04 03:08:25 -0700226/* 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
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700239
240/* 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
Mohan Pallakab6acab42012-06-13 11:59:04 +0530269/* Touch suppression */
270#define MXT_TCHSUP_ACTIVE (1 << 0)
271
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700272/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800273#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700274
Iiro Valkonen7686b102011-02-02 23:21:58 -0800275#define MXT_MAX_FINGER 10
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700276
Jing Lin36aee812011-10-17 17:17:28 -0700277#define T7_DATA_SIZE 3
278#define MXT_MAX_RW_TRIES 3
279#define MXT_BLOCK_SIZE 256
Jing Lin8fadad72012-02-24 10:10:50 -0800280#define MXT_CFG_VERSION_LEN 3
281#define MXT_CFG_VERSION_EQUAL 0
282#define MXT_CFG_VERSION_LESS 1
283#define MXT_CFG_VERSION_GREATER 2
Mohan Pallakaab51f2b2011-09-29 18:17:35 +0530284
Jing Lin6cfc00e2011-11-02 15:15:30 -0700285#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
286#define MXT_DEBUGFS_FILE "object"
287
Iiro Valkonen7686b102011-02-02 23:21:58 -0800288struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700289 u8 family_id;
290 u8 variant_id;
291 u8 version;
292 u8 build;
293 u8 matrix_xsize;
294 u8 matrix_ysize;
295 u8 object_num;
296};
297
Iiro Valkonen7686b102011-02-02 23:21:58 -0800298struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700299 u8 type;
300 u16 start_address;
301 u8 size;
302 u8 instances;
303 u8 num_report_ids;
304
305 /* to map object and message */
306 u8 max_reportid;
307};
308
Iiro Valkonen7686b102011-02-02 23:21:58 -0800309struct mxt_message {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700310 u8 reportid;
311 u8 message[7];
312 u8 checksum;
313};
314
Iiro Valkonen7686b102011-02-02 23:21:58 -0800315struct mxt_finger {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700316 int status;
317 int x;
318 int y;
319 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700320 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700321};
322
323/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800324struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700325 struct i2c_client *client;
326 struct input_dev *input_dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800327 const struct mxt_platform_data *pdata;
Jing Lindc4413c2012-01-16 15:22:52 -0800328 const struct mxt_config_info *config_info;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530329 enum mxt_device_state state;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800330 struct mxt_object *object_table;
331 struct mxt_info info;
332 struct mxt_finger finger[MXT_MAX_FINGER];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700333 unsigned int irq;
Amy Maloche21115eb2011-11-02 09:04:37 -0700334 struct regulator *vcc_ana;
335 struct regulator *vcc_dig;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +0530336 struct regulator *vcc_i2c;
Anirudh Ghayal253ce122011-08-09 19:32:57 +0530337#if defined(CONFIG_HAS_EARLYSUSPEND)
338 struct early_suspend early_suspend;
339#endif
Jing Lin36aee812011-10-17 17:17:28 -0700340
Amy Maloche52262212011-09-15 16:46:57 -0700341 u8 t7_data[T7_DATA_SIZE];
Jing Lin36aee812011-10-17 17:17:28 -0700342 u16 t7_start_addr;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800343 u32 keyarray_old;
344 u32 keyarray_new;
345 u8 t9_max_reportid;
346 u8 t9_min_reportid;
347 u8 t15_max_reportid;
348 u8 t15_min_reportid;
Mohan Pallakab6acab42012-06-13 11:59:04 +0530349 u8 t42_max_reportid;
350 u8 t42_min_reportid;
Jing Lin8fadad72012-02-24 10:10:50 -0800351 u8 cfg_version[MXT_CFG_VERSION_LEN];
Jing Lindc4413c2012-01-16 15:22:52 -0800352 int cfg_version_idx;
Jing Lin8a9472d2012-03-21 15:43:45 -0700353 int t38_start_addr;
Jing Lin8fadad72012-02-24 10:10:50 -0800354 bool update_cfg;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -0800355 const char *fw_name;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700356};
357
Jing Lin6cfc00e2011-11-02 15:15:30 -0700358static struct dentry *debug_base;
359
Iiro Valkonen7686b102011-02-02 23:21:58 -0800360static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700361{
362 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700363 case MXT_GEN_MESSAGE_T5:
364 case MXT_GEN_COMMAND_T6:
365 case MXT_GEN_POWER_T7:
366 case MXT_GEN_ACQUIRE_T8:
367 case MXT_GEN_DATASOURCE_T53:
368 case MXT_TOUCH_MULTI_T9:
369 case MXT_TOUCH_KEYARRAY_T15:
370 case MXT_TOUCH_PROXIMITY_T23:
371 case MXT_TOUCH_PROXKEY_T52:
372 case MXT_PROCI_GRIPFACE_T20:
373 case MXT_PROCG_NOISE_T22:
374 case MXT_PROCI_ONETOUCH_T24:
375 case MXT_PROCI_TWOTOUCH_T27:
376 case MXT_PROCI_GRIP_T40:
377 case MXT_PROCI_PALM_T41:
378 case MXT_PROCI_TOUCHSUPPRESSION_T42:
379 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800380 case MXT_PROCI_SHIELDLESS_T56:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700381 case MXT_PROCG_NOISESUPPRESSION_T48:
382 case MXT_SPT_COMMSCONFIG_T18:
383 case MXT_SPT_GPIOPWM_T19:
384 case MXT_SPT_SELFTEST_T25:
385 case MXT_SPT_CTECONFIG_T28:
386 case MXT_SPT_USERDATA_T38:
387 case MXT_SPT_DIGITIZER_T43:
388 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700389 return true;
390 default:
391 return false;
392 }
393}
394
Iiro Valkonen7686b102011-02-02 23:21:58 -0800395static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700396{
397 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700398 case MXT_GEN_COMMAND_T6:
399 case MXT_GEN_POWER_T7:
400 case MXT_GEN_ACQUIRE_T8:
401 case MXT_TOUCH_MULTI_T9:
402 case MXT_TOUCH_KEYARRAY_T15:
403 case MXT_TOUCH_PROXIMITY_T23:
404 case MXT_TOUCH_PROXKEY_T52:
405 case MXT_PROCI_GRIPFACE_T20:
406 case MXT_PROCG_NOISE_T22:
407 case MXT_PROCI_ONETOUCH_T24:
408 case MXT_PROCI_TWOTOUCH_T27:
409 case MXT_PROCI_GRIP_T40:
410 case MXT_PROCI_PALM_T41:
411 case MXT_PROCI_TOUCHSUPPRESSION_T42:
412 case MXT_PROCI_STYLUS_T47:
Jing Linc7fc4052011-12-21 16:16:19 -0800413 case MXT_PROCI_SHIELDLESS_T56:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700414 case MXT_PROCG_NOISESUPPRESSION_T48:
415 case MXT_SPT_COMMSCONFIG_T18:
416 case MXT_SPT_GPIOPWM_T19:
417 case MXT_SPT_SELFTEST_T25:
418 case MXT_SPT_CTECONFIG_T28:
Iiro Valkonene8645592011-11-18 12:56:19 -0800419 case MXT_SPT_USERDATA_T38:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700420 case MXT_SPT_DIGITIZER_T43:
421 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700422 return true;
423 default:
424 return false;
425 }
426}
427
Iiro Valkonen7686b102011-02-02 23:21:58 -0800428static void mxt_dump_message(struct device *dev,
429 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700430{
431 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
432 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
433 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
434 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
435 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
436 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
437 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
438 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
439 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
440}
441
Nick Dyer0a4016c2012-01-18 15:17:59 +0530442static int mxt_switch_to_bootloader_address(struct mxt_data *data)
443{
444 int i;
445 struct i2c_client *client = data->client;
446
447 if (data->state == BOOTLOADER) {
448 dev_err(&client->dev, "Already in BOOTLOADER state\n");
449 return -EINVAL;
450 }
451
452 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
453 if (mxt_slave_addresses[i].application == client->addr) {
454 dev_info(&client->dev, "Changing to bootloader address: "
455 "%02x -> %02x",
456 client->addr,
457 mxt_slave_addresses[i].bootloader);
458
459 client->addr = mxt_slave_addresses[i].bootloader;
460 data->state = BOOTLOADER;
461 return 0;
462 }
463 }
464
465 dev_err(&client->dev, "Address 0x%02x not found in address table",
466 client->addr);
467 return -EINVAL;
468}
469
470static int mxt_switch_to_appmode_address(struct mxt_data *data)
471{
472 int i;
473 struct i2c_client *client = data->client;
474
475 if (data->state == APPMODE) {
476 dev_err(&client->dev, "Already in APPMODE state\n");
477 return -EINVAL;
478 }
479
480 for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
481 if (mxt_slave_addresses[i].bootloader == client->addr) {
482 dev_info(&client->dev,
483 "Changing to application mode address: "
484 "0x%02x -> 0x%02x",
485 client->addr,
486 mxt_slave_addresses[i].application);
487
488 client->addr = mxt_slave_addresses[i].application;
489 data->state = APPMODE;
490 return 0;
491 }
492 }
493
494 dev_err(&client->dev, "Address 0x%02x not found in address table",
495 client->addr);
496 return -EINVAL;
497}
498
499static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
500{
501 u8 buf[3];
502
503 if (val | MXT_BOOT_EXTENDED_ID) {
504 dev_dbg(&client->dev,
505 "Retrieving extended mode ID information");
506
507 if (i2c_master_recv(client, &buf[0], 3) != 3) {
508 dev_err(&client->dev, "%s: i2c recv failed\n",
509 __func__);
510 return -EIO;
511 }
512
513 dev_info(&client->dev, "Bootloader ID:%d Version:%d",
514 buf[1], buf[2]);
515
516 return buf[0];
517 } else {
518 dev_info(&client->dev, "Bootloader ID:%d",
519 val & MXT_BOOT_ID_MASK);
520
521 return val;
522 }
523}
524
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -0800525static int mxt_get_bootloader_id(struct i2c_client *client)
526{
527 u8 val;
528 u8 buf[3];
529
530 if (i2c_master_recv(client, &val, 1) != 1) {
531 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
532 return -EIO;
533 }
534
535 if (val | MXT_BOOT_EXTENDED_ID) {
536 if (i2c_master_recv(client, &buf[0], 3) != 3) {
537 dev_err(&client->dev, "%s: i2c recv failed\n",
538 __func__);
539 return -EIO;
540 }
541 return buf[1];
542 } else {
543 dev_info(&client->dev, "Bootloader ID:%d",
544 val & MXT_BOOT_ID_MASK);
545
546 return val & MXT_BOOT_ID_MASK;
547 }
548}
549
Iiro Valkonen7686b102011-02-02 23:21:58 -0800550static int mxt_check_bootloader(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530551 unsigned int state)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700552{
553 u8 val;
554
555recheck:
556 if (i2c_master_recv(client, &val, 1) != 1) {
557 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
558 return -EIO;
559 }
560
561 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800562 case MXT_WAITING_BOOTLOAD_CMD:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530563 val = mxt_get_bootloader_version(client, val);
564 val &= ~MXT_BOOT_STATUS_MASK;
565 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800566 case MXT_WAITING_FRAME_DATA:
Nick Dyer0a4016c2012-01-18 15:17:59 +0530567 case MXT_APP_CRC_FAIL:
Iiro Valkonen7686b102011-02-02 23:21:58 -0800568 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700569 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800570 case MXT_FRAME_CRC_PASS:
571 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700572 goto recheck;
Nick Dyer0a4016c2012-01-18 15:17:59 +0530573 if (val == MXT_FRAME_CRC_FAIL) {
574 dev_err(&client->dev, "Bootloader CRC fail\n");
575 return -EINVAL;
576 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700577 break;
578 default:
579 return -EINVAL;
580 }
581
582 if (val != state) {
Nick Dyer0a4016c2012-01-18 15:17:59 +0530583 dev_err(&client->dev, "Invalid bootloader mode state %X\n",
584 val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700585 return -EINVAL;
586 }
587
588 return 0;
589}
590
Iiro Valkonen7686b102011-02-02 23:21:58 -0800591static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700592{
593 u8 buf[2];
594
Iiro Valkonen7686b102011-02-02 23:21:58 -0800595 buf[0] = MXT_UNLOCK_CMD_LSB;
596 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700597
598 if (i2c_master_send(client, buf, 2) != 2) {
599 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
600 return -EIO;
601 }
602
603 return 0;
604}
605
Iiro Valkonen7686b102011-02-02 23:21:58 -0800606static int mxt_fw_write(struct i2c_client *client,
Nick Dyer0a4016c2012-01-18 15:17:59 +0530607 const u8 *data, unsigned int frame_size)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700608{
609 if (i2c_master_send(client, data, frame_size) != frame_size) {
610 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
611 return -EIO;
612 }
613
614 return 0;
615}
616
Iiro Valkonen7686b102011-02-02 23:21:58 -0800617static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700618 u16 reg, u16 len, void *val)
619{
620 struct i2c_msg xfer[2];
621 u8 buf[2];
Jing Lin36aee812011-10-17 17:17:28 -0700622 int i = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700623
624 buf[0] = reg & 0xff;
625 buf[1] = (reg >> 8) & 0xff;
626
627 /* Write register */
628 xfer[0].addr = client->addr;
629 xfer[0].flags = 0;
630 xfer[0].len = 2;
631 xfer[0].buf = buf;
632
633 /* Read data */
634 xfer[1].addr = client->addr;
635 xfer[1].flags = I2C_M_RD;
636 xfer[1].len = len;
637 xfer[1].buf = val;
638
Jing Lin36aee812011-10-17 17:17:28 -0700639 do {
640 if (i2c_transfer(client->adapter, xfer, 2) == 2)
641 return 0;
642 msleep(MXT_WAKE_TIME);
643 } while (++i < MXT_MAX_RW_TRIES);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700644
Jing Lin36aee812011-10-17 17:17:28 -0700645 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
646 return -EIO;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700647}
648
Iiro Valkonen7686b102011-02-02 23:21:58 -0800649static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700650{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800651 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700652}
653
Jing Lin36aee812011-10-17 17:17:28 -0700654static int __mxt_write_reg(struct i2c_client *client,
655 u16 addr, u16 length, u8 *value)
656{
657 u8 buf[MXT_BLOCK_SIZE + 2];
658 int i, tries = 0;
659
660 if (length > MXT_BLOCK_SIZE)
661 return -EINVAL;
662
663 buf[0] = addr & 0xff;
664 buf[1] = (addr >> 8) & 0xff;
665 for (i = 0; i < length; i++)
666 buf[i + 2] = *value++;
667
668 do {
669 if (i2c_master_send(client, buf, length + 2) == (length + 2))
670 return 0;
671 msleep(MXT_WAKE_TIME);
672 } while (++tries < MXT_MAX_RW_TRIES);
673
674 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
675 return -EIO;
676}
677
Iiro Valkonen7686b102011-02-02 23:21:58 -0800678static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700679{
Jing Lin36aee812011-10-17 17:17:28 -0700680 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700681}
682
Iiro Valkonen7686b102011-02-02 23:21:58 -0800683static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700684 u16 reg, u8 *object_buf)
685{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800686 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700687 object_buf);
688}
689
Iiro Valkonen7686b102011-02-02 23:21:58 -0800690static struct mxt_object *
691mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700692{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800693 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700694 int i;
695
696 for (i = 0; i < data->info.object_num; i++) {
697 object = data->object_table + i;
698 if (object->type == type)
699 return object;
700 }
701
702 dev_err(&data->client->dev, "Invalid object type\n");
703 return NULL;
704}
705
Iiro Valkonen7686b102011-02-02 23:21:58 -0800706static int mxt_read_message(struct mxt_data *data,
707 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700708{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800709 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700710 u16 reg;
711
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700712 object = mxt_get_object(data, MXT_GEN_MESSAGE_T5);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700713 if (!object)
714 return -EINVAL;
715
716 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800717 return __mxt_read_reg(data->client, reg,
718 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700719}
720
Iiro Valkonen7686b102011-02-02 23:21:58 -0800721static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700722 u8 type, u8 offset, u8 *val)
723{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800724 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700725 u16 reg;
726
Iiro Valkonen7686b102011-02-02 23:21:58 -0800727 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700728 if (!object)
729 return -EINVAL;
730
731 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800732 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700733}
734
Iiro Valkonen7686b102011-02-02 23:21:58 -0800735static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700736 u8 type, u8 offset, u8 val)
737{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800738 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700739 u16 reg;
740
Iiro Valkonen7686b102011-02-02 23:21:58 -0800741 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700742 if (!object)
743 return -EINVAL;
744
745 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800746 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700747}
748
Iiro Valkonen7686b102011-02-02 23:21:58 -0800749static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700750{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800751 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700752 struct input_dev *input_dev = data->input_dev;
753 int status = finger[single_id].status;
754 int finger_num = 0;
755 int id;
756
Iiro Valkonen7686b102011-02-02 23:21:58 -0800757 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700758 if (!finger[id].status)
759 continue;
760
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700761 input_mt_slot(input_dev, id);
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800762 /* Firmware reports min/max values when the touch is
763 * outside screen area. Send a release event in
764 * such cases to avoid unwanted touches.
765 */
766 if (finger[id].x <= data->pdata->panel_minx ||
767 finger[id].x >= data->pdata->panel_maxx ||
768 finger[id].y <= data->pdata->panel_miny ||
769 finger[id].y >= data->pdata->panel_maxy) {
770 finger[id].status = MXT_RELEASE;
771 }
772
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700773 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
774 finger[id].status != MXT_RELEASE);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700775
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700776 if (finger[id].status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700777 finger_num++;
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700778 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
779 finger[id].area);
780 input_report_abs(input_dev, ABS_MT_POSITION_X,
781 finger[id].x);
782 input_report_abs(input_dev, ABS_MT_POSITION_Y,
783 finger[id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700784 input_report_abs(input_dev, ABS_MT_PRESSURE,
Anirudh Ghayal279a2ae52012-05-18 18:07:46 +0530785 finger[id].pressure);
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -0700786 } else {
787 finger[id].status = 0;
788 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700789 }
790
791 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
792
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800793 if (finger[single_id].x <= data->pdata->panel_minx ||
794 finger[single_id].x >= data->pdata->panel_maxx ||
795 finger[single_id].y <= data->pdata->panel_miny ||
796 finger[single_id].y >= data->pdata->panel_maxy) {
797 status = MXT_RELEASE;
798 }
799
Iiro Valkonen7686b102011-02-02 23:21:58 -0800800 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700801 input_report_abs(input_dev, ABS_X, finger[single_id].x);
802 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
Yufeng Shen28ac2932011-08-16 00:40:54 -0700803 input_report_abs(input_dev,
Yufeng Shene6eb36a2011-10-11 12:28:21 -0700804 ABS_PRESSURE, finger[single_id].pressure);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700805 }
806
807 input_sync(input_dev);
808}
809
Iiro Valkonen7686b102011-02-02 23:21:58 -0800810static void mxt_input_touchevent(struct mxt_data *data,
811 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700812{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800813 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700814 struct device *dev = &data->client->dev;
815 u8 status = message->message[0];
816 int x;
817 int y;
818 int area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700819 int pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700820
821 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800822 if (!(status & MXT_DETECT)) {
823 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700824 dev_dbg(dev, "[%d] released\n", id);
825
Iiro Valkonen7686b102011-02-02 23:21:58 -0800826 finger[id].status = MXT_RELEASE;
827 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700828 }
829 return;
830 }
831
832 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800833 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700834 return;
835
Joonyoung Shim910d8052011-04-12 23:14:38 -0700836 x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
837 y = (message->message[2] << 4) | ((message->message[3] & 0xf));
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800838 if (data->pdata->panel_maxx < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700839 x = x >> 2;
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -0800840 if (data->pdata->panel_maxy < 1024)
Joonyoung Shim910d8052011-04-12 23:14:38 -0700841 y = y >> 2;
842
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700843 area = message->message[4];
Yufeng Shen28ac2932011-08-16 00:40:54 -0700844 pressure = message->message[5];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700845
846 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800847 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700848 x, y, area);
849
Iiro Valkonen7686b102011-02-02 23:21:58 -0800850 finger[id].status = status & MXT_MOVE ?
851 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700852 finger[id].x = x;
853 finger[id].y = y;
854 finger[id].area = area;
Yufeng Shen28ac2932011-08-16 00:40:54 -0700855 finger[id].pressure = pressure;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700856
Iiro Valkonen7686b102011-02-02 23:21:58 -0800857 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700858}
859
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800860static void mxt_handle_key_array(struct mxt_data *data,
861 struct mxt_message *message)
862{
863 u32 keys_changed;
864 int i;
865
866 if (!data->pdata->key_codes) {
867 dev_err(&data->client->dev, "keyarray is not supported\n");
868 return;
869 }
870
871 data->keyarray_new = message->message[1] |
872 (message->message[2] << 8) |
873 (message->message[3] << 16) |
874 (message->message[4] << 24);
875
876 keys_changed = data->keyarray_old ^ data->keyarray_new;
877
878 if (!keys_changed) {
879 dev_dbg(&data->client->dev, "no keys changed\n");
880 return;
881 }
882
883 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
884 if (!(keys_changed & (1 << i)))
885 continue;
886
887 input_report_key(data->input_dev, data->pdata->key_codes[i],
888 (data->keyarray_new & (1 << i)));
889 input_sync(data->input_dev);
890 }
891
892 data->keyarray_old = data->keyarray_new;
893}
894
Mohan Pallakab6acab42012-06-13 11:59:04 +0530895static void mxt_release_all(struct mxt_data *data)
896{
897 int id;
898
899 for (id = 0; id < MXT_MAX_FINGER; id++)
900 if (data->finger[id].status)
901 data->finger[id].status = MXT_RELEASE;
902
903 mxt_input_report(data, 0);
904}
905
906static void mxt_handle_touch_supression(struct mxt_data *data, u8 status)
907{
908 dev_dbg(&data->client->dev, "touch suppression\n");
909 /* release all touches */
910 if (status & MXT_TCHSUP_ACTIVE)
911 mxt_release_all(data);
912}
913
Iiro Valkonen7686b102011-02-02 23:21:58 -0800914static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700915{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800916 struct mxt_data *data = dev_id;
917 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700918 struct device *dev = &data->client->dev;
919 int id;
920 u8 reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700921
Nick Dyer0a4016c2012-01-18 15:17:59 +0530922 if (data->state != APPMODE) {
923 dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
924 return IRQ_HANDLED;
925 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700926
927 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800928 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700929 dev_err(dev, "Failed to read message\n");
930 goto end;
931 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700932 reportid = message.reportid;
933
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800934 if (!reportid) {
935 dev_dbg(dev, "Report id 0 is reserved\n");
936 continue;
937 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700938
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800939 /* check whether report id is part of T9 or T15 */
940 id = reportid - data->t9_min_reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700941
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800942 if (reportid >= data->t9_min_reportid &&
943 reportid <= data->t9_max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -0800944 mxt_input_touchevent(data, &message, id);
Mohan Pallaka382d3ce2012-01-02 20:24:28 +0800945 else if (reportid >= data->t15_min_reportid &&
946 reportid <= data->t15_max_reportid)
947 mxt_handle_key_array(data, &message);
Mohan Pallakab6acab42012-06-13 11:59:04 +0530948 else if (reportid >= data->t42_min_reportid &&
949 reportid <= data->t42_max_reportid)
950 mxt_handle_touch_supression(data, message.message[0]);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700951 else
Iiro Valkonen7686b102011-02-02 23:21:58 -0800952 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700953 } while (reportid != 0xff);
954
955end:
956 return IRQ_HANDLED;
957}
958
Iiro Valkonen7686b102011-02-02 23:21:58 -0800959static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700960{
Jing Lindc4413c2012-01-16 15:22:52 -0800961 const struct mxt_config_info *config_info = data->config_info;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800962 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700963 struct device *dev = &data->client->dev;
964 int index = 0;
Iiro Valkonen71749f52011-02-15 13:36:52 -0800965 int i, j, config_offset;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700966
Jing Lindc4413c2012-01-16 15:22:52 -0800967 if (!config_info) {
Iiro Valkonen71749f52011-02-15 13:36:52 -0800968 dev_dbg(dev, "No cfg data defined, skipping reg init\n");
969 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700970 }
971
972 for (i = 0; i < data->info.object_num; i++) {
973 object = data->object_table + i;
974
Iiro Valkonen7686b102011-02-02 23:21:58 -0800975 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700976 continue;
977
Iiro Valkonen71749f52011-02-15 13:36:52 -0800978 for (j = 0; j < object->size + 1; j++) {
979 config_offset = index + j;
Jing Lindc4413c2012-01-16 15:22:52 -0800980 if (config_offset > config_info->config_length) {
Iiro Valkonen71749f52011-02-15 13:36:52 -0800981 dev_err(dev, "Not enough config data!\n");
982 return -EINVAL;
983 }
Iiro Valkonen7686b102011-02-02 23:21:58 -0800984 mxt_write_object(data, object->type, j,
Jing Lindc4413c2012-01-16 15:22:52 -0800985 config_info->config[config_offset]);
Iiro Valkonen71749f52011-02-15 13:36:52 -0800986 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700987 index += object->size + 1;
988 }
989
990 return 0;
991}
992
Iiro Valkonen7686b102011-02-02 23:21:58 -0800993static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700994{
995 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800996 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700997 int count = 10;
998 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700999
1000 /* Read dummy message to make high CHG pin */
1001 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001002 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001003 if (error)
1004 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -08001005 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001006
1007 if (!count) {
1008 dev_err(dev, "CHG pin isn't cleared\n");
1009 return -EBUSY;
1010 }
1011
1012 return 0;
1013}
1014
Iiro Valkonen7686b102011-02-02 23:21:58 -08001015static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001016{
1017 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001018 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001019 int error;
1020 u8 val;
1021
Iiro Valkonen7686b102011-02-02 23:21:58 -08001022 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001023 if (error)
1024 return error;
1025 info->family_id = val;
1026
Iiro Valkonen7686b102011-02-02 23:21:58 -08001027 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001028 if (error)
1029 return error;
1030 info->variant_id = val;
1031
Iiro Valkonen7686b102011-02-02 23:21:58 -08001032 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001033 if (error)
1034 return error;
1035 info->version = val;
1036
Iiro Valkonen7686b102011-02-02 23:21:58 -08001037 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001038 if (error)
1039 return error;
1040 info->build = val;
1041
Iiro Valkonen7686b102011-02-02 23:21:58 -08001042 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001043 if (error)
1044 return error;
1045 info->object_num = val;
1046
1047 return 0;
1048}
1049
Iiro Valkonen7686b102011-02-02 23:21:58 -08001050static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001051{
1052 int error;
1053 int i;
1054 u16 reg;
1055 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001056 u8 buf[MXT_OBJECT_SIZE];
Jing Lindc4413c2012-01-16 15:22:52 -08001057 bool found_t38 = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001058
1059 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001060 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001061
Iiro Valkonen7686b102011-02-02 23:21:58 -08001062 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
1063 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001064 if (error)
1065 return error;
1066
1067 object->type = buf[0];
1068 object->start_address = (buf[2] << 8) | buf[1];
1069 object->size = buf[3];
1070 object->instances = buf[4];
1071 object->num_report_ids = buf[5];
1072
1073 if (object->num_report_ids) {
1074 reportid += object->num_report_ids *
1075 (object->instances + 1);
1076 object->max_reportid = reportid;
1077 }
Jing Lindc4413c2012-01-16 15:22:52 -08001078
1079 /* Calculate index for config major version in config array.
1080 * Major version is the first byte in object T38.
1081 */
Jing Lin8a9472d2012-03-21 15:43:45 -07001082 if (object->type == MXT_SPT_USERDATA_T38) {
1083 data->t38_start_addr = object->start_address;
Jing Lindc4413c2012-01-16 15:22:52 -08001084 found_t38 = true;
Jing Lin8a9472d2012-03-21 15:43:45 -07001085 }
Jing Lindc4413c2012-01-16 15:22:52 -08001086 if (!found_t38 && mxt_object_writable(object->type))
1087 data->cfg_version_idx += object->size + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001088 }
1089
1090 return 0;
1091}
1092
Jing Lin8fadad72012-02-24 10:10:50 -08001093static int compare_versions(const u8 *v1, const u8 *v2)
1094{
1095 int i;
1096
1097 if (!v1 || !v2)
1098 return -EINVAL;
1099
1100 /* The major version number stays the same across different versions for
1101 * a particular controller on a target. The minor and sub-minor version
1102 * numbers indicate which version is newer.
1103 */
1104 if (v1[0] != v2[0])
1105 return -EINVAL;
1106
1107 for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
1108 if (v1[i] > v2[i])
1109 return MXT_CFG_VERSION_LESS; /* v2 is older */
1110
1111 if (v1[i] < v2[i])
1112 return MXT_CFG_VERSION_GREATER; /* v2 is newer */
1113 }
1114
1115 return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
1116}
1117
1118static void mxt_check_config_version(struct mxt_data *data,
1119 const struct mxt_config_info *cfg_info,
1120 bool match_major,
1121 const u8 **cfg_version_found,
1122 bool *found_cfg_major_match)
1123{
1124 const u8 *cfg_version;
1125 int result = -EINVAL;
1126
1127 cfg_version = cfg_info->config + data->cfg_version_idx;
1128
1129 if (*cfg_version_found)
1130 result = compare_versions(*cfg_version_found, cfg_version);
1131
1132 if (match_major) {
1133 if (result >= MXT_CFG_VERSION_EQUAL)
1134 *found_cfg_major_match = true;
1135
1136 if (result == MXT_CFG_VERSION_EQUAL ||
1137 result == MXT_CFG_VERSION_GREATER) {
1138 data->config_info = cfg_info;
1139 data->fw_name = cfg_info->fw_name;
1140 *cfg_version_found = cfg_version;
1141 }
1142
1143 if (result == MXT_CFG_VERSION_GREATER)
1144 data->update_cfg = true;
1145 } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
1146 data->config_info = cfg_info;
1147 data->fw_name = cfg_info->fw_name;
1148 data->update_cfg = true;
1149 *cfg_version_found = cfg_version;
1150 }
1151}
1152
1153/* If the controller's config version has a non-zero major number, call this
1154 * function with match_major = true to look for the latest config present in
1155 * the pdata based on matching family id, variant id, f/w version, build, and
1156 * config major number. If the controller is programmed with wrong config data
1157 * previously, call this function with match_major = false to look for latest
1158 * config based on based on matching family id, variant id, f/w version and
1159 * build only.
1160 */
1161static int mxt_search_config_array(struct mxt_data *data, bool match_major)
Jing Lindc4413c2012-01-16 15:22:52 -08001162{
1163
1164 const struct mxt_platform_data *pdata = data->pdata;
1165 const struct mxt_config_info *cfg_info;
Jing Lin8fadad72012-02-24 10:10:50 -08001166 const struct mxt_info *info = &data->info;
1167 const u8 *cfg_version_found;
1168 bool found_cfg_major_match = false;
Jing Lindc4413c2012-01-16 15:22:52 -08001169 int i;
Jing Lin8fadad72012-02-24 10:10:50 -08001170
1171 cfg_version_found = match_major ? data->cfg_version : NULL;
Jing Lindc4413c2012-01-16 15:22:52 -08001172
1173 for (i = 0; i < pdata->config_array_size; i++) {
1174
1175 cfg_info = &pdata->config_array[i];
1176
1177 if (!cfg_info->config || !cfg_info->config_length)
1178 continue;
1179
1180 if (info->family_id == cfg_info->family_id &&
1181 info->variant_id == cfg_info->variant_id &&
1182 info->version == cfg_info->version &&
1183 info->build == cfg_info->build) {
1184
Jing Lin8fadad72012-02-24 10:10:50 -08001185 mxt_check_config_version(data, cfg_info, match_major,
1186 &cfg_version_found, &found_cfg_major_match);
Jing Lindc4413c2012-01-16 15:22:52 -08001187 }
1188 }
1189
Jing Lin8fadad72012-02-24 10:10:50 -08001190 if (data->config_info || found_cfg_major_match)
1191 return 0;
1192
1193 data->config_info = NULL;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001194 data->fw_name = NULL;
Jing Lin8fadad72012-02-24 10:10:50 -08001195
Jing Lindc4413c2012-01-16 15:22:52 -08001196 return -EINVAL;
1197}
1198
1199static int mxt_get_config(struct mxt_data *data)
1200{
1201 const struct mxt_platform_data *pdata = data->pdata;
1202 struct device *dev = &data->client->dev;
1203 struct mxt_object *object;
1204 int error;
1205
1206 if (!pdata->config_array || !pdata->config_array_size) {
1207 dev_dbg(dev, "No cfg data provided by platform data\n");
1208 return 0;
1209 }
1210
1211 /* Get current config version */
1212 object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
1213 if (!object) {
1214 dev_err(dev, "Unable to obtain USERDATA object\n");
1215 return -EINVAL;
1216 }
1217
Jing Lin8fadad72012-02-24 10:10:50 -08001218 error = __mxt_read_reg(data->client, object->start_address,
1219 sizeof(data->cfg_version), data->cfg_version);
Jing Lindc4413c2012-01-16 15:22:52 -08001220 if (error) {
1221 dev_err(dev, "Unable to read config version\n");
1222 return error;
1223 }
Jing Lin8fadad72012-02-24 10:10:50 -08001224 dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
1225 data->cfg_version[0], data->cfg_version[1],
1226 data->cfg_version[2]);
Jing Lindc4413c2012-01-16 15:22:52 -08001227
1228 /* It is possible that the config data on the controller is not
1229 * versioned and the version number returns 0. In this case,
1230 * find a match without the config version checking.
1231 */
1232 error = mxt_search_config_array(data,
Jing Lin8fadad72012-02-24 10:10:50 -08001233 data->cfg_version[0] != 0 ? true : false);
1234 if (error) {
1235 /* If a match wasn't found for a non-zero config version,
1236 * it means the controller has the wrong config data. Search
1237 * for a best match based on controller and firmware version,
1238 * but not config version.
1239 */
1240 if (data->cfg_version[0])
1241 error = mxt_search_config_array(data, false);
1242 if (error) {
1243 dev_err(dev,
1244 "Unable to find matching config in pdata\n");
1245 return error;
1246 }
1247 }
Jing Lindc4413c2012-01-16 15:22:52 -08001248
1249 return 0;
1250}
Jing Lin8fadad72012-02-24 10:10:50 -08001251
Amy Maloche7e447432011-09-14 11:36:30 -07001252static void mxt_reset_delay(struct mxt_data *data)
1253{
1254 struct mxt_info *info = &data->info;
1255
1256 switch (info->family_id) {
1257 case MXT224_ID:
1258 msleep(MXT224_RESET_TIME);
1259 break;
Amy Maloche380cc0b2011-11-03 12:55:04 -07001260 case MXT224E_ID:
1261 msleep(MXT224E_RESET_TIME);
1262 break;
Amy Maloche7e447432011-09-14 11:36:30 -07001263 case MXT1386_ID:
1264 msleep(MXT1386_RESET_TIME);
1265 break;
1266 default:
1267 msleep(MXT_RESET_TIME);
1268 }
1269}
1270
Jing Lin8fadad72012-02-24 10:10:50 -08001271static int mxt_backup_nv(struct mxt_data *data)
1272{
1273 int error;
1274 u8 command_register;
1275 int timeout_counter = 0;
1276
1277 /* Backup to memory */
1278 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1279 MXT_COMMAND_BACKUPNV,
1280 MXT_BACKUP_VALUE);
1281 msleep(MXT_BACKUP_TIME);
1282
1283 do {
1284 error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
1285 MXT_COMMAND_BACKUPNV,
1286 &command_register);
1287 if (error)
1288 return error;
1289
1290 usleep_range(1000, 2000);
1291
1292 } while ((command_register != 0) && (++timeout_counter <= 100));
1293
1294 if (timeout_counter > 100) {
1295 dev_err(&data->client->dev, "No response after backup!\n");
1296 return -EIO;
1297 }
1298
1299 /* Soft reset */
1300 mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
1301
1302 mxt_reset_delay(data);
1303
1304 return 0;
1305}
1306
Jing Lin412aedc2012-02-28 13:57:19 -08001307static int mxt_save_objects(struct mxt_data *data)
1308{
1309 struct i2c_client *client = data->client;
1310 struct mxt_object *t7_object;
1311 struct mxt_object *t9_object;
1312 struct mxt_object *t15_object;
Mohan Pallakab6acab42012-06-13 11:59:04 +05301313 struct mxt_object *t42_object;
Jing Lin412aedc2012-02-28 13:57:19 -08001314 int error;
1315
1316 /* Store T7 and T9 locally, used in suspend/resume operations */
1317 t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
1318 if (!t7_object) {
1319 dev_err(&client->dev, "Failed to get T7 object\n");
1320 return -EINVAL;
1321 }
1322
1323 data->t7_start_addr = t7_object->start_address;
1324 error = __mxt_read_reg(client, data->t7_start_addr,
1325 T7_DATA_SIZE, data->t7_data);
1326 if (error < 0) {
1327 dev_err(&client->dev,
1328 "Failed to save current power state\n");
1329 return error;
1330 }
1331
Jing Lin412aedc2012-02-28 13:57:19 -08001332 /* Store T9, T15's min and max report ids */
1333 t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1334 if (!t9_object) {
1335 dev_err(&client->dev, "Failed to get T9 object\n");
1336 return -EINVAL;
1337 }
1338 data->t9_max_reportid = t9_object->max_reportid;
1339 data->t9_min_reportid = t9_object->max_reportid -
1340 t9_object->num_report_ids + 1;
1341
1342 if (data->pdata->key_codes) {
1343 t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
1344 if (!t15_object)
1345 dev_dbg(&client->dev, "T15 object is not available\n");
1346 else {
1347 data->t15_max_reportid = t15_object->max_reportid;
1348 data->t15_min_reportid = t15_object->max_reportid -
1349 t15_object->num_report_ids + 1;
1350 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001351 }
1352
Mohan Pallakab6acab42012-06-13 11:59:04 +05301353 /* Store T42 min and max report ids */
1354 t42_object = mxt_get_object(data, MXT_PROCI_TOUCHSUPPRESSION_T42);
1355 if (!t42_object)
1356 dev_dbg(&client->dev, "T42 object is not available\n");
1357 else {
1358 data->t42_max_reportid = t42_object->max_reportid;
1359 data->t42_min_reportid = t42_object->max_reportid -
1360 t42_object->num_report_ids + 1;
1361 }
1362
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001363 return 0;
1364}
1365
Iiro Valkonen7686b102011-02-02 23:21:58 -08001366static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001367{
1368 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001369 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001370 int error;
1371 u8 val;
Jing Lin8fadad72012-02-24 10:10:50 -08001372 const u8 *cfg_ver;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001373
Iiro Valkonen7686b102011-02-02 23:21:58 -08001374 error = mxt_get_info(data);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301375 if (error) {
1376 /* Try bootloader mode */
1377 error = mxt_switch_to_bootloader_address(data);
1378 if (error)
1379 return error;
1380
1381 error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
1382 if (error)
1383 return error;
1384
1385 dev_err(&client->dev, "Application CRC failure\n");
1386 data->state = BOOTLOADER;
1387
1388 return 0;
1389 }
1390
1391 dev_info(&client->dev,
1392 "Family ID: %d Variant ID: %d Version: %d.%d "
1393 "Build: 0x%02X Object Num: %d\n",
1394 info->family_id, info->variant_id,
1395 info->version >> 4, info->version & 0xf,
1396 info->build, info->object_num);
1397
1398 data->state = APPMODE;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001399
1400 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001401 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001402 GFP_KERNEL);
1403 if (!data->object_table) {
1404 dev_err(&client->dev, "Failed to allocate memory\n");
1405 return -ENOMEM;
1406 }
1407
1408 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001409 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001410 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001411 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001412
Jing Lindc4413c2012-01-16 15:22:52 -08001413 /* Get config data from platform data */
1414 error = mxt_get_config(data);
1415 if (error)
1416 dev_dbg(&client->dev, "Config info not found.\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001417
1418 /* Check register init values */
Jing Lin8fadad72012-02-24 10:10:50 -08001419 if (data->config_info && data->config_info->config) {
1420 if (data->update_cfg) {
1421 error = mxt_check_reg_init(data);
1422 if (error) {
1423 dev_err(&client->dev,
1424 "Failed to check reg init value\n");
1425 goto free_object_table;
1426 }
1427
1428 error = mxt_backup_nv(data);
1429 if (error) {
1430 dev_err(&client->dev, "Failed to back up NV\n");
1431 goto free_object_table;
1432 }
1433
1434 cfg_ver = data->config_info->config +
1435 data->cfg_version_idx;
1436 dev_info(&client->dev,
1437 "Config updated from %d.%d.%d to %d.%d.%d\n",
1438 data->cfg_version[0], data->cfg_version[1],
1439 data->cfg_version[2],
1440 cfg_ver[0], cfg_ver[1], cfg_ver[2]);
1441
1442 memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
1443 }
1444 } else {
1445 dev_info(&client->dev,
1446 "No cfg data defined, skipping check reg init\n");
1447 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001448
Jing Lin412aedc2012-02-28 13:57:19 -08001449 error = mxt_save_objects(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001450 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001451 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001452
1453 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001454 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001455 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001456 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001457 info->matrix_xsize = val;
1458
Iiro Valkonen7686b102011-02-02 23:21:58 -08001459 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001460 if (error)
Jing Lin32c72532011-11-03 12:02:33 -07001461 goto free_object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001462 info->matrix_ysize = val;
1463
1464 dev_info(&client->dev,
Nick Dyer0a4016c2012-01-18 15:17:59 +05301465 "Matrix X Size: %d Matrix Y Size: %d\n",
1466 info->matrix_xsize, info->matrix_ysize);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001467
1468 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001469
Jing Lin32c72532011-11-03 12:02:33 -07001470free_object_table:
1471 kfree(data->object_table);
1472 return error;
Joonyoung Shim910d8052011-04-12 23:14:38 -07001473}
1474
Iiro Valkonen7686b102011-02-02 23:21:58 -08001475static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001476 struct device_attribute *attr, char *buf)
1477{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001478 struct mxt_data *data = dev_get_drvdata(dev);
1479 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001480 int count = 0;
1481 int i, j;
1482 int error;
1483 u8 val;
1484
1485 for (i = 0; i < data->info.object_num; i++) {
1486 object = data->object_table + i;
1487
Daniel Kurtz626af862011-10-06 15:43:20 -07001488 count += snprintf(buf + count, PAGE_SIZE - count,
1489 "Object[%d] (Type %d)\n",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001490 i + 1, object->type);
Daniel Kurtz626af862011-10-06 15:43:20 -07001491 if (count >= PAGE_SIZE)
1492 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001493
Iiro Valkonen7686b102011-02-02 23:21:58 -08001494 if (!mxt_object_readable(object->type)) {
Daniel Kurtz626af862011-10-06 15:43:20 -07001495 count += snprintf(buf + count, PAGE_SIZE - count,
1496 "\n");
1497 if (count >= PAGE_SIZE)
1498 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001499 continue;
1500 }
1501
1502 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001503 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001504 object->type, j, &val);
1505 if (error)
1506 return error;
1507
Daniel Kurtz626af862011-10-06 15:43:20 -07001508 count += snprintf(buf + count, PAGE_SIZE - count,
1509 "\t[%2d]: %02x (%d)\n", j, val, val);
1510 if (count >= PAGE_SIZE)
1511 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001512 }
1513
Daniel Kurtz626af862011-10-06 15:43:20 -07001514 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1515 if (count >= PAGE_SIZE)
1516 return PAGE_SIZE - 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001517 }
1518
1519 return count;
1520}
1521
Jing Lincc974cb2012-02-01 23:13:14 -08001522static int strtobyte(const char *data, u8 *value)
1523{
1524 char str[3];
1525
1526 str[0] = data[0];
1527 str[1] = data[1];
1528 str[2] = '\0';
1529
1530 return kstrtou8(str, 16, value);
1531}
1532
Iiro Valkonen7686b102011-02-02 23:21:58 -08001533static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001534{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001535 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001536 struct i2c_client *client = data->client;
1537 const struct firmware *fw = NULL;
1538 unsigned int frame_size;
Nick Dyer0a4016c2012-01-18 15:17:59 +05301539 unsigned int retry = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001540 unsigned int pos = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001541 int ret, i, max_frame_size;
1542 u8 *frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001543
Jing Lincc974cb2012-02-01 23:13:14 -08001544 switch (data->info.family_id) {
1545 case MXT224_ID:
1546 max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
1547 break;
1548 case MXT1386_ID:
1549 max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
1550 break;
1551 default:
1552 return -EINVAL;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001553 }
1554
Jing Lincc974cb2012-02-01 23:13:14 -08001555 frame = kmalloc(max_frame_size, GFP_KERNEL);
1556 if (!frame) {
1557 dev_err(dev, "Unable to allocate memory for frame data\n");
1558 return -ENOMEM;
1559 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001560
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001561 ret = request_firmware(&fw, fn, dev);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301562 if (ret < 0) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001563 dev_err(dev, "Unable to open firmware %s\n", fn);
Jing Lincc974cb2012-02-01 23:13:14 -08001564 goto free_frame;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001565 }
1566
Nick Dyer0a4016c2012-01-18 15:17:59 +05301567 if (data->state != BOOTLOADER) {
1568 /* Change to the bootloader mode */
1569 mxt_write_object(data, MXT_GEN_COMMAND_T6,
1570 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1571 mxt_reset_delay(data);
Amy Maloche7e447432011-09-14 11:36:30 -07001572
Nick Dyer0a4016c2012-01-18 15:17:59 +05301573 ret = mxt_switch_to_bootloader_address(data);
1574 if (ret)
1575 goto release_firmware;
1576 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001577
Iiro Valkonen7686b102011-02-02 23:21:58 -08001578 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301579 if (ret) {
1580 /* Bootloader may still be unlocked from previous update
1581 * attempt */
1582 ret = mxt_check_bootloader(client,
1583 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001584
Nick Dyer0a4016c2012-01-18 15:17:59 +05301585 if (ret)
1586 goto return_to_app_mode;
1587 } else {
1588 dev_info(dev, "Unlocking bootloader\n");
1589 /* Unlock bootloader */
1590 mxt_unlock_bootloader(client);
1591 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001592
1593 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001594 ret = mxt_check_bootloader(client,
1595 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001596 if (ret)
Nick Dyer0a4016c2012-01-18 15:17:59 +05301597 goto release_firmware;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001598
Jing Lincc974cb2012-02-01 23:13:14 -08001599 /* Get frame length MSB */
1600 ret = strtobyte(fw->data + pos, frame);
1601 if (ret)
1602 goto release_firmware;
1603
1604 /* Get frame length LSB */
1605 ret = strtobyte(fw->data + pos + 2, frame + 1);
1606 if (ret)
1607 goto release_firmware;
1608
1609 frame_size = ((*frame << 8) | *(frame + 1));
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001610
1611 /* We should add 2 at frame size as the the firmware data is not
1612 * included the CRC bytes.
1613 */
1614 frame_size += 2;
1615
Jing Lincc974cb2012-02-01 23:13:14 -08001616 if (frame_size > max_frame_size) {
1617 dev_err(dev, "Invalid frame size - %d\n", frame_size);
1618 ret = -EINVAL;
1619 goto release_firmware;
1620 }
1621
1622 /* Convert frame data and CRC from hex to binary */
1623 for (i = 2; i < frame_size; i++) {
1624 ret = strtobyte(fw->data + pos + i * 2, frame + i);
1625 if (ret)
1626 goto release_firmware;
1627 }
1628
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001629 /* Write one frame to device */
Jing Lincc974cb2012-02-01 23:13:14 -08001630 mxt_fw_write(client, frame, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001631
Iiro Valkonen7686b102011-02-02 23:21:58 -08001632 ret = mxt_check_bootloader(client,
1633 MXT_FRAME_CRC_PASS);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301634 if (ret) {
1635 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001636
Nick Dyer0a4016c2012-01-18 15:17:59 +05301637 /* Back off by 20ms per retry */
1638 msleep(retry * 20);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001639
Nick Dyer0a4016c2012-01-18 15:17:59 +05301640 if (retry > 20)
1641 goto release_firmware;
1642 } else {
1643 retry = 0;
Jing Lincc974cb2012-02-01 23:13:14 -08001644 pos += frame_size * 2;
1645 dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
Nick Dyer0a4016c2012-01-18 15:17:59 +05301646 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001647 }
1648
Nick Dyer0a4016c2012-01-18 15:17:59 +05301649return_to_app_mode:
1650 mxt_switch_to_appmode_address(data);
1651release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001652 release_firmware(fw);
Jing Lincc974cb2012-02-01 23:13:14 -08001653free_frame:
1654 kfree(frame);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001655
1656 return ret;
1657}
1658
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001659static const char *
1660mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
1661{
1662 const struct mxt_platform_data *pdata = data->pdata;
1663 const struct mxt_config_info *cfg_info;
1664 const char *fw_name = NULL;
1665 int i;
1666
1667 for (i = 0; i < pdata->config_array_size; i++) {
1668 cfg_info = &pdata->config_array[i];
1669 if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
1670 data->config_info = cfg_info;
1671 data->info.family_id = cfg_info->family_id;
1672 fw_name = cfg_info->fw_name;
1673 }
1674 }
1675
1676 return fw_name;
1677}
1678
Iiro Valkonen7686b102011-02-02 23:21:58 -08001679static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001680 struct device_attribute *attr,
1681 const char *buf, size_t count)
1682{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001683 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001684 int error;
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001685 const char *fw_name;
1686 u8 bootldr_id;
Jing Lin8a9472d2012-03-21 15:43:45 -07001687 u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001688
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001689 /* If fw_name is set, then the existing firmware has an upgrade */
1690 if (!data->fw_name) {
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001691 /*
1692 * If the device boots up in the bootloader mode, check if
1693 * there is a firmware to upgrade.
1694 */
1695 if (data->state == BOOTLOADER) {
1696 bootldr_id = mxt_get_bootloader_id(data->client);
1697 if (bootldr_id <= 0) {
1698 dev_err(dev,
1699 "Unable to retrieve bootloader id\n");
1700 return -EINVAL;
1701 }
1702 fw_name = mxt_search_fw_name(data, bootldr_id);
1703 if (fw_name == NULL) {
1704 dev_err(dev,
1705 "Unable to find fw from bootloader id\n");
1706 return -EINVAL;
1707 }
1708 } else {
1709 /* In APPMODE, if the f/w name does not exist, quit */
1710 dev_err(dev,
1711 "Firmware name not specified in platform data\n");
1712 return -EINVAL;
1713 }
1714 } else {
1715 fw_name = data->fw_name;
Anirudh Ghayal0bcb5b52012-02-17 14:58:25 -08001716 }
1717
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001718 dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001719
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001720 disable_irq(data->irq);
1721
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001722 error = mxt_load_fw(dev, fw_name);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001723 if (error) {
1724 dev_err(dev, "The firmware update failed(%d)\n", error);
1725 count = error;
1726 } else {
Nick Dyer0a4016c2012-01-18 15:17:59 +05301727 dev_info(dev, "The firmware update succeeded\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001728
1729 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001730 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001731
Nick Dyer0a4016c2012-01-18 15:17:59 +05301732 data->state = INIT;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001733 kfree(data->object_table);
1734 data->object_table = NULL;
Jing Lincc974cb2012-02-01 23:13:14 -08001735 data->cfg_version_idx = 0;
Jing Lin8fadad72012-02-24 10:10:50 -08001736 data->update_cfg = false;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001737
Jing Lin8a9472d2012-03-21 15:43:45 -07001738 error = __mxt_write_reg(data->client, data->t38_start_addr,
1739 sizeof(cfg_version), cfg_version);
1740 if (error)
1741 dev_err(dev,
1742 "Unable to zero out config version after fw upgrade\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001743
Iiro Valkonen7686b102011-02-02 23:21:58 -08001744 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001745 }
1746
Nick Dyer0a4016c2012-01-18 15:17:59 +05301747 if (data->state == APPMODE) {
1748 enable_irq(data->irq);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001749
Nick Dyer0a4016c2012-01-18 15:17:59 +05301750 error = mxt_make_highchg(data);
1751 if (error)
1752 return error;
1753 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07001754
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001755 return count;
1756}
1757
Iiro Valkonen7686b102011-02-02 23:21:58 -08001758static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
1759static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001760
Iiro Valkonen7686b102011-02-02 23:21:58 -08001761static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001762 &dev_attr_object.attr,
1763 &dev_attr_update_fw.attr,
1764 NULL
1765};
1766
Iiro Valkonen7686b102011-02-02 23:21:58 -08001767static const struct attribute_group mxt_attr_group = {
1768 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001769};
1770
Amy Maloche52262212011-09-15 16:46:57 -07001771static int mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001772{
Jing Lin36aee812011-10-17 17:17:28 -07001773 int error;
1774
Amy Maloche52262212011-09-15 16:46:57 -07001775 /* restore the old power state values and reenable touch */
Jing Lin36aee812011-10-17 17:17:28 -07001776 error = __mxt_write_reg(data->client, data->t7_start_addr,
1777 T7_DATA_SIZE, data->t7_data);
1778 if (error < 0) {
1779 dev_err(&data->client->dev,
1780 "failed to restore old power state\n");
1781 return error;
Amy Maloche52262212011-09-15 16:46:57 -07001782 }
Jing Lin36aee812011-10-17 17:17:28 -07001783
Amy Maloche52262212011-09-15 16:46:57 -07001784 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001785}
1786
Amy Maloche52262212011-09-15 16:46:57 -07001787static int mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001788{
Jing Lin36aee812011-10-17 17:17:28 -07001789 int error;
1790 u8 t7_data[T7_DATA_SIZE] = {0};
1791
Jing Lin36aee812011-10-17 17:17:28 -07001792 error = __mxt_write_reg(data->client, data->t7_start_addr,
1793 T7_DATA_SIZE, t7_data);
Amy Maloche52262212011-09-15 16:46:57 -07001794 if (error < 0) {
1795 dev_err(&data->client->dev,
Jing Lin36aee812011-10-17 17:17:28 -07001796 "failed to configure deep sleep mode\n");
Amy Maloche52262212011-09-15 16:46:57 -07001797 return error;
1798 }
1799
1800 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001801}
1802
Iiro Valkonen7686b102011-02-02 23:21:58 -08001803static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001804{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001805 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001806 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001807
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001808 if (data->state == APPMODE) {
1809 error = mxt_start(data);
1810 if (error < 0) {
1811 dev_err(&data->client->dev, "mxt_start failed in input_open\n");
1812 return error;
1813 }
Amy Maloche52262212011-09-15 16:46:57 -07001814 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001815
1816 return 0;
1817}
1818
Iiro Valkonen7686b102011-02-02 23:21:58 -08001819static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001820{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001821 struct mxt_data *data = input_get_drvdata(dev);
Amy Maloche52262212011-09-15 16:46:57 -07001822 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001823
Anirudh Ghayal6c3b37b2012-02-23 18:39:42 -08001824 if (data->state == APPMODE) {
1825 error = mxt_stop(data);
1826 if (error < 0)
1827 dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
1828 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001829}
1830
Amy Malochec331f842012-01-24 10:33:47 -08001831static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
1832{
1833 return (regulator_count_voltages(reg) > 0) ?
1834 regulator_set_optimum_mode(reg, load_uA) : 0;
1835}
1836
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301837static int mxt_power_on(struct mxt_data *data, bool on)
1838{
1839 int rc;
1840
1841 if (on == false)
1842 goto power_off;
1843
Amy Malochec331f842012-01-24 10:33:47 -08001844 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301845 if (rc < 0) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001846 dev_err(&data->client->dev,
1847 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301848 return rc;
1849 }
1850
Amy Maloche21115eb2011-11-02 09:04:37 -07001851 rc = regulator_enable(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301852 if (rc) {
Amy Maloche21115eb2011-11-02 09:04:37 -07001853 dev_err(&data->client->dev,
1854 "Regulator vcc_ana enable failed rc=%d\n", rc);
1855 goto error_reg_en_vcc_ana;
1856 }
1857
1858 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001859 rc = reg_set_optimum_mode_check(data->vcc_dig,
1860 MXT_ACTIVE_LOAD_DIG_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07001861 if (rc < 0) {
1862 dev_err(&data->client->dev,
1863 "Regulator vcc_dig set_opt failed rc=%d\n",
1864 rc);
1865 goto error_reg_opt_vcc_dig;
1866 }
1867
1868 rc = regulator_enable(data->vcc_dig);
1869 if (rc) {
1870 dev_err(&data->client->dev,
1871 "Regulator vcc_dig enable failed rc=%d\n", rc);
1872 goto error_reg_en_vcc_dig;
1873 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301874 }
1875
1876 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001877 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301878 if (rc < 0) {
1879 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001880 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301881 goto error_reg_opt_i2c;
1882 }
1883
1884 rc = regulator_enable(data->vcc_i2c);
1885 if (rc) {
1886 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07001887 "Regulator vcc_i2c enable failed rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301888 goto error_reg_en_vcc_i2c;
1889 }
1890 }
1891
Amy Malochef0d7b8d2011-10-17 12:10:51 -07001892 msleep(130);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301893
1894 return 0;
1895
1896error_reg_en_vcc_i2c:
1897 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08001898 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301899error_reg_opt_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001900 if (data->pdata->digital_pwr_regulator)
1901 regulator_disable(data->vcc_dig);
1902error_reg_en_vcc_dig:
1903 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08001904 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001905error_reg_opt_vcc_dig:
1906 regulator_disable(data->vcc_ana);
1907error_reg_en_vcc_ana:
Amy Malochec331f842012-01-24 10:33:47 -08001908 reg_set_optimum_mode_check(data->vcc_ana, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301909 return rc;
1910
1911power_off:
Amy Malochec331f842012-01-24 10:33:47 -08001912 reg_set_optimum_mode_check(data->vcc_ana, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001913 regulator_disable(data->vcc_ana);
1914 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08001915 reg_set_optimum_mode_check(data->vcc_dig, 0);
Amy Maloche21115eb2011-11-02 09:04:37 -07001916 regulator_disable(data->vcc_dig);
1917 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301918 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08001919 reg_set_optimum_mode_check(data->vcc_i2c, 0);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301920 regulator_disable(data->vcc_i2c);
1921 }
1922 msleep(50);
1923 return 0;
1924}
1925
1926static int mxt_regulator_configure(struct mxt_data *data, bool on)
1927{
1928 int rc;
1929
1930 if (on == false)
1931 goto hw_shutdown;
1932
Amy Maloche21115eb2011-11-02 09:04:37 -07001933 data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
1934 if (IS_ERR(data->vcc_ana)) {
1935 rc = PTR_ERR(data->vcc_ana);
1936 dev_err(&data->client->dev,
1937 "Regulator get failed vcc_ana rc=%d\n", rc);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301938 return rc;
1939 }
1940
Amy Maloche21115eb2011-11-02 09:04:37 -07001941 if (regulator_count_voltages(data->vcc_ana) > 0) {
1942 rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301943 MXT_VTG_MAX_UV);
1944 if (rc) {
1945 dev_err(&data->client->dev,
1946 "regulator set_vtg failed rc=%d\n", rc);
Amy Maloche21115eb2011-11-02 09:04:37 -07001947 goto error_set_vtg_vcc_ana;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301948 }
1949 }
Amy Maloche21115eb2011-11-02 09:04:37 -07001950 if (data->pdata->digital_pwr_regulator) {
1951 data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
1952 if (IS_ERR(data->vcc_dig)) {
1953 rc = PTR_ERR(data->vcc_dig);
1954 dev_err(&data->client->dev,
1955 "Regulator get dig failed rc=%d\n", rc);
1956 goto error_get_vtg_vcc_dig;
1957 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301958
Amy Maloche21115eb2011-11-02 09:04:37 -07001959 if (regulator_count_voltages(data->vcc_dig) > 0) {
1960 rc = regulator_set_voltage(data->vcc_dig,
1961 MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
1962 if (rc) {
1963 dev_err(&data->client->dev,
1964 "regulator set_vtg failed rc=%d\n", rc);
1965 goto error_set_vtg_vcc_dig;
1966 }
1967 }
1968 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05301969 if (data->pdata->i2c_pull_up) {
1970 data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
1971 if (IS_ERR(data->vcc_i2c)) {
1972 rc = PTR_ERR(data->vcc_i2c);
1973 dev_err(&data->client->dev,
1974 "Regulator get failed rc=%d\n", rc);
1975 goto error_get_vtg_i2c;
1976 }
1977 if (regulator_count_voltages(data->vcc_i2c) > 0) {
1978 rc = regulator_set_voltage(data->vcc_i2c,
1979 MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
1980 if (rc) {
1981 dev_err(&data->client->dev,
1982 "regulator set_vtg failed rc=%d\n", rc);
1983 goto error_set_vtg_i2c;
1984 }
1985 }
1986 }
1987
1988 return 0;
1989
1990error_set_vtg_i2c:
1991 regulator_put(data->vcc_i2c);
1992error_get_vtg_i2c:
Amy Maloche21115eb2011-11-02 09:04:37 -07001993 if (data->pdata->digital_pwr_regulator)
1994 if (regulator_count_voltages(data->vcc_dig) > 0)
1995 regulator_set_voltage(data->vcc_dig, 0,
1996 MXT_VTG_DIG_MAX_UV);
1997error_set_vtg_vcc_dig:
1998 if (data->pdata->digital_pwr_regulator)
1999 regulator_put(data->vcc_dig);
2000error_get_vtg_vcc_dig:
2001 if (regulator_count_voltages(data->vcc_ana) > 0)
2002 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2003error_set_vtg_vcc_ana:
2004 regulator_put(data->vcc_ana);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302005 return rc;
2006
2007hw_shutdown:
Amy Maloche21115eb2011-11-02 09:04:37 -07002008 if (regulator_count_voltages(data->vcc_ana) > 0)
2009 regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
2010 regulator_put(data->vcc_ana);
2011 if (data->pdata->digital_pwr_regulator) {
2012 if (regulator_count_voltages(data->vcc_dig) > 0)
2013 regulator_set_voltage(data->vcc_dig, 0,
2014 MXT_VTG_DIG_MAX_UV);
2015 regulator_put(data->vcc_dig);
2016 }
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302017 if (data->pdata->i2c_pull_up) {
2018 if (regulator_count_voltages(data->vcc_i2c) > 0)
2019 regulator_set_voltage(data->vcc_i2c, 0,
2020 MXT_I2C_VTG_MAX_UV);
2021 regulator_put(data->vcc_i2c);
2022 }
2023 return 0;
2024}
2025
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302026#ifdef CONFIG_PM
Jing Linbace50b2011-10-18 22:55:47 -07002027static int mxt_regulator_lpm(struct mxt_data *data, bool on)
2028{
2029
2030 int rc;
2031
2032 if (on == false)
2033 goto regulator_hpm;
2034
Amy Malochec331f842012-01-24 10:33:47 -08002035 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002036 if (rc < 0) {
2037 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002038 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002039 goto fail_regulator_lpm;
2040 }
2041
Amy Maloche21115eb2011-11-02 09:04:37 -07002042 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002043 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002044 MXT_LPM_LOAD_DIG_UA);
2045 if (rc < 0) {
2046 dev_err(&data->client->dev,
2047 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2048 goto fail_regulator_lpm;
2049 }
2050 }
2051
Jing Linbace50b2011-10-18 22:55:47 -07002052 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002053 rc = reg_set_optimum_mode_check(data->vcc_i2c,
Jing Linbace50b2011-10-18 22:55:47 -07002054 MXT_I2C_LPM_LOAD_UA);
2055 if (rc < 0) {
2056 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002057 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002058 goto fail_regulator_lpm;
2059 }
2060 }
2061
2062 return 0;
2063
2064regulator_hpm:
2065
Amy Malochec331f842012-01-24 10:33:47 -08002066 rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002067 if (rc < 0) {
2068 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002069 "Regulator vcc_ana set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002070 goto fail_regulator_hpm;
2071 }
2072
Amy Maloche21115eb2011-11-02 09:04:37 -07002073 if (data->pdata->digital_pwr_regulator) {
Amy Malochec331f842012-01-24 10:33:47 -08002074 rc = reg_set_optimum_mode_check(data->vcc_dig,
Amy Maloche21115eb2011-11-02 09:04:37 -07002075 MXT_ACTIVE_LOAD_DIG_UA);
2076 if (rc < 0) {
2077 dev_err(&data->client->dev,
2078 "Regulator vcc_dig set_opt failed rc=%d\n", rc);
2079 goto fail_regulator_hpm;
2080 }
2081 }
2082
Jing Linbace50b2011-10-18 22:55:47 -07002083 if (data->pdata->i2c_pull_up) {
Amy Malochec331f842012-01-24 10:33:47 -08002084 rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002085 if (rc < 0) {
2086 dev_err(&data->client->dev,
Amy Maloche21115eb2011-11-02 09:04:37 -07002087 "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
Jing Linbace50b2011-10-18 22:55:47 -07002088 goto fail_regulator_hpm;
2089 }
2090 }
2091
2092 return 0;
2093
2094fail_regulator_lpm:
Amy Malochec331f842012-01-24 10:33:47 -08002095 reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002096 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002097 reg_set_optimum_mode_check(data->vcc_dig,
2098 MXT_ACTIVE_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002099 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002100 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002101
2102 return rc;
2103
2104fail_regulator_hpm:
Amy Malochec331f842012-01-24 10:33:47 -08002105 reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
Amy Maloche21115eb2011-11-02 09:04:37 -07002106 if (data->pdata->digital_pwr_regulator)
Amy Malochec331f842012-01-24 10:33:47 -08002107 reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002108 if (data->pdata->i2c_pull_up)
Amy Malochec331f842012-01-24 10:33:47 -08002109 reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
Jing Linbace50b2011-10-18 22:55:47 -07002110
2111 return rc;
2112}
2113
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302114static int mxt_suspend(struct device *dev)
2115{
2116 struct i2c_client *client = to_i2c_client(dev);
2117 struct mxt_data *data = i2c_get_clientdata(client);
2118 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002119 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302120
2121 mutex_lock(&input_dev->mutex);
2122
Amy Maloche52262212011-09-15 16:46:57 -07002123 if (input_dev->users) {
2124 error = mxt_stop(data);
2125 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002126 dev_err(dev, "mxt_stop failed in suspend\n");
Amy Maloche52262212011-09-15 16:46:57 -07002127 mutex_unlock(&input_dev->mutex);
2128 return error;
2129 }
2130
2131 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302132
2133 mutex_unlock(&input_dev->mutex);
2134
Jing Linbace50b2011-10-18 22:55:47 -07002135 /* put regulators in low power mode */
2136 error = mxt_regulator_lpm(data, true);
2137 if (error < 0) {
2138 dev_err(dev, "failed to enter low power mode\n");
2139 return error;
2140 }
2141
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302142 return 0;
2143}
2144
2145static int mxt_resume(struct device *dev)
2146{
2147 struct i2c_client *client = to_i2c_client(dev);
2148 struct mxt_data *data = i2c_get_clientdata(client);
2149 struct input_dev *input_dev = data->input_dev;
Amy Maloche52262212011-09-15 16:46:57 -07002150 int error;
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302151
Jing Linbace50b2011-10-18 22:55:47 -07002152 /* put regulators in high power mode */
2153 error = mxt_regulator_lpm(data, false);
2154 if (error < 0) {
2155 dev_err(dev, "failed to enter high power mode\n");
2156 return error;
2157 }
2158
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302159 mutex_lock(&input_dev->mutex);
2160
Amy Maloche52262212011-09-15 16:46:57 -07002161 if (input_dev->users) {
2162 error = mxt_start(data);
2163 if (error < 0) {
Jing Lin36aee812011-10-17 17:17:28 -07002164 dev_err(dev, "mxt_start failed in resume\n");
Amy Maloche52262212011-09-15 16:46:57 -07002165 mutex_unlock(&input_dev->mutex);
2166 return error;
2167 }
2168 }
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302169
2170 mutex_unlock(&input_dev->mutex);
2171
2172 return 0;
2173}
2174
2175#if defined(CONFIG_HAS_EARLYSUSPEND)
2176static void mxt_early_suspend(struct early_suspend *h)
2177{
2178 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2179
2180 mxt_suspend(&data->client->dev);
2181}
2182
2183static void mxt_late_resume(struct early_suspend *h)
2184{
2185 struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
2186
2187 mxt_resume(&data->client->dev);
2188}
2189#endif
2190
2191static const struct dev_pm_ops mxt_pm_ops = {
2192#ifndef CONFIG_HAS_EARLYSUSPEND
2193 .suspend = mxt_suspend,
2194 .resume = mxt_resume,
2195#endif
2196};
2197#endif
2198
Jing Lin6cfc00e2011-11-02 15:15:30 -07002199static int mxt_debugfs_object_show(struct seq_file *m, void *v)
2200{
2201 struct mxt_data *data = m->private;
2202 struct mxt_object *object;
2203 struct device *dev = &data->client->dev;
2204 int i, j, k;
2205 int error;
2206 int obj_size;
2207 u8 val;
2208
2209 for (i = 0; i < data->info.object_num; i++) {
2210 object = data->object_table + i;
2211 obj_size = object->size + 1;
2212
2213 seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
2214
2215 for (j = 0; j < object->instances + 1; j++) {
2216 seq_printf(m, "[Instance %d]\n", j);
2217
2218 for (k = 0; k < obj_size; k++) {
2219 error = mxt_read_object(data, object->type,
2220 j * obj_size + k, &val);
2221 if (error) {
2222 dev_err(dev,
2223 "Failed to read object %d "
2224 "instance %d at offset %d\n",
2225 object->type, j, k);
2226 return error;
2227 }
2228
2229 seq_printf(m, "Byte %d: 0x%02x (%d)\n",
2230 k, val, val);
2231 }
2232 }
2233 }
2234
2235 return 0;
2236}
2237
2238static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
2239{
2240 return single_open(file, mxt_debugfs_object_show, inode->i_private);
2241}
2242
2243static const struct file_operations mxt_object_fops = {
2244 .owner = THIS_MODULE,
2245 .open = mxt_debugfs_object_open,
2246 .read = seq_read,
2247 .release = single_release,
2248};
2249
Stephen Boyd0d578692012-04-25 11:49:18 -07002250static void __devinit mxt_debugfs_init(struct mxt_data *data)
Jing Lin6cfc00e2011-11-02 15:15:30 -07002251{
2252 debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
2253 if (IS_ERR_OR_NULL(debug_base))
2254 pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
2255 if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
2256 0444,
2257 debug_base,
2258 data,
2259 &mxt_object_fops))) {
2260 pr_err("atmel_mxt_ts: Failed to create object file\n");
2261 debugfs_remove_recursive(debug_base);
2262 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002263}
2264
Iiro Valkonen7686b102011-02-02 23:21:58 -08002265static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002266 const struct i2c_device_id *id)
2267{
Iiro Valkonen919ed892011-02-15 13:36:52 -08002268 const struct mxt_platform_data *pdata = client->dev.platform_data;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002269 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002270 struct input_dev *input_dev;
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002271 int error, i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002272
Iiro Valkonen919ed892011-02-15 13:36:52 -08002273 if (!pdata)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002274 return -EINVAL;
2275
Iiro Valkonen7686b102011-02-02 23:21:58 -08002276 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002277 input_dev = input_allocate_device();
2278 if (!data || !input_dev) {
2279 dev_err(&client->dev, "Failed to allocate memory\n");
2280 error = -ENOMEM;
2281 goto err_free_mem;
2282 }
2283
Nick Dyer0a4016c2012-01-18 15:17:59 +05302284 data->state = INIT;
Amy Maloche83c385a2012-02-01 10:32:03 +05302285 input_dev->name = "atmel_mxt_ts";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002286 input_dev->id.bustype = BUS_I2C;
2287 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08002288 input_dev->open = mxt_input_open;
2289 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002290
Joonyoung Shim910d8052011-04-12 23:14:38 -07002291 data->client = client;
2292 data->input_dev = input_dev;
2293 data->pdata = pdata;
2294 data->irq = client->irq;
2295
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002296 __set_bit(EV_ABS, input_dev->evbit);
2297 __set_bit(EV_KEY, input_dev->evbit);
2298 __set_bit(BTN_TOUCH, input_dev->keybit);
2299
2300 /* For single touch */
2301 input_set_abs_params(input_dev, ABS_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002302 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002303 input_set_abs_params(input_dev, ABS_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002304 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002305 input_set_abs_params(input_dev, ABS_PRESSURE,
2306 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002307
2308 /* For multi touch */
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -07002309 input_mt_init_slots(input_dev, MXT_MAX_FINGER);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002310 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08002311 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002312 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002313 pdata->disp_minx, pdata->disp_maxx, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002314 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Mohan Pallaka56a1a5d2012-02-23 12:05:13 -08002315 pdata->disp_miny, pdata->disp_maxy, 0, 0);
Yufeng Shen28ac2932011-08-16 00:40:54 -07002316 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2317 0, 255, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002318
Mohan Pallaka382d3ce2012-01-02 20:24:28 +08002319 /* set key array supported keys */
2320 if (pdata->key_codes) {
2321 for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
2322 if (pdata->key_codes[i])
2323 input_set_capability(input_dev, EV_KEY,
2324 pdata->key_codes[i]);
2325 }
2326 }
2327
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002328 input_set_drvdata(input_dev, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002329 i2c_set_clientdata(client, data);
2330
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302331 if (pdata->init_hw)
2332 error = pdata->init_hw(true);
2333 else
2334 error = mxt_regulator_configure(data, true);
2335 if (error) {
2336 dev_err(&client->dev, "Failed to intialize hardware\n");
Jing Lin32c72532011-11-03 12:02:33 -07002337 goto err_free_mem;
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302338 }
2339
2340 if (pdata->power_on)
2341 error = pdata->power_on(true);
2342 else
2343 error = mxt_power_on(data, true);
2344 if (error) {
2345 dev_err(&client->dev, "Failed to power on hardware\n");
2346 goto err_regulator_on;
2347 }
2348
Amy Maloche08266db2011-11-04 11:07:16 -07002349 if (gpio_is_valid(pdata->irq_gpio)) {
2350 /* configure touchscreen irq gpio */
2351 error = gpio_request(pdata->irq_gpio,
2352 "mxt_irq_gpio");
2353 if (error) {
2354 pr_err("%s: unable to request gpio [%d]\n", __func__,
2355 pdata->irq_gpio);
2356 goto err_power_on;
2357 }
2358 error = gpio_direction_input(pdata->irq_gpio);
2359 if (error) {
2360 pr_err("%s: unable to set_direction for gpio [%d]\n",
2361 __func__, pdata->irq_gpio);
2362 goto err_irq_gpio_req;
2363 }
2364 }
2365
2366 if (gpio_is_valid(pdata->reset_gpio)) {
2367 /* configure touchscreen reset out gpio */
2368 error = gpio_request(pdata->reset_gpio,
2369 "mxt_reset_gpio");
2370 if (error) {
2371 pr_err("%s: unable to request reset gpio %d\n",
2372 __func__, pdata->reset_gpio);
2373 goto err_irq_gpio_req;
2374 }
2375
2376 error = gpio_direction_output(
2377 pdata->reset_gpio, 1);
2378 if (error) {
2379 pr_err("%s: unable to set direction for gpio %d\n",
2380 __func__, pdata->reset_gpio);
2381 goto err_reset_gpio_req;
2382 }
2383 }
2384
2385 mxt_reset_delay(data);
2386
Iiro Valkonen7686b102011-02-02 23:21:58 -08002387 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002388 if (error)
Amy Maloche08266db2011-11-04 11:07:16 -07002389 goto err_reset_gpio_req;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002390
Iiro Valkonen7686b102011-02-02 23:21:58 -08002391 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Iiro Valkonen919ed892011-02-15 13:36:52 -08002392 pdata->irqflags, client->dev.driver->name, data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002393 if (error) {
2394 dev_err(&client->dev, "Failed to register interrupt\n");
2395 goto err_free_object;
2396 }
2397
Nick Dyer0a4016c2012-01-18 15:17:59 +05302398 if (data->state == APPMODE) {
2399 error = mxt_make_highchg(data);
2400 if (error) {
2401 dev_err(&client->dev, "Failed to make high CHG\n");
2402 goto err_free_irq;
2403 }
2404 }
Iiro Valkonen08960a02011-04-12 23:16:40 -07002405
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002406 error = input_register_device(input_dev);
2407 if (error)
2408 goto err_free_irq;
2409
Iiro Valkonen7686b102011-02-02 23:21:58 -08002410 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002411 if (error)
2412 goto err_unregister_device;
2413
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302414#if defined(CONFIG_HAS_EARLYSUSPEND)
2415 data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
2416 MXT_SUSPEND_LEVEL;
2417 data->early_suspend.suspend = mxt_early_suspend;
2418 data->early_suspend.resume = mxt_late_resume;
2419 register_early_suspend(&data->early_suspend);
2420#endif
2421
Jing Lin6cfc00e2011-11-02 15:15:30 -07002422 mxt_debugfs_init(data);
2423
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002424 return 0;
2425
2426err_unregister_device:
2427 input_unregister_device(input_dev);
2428 input_dev = NULL;
2429err_free_irq:
2430 free_irq(client->irq, data);
2431err_free_object:
2432 kfree(data->object_table);
Amy Maloche08266db2011-11-04 11:07:16 -07002433err_reset_gpio_req:
2434 if (gpio_is_valid(pdata->reset_gpio))
2435 gpio_free(pdata->reset_gpio);
2436err_irq_gpio_req:
2437 if (gpio_is_valid(pdata->irq_gpio))
2438 gpio_free(pdata->irq_gpio);
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302439err_power_on:
2440 if (pdata->power_on)
2441 pdata->power_on(false);
2442 else
2443 mxt_power_on(data, false);
2444err_regulator_on:
2445 if (pdata->init_hw)
2446 pdata->init_hw(false);
2447 else
2448 mxt_regulator_configure(data, false);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002449err_free_mem:
2450 input_free_device(input_dev);
2451 kfree(data);
2452 return error;
2453}
2454
Iiro Valkonen7686b102011-02-02 23:21:58 -08002455static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002456{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002457 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002458
Iiro Valkonen7686b102011-02-02 23:21:58 -08002459 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002460 free_irq(data->irq, data);
2461 input_unregister_device(data->input_dev);
Anirudh Ghayal253ce122011-08-09 19:32:57 +05302462#if defined(CONFIG_HAS_EARLYSUSPEND)
2463 unregister_early_suspend(&data->early_suspend);
2464#endif
Anirudh Ghayala498e4d2011-08-09 19:10:12 +05302465
2466 if (data->pdata->power_on)
2467 data->pdata->power_on(false);
2468 else
2469 mxt_power_on(data, false);
2470
2471 if (data->pdata->init_hw)
2472 data->pdata->init_hw(false);
2473 else
2474 mxt_regulator_configure(data, false);
2475
Mohan Pallakabfe8f302012-01-02 18:32:08 +08002476 if (gpio_is_valid(data->pdata->reset_gpio))
2477 gpio_free(data->pdata->reset_gpio);
2478
2479 if (gpio_is_valid(data->pdata->irq_gpio))
2480 gpio_free(data->pdata->irq_gpio);
2481
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002482 kfree(data->object_table);
2483 kfree(data);
2484
Jing Lin6cfc00e2011-11-02 15:15:30 -07002485 debugfs_remove_recursive(debug_base);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002486
2487 return 0;
2488}
2489
Iiro Valkonen7686b102011-02-02 23:21:58 -08002490static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002491 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002492 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08002493 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002494 { }
2495};
Iiro Valkonen7686b102011-02-02 23:21:58 -08002496MODULE_DEVICE_TABLE(i2c, mxt_id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002497
Iiro Valkonen7686b102011-02-02 23:21:58 -08002498static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002499 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08002500 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002501 .owner = THIS_MODULE,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002502#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08002503 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08002504#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002505 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08002506 .probe = mxt_probe,
2507 .remove = __devexit_p(mxt_remove),
2508 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002509};
2510
Axel Lin1b92c1c2012-03-16 23:05:41 -07002511module_i2c_driver(mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002512
2513/* Module information */
2514MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08002515MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002516MODULE_LICENSE("GPL");