blob: fe8902e1f010e348e5178473df6cd67d56f0aba5 [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>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/firmware.h>
18#include <linux/i2c.h>
Dmitry Torokhov964de522011-02-02 23:21:58 -080019#include <linux/i2c/atmel_mxt_ts.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070020#include <linux/input.h>
21#include <linux/interrupt.h>
22#include <linux/slab.h>
23
24/* Version */
Iiro Valkonen7686b102011-02-02 23:21:58 -080025#define MXT_VER_20 20
26#define MXT_VER_21 21
27#define MXT_VER_22 22
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070028
29/* Slave addresses */
Iiro Valkonen7686b102011-02-02 23:21:58 -080030#define MXT_APP_LOW 0x4a
31#define MXT_APP_HIGH 0x4b
32#define MXT_BOOT_LOW 0x24
33#define MXT_BOOT_HIGH 0x25
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070034
35/* Firmware */
Iiro Valkonen7686b102011-02-02 23:21:58 -080036#define MXT_FW_NAME "maxtouch.fw"
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070037
38/* Registers */
Iiro Valkonen7686b102011-02-02 23:21:58 -080039#define MXT_FAMILY_ID 0x00
40#define MXT_VARIANT_ID 0x01
41#define MXT_VERSION 0x02
42#define MXT_BUILD 0x03
43#define MXT_MATRIX_X_SIZE 0x04
44#define MXT_MATRIX_Y_SIZE 0x05
45#define MXT_OBJECT_NUM 0x06
46#define MXT_OBJECT_START 0x07
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070047
Iiro Valkonen7686b102011-02-02 23:21:58 -080048#define MXT_OBJECT_SIZE 6
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070049
50/* Object types */
Iiro Valkonen7686b102011-02-02 23:21:58 -080051#define MXT_DEBUG_DIAGNOSTIC 37
52#define MXT_GEN_MESSAGE 5
53#define MXT_GEN_COMMAND 6
54#define MXT_GEN_POWER 7
55#define MXT_GEN_ACQUIRE 8
56#define MXT_TOUCH_MULTI 9
57#define MXT_TOUCH_KEYARRAY 15
58#define MXT_TOUCH_PROXIMITY 23
59#define MXT_PROCI_GRIPFACE 20
60#define MXT_PROCG_NOISE 22
61#define MXT_PROCI_ONETOUCH 24
62#define MXT_PROCI_TWOTOUCH 27
63#define MXT_SPT_COMMSCONFIG 18 /* firmware ver 21 over */
64#define MXT_SPT_GPIOPWM 19
65#define MXT_SPT_SELFTEST 25
66#define MXT_SPT_CTECONFIG 28
67#define MXT_SPT_USERDATA 38 /* firmware ver 21 over */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070068
Iiro Valkonen7686b102011-02-02 23:21:58 -080069/* MXT_GEN_COMMAND field */
70#define MXT_COMMAND_RESET 0
71#define MXT_COMMAND_BACKUPNV 1
72#define MXT_COMMAND_CALIBRATE 2
73#define MXT_COMMAND_REPORTALL 3
74#define MXT_COMMAND_DIAGNOSTIC 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070075
Iiro Valkonen7686b102011-02-02 23:21:58 -080076/* MXT_GEN_POWER field */
77#define MXT_POWER_IDLEACQINT 0
78#define MXT_POWER_ACTVACQINT 1
79#define MXT_POWER_ACTV2IDLETO 2
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070080
Iiro Valkonen7686b102011-02-02 23:21:58 -080081/* MXT_GEN_ACQUIRE field */
82#define MXT_ACQUIRE_CHRGTIME 0
83#define MXT_ACQUIRE_TCHDRIFT 2
84#define MXT_ACQUIRE_DRIFTST 3
85#define MXT_ACQUIRE_TCHAUTOCAL 4
86#define MXT_ACQUIRE_SYNC 5
87#define MXT_ACQUIRE_ATCHCALST 6
88#define MXT_ACQUIRE_ATCHCALSTHR 7
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070089
Iiro Valkonen7686b102011-02-02 23:21:58 -080090/* MXT_TOUCH_MULTI field */
91#define MXT_TOUCH_CTRL 0
92#define MXT_TOUCH_XORIGIN 1
93#define MXT_TOUCH_YORIGIN 2
94#define MXT_TOUCH_XSIZE 3
95#define MXT_TOUCH_YSIZE 4
96#define MXT_TOUCH_BLEN 6
97#define MXT_TOUCH_TCHTHR 7
98#define MXT_TOUCH_TCHDI 8
99#define MXT_TOUCH_ORIENT 9
100#define MXT_TOUCH_MOVHYSTI 11
101#define MXT_TOUCH_MOVHYSTN 12
102#define MXT_TOUCH_NUMTOUCH 14
103#define MXT_TOUCH_MRGHYST 15
104#define MXT_TOUCH_MRGTHR 16
105#define MXT_TOUCH_AMPHYST 17
106#define MXT_TOUCH_XRANGE_LSB 18
107#define MXT_TOUCH_XRANGE_MSB 19
108#define MXT_TOUCH_YRANGE_LSB 20
109#define MXT_TOUCH_YRANGE_MSB 21
110#define MXT_TOUCH_XLOCLIP 22
111#define MXT_TOUCH_XHICLIP 23
112#define MXT_TOUCH_YLOCLIP 24
113#define MXT_TOUCH_YHICLIP 25
114#define MXT_TOUCH_XEDGECTRL 26
115#define MXT_TOUCH_XEDGEDIST 27
116#define MXT_TOUCH_YEDGECTRL 28
117#define MXT_TOUCH_YEDGEDIST 29
118#define MXT_TOUCH_JUMPLIMIT 30 /* firmware ver 22 over */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700119
Iiro Valkonen7686b102011-02-02 23:21:58 -0800120/* MXT_PROCI_GRIPFACE field */
121#define MXT_GRIPFACE_CTRL 0
122#define MXT_GRIPFACE_XLOGRIP 1
123#define MXT_GRIPFACE_XHIGRIP 2
124#define MXT_GRIPFACE_YLOGRIP 3
125#define MXT_GRIPFACE_YHIGRIP 4
126#define MXT_GRIPFACE_MAXTCHS 5
127#define MXT_GRIPFACE_SZTHR1 7
128#define MXT_GRIPFACE_SZTHR2 8
129#define MXT_GRIPFACE_SHPTHR1 9
130#define MXT_GRIPFACE_SHPTHR2 10
131#define MXT_GRIPFACE_SUPEXTTO 11
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700132
Iiro Valkonen7686b102011-02-02 23:21:58 -0800133/* MXT_PROCI_NOISE field */
134#define MXT_NOISE_CTRL 0
135#define MXT_NOISE_OUTFLEN 1
136#define MXT_NOISE_GCAFUL_LSB 3
137#define MXT_NOISE_GCAFUL_MSB 4
138#define MXT_NOISE_GCAFLL_LSB 5
139#define MXT_NOISE_GCAFLL_MSB 6
140#define MXT_NOISE_ACTVGCAFVALID 7
141#define MXT_NOISE_NOISETHR 8
142#define MXT_NOISE_FREQHOPSCALE 10
143#define MXT_NOISE_FREQ0 11
144#define MXT_NOISE_FREQ1 12
145#define MXT_NOISE_FREQ2 13
146#define MXT_NOISE_FREQ3 14
147#define MXT_NOISE_FREQ4 15
148#define MXT_NOISE_IDLEGCAFVALID 16
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700149
Iiro Valkonen7686b102011-02-02 23:21:58 -0800150/* MXT_SPT_COMMSCONFIG */
151#define MXT_COMMS_CTRL 0
152#define MXT_COMMS_CMD 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700153
Iiro Valkonen7686b102011-02-02 23:21:58 -0800154/* MXT_SPT_CTECONFIG field */
155#define MXT_CTE_CTRL 0
156#define MXT_CTE_CMD 1
157#define MXT_CTE_MODE 2
158#define MXT_CTE_IDLEGCAFDEPTH 3
159#define MXT_CTE_ACTVGCAFDEPTH 4
160#define MXT_CTE_VOLTAGE 5 /* firmware ver 21 over */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700161
Iiro Valkonen7686b102011-02-02 23:21:58 -0800162#define MXT_VOLTAGE_DEFAULT 2700000
163#define MXT_VOLTAGE_STEP 10000
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700164
Iiro Valkonen7686b102011-02-02 23:21:58 -0800165/* Define for MXT_GEN_COMMAND */
166#define MXT_BOOT_VALUE 0xa5
167#define MXT_BACKUP_VALUE 0x55
168#define MXT_BACKUP_TIME 25 /* msec */
169#define MXT_RESET_TIME 65 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700170
Iiro Valkonen7686b102011-02-02 23:21:58 -0800171#define MXT_FWRESET_TIME 175 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700172
173/* Command to unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800174#define MXT_UNLOCK_CMD_MSB 0xaa
175#define MXT_UNLOCK_CMD_LSB 0xdc
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700176
177/* Bootloader mode status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800178#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
179#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
180#define MXT_FRAME_CRC_CHECK 0x02
181#define MXT_FRAME_CRC_FAIL 0x03
182#define MXT_FRAME_CRC_PASS 0x04
183#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
184#define MXT_BOOT_STATUS_MASK 0x3f
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700185
186/* Touch status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800187#define MXT_SUPPRESS (1 << 1)
188#define MXT_AMP (1 << 2)
189#define MXT_VECTOR (1 << 3)
190#define MXT_MOVE (1 << 4)
191#define MXT_RELEASE (1 << 5)
192#define MXT_PRESS (1 << 6)
193#define MXT_DETECT (1 << 7)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700194
195/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800196#define MXT_MAX_XC 0x3ff
197#define MXT_MAX_YC 0x3ff
198#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700199
Iiro Valkonen7686b102011-02-02 23:21:58 -0800200#define MXT_MAX_FINGER 10
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700201
202/* Initial register values recommended from chip vendor */
203static const u8 init_vals_ver_20[] = {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800204 /* MXT_GEN_COMMAND(6) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800206 /* MXT_GEN_POWER(7) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700207 0x20, 0xff, 0x32,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800208 /* MXT_GEN_ACQUIRE(8) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700209 0x08, 0x05, 0x05, 0x00, 0x00, 0x00, 0x05, 0x14,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800210 /* MXT_TOUCH_MULTI(9) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700211 0x00, 0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00,
212 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x64,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800214 /* MXT_TOUCH_KEYARRAY(15) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700215 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800217 /* MXT_SPT_GPIOPWM(19) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800220 /* MXT_PROCI_GRIPFACE(20) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700221 0x00, 0x64, 0x64, 0x64, 0x64, 0x00, 0x00, 0x1e, 0x14, 0x04,
222 0x1e, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800223 /* MXT_PROCG_NOISE(22) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700224 0x05, 0x00, 0x00, 0x19, 0x00, 0xe7, 0xff, 0x04, 0x32, 0x00,
225 0x01, 0x0a, 0x0f, 0x14, 0x00, 0x00, 0xe8,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800226 /* MXT_TOUCH_PROXIMITY(23) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700227 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800229 /* MXT_PROCI_ONETOUCH(24) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700230 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800232 /* MXT_SPT_SELFTEST(25) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800235 /* MXT_PROCI_TWOTOUCH(27) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800237 /* MXT_SPT_CTECONFIG(28) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700238 0x00, 0x00, 0x00, 0x04, 0x08,
239};
240
241static const u8 init_vals_ver_21[] = {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800242 /* MXT_GEN_COMMAND(6) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800244 /* MXT_GEN_POWER(7) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700245 0x20, 0xff, 0x32,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800246 /* MXT_GEN_ACQUIRE(8) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700247 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800248 /* MXT_TOUCH_MULTI(9) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700249 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
250 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800252 /* MXT_TOUCH_KEYARRAY(15) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800255 /* MXT_SPT_GPIOPWM(19) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800258 /* MXT_PROCI_GRIPFACE(20) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700259 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
260 0x0f, 0x0a,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800261 /* MXT_PROCG_NOISE(22) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700262 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
263 0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800264 /* MXT_TOUCH_PROXIMITY(23) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800267 /* MXT_PROCI_ONETOUCH(24) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800270 /* MXT_SPT_SELFTEST(25) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800273 /* MXT_PROCI_TWOTOUCH(27) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800275 /* MXT_SPT_CTECONFIG(28) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700276 0x00, 0x00, 0x00, 0x08, 0x10, 0x00,
277};
278
279static const u8 init_vals_ver_22[] = {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800280 /* MXT_GEN_COMMAND(6) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800282 /* MXT_GEN_POWER(7) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700283 0x20, 0xff, 0x32,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800284 /* MXT_GEN_ACQUIRE(8) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700285 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800286 /* MXT_TOUCH_MULTI(9) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700287 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
288 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800291 /* MXT_TOUCH_KEYARRAY(15) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800294 /* MXT_SPT_GPIOPWM(19) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800297 /* MXT_PROCI_GRIPFACE(20) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700298 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
299 0x0f, 0x0a,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800300 /* MXT_PROCG_NOISE(22) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700301 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
302 0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800303 /* MXT_TOUCH_PROXIMITY(23) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
305 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800306 /* MXT_PROCI_ONETOUCH(24) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800309 /* MXT_SPT_SELFTEST(25) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800312 /* MXT_PROCI_TWOTOUCH(27) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700313 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800314 /* MXT_SPT_CTECONFIG(28) */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700315 0x00, 0x00, 0x00, 0x08, 0x10, 0x00,
316};
317
Iiro Valkonen7686b102011-02-02 23:21:58 -0800318struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700319 u8 family_id;
320 u8 variant_id;
321 u8 version;
322 u8 build;
323 u8 matrix_xsize;
324 u8 matrix_ysize;
325 u8 object_num;
326};
327
Iiro Valkonen7686b102011-02-02 23:21:58 -0800328struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700329 u8 type;
330 u16 start_address;
331 u8 size;
332 u8 instances;
333 u8 num_report_ids;
334
335 /* to map object and message */
336 u8 max_reportid;
337};
338
Iiro Valkonen7686b102011-02-02 23:21:58 -0800339struct mxt_message {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700340 u8 reportid;
341 u8 message[7];
342 u8 checksum;
343};
344
Iiro Valkonen7686b102011-02-02 23:21:58 -0800345struct mxt_finger {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700346 int status;
347 int x;
348 int y;
349 int area;
350};
351
352/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800353struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700354 struct i2c_client *client;
355 struct input_dev *input_dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800356 const struct mxt_platform_data *pdata;
357 struct mxt_object *object_table;
358 struct mxt_info info;
359 struct mxt_finger finger[MXT_MAX_FINGER];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700360 unsigned int irq;
361};
362
Iiro Valkonen7686b102011-02-02 23:21:58 -0800363static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700364{
365 switch (type) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800366 case MXT_GEN_MESSAGE:
367 case MXT_GEN_COMMAND:
368 case MXT_GEN_POWER:
369 case MXT_GEN_ACQUIRE:
370 case MXT_TOUCH_MULTI:
371 case MXT_TOUCH_KEYARRAY:
372 case MXT_TOUCH_PROXIMITY:
373 case MXT_PROCI_GRIPFACE:
374 case MXT_PROCG_NOISE:
375 case MXT_PROCI_ONETOUCH:
376 case MXT_PROCI_TWOTOUCH:
377 case MXT_SPT_COMMSCONFIG:
378 case MXT_SPT_GPIOPWM:
379 case MXT_SPT_SELFTEST:
380 case MXT_SPT_CTECONFIG:
381 case MXT_SPT_USERDATA:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700382 return true;
383 default:
384 return false;
385 }
386}
387
Iiro Valkonen7686b102011-02-02 23:21:58 -0800388static bool mxt_object_writable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700389{
390 switch (type) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800391 case MXT_GEN_COMMAND:
392 case MXT_GEN_POWER:
393 case MXT_GEN_ACQUIRE:
394 case MXT_TOUCH_MULTI:
395 case MXT_TOUCH_KEYARRAY:
396 case MXT_TOUCH_PROXIMITY:
397 case MXT_PROCI_GRIPFACE:
398 case MXT_PROCG_NOISE:
399 case MXT_PROCI_ONETOUCH:
400 case MXT_PROCI_TWOTOUCH:
401 case MXT_SPT_GPIOPWM:
402 case MXT_SPT_SELFTEST:
403 case MXT_SPT_CTECONFIG:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700404 return true;
405 default:
406 return false;
407 }
408}
409
Iiro Valkonen7686b102011-02-02 23:21:58 -0800410static void mxt_dump_message(struct device *dev,
411 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700412{
413 dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
414 dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
415 dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
416 dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
417 dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
418 dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
419 dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
420 dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
421 dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
422}
423
Iiro Valkonen7686b102011-02-02 23:21:58 -0800424static int mxt_check_bootloader(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700425 unsigned int state)
426{
427 u8 val;
428
429recheck:
430 if (i2c_master_recv(client, &val, 1) != 1) {
431 dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
432 return -EIO;
433 }
434
435 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800436 case MXT_WAITING_BOOTLOAD_CMD:
437 case MXT_WAITING_FRAME_DATA:
438 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700439 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800440 case MXT_FRAME_CRC_PASS:
441 if (val == MXT_FRAME_CRC_CHECK)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700442 goto recheck;
443 break;
444 default:
445 return -EINVAL;
446 }
447
448 if (val != state) {
449 dev_err(&client->dev, "Unvalid bootloader mode state\n");
450 return -EINVAL;
451 }
452
453 return 0;
454}
455
Iiro Valkonen7686b102011-02-02 23:21:58 -0800456static int mxt_unlock_bootloader(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700457{
458 u8 buf[2];
459
Iiro Valkonen7686b102011-02-02 23:21:58 -0800460 buf[0] = MXT_UNLOCK_CMD_LSB;
461 buf[1] = MXT_UNLOCK_CMD_MSB;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700462
463 if (i2c_master_send(client, buf, 2) != 2) {
464 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
465 return -EIO;
466 }
467
468 return 0;
469}
470
Iiro Valkonen7686b102011-02-02 23:21:58 -0800471static int mxt_fw_write(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700472 const u8 *data, unsigned int frame_size)
473{
474 if (i2c_master_send(client, data, frame_size) != frame_size) {
475 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
476 return -EIO;
477 }
478
479 return 0;
480}
481
Iiro Valkonen7686b102011-02-02 23:21:58 -0800482static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700483 u16 reg, u16 len, void *val)
484{
485 struct i2c_msg xfer[2];
486 u8 buf[2];
487
488 buf[0] = reg & 0xff;
489 buf[1] = (reg >> 8) & 0xff;
490
491 /* Write register */
492 xfer[0].addr = client->addr;
493 xfer[0].flags = 0;
494 xfer[0].len = 2;
495 xfer[0].buf = buf;
496
497 /* Read data */
498 xfer[1].addr = client->addr;
499 xfer[1].flags = I2C_M_RD;
500 xfer[1].len = len;
501 xfer[1].buf = val;
502
503 if (i2c_transfer(client->adapter, xfer, 2) != 2) {
504 dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
505 return -EIO;
506 }
507
508 return 0;
509}
510
Iiro Valkonen7686b102011-02-02 23:21:58 -0800511static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700512{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800513 return __mxt_read_reg(client, reg, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700514}
515
Iiro Valkonen7686b102011-02-02 23:21:58 -0800516static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700517{
518 u8 buf[3];
519
520 buf[0] = reg & 0xff;
521 buf[1] = (reg >> 8) & 0xff;
522 buf[2] = val;
523
524 if (i2c_master_send(client, buf, 3) != 3) {
525 dev_err(&client->dev, "%s: i2c send failed\n", __func__);
526 return -EIO;
527 }
528
529 return 0;
530}
531
Iiro Valkonen7686b102011-02-02 23:21:58 -0800532static int mxt_read_object_table(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700533 u16 reg, u8 *object_buf)
534{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800535 return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700536 object_buf);
537}
538
Iiro Valkonen7686b102011-02-02 23:21:58 -0800539static struct mxt_object *
540mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700541{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800542 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700543 int i;
544
545 for (i = 0; i < data->info.object_num; i++) {
546 object = data->object_table + i;
547 if (object->type == type)
548 return object;
549 }
550
551 dev_err(&data->client->dev, "Invalid object type\n");
552 return NULL;
553}
554
Iiro Valkonen7686b102011-02-02 23:21:58 -0800555static int mxt_read_message(struct mxt_data *data,
556 struct mxt_message *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700557{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800558 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700559 u16 reg;
560
Iiro Valkonen7686b102011-02-02 23:21:58 -0800561 object = mxt_get_object(data, MXT_GEN_MESSAGE);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700562 if (!object)
563 return -EINVAL;
564
565 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800566 return __mxt_read_reg(data->client, reg,
567 sizeof(struct mxt_message), message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700568}
569
Iiro Valkonen7686b102011-02-02 23:21:58 -0800570static int mxt_read_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700571 u8 type, u8 offset, u8 *val)
572{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800573 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700574 u16 reg;
575
Iiro Valkonen7686b102011-02-02 23:21:58 -0800576 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700577 if (!object)
578 return -EINVAL;
579
580 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800581 return __mxt_read_reg(data->client, reg + offset, 1, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700582}
583
Iiro Valkonen7686b102011-02-02 23:21:58 -0800584static int mxt_write_object(struct mxt_data *data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700585 u8 type, u8 offset, u8 val)
586{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800587 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700588 u16 reg;
589
Iiro Valkonen7686b102011-02-02 23:21:58 -0800590 object = mxt_get_object(data, type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700591 if (!object)
592 return -EINVAL;
593
594 reg = object->start_address;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800595 return mxt_write_reg(data->client, reg + offset, val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700596}
597
Iiro Valkonen7686b102011-02-02 23:21:58 -0800598static void mxt_input_report(struct mxt_data *data, int single_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700599{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800600 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700601 struct input_dev *input_dev = data->input_dev;
602 int status = finger[single_id].status;
603 int finger_num = 0;
604 int id;
605
Iiro Valkonen7686b102011-02-02 23:21:58 -0800606 for (id = 0; id < MXT_MAX_FINGER; id++) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700607 if (!finger[id].status)
608 continue;
609
610 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800611 finger[id].status != MXT_RELEASE ?
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700612 finger[id].area : 0);
613 input_report_abs(input_dev, ABS_MT_POSITION_X,
614 finger[id].x);
615 input_report_abs(input_dev, ABS_MT_POSITION_Y,
616 finger[id].y);
617 input_mt_sync(input_dev);
618
Iiro Valkonen7686b102011-02-02 23:21:58 -0800619 if (finger[id].status == MXT_RELEASE)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700620 finger[id].status = 0;
621 else
622 finger_num++;
623 }
624
625 input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
626
Iiro Valkonen7686b102011-02-02 23:21:58 -0800627 if (status != MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700628 input_report_abs(input_dev, ABS_X, finger[single_id].x);
629 input_report_abs(input_dev, ABS_Y, finger[single_id].y);
630 }
631
632 input_sync(input_dev);
633}
634
Iiro Valkonen7686b102011-02-02 23:21:58 -0800635static void mxt_input_touchevent(struct mxt_data *data,
636 struct mxt_message *message, int id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700637{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800638 struct mxt_finger *finger = data->finger;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700639 struct device *dev = &data->client->dev;
640 u8 status = message->message[0];
641 int x;
642 int y;
643 int area;
644
645 /* Check the touch is present on the screen */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800646 if (!(status & MXT_DETECT)) {
647 if (status & MXT_RELEASE) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700648 dev_dbg(dev, "[%d] released\n", id);
649
Iiro Valkonen7686b102011-02-02 23:21:58 -0800650 finger[id].status = MXT_RELEASE;
651 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700652 }
653 return;
654 }
655
656 /* Check only AMP detection */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800657 if (!(status & (MXT_PRESS | MXT_MOVE)))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700658 return;
659
660 x = (message->message[1] << 2) | ((message->message[3] & ~0x3f) >> 6);
661 y = (message->message[2] << 2) | ((message->message[3] & ~0xf3) >> 2);
662 area = message->message[4];
663
664 dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800665 status & MXT_MOVE ? "moved" : "pressed",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700666 x, y, area);
667
Iiro Valkonen7686b102011-02-02 23:21:58 -0800668 finger[id].status = status & MXT_MOVE ?
669 MXT_MOVE : MXT_PRESS;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700670 finger[id].x = x;
671 finger[id].y = y;
672 finger[id].area = area;
673
Iiro Valkonen7686b102011-02-02 23:21:58 -0800674 mxt_input_report(data, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700675}
676
Iiro Valkonen7686b102011-02-02 23:21:58 -0800677static irqreturn_t mxt_interrupt(int irq, void *dev_id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700678{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800679 struct mxt_data *data = dev_id;
680 struct mxt_message message;
681 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700682 struct device *dev = &data->client->dev;
683 int id;
684 u8 reportid;
685 u8 max_reportid;
686 u8 min_reportid;
687
688 do {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800689 if (mxt_read_message(data, &message)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700690 dev_err(dev, "Failed to read message\n");
691 goto end;
692 }
693
694 reportid = message.reportid;
695
Iiro Valkonen7686b102011-02-02 23:21:58 -0800696 /* whether reportid is thing of MXT_TOUCH_MULTI */
697 object = mxt_get_object(data, MXT_TOUCH_MULTI);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700698 if (!object)
699 goto end;
700
701 max_reportid = object->max_reportid;
702 min_reportid = max_reportid - object->num_report_ids + 1;
703 id = reportid - min_reportid;
704
705 if (reportid >= min_reportid && reportid <= max_reportid)
Iiro Valkonen7686b102011-02-02 23:21:58 -0800706 mxt_input_touchevent(data, &message, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700707 else
Iiro Valkonen7686b102011-02-02 23:21:58 -0800708 mxt_dump_message(dev, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700709 } while (reportid != 0xff);
710
711end:
712 return IRQ_HANDLED;
713}
714
Iiro Valkonen7686b102011-02-02 23:21:58 -0800715static int mxt_check_reg_init(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700716{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800717 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700718 struct device *dev = &data->client->dev;
719 int index = 0;
720 int i, j;
721 u8 version = data->info.version;
722 u8 *init_vals;
723
724 switch (version) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800725 case MXT_VER_20:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700726 init_vals = (u8 *)init_vals_ver_20;
727 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800728 case MXT_VER_21:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700729 init_vals = (u8 *)init_vals_ver_21;
730 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800731 case MXT_VER_22:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700732 init_vals = (u8 *)init_vals_ver_22;
733 break;
734 default:
735 dev_err(dev, "Firmware version %d doesn't support\n", version);
736 return -EINVAL;
737 }
738
739 for (i = 0; i < data->info.object_num; i++) {
740 object = data->object_table + i;
741
Iiro Valkonen7686b102011-02-02 23:21:58 -0800742 if (!mxt_object_writable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700743 continue;
744
745 for (j = 0; j < object->size + 1; j++)
Iiro Valkonen7686b102011-02-02 23:21:58 -0800746 mxt_write_object(data, object->type, j,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700747 init_vals[index + j]);
748
749 index += object->size + 1;
750 }
751
752 return 0;
753}
754
Iiro Valkonen7686b102011-02-02 23:21:58 -0800755static int mxt_check_matrix_size(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700756{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800757 const struct mxt_platform_data *pdata = data->pdata;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700758 struct device *dev = &data->client->dev;
759 int mode = -1;
760 int error;
761 u8 val;
762
763 dev_dbg(dev, "Number of X lines: %d\n", pdata->x_line);
764 dev_dbg(dev, "Number of Y lines: %d\n", pdata->y_line);
765
766 switch (pdata->x_line) {
767 case 0 ... 15:
768 if (pdata->y_line <= 14)
769 mode = 0;
770 break;
771 case 16:
772 if (pdata->y_line <= 12)
773 mode = 1;
774 if (pdata->y_line == 13 || pdata->y_line == 14)
775 mode = 0;
776 break;
777 case 17:
778 if (pdata->y_line <= 11)
779 mode = 2;
780 if (pdata->y_line == 12 || pdata->y_line == 13)
781 mode = 1;
782 break;
783 case 18:
784 if (pdata->y_line <= 10)
785 mode = 3;
786 if (pdata->y_line == 11 || pdata->y_line == 12)
787 mode = 2;
788 break;
789 case 19:
790 if (pdata->y_line <= 9)
791 mode = 4;
792 if (pdata->y_line == 10 || pdata->y_line == 11)
793 mode = 3;
794 break;
795 case 20:
796 mode = 4;
797 }
798
799 if (mode < 0) {
800 dev_err(dev, "Invalid X/Y lines\n");
801 return -EINVAL;
802 }
803
Iiro Valkonen7686b102011-02-02 23:21:58 -0800804 error = mxt_read_object(data, MXT_SPT_CTECONFIG,
805 MXT_CTE_MODE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700806 if (error)
807 return error;
808
809 if (mode == val)
810 return 0;
811
812 /* Change the CTE configuration */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800813 mxt_write_object(data, MXT_SPT_CTECONFIG,
814 MXT_CTE_CTRL, 1);
815 mxt_write_object(data, MXT_SPT_CTECONFIG,
816 MXT_CTE_MODE, mode);
817 mxt_write_object(data, MXT_SPT_CTECONFIG,
818 MXT_CTE_CTRL, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700819
820 return 0;
821}
822
Iiro Valkonen7686b102011-02-02 23:21:58 -0800823static int mxt_make_highchg(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700824{
825 struct device *dev = &data->client->dev;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800826 struct mxt_message message;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700827 int count = 10;
828 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700829
830 /* Read dummy message to make high CHG pin */
831 do {
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800832 error = mxt_read_message(data, &message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700833 if (error)
834 return error;
Iiro Valkonen26cdb1a2011-02-04 00:51:05 -0800835 } while (message.reportid != 0xff && --count);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700836
837 if (!count) {
838 dev_err(dev, "CHG pin isn't cleared\n");
839 return -EBUSY;
840 }
841
842 return 0;
843}
844
Iiro Valkonen7686b102011-02-02 23:21:58 -0800845static void mxt_handle_pdata(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700846{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800847 const struct mxt_platform_data *pdata = data->pdata;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700848 u8 voltage;
849
850 /* Set touchscreen lines */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800851 mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700852 pdata->x_line);
Iiro Valkonen7686b102011-02-02 23:21:58 -0800853 mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700854 pdata->y_line);
855
856 /* Set touchscreen orient */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800857 mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700858 pdata->orient);
859
860 /* Set touchscreen burst length */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800861 mxt_write_object(data, MXT_TOUCH_MULTI,
862 MXT_TOUCH_BLEN, pdata->blen);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700863
864 /* Set touchscreen threshold */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800865 mxt_write_object(data, MXT_TOUCH_MULTI,
866 MXT_TOUCH_TCHTHR, pdata->threshold);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700867
868 /* Set touchscreen resolution */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800869 mxt_write_object(data, MXT_TOUCH_MULTI,
870 MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
871 mxt_write_object(data, MXT_TOUCH_MULTI,
872 MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
873 mxt_write_object(data, MXT_TOUCH_MULTI,
874 MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
875 mxt_write_object(data, MXT_TOUCH_MULTI,
876 MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700877
878 /* Set touchscreen voltage */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800879 if (data->info.version >= MXT_VER_21 && pdata->voltage) {
880 if (pdata->voltage < MXT_VOLTAGE_DEFAULT) {
881 voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) /
882 MXT_VOLTAGE_STEP;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700883 voltage = 0xff - voltage + 1;
884 } else
Iiro Valkonen7686b102011-02-02 23:21:58 -0800885 voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) /
886 MXT_VOLTAGE_STEP;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700887
Iiro Valkonen7686b102011-02-02 23:21:58 -0800888 mxt_write_object(data, MXT_SPT_CTECONFIG,
889 MXT_CTE_VOLTAGE, voltage);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700890 }
891}
892
Iiro Valkonen7686b102011-02-02 23:21:58 -0800893static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700894{
895 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800896 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700897 int error;
898 u8 val;
899
Iiro Valkonen7686b102011-02-02 23:21:58 -0800900 error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700901 if (error)
902 return error;
903 info->family_id = val;
904
Iiro Valkonen7686b102011-02-02 23:21:58 -0800905 error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700906 if (error)
907 return error;
908 info->variant_id = val;
909
Iiro Valkonen7686b102011-02-02 23:21:58 -0800910 error = mxt_read_reg(client, MXT_VERSION, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700911 if (error)
912 return error;
913 info->version = val;
914
Iiro Valkonen7686b102011-02-02 23:21:58 -0800915 error = mxt_read_reg(client, MXT_BUILD, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700916 if (error)
917 return error;
918 info->build = val;
919
Iiro Valkonen7686b102011-02-02 23:21:58 -0800920 error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700921 if (error)
922 return error;
923 info->object_num = val;
924
925 return 0;
926}
927
Iiro Valkonen7686b102011-02-02 23:21:58 -0800928static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700929{
930 int error;
931 int i;
932 u16 reg;
933 u8 reportid = 0;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800934 u8 buf[MXT_OBJECT_SIZE];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700935
936 for (i = 0; i < data->info.object_num; i++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800937 struct mxt_object *object = data->object_table + i;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700938
Iiro Valkonen7686b102011-02-02 23:21:58 -0800939 reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
940 error = mxt_read_object_table(data->client, reg, buf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700941 if (error)
942 return error;
943
944 object->type = buf[0];
945 object->start_address = (buf[2] << 8) | buf[1];
946 object->size = buf[3];
947 object->instances = buf[4];
948 object->num_report_ids = buf[5];
949
950 if (object->num_report_ids) {
951 reportid += object->num_report_ids *
952 (object->instances + 1);
953 object->max_reportid = reportid;
954 }
955 }
956
957 return 0;
958}
959
Iiro Valkonen7686b102011-02-02 23:21:58 -0800960static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700961{
962 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800963 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700964 int error;
965 u8 val;
966
Iiro Valkonen7686b102011-02-02 23:21:58 -0800967 error = mxt_get_info(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700968 if (error)
969 return error;
970
971 data->object_table = kcalloc(info->object_num,
Iiro Valkonen7686b102011-02-02 23:21:58 -0800972 sizeof(struct mxt_object),
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700973 GFP_KERNEL);
974 if (!data->object_table) {
975 dev_err(&client->dev, "Failed to allocate memory\n");
976 return -ENOMEM;
977 }
978
979 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800980 error = mxt_get_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700981 if (error)
982 return error;
983
984 /* Check register init values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800985 error = mxt_check_reg_init(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700986 if (error)
987 return error;
988
989 /* Check X/Y matrix size */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800990 error = mxt_check_matrix_size(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700991 if (error)
992 return error;
993
Iiro Valkonen7686b102011-02-02 23:21:58 -0800994 error = mxt_make_highchg(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700995 if (error)
996 return error;
997
Iiro Valkonen7686b102011-02-02 23:21:58 -0800998 mxt_handle_pdata(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700999
1000 /* Backup to memory */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001001 mxt_write_object(data, MXT_GEN_COMMAND,
1002 MXT_COMMAND_BACKUPNV,
1003 MXT_BACKUP_VALUE);
1004 msleep(MXT_BACKUP_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001005
1006 /* Soft reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001007 mxt_write_object(data, MXT_GEN_COMMAND,
1008 MXT_COMMAND_RESET, 1);
1009 msleep(MXT_RESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001010
1011 /* Update matrix size at info struct */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001012 error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001013 if (error)
1014 return error;
1015 info->matrix_xsize = val;
1016
Iiro Valkonen7686b102011-02-02 23:21:58 -08001017 error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001018 if (error)
1019 return error;
1020 info->matrix_ysize = val;
1021
1022 dev_info(&client->dev,
1023 "Family ID: %d Variant ID: %d Version: %d Build: %d\n",
1024 info->family_id, info->variant_id, info->version,
1025 info->build);
1026
1027 dev_info(&client->dev,
1028 "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
1029 info->matrix_xsize, info->matrix_ysize,
1030 info->object_num);
1031
1032 return 0;
1033}
1034
Iiro Valkonen7686b102011-02-02 23:21:58 -08001035static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001036 struct device_attribute *attr, char *buf)
1037{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001038 struct mxt_data *data = dev_get_drvdata(dev);
1039 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001040 int count = 0;
1041 int i, j;
1042 int error;
1043 u8 val;
1044
1045 for (i = 0; i < data->info.object_num; i++) {
1046 object = data->object_table + i;
1047
1048 count += sprintf(buf + count,
1049 "Object Table Element %d(Type %d)\n",
1050 i + 1, object->type);
1051
Iiro Valkonen7686b102011-02-02 23:21:58 -08001052 if (!mxt_object_readable(object->type)) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001053 count += sprintf(buf + count, "\n");
1054 continue;
1055 }
1056
1057 for (j = 0; j < object->size + 1; j++) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001058 error = mxt_read_object(data,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001059 object->type, j, &val);
1060 if (error)
1061 return error;
1062
1063 count += sprintf(buf + count,
1064 " Byte %d: 0x%x (%d)\n", j, val, val);
1065 }
1066
1067 count += sprintf(buf + count, "\n");
1068 }
1069
1070 return count;
1071}
1072
Iiro Valkonen7686b102011-02-02 23:21:58 -08001073static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001074{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001075 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001076 struct i2c_client *client = data->client;
1077 const struct firmware *fw = NULL;
1078 unsigned int frame_size;
1079 unsigned int pos = 0;
1080 int ret;
1081
1082 ret = request_firmware(&fw, fn, dev);
1083 if (ret) {
1084 dev_err(dev, "Unable to open firmware %s\n", fn);
1085 return ret;
1086 }
1087
1088 /* Change to the bootloader mode */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001089 mxt_write_object(data, MXT_GEN_COMMAND,
1090 MXT_COMMAND_RESET, MXT_BOOT_VALUE);
1091 msleep(MXT_RESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001092
1093 /* Change to slave address of bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001094 if (client->addr == MXT_APP_LOW)
1095 client->addr = MXT_BOOT_LOW;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001096 else
Iiro Valkonen7686b102011-02-02 23:21:58 -08001097 client->addr = MXT_BOOT_HIGH;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001098
Iiro Valkonen7686b102011-02-02 23:21:58 -08001099 ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001100 if (ret)
1101 goto out;
1102
1103 /* Unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001104 mxt_unlock_bootloader(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001105
1106 while (pos < fw->size) {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001107 ret = mxt_check_bootloader(client,
1108 MXT_WAITING_FRAME_DATA);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001109 if (ret)
1110 goto out;
1111
1112 frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
1113
1114 /* We should add 2 at frame size as the the firmware data is not
1115 * included the CRC bytes.
1116 */
1117 frame_size += 2;
1118
1119 /* Write one frame to device */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001120 mxt_fw_write(client, fw->data + pos, frame_size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001121
Iiro Valkonen7686b102011-02-02 23:21:58 -08001122 ret = mxt_check_bootloader(client,
1123 MXT_FRAME_CRC_PASS);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001124 if (ret)
1125 goto out;
1126
1127 pos += frame_size;
1128
1129 dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
1130 }
1131
1132out:
1133 release_firmware(fw);
1134
1135 /* Change to slave address of application */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001136 if (client->addr == MXT_BOOT_LOW)
1137 client->addr = MXT_APP_LOW;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001138 else
Iiro Valkonen7686b102011-02-02 23:21:58 -08001139 client->addr = MXT_APP_HIGH;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001140
1141 return ret;
1142}
1143
Iiro Valkonen7686b102011-02-02 23:21:58 -08001144static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001145 struct device_attribute *attr,
1146 const char *buf, size_t count)
1147{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001148 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001149 unsigned int version;
1150 int error;
1151
1152 if (sscanf(buf, "%u", &version) != 1) {
1153 dev_err(dev, "Invalid values\n");
1154 return -EINVAL;
1155 }
1156
Iiro Valkonen7686b102011-02-02 23:21:58 -08001157 if (data->info.version < MXT_VER_21 || version < MXT_VER_21) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001158 dev_err(dev, "FW update supported starting with version 21\n");
1159 return -EINVAL;
1160 }
1161
1162 disable_irq(data->irq);
1163
Iiro Valkonen7686b102011-02-02 23:21:58 -08001164 error = mxt_load_fw(dev, MXT_FW_NAME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001165 if (error) {
1166 dev_err(dev, "The firmware update failed(%d)\n", error);
1167 count = error;
1168 } else {
1169 dev_dbg(dev, "The firmware update succeeded\n");
1170
1171 /* Wait for reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001172 msleep(MXT_FWRESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001173
1174 kfree(data->object_table);
1175 data->object_table = NULL;
1176
Iiro Valkonen7686b102011-02-02 23:21:58 -08001177 mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001178 }
1179
1180 enable_irq(data->irq);
1181
1182 return count;
1183}
1184
Iiro Valkonen7686b102011-02-02 23:21:58 -08001185static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
1186static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001187
Iiro Valkonen7686b102011-02-02 23:21:58 -08001188static struct attribute *mxt_attrs[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001189 &dev_attr_object.attr,
1190 &dev_attr_update_fw.attr,
1191 NULL
1192};
1193
Iiro Valkonen7686b102011-02-02 23:21:58 -08001194static const struct attribute_group mxt_attr_group = {
1195 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001196};
1197
Iiro Valkonen7686b102011-02-02 23:21:58 -08001198static void mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001199{
1200 /* Touch enable */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001201 mxt_write_object(data,
1202 MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0x83);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001203}
1204
Iiro Valkonen7686b102011-02-02 23:21:58 -08001205static void mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001206{
1207 /* Touch disable */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001208 mxt_write_object(data,
1209 MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001210}
1211
Iiro Valkonen7686b102011-02-02 23:21:58 -08001212static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001213{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001214 struct mxt_data *data = input_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001215
Iiro Valkonen7686b102011-02-02 23:21:58 -08001216 mxt_start(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001217
1218 return 0;
1219}
1220
Iiro Valkonen7686b102011-02-02 23:21:58 -08001221static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001222{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001223 struct mxt_data *data = input_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001224
Iiro Valkonen7686b102011-02-02 23:21:58 -08001225 mxt_stop(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001226}
1227
Iiro Valkonen7686b102011-02-02 23:21:58 -08001228static int __devinit mxt_probe(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001229 const struct i2c_device_id *id)
1230{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001231 struct mxt_data *data;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001232 struct input_dev *input_dev;
1233 int error;
1234
1235 if (!client->dev.platform_data)
1236 return -EINVAL;
1237
Iiro Valkonen7686b102011-02-02 23:21:58 -08001238 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001239 input_dev = input_allocate_device();
1240 if (!data || !input_dev) {
1241 dev_err(&client->dev, "Failed to allocate memory\n");
1242 error = -ENOMEM;
1243 goto err_free_mem;
1244 }
1245
Iiro Valkonen7686b102011-02-02 23:21:58 -08001246 input_dev->name = "Atmel maXTouch Touchscreen";
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001247 input_dev->id.bustype = BUS_I2C;
1248 input_dev->dev.parent = &client->dev;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001249 input_dev->open = mxt_input_open;
1250 input_dev->close = mxt_input_close;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001251
1252 __set_bit(EV_ABS, input_dev->evbit);
1253 __set_bit(EV_KEY, input_dev->evbit);
1254 __set_bit(BTN_TOUCH, input_dev->keybit);
1255
1256 /* For single touch */
1257 input_set_abs_params(input_dev, ABS_X,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001258 0, MXT_MAX_XC, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001259 input_set_abs_params(input_dev, ABS_Y,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001260 0, MXT_MAX_YC, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001261
1262 /* For multi touch */
1263 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001264 0, MXT_MAX_AREA, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001265 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001266 0, MXT_MAX_XC, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001267 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
Iiro Valkonen7686b102011-02-02 23:21:58 -08001268 0, MXT_MAX_YC, 0, 0);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001269
1270 input_set_drvdata(input_dev, data);
1271
1272 data->client = client;
1273 data->input_dev = input_dev;
1274 data->pdata = client->dev.platform_data;
1275 data->irq = client->irq;
1276
1277 i2c_set_clientdata(client, data);
1278
Iiro Valkonen7686b102011-02-02 23:21:58 -08001279 error = mxt_initialize(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001280 if (error)
1281 goto err_free_object;
1282
Iiro Valkonen7686b102011-02-02 23:21:58 -08001283 error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001284 IRQF_TRIGGER_FALLING, client->dev.driver->name, data);
1285 if (error) {
1286 dev_err(&client->dev, "Failed to register interrupt\n");
1287 goto err_free_object;
1288 }
1289
1290 error = input_register_device(input_dev);
1291 if (error)
1292 goto err_free_irq;
1293
Iiro Valkonen7686b102011-02-02 23:21:58 -08001294 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001295 if (error)
1296 goto err_unregister_device;
1297
1298 return 0;
1299
1300err_unregister_device:
1301 input_unregister_device(input_dev);
1302 input_dev = NULL;
1303err_free_irq:
1304 free_irq(client->irq, data);
1305err_free_object:
1306 kfree(data->object_table);
1307err_free_mem:
1308 input_free_device(input_dev);
1309 kfree(data);
1310 return error;
1311}
1312
Iiro Valkonen7686b102011-02-02 23:21:58 -08001313static int __devexit mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001314{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001315 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001316
Iiro Valkonen7686b102011-02-02 23:21:58 -08001317 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001318 free_irq(data->irq, data);
1319 input_unregister_device(data->input_dev);
1320 kfree(data->object_table);
1321 kfree(data);
1322
1323 return 0;
1324}
1325
1326#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08001327static int mxt_suspend(struct device *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001328{
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08001329 struct i2c_client *client = to_i2c_client(dev);
Iiro Valkonen7686b102011-02-02 23:21:58 -08001330 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001331 struct input_dev *input_dev = data->input_dev;
1332
1333 mutex_lock(&input_dev->mutex);
1334
1335 if (input_dev->users)
Iiro Valkonen7686b102011-02-02 23:21:58 -08001336 mxt_stop(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001337
1338 mutex_unlock(&input_dev->mutex);
1339
1340 return 0;
1341}
1342
Iiro Valkonen7686b102011-02-02 23:21:58 -08001343static int mxt_resume(struct device *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001344{
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08001345 struct i2c_client *client = to_i2c_client(dev);
Iiro Valkonen7686b102011-02-02 23:21:58 -08001346 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001347 struct input_dev *input_dev = data->input_dev;
1348
1349 /* Soft reset */
Iiro Valkonen7686b102011-02-02 23:21:58 -08001350 mxt_write_object(data, MXT_GEN_COMMAND,
1351 MXT_COMMAND_RESET, 1);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001352
Iiro Valkonen7686b102011-02-02 23:21:58 -08001353 msleep(MXT_RESET_TIME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001354
1355 mutex_lock(&input_dev->mutex);
1356
1357 if (input_dev->users)
Iiro Valkonen7686b102011-02-02 23:21:58 -08001358 mxt_start(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001359
1360 mutex_unlock(&input_dev->mutex);
1361
1362 return 0;
1363}
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08001364
Iiro Valkonen7686b102011-02-02 23:21:58 -08001365static const struct dev_pm_ops mxt_pm_ops = {
1366 .suspend = mxt_suspend,
1367 .resume = mxt_resume,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08001368};
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001369#endif
1370
Iiro Valkonen7686b102011-02-02 23:21:58 -08001371static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001372 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08001373 { "atmel_mxt_ts", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08001374 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001375 { }
1376};
Iiro Valkonen7686b102011-02-02 23:21:58 -08001377MODULE_DEVICE_TABLE(i2c, mxt_id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001378
Iiro Valkonen7686b102011-02-02 23:21:58 -08001379static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001380 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08001381 .name = "atmel_mxt_ts",
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001382 .owner = THIS_MODULE,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08001383#ifdef CONFIG_PM
Iiro Valkonen7686b102011-02-02 23:21:58 -08001384 .pm = &mxt_pm_ops,
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08001385#endif
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001386 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08001387 .probe = mxt_probe,
1388 .remove = __devexit_p(mxt_remove),
1389 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001390};
1391
Iiro Valkonen7686b102011-02-02 23:21:58 -08001392static int __init mxt_init(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001393{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001394 return i2c_add_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001395}
1396
Iiro Valkonen7686b102011-02-02 23:21:58 -08001397static void __exit mxt_exit(void)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001398{
Iiro Valkonen7686b102011-02-02 23:21:58 -08001399 i2c_del_driver(&mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001400}
1401
Iiro Valkonen7686b102011-02-02 23:21:58 -08001402module_init(mxt_init);
1403module_exit(mxt_exit);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001404
1405/* Module information */
1406MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08001407MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001408MODULE_LICENSE("GPL");