blob: 799d2ac35787b4da3ae025e10b8899c19f57887d [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
Nick Dyer50a77c62014-07-23 12:38:48 -07005 * Copyright (C) 2011-2014 Atmel Corporation
Daniel Kurtz1e0c0c52014-05-18 23:01:12 -07006 * Copyright (C) 2012 Google, Inc.
Nick Dyerf3c4a8f2016-09-15 17:30:43 -03007 * Copyright (C) 2016 Zodiac Inflight Innovations
Daniel Kurtz1e0c0c52014-05-18 23:01:12 -07008 *
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07009 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 */
17
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -070018#include <linux/acpi.h>
19#include <linux/dmi.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070020#include <linux/module.h>
Benson Leungd79e7e42014-05-18 23:02:52 -070021#include <linux/init.h>
22#include <linux/completion.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070023#include <linux/delay.h>
24#include <linux/firmware.h>
25#include <linux/i2c.h>
Nick Dyer7f3884f72015-08-04 16:36:29 -070026#include <linux/platform_data/atmel_mxt_ts.h>
Joonyoung Shim8b86c1c2011-04-12 23:18:59 -070027#include <linux/input/mt.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070028#include <linux/interrupt.h>
Stephen Warren78188be2014-07-23 12:23:23 -070029#include <linux/of.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070030#include <linux/slab.h>
Sebastian Reichelf657b002017-07-25 14:11:34 -070031#include <linux/gpio/consumer.h>
Dmitry Torokhov93afb1d2018-03-20 15:31:26 -070032#include <linux/property.h>
Nick Dyerb23157d2015-04-06 11:25:13 -070033#include <asm/unaligned.h>
Nick Dyerecfdd7e2016-07-18 18:10:32 -030034#include <media/v4l2-device.h>
35#include <media/v4l2-ioctl.h>
36#include <media/videobuf2-v4l2.h>
37#include <media/videobuf2-vmalloc.h>
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070038
Nick Dyer50a77c62014-07-23 12:38:48 -070039/* Firmware files */
Iiro Valkonen7686b102011-02-02 23:21:58 -080040#define MXT_FW_NAME "maxtouch.fw"
Nick Dyer50a77c62014-07-23 12:38:48 -070041#define MXT_CFG_NAME "maxtouch.cfg"
42#define MXT_CFG_MAGIC "OBP_RAW V1"
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070043
44/* Registers */
Iiro Valkonen7686b102011-02-02 23:21:58 -080045#define MXT_OBJECT_START 0x07
Iiro Valkonen7686b102011-02-02 23:21:58 -080046#define MXT_OBJECT_SIZE 6
Nick Dyer4ce6fa02014-07-23 12:40:09 -070047#define MXT_INFO_CHECKSUM_SIZE 3
48#define MXT_MAX_BLOCK_WRITE 256
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070049
50/* Object types */
Iiro Valkonen81c88a72011-07-04 03:08:25 -070051#define MXT_DEBUG_DIAGNOSTIC_T37 37
52#define MXT_GEN_MESSAGE_T5 5
53#define MXT_GEN_COMMAND_T6 6
54#define MXT_GEN_POWER_T7 7
55#define MXT_GEN_ACQUIRE_T8 8
56#define MXT_GEN_DATASOURCE_T53 53
57#define MXT_TOUCH_MULTI_T9 9
58#define MXT_TOUCH_KEYARRAY_T15 15
59#define MXT_TOUCH_PROXIMITY_T23 23
60#define MXT_TOUCH_PROXKEY_T52 52
61#define MXT_PROCI_GRIPFACE_T20 20
62#define MXT_PROCG_NOISE_T22 22
63#define MXT_PROCI_ONETOUCH_T24 24
64#define MXT_PROCI_TWOTOUCH_T27 27
65#define MXT_PROCI_GRIP_T40 40
66#define MXT_PROCI_PALM_T41 41
67#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
68#define MXT_PROCI_STYLUS_T47 47
69#define MXT_PROCG_NOISESUPPRESSION_T48 48
70#define MXT_SPT_COMMSCONFIG_T18 18
71#define MXT_SPT_GPIOPWM_T19 19
72#define MXT_SPT_SELFTEST_T25 25
73#define MXT_SPT_CTECONFIG_T28 28
74#define MXT_SPT_USERDATA_T38 38
75#define MXT_SPT_DIGITIZER_T43 43
76#define MXT_SPT_MESSAGECOUNT_T44 44
77#define MXT_SPT_CTECONFIG_T46 46
Nick Dyerb23157d2015-04-06 11:25:13 -070078#define MXT_TOUCH_MULTITOUCHSCREEN_T100 100
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070079
Nick Dyer5f3f9bc2014-07-23 12:46:55 -070080/* MXT_GEN_MESSAGE_T5 object */
81#define MXT_RPTID_NOMSG 0xff
82
Iiro Valkonen81c88a72011-07-04 03:08:25 -070083/* MXT_GEN_COMMAND_T6 field */
Iiro Valkonen7686b102011-02-02 23:21:58 -080084#define MXT_COMMAND_RESET 0
85#define MXT_COMMAND_BACKUPNV 1
86#define MXT_COMMAND_CALIBRATE 2
87#define MXT_COMMAND_REPORTALL 3
88#define MXT_COMMAND_DIAGNOSTIC 5
Joonyoung Shim4cf51c32010-07-14 21:55:30 -070089
Iiro Valkonena4a2ef42014-05-18 23:03:44 -070090/* Define for T6 status byte */
91#define MXT_T6_STATUS_RESET (1 << 7)
Nick Dyer497767d2014-07-23 12:47:50 -070092#define MXT_T6_STATUS_OFL (1 << 6)
93#define MXT_T6_STATUS_SIGERR (1 << 5)
94#define MXT_T6_STATUS_CAL (1 << 4)
95#define MXT_T6_STATUS_CFGERR (1 << 3)
96#define MXT_T6_STATUS_COMSERR (1 << 2)
Iiro Valkonena4a2ef42014-05-18 23:03:44 -070097
Iiro Valkonen81c88a72011-07-04 03:08:25 -070098/* MXT_GEN_POWER_T7 field */
Nick Dyer7f3884f72015-08-04 16:36:29 -070099struct t7_config {
100 u8 idle;
101 u8 active;
102} __packed;
103
104#define MXT_POWER_CFG_RUN 0
105#define MXT_POWER_CFG_DEEPSLEEP 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700106
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700107/* MXT_TOUCH_MULTI_T9 field */
Nick Dyer7f3884f72015-08-04 16:36:29 -0700108#define MXT_T9_CTRL 0
Nick Dyer27864892016-07-18 18:10:33 -0300109#define MXT_T9_XSIZE 3
110#define MXT_T9_YSIZE 4
Nick Dyer61dc1ab2014-05-18 23:16:49 -0700111#define MXT_T9_ORIENT 9
112#define MXT_T9_RANGE 18
113
Nick Dyerf3889ed2014-05-18 23:22:04 -0700114/* MXT_TOUCH_MULTI_T9 status */
115#define MXT_T9_UNGRIP (1 << 0)
116#define MXT_T9_SUPPRESS (1 << 1)
117#define MXT_T9_AMP (1 << 2)
118#define MXT_T9_VECTOR (1 << 3)
119#define MXT_T9_MOVE (1 << 4)
120#define MXT_T9_RELEASE (1 << 5)
121#define MXT_T9_PRESS (1 << 6)
122#define MXT_T9_DETECT (1 << 7)
123
Nick Dyer61dc1ab2014-05-18 23:16:49 -0700124struct t9_range {
Nick Dyer1c0276d2016-01-10 18:29:34 -0800125 __le16 x;
126 __le16 y;
Nick Dyer61dc1ab2014-05-18 23:16:49 -0700127} __packed;
128
Nick Dyerf3889ed2014-05-18 23:22:04 -0700129/* MXT_TOUCH_MULTI_T9 orient */
130#define MXT_T9_ORIENT_SWITCH (1 << 0)
Nick Dyerde601f72016-07-18 18:10:34 -0300131#define MXT_T9_ORIENT_INVERTX (1 << 1)
132#define MXT_T9_ORIENT_INVERTY (1 << 2)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700133
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700134/* MXT_SPT_COMMSCONFIG_T18 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800135#define MXT_COMMS_CTRL 0
136#define MXT_COMMS_CMD 1
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700137
Nick Dyerd6a39402016-07-18 18:10:31 -0300138/* MXT_DEBUG_DIAGNOSTIC_T37 */
139#define MXT_DIAGNOSTIC_PAGEUP 0x01
140#define MXT_DIAGNOSTIC_DELTAS 0x10
Nick Dyer06b3d3f2016-07-18 18:10:36 -0300141#define MXT_DIAGNOSTIC_REFS 0x11
Nick Dyerd6a39402016-07-18 18:10:31 -0300142#define MXT_DIAGNOSTIC_SIZE 128
143
Nick Dyer566d5332016-07-18 18:10:35 -0300144#define MXT_FAMILY_1386 160
145#define MXT1386_COLUMNS 3
146#define MXT1386_PAGES_PER_COLUMN 8
147
Nick Dyerd6a39402016-07-18 18:10:31 -0300148struct t37_debug {
149#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37
150 u8 mode;
151 u8 page;
152 u8 data[MXT_DIAGNOSTIC_SIZE];
153#endif
154};
155
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700156/* Define for MXT_GEN_COMMAND_T6 */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800157#define MXT_BOOT_VALUE 0xa5
Iiro Valkonena4a2ef42014-05-18 23:03:44 -0700158#define MXT_RESET_VALUE 0x01
Iiro Valkonen7686b102011-02-02 23:21:58 -0800159#define MXT_BACKUP_VALUE 0x55
Iiro Valkonena4a2ef42014-05-18 23:03:44 -0700160
Nick Dyerb23157d2015-04-06 11:25:13 -0700161/* T100 Multiple Touch Touchscreen */
162#define MXT_T100_CTRL 0
163#define MXT_T100_CFG1 1
164#define MXT_T100_TCHAUX 3
Nick Dyer27864892016-07-18 18:10:33 -0300165#define MXT_T100_XSIZE 9
Nick Dyerb23157d2015-04-06 11:25:13 -0700166#define MXT_T100_XRANGE 13
Nick Dyer27864892016-07-18 18:10:33 -0300167#define MXT_T100_YSIZE 20
Nick Dyerb23157d2015-04-06 11:25:13 -0700168#define MXT_T100_YRANGE 24
169
170#define MXT_T100_CFG_SWITCHXY BIT(5)
Nick Dyerde601f72016-07-18 18:10:34 -0300171#define MXT_T100_CFG_INVERTY BIT(6)
172#define MXT_T100_CFG_INVERTX BIT(7)
Nick Dyerb23157d2015-04-06 11:25:13 -0700173
174#define MXT_T100_TCHAUX_VECT BIT(0)
175#define MXT_T100_TCHAUX_AMPL BIT(1)
176#define MXT_T100_TCHAUX_AREA BIT(2)
177
178#define MXT_T100_DETECT BIT(7)
179#define MXT_T100_TYPE_MASK 0x70
180
181enum t100_type {
182 MXT_T100_TYPE_FINGER = 1,
183 MXT_T100_TYPE_PASSIVE_STYLUS = 2,
184 MXT_T100_TYPE_HOVERING_FINGER = 4,
185 MXT_T100_TYPE_GLOVE = 5,
186 MXT_T100_TYPE_LARGE_TOUCH = 6,
187};
188
189#define MXT_DISTANCE_ACTIVE_TOUCH 0
190#define MXT_DISTANCE_HOVERING 1
191
192#define MXT_TOUCH_MAJOR_DEFAULT 1
193#define MXT_PRESSURE_DEFAULT 1
194
Iiro Valkonena4a2ef42014-05-18 23:03:44 -0700195/* Delay times */
Linus Torvalds8343bce2013-03-09 10:31:01 -0800196#define MXT_BACKUP_TIME 50 /* msec */
197#define MXT_RESET_TIME 200 /* msec */
Iiro Valkonena4a2ef42014-05-18 23:03:44 -0700198#define MXT_RESET_TIMEOUT 3000 /* msec */
Nick Dyerc3f78042014-05-18 23:04:46 -0700199#define MXT_CRC_TIMEOUT 1000 /* msec */
Benson Leunga0434b72014-05-18 23:03:09 -0700200#define MXT_FW_RESET_TIME 3000 /* msec */
201#define MXT_FW_CHG_TIMEOUT 300 /* msec */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700202
203/* Command to unlock bootloader */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800204#define MXT_UNLOCK_CMD_MSB 0xaa
205#define MXT_UNLOCK_CMD_LSB 0xdc
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700206
207/* Bootloader mode status */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800208#define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
209#define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
210#define MXT_FRAME_CRC_CHECK 0x02
211#define MXT_FRAME_CRC_FAIL 0x03
212#define MXT_FRAME_CRC_PASS 0x04
213#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
214#define MXT_BOOT_STATUS_MASK 0x3f
Nick Dyere57a66a2014-05-18 23:13:40 -0700215#define MXT_BOOT_EXTENDED_ID (1 << 5)
216#define MXT_BOOT_ID_MASK 0x1f
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700217
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700218/* Touchscreen absolute values */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800219#define MXT_MAX_AREA 0xff
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700220
Daniel Kurtz22dfab72013-03-07 19:43:33 -0800221#define MXT_PIXELS_PER_MM 20
222
Iiro Valkonen7686b102011-02-02 23:21:58 -0800223struct mxt_info {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700224 u8 family_id;
225 u8 variant_id;
226 u8 version;
227 u8 build;
228 u8 matrix_xsize;
229 u8 matrix_ysize;
230 u8 object_num;
231};
232
Iiro Valkonen7686b102011-02-02 23:21:58 -0800233struct mxt_object {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700234 u8 type;
235 u16 start_address;
Daniel Kurtz1e0c0c52014-05-18 23:01:12 -0700236 u8 size_minus_one;
237 u8 instances_minus_one;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700238 u8 num_report_ids;
Daniel Kurtz333e5a92012-06-28 21:08:20 +0800239} __packed;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700240
Nick Dyerd6a39402016-07-18 18:10:31 -0300241struct mxt_dbg {
242 u16 t37_address;
243 u16 diag_cmd_address;
244 struct t37_debug *t37_buf;
245 unsigned int t37_pages;
246 unsigned int t37_nodes;
Nick Dyerecfdd7e2016-07-18 18:10:32 -0300247
248 struct v4l2_device v4l2;
249 struct v4l2_pix_format format;
250 struct video_device vdev;
251 struct vb2_queue queue;
252 struct mutex lock;
253 int input;
254};
255
Nick Dyer06b3d3f2016-07-18 18:10:36 -0300256enum v4l_dbg_inputs {
257 MXT_V4L_INPUT_DELTAS,
258 MXT_V4L_INPUT_REFS,
259 MXT_V4L_INPUT_MAX,
260};
261
Nick Dyerecfdd7e2016-07-18 18:10:32 -0300262static const struct v4l2_file_operations mxt_video_fops = {
263 .owner = THIS_MODULE,
264 .open = v4l2_fh_open,
265 .release = vb2_fop_release,
266 .unlocked_ioctl = video_ioctl2,
267 .read = vb2_fop_read,
268 .mmap = vb2_fop_mmap,
269 .poll = vb2_fop_poll,
Nick Dyerd6a39402016-07-18 18:10:31 -0300270};
271
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700272/* Each client has this additional data */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800273struct mxt_data {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700274 struct i2c_client *client;
275 struct input_dev *input_dev;
Daniel Kurtzec02ac22012-06-28 21:08:02 +0800276 char phys[64]; /* device physical location */
Iiro Valkonen7686b102011-02-02 23:21:58 -0800277 const struct mxt_platform_data *pdata;
278 struct mxt_object *object_table;
279 struct mxt_info info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700280 unsigned int irq;
Joonyoung Shim910d8052011-04-12 23:14:38 -0700281 unsigned int max_x;
282 unsigned int max_y;
Nick Dyerde601f72016-07-18 18:10:34 -0300283 bool invertx;
284 bool inverty;
Nick Dyer1c0276d2016-01-10 18:29:34 -0800285 bool xy_switch;
Nick Dyer27864892016-07-18 18:10:33 -0300286 u8 xsize;
287 u8 ysize;
Benson Leungd79e7e42014-05-18 23:02:52 -0700288 bool in_bootloader;
Nick Dyer4ce6fa02014-07-23 12:40:09 -0700289 u16 mem_size;
Nick Dyerb23157d2015-04-06 11:25:13 -0700290 u8 t100_aux_ampl;
291 u8 t100_aux_area;
292 u8 t100_aux_vect;
Nick Dyer9d8dc3e2014-07-23 12:49:04 -0700293 u8 max_reportid;
Nick Dyerc3f78042014-05-18 23:04:46 -0700294 u32 config_crc;
Nick Dyer4ce6fa02014-07-23 12:40:09 -0700295 u32 info_crc;
Nick Dyerf28a8422014-05-18 23:10:49 -0700296 u8 bootloader_addr;
Nick Dyer5f3f9bc2014-07-23 12:46:55 -0700297 u8 *msg_buf;
Nick Dyer497767d2014-07-23 12:47:50 -0700298 u8 t6_status;
Nick Dyerb9b05a82014-07-23 12:48:13 -0700299 bool update_input;
Nick Dyer9d8dc3e2014-07-23 12:49:04 -0700300 u8 last_message_count;
301 u8 num_touchids;
Nick Dyerb23157d2015-04-06 11:25:13 -0700302 u8 multitouch;
Nick Dyer7f3884f72015-08-04 16:36:29 -0700303 struct t7_config t7_cfg;
Nick Dyerd6a39402016-07-18 18:10:31 -0300304 struct mxt_dbg dbg;
Sebastian Reichelf657b002017-07-25 14:11:34 -0700305 struct gpio_desc *reset_gpio;
Daniel Kurtz333e5a92012-06-28 21:08:20 +0800306
307 /* Cached parameters from object table */
Nick Dyerb9b05a82014-07-23 12:48:13 -0700308 u16 T5_address;
Nick Dyer5f3f9bc2014-07-23 12:46:55 -0700309 u8 T5_msg_size;
Daniel Kurtzfdf804212012-06-28 21:08:24 +0800310 u8 T6_reportid;
Iiro Valkonena4a2ef42014-05-18 23:03:44 -0700311 u16 T6_address;
Nick Dyer4ce6fa02014-07-23 12:40:09 -0700312 u16 T7_address;
Daniel Kurtz333e5a92012-06-28 21:08:20 +0800313 u8 T9_reportid_min;
314 u8 T9_reportid_max;
Daniel Kurtz22dfab72013-03-07 19:43:33 -0800315 u8 T19_reportid;
Nick Dyer9d8dc3e2014-07-23 12:49:04 -0700316 u16 T44_address;
Nick Dyerb23157d2015-04-06 11:25:13 -0700317 u8 T100_reportid_min;
318 u8 T100_reportid_max;
Benson Leungd79e7e42014-05-18 23:02:52 -0700319
320 /* for fw update in bootloader */
321 struct completion bl_completion;
Iiro Valkonena4a2ef42014-05-18 23:03:44 -0700322
323 /* for reset handling */
324 struct completion reset_completion;
Nick Dyerc3f78042014-05-18 23:04:46 -0700325
326 /* for config update handling */
327 struct completion crc_completion;
Dmitry Torokhovd80808e2018-03-20 15:31:25 -0700328
329 enum mxt_suspend_mode suspend_mode;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700330};
331
Nick Dyerecfdd7e2016-07-18 18:10:32 -0300332struct mxt_vb2_buffer {
333 struct vb2_buffer vb;
334 struct list_head list;
335};
336
Daniel Kurtz1e0c0c52014-05-18 23:01:12 -0700337static size_t mxt_obj_size(const struct mxt_object *obj)
338{
339 return obj->size_minus_one + 1;
340}
341
342static size_t mxt_obj_instances(const struct mxt_object *obj)
343{
344 return obj->instances_minus_one + 1;
345}
346
Iiro Valkonen7686b102011-02-02 23:21:58 -0800347static bool mxt_object_readable(unsigned int type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700348{
349 switch (type) {
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700350 case MXT_GEN_COMMAND_T6:
351 case MXT_GEN_POWER_T7:
352 case MXT_GEN_ACQUIRE_T8:
353 case MXT_GEN_DATASOURCE_T53:
354 case MXT_TOUCH_MULTI_T9:
355 case MXT_TOUCH_KEYARRAY_T15:
356 case MXT_TOUCH_PROXIMITY_T23:
357 case MXT_TOUCH_PROXKEY_T52:
Maxime Roussin-Bélanger089b50d2017-05-19 14:59:03 -0700358 case MXT_TOUCH_MULTITOUCHSCREEN_T100:
Iiro Valkonen81c88a72011-07-04 03:08:25 -0700359 case MXT_PROCI_GRIPFACE_T20:
360 case MXT_PROCG_NOISE_T22:
361 case MXT_PROCI_ONETOUCH_T24:
362 case MXT_PROCI_TWOTOUCH_T27:
363 case MXT_PROCI_GRIP_T40:
364 case MXT_PROCI_PALM_T41:
365 case MXT_PROCI_TOUCHSUPPRESSION_T42:
366 case MXT_PROCI_STYLUS_T47:
367 case MXT_PROCG_NOISESUPPRESSION_T48:
368 case MXT_SPT_COMMSCONFIG_T18:
369 case MXT_SPT_GPIOPWM_T19:
370 case MXT_SPT_SELFTEST_T25:
371 case MXT_SPT_CTECONFIG_T28:
372 case MXT_SPT_USERDATA_T38:
373 case MXT_SPT_DIGITIZER_T43:
374 case MXT_SPT_CTECONFIG_T46:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700375 return true;
376 default:
377 return false;
378 }
379}
380
Nick Dyer5f3f9bc2014-07-23 12:46:55 -0700381static void mxt_dump_message(struct mxt_data *data, u8 *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700382{
Nick Dyer5f3f9bc2014-07-23 12:46:55 -0700383 dev_dbg(&data->client->dev, "message: %*ph\n",
384 data->T5_msg_size, message);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700385}
386
Iiro Valkonena4a2ef42014-05-18 23:03:44 -0700387static int mxt_wait_for_completion(struct mxt_data *data,
388 struct completion *comp,
389 unsigned int timeout_ms)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700390{
Benson Leungd79e7e42014-05-18 23:02:52 -0700391 struct device *dev = &data->client->dev;
Benson Leungd79e7e42014-05-18 23:02:52 -0700392 unsigned long timeout = msecs_to_jiffies(timeout_ms);
393 long ret;
394
395 ret = wait_for_completion_interruptible_timeout(comp, timeout);
396 if (ret < 0) {
397 return ret;
398 } else if (ret == 0) {
399 dev_err(dev, "Wait for completion timed out.\n");
400 return -ETIMEDOUT;
401 }
402 return 0;
403}
404
Nick Dyerf28a8422014-05-18 23:10:49 -0700405static int mxt_bootloader_read(struct mxt_data *data,
406 u8 *val, unsigned int count)
407{
408 int ret;
409 struct i2c_msg msg;
410
411 msg.addr = data->bootloader_addr;
412 msg.flags = data->client->flags & I2C_M_TEN;
413 msg.flags |= I2C_M_RD;
414 msg.len = count;
415 msg.buf = val;
416
417 ret = i2c_transfer(data->client->adapter, &msg, 1);
Nick Dyerf28a8422014-05-18 23:10:49 -0700418 if (ret == 1) {
419 ret = 0;
420 } else {
421 ret = ret < 0 ? ret : -EIO;
422 dev_err(&data->client->dev, "%s: i2c recv failed (%d)\n",
423 __func__, ret);
424 }
425
426 return ret;
427}
428
429static int mxt_bootloader_write(struct mxt_data *data,
430 const u8 * const val, unsigned int count)
431{
432 int ret;
433 struct i2c_msg msg;
434
435 msg.addr = data->bootloader_addr;
436 msg.flags = data->client->flags & I2C_M_TEN;
437 msg.len = count;
438 msg.buf = (u8 *)val;
439
440 ret = i2c_transfer(data->client->adapter, &msg, 1);
441 if (ret == 1) {
442 ret = 0;
443 } else {
444 ret = ret < 0 ? ret : -EIO;
445 dev_err(&data->client->dev, "%s: i2c send failed (%d)\n",
446 __func__, ret);
447 }
448
449 return ret;
450}
451
Nick Dyer8efaa5e2014-07-23 12:45:49 -0700452static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry)
Nick Dyerf28a8422014-05-18 23:10:49 -0700453{
454 u8 appmode = data->client->addr;
455 u8 bootloader;
456
457 switch (appmode) {
458 case 0x4a:
459 case 0x4b:
Nick Dyer44a0bab2014-07-23 12:45:26 -0700460 /* Chips after 1664S use different scheme */
Nick Dyer8efaa5e2014-07-23 12:45:49 -0700461 if (retry || data->info.family_id >= 0xa2) {
Nick Dyer44a0bab2014-07-23 12:45:26 -0700462 bootloader = appmode - 0x24;
463 break;
464 }
465 /* Fall through for normal case */
Nick Dyerf28a8422014-05-18 23:10:49 -0700466 case 0x4c:
467 case 0x4d:
468 case 0x5a:
469 case 0x5b:
470 bootloader = appmode - 0x26;
471 break;
Dmitry Torokhov6cd1ab02014-08-08 09:28:45 -0700472
Nick Dyerf28a8422014-05-18 23:10:49 -0700473 default:
474 dev_err(&data->client->dev,
475 "Appmode i2c address 0x%02x not found\n",
476 appmode);
477 return -EINVAL;
478 }
479
480 data->bootloader_addr = bootloader;
481 return 0;
482}
483
Dmitry Torokhov6cd1ab02014-08-08 09:28:45 -0700484static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address)
Nick Dyera9fdd1e2014-07-23 12:41:58 -0700485{
486 struct device *dev = &data->client->dev;
Dmitry Torokhov6cd1ab02014-08-08 09:28:45 -0700487 int error;
Nick Dyera9fdd1e2014-07-23 12:41:58 -0700488 u8 val;
489 bool crc_failure;
490
Dmitry Torokhov6cd1ab02014-08-08 09:28:45 -0700491 error = mxt_lookup_bootloader_address(data, alt_address);
492 if (error)
493 return error;
Nick Dyera9fdd1e2014-07-23 12:41:58 -0700494
Dmitry Torokhov6cd1ab02014-08-08 09:28:45 -0700495 error = mxt_bootloader_read(data, &val, 1);
496 if (error)
497 return error;
Nick Dyera9fdd1e2014-07-23 12:41:58 -0700498
499 /* Check app crc fail mode */
500 crc_failure = (val & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL;
501
502 dev_err(dev, "Detected bootloader, status:%02X%s\n",
503 val, crc_failure ? ", APP_CRC_FAIL" : "");
504
505 return 0;
506}
507
Nick Dyere57a66a2014-05-18 23:13:40 -0700508static u8 mxt_get_bootloader_version(struct mxt_data *data, u8 val)
509{
510 struct device *dev = &data->client->dev;
511 u8 buf[3];
512
513 if (val & MXT_BOOT_EXTENDED_ID) {
514 if (mxt_bootloader_read(data, &buf[0], 3) != 0) {
515 dev_err(dev, "%s: i2c failure\n", __func__);
Nick Dyer68807a02014-06-07 23:17:26 -0700516 return val;
Nick Dyere57a66a2014-05-18 23:13:40 -0700517 }
518
519 dev_dbg(dev, "Bootloader ID:%d Version:%d\n", buf[1], buf[2]);
520
521 return buf[0];
522 } else {
523 dev_dbg(dev, "Bootloader ID:%d\n", val & MXT_BOOT_ID_MASK);
524
525 return val;
526 }
527}
528
Nick Dyer385deb92014-07-23 12:42:40 -0700529static int mxt_check_bootloader(struct mxt_data *data, unsigned int state,
530 bool wait)
Benson Leungd79e7e42014-05-18 23:02:52 -0700531{
Nick Dyerf28a8422014-05-18 23:10:49 -0700532 struct device *dev = &data->client->dev;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700533 u8 val;
Benson Leungd79e7e42014-05-18 23:02:52 -0700534 int ret;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700535
536recheck:
Nick Dyer385deb92014-07-23 12:42:40 -0700537 if (wait) {
Benson Leungd79e7e42014-05-18 23:02:52 -0700538 /*
539 * In application update mode, the interrupt
540 * line signals state transitions. We must wait for the
541 * CHG assertion before reading the status byte.
542 * Once the status byte has been read, the line is deasserted.
543 */
Iiro Valkonena4a2ef42014-05-18 23:03:44 -0700544 ret = mxt_wait_for_completion(data, &data->bl_completion,
545 MXT_FW_CHG_TIMEOUT);
Benson Leungd79e7e42014-05-18 23:02:52 -0700546 if (ret) {
547 /*
548 * TODO: handle -ERESTARTSYS better by terminating
549 * fw update process before returning to userspace
550 * by writing length 0x000 to device (iff we are in
551 * WAITING_FRAME_DATA state).
552 */
Nick Dyerf28a8422014-05-18 23:10:49 -0700553 dev_err(dev, "Update wait error %d\n", ret);
Benson Leungd79e7e42014-05-18 23:02:52 -0700554 return ret;
555 }
556 }
557
Nick Dyerf28a8422014-05-18 23:10:49 -0700558 ret = mxt_bootloader_read(data, &val, 1);
559 if (ret)
560 return ret;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700561
Nick Dyere57a66a2014-05-18 23:13:40 -0700562 if (state == MXT_WAITING_BOOTLOAD_CMD)
563 val = mxt_get_bootloader_version(data, val);
564
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700565 switch (state) {
Iiro Valkonen7686b102011-02-02 23:21:58 -0800566 case MXT_WAITING_BOOTLOAD_CMD:
567 case MXT_WAITING_FRAME_DATA:
Nick Dyera9fdd1e2014-07-23 12:41:58 -0700568 case MXT_APP_CRC_FAIL:
Iiro Valkonen7686b102011-02-02 23:21:58 -0800569 val &= ~MXT_BOOT_STATUS_MASK;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700570 break;
Iiro Valkonen7686b102011-02-02 23:21:58 -0800571 case MXT_FRAME_CRC_PASS:
Nick Dyerf943c742014-05-18 23:14:20 -0700572 if (val == MXT_FRAME_CRC_CHECK) {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700573 goto recheck;
Nick Dyerf943c742014-05-18 23:14:20 -0700574 } else if (val == MXT_FRAME_CRC_FAIL) {
575 dev_err(dev, "Bootloader CRC fail\n");
576 return -EINVAL;
577 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700578 break;
579 default:
580 return -EINVAL;
581 }
582
583 if (val != state) {
Nick Dyerf28a8422014-05-18 23:10:49 -0700584 dev_err(dev, "Invalid bootloader state %02X != %02X\n",
Nick Dyer7bed6802014-05-18 23:04:09 -0700585 val, state);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700586 return -EINVAL;
587 }
588
589 return 0;
590}
591
Nick Dyer8efaa5e2014-07-23 12:45:49 -0700592static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700593{
Nick Dyerf28a8422014-05-18 23:10:49 -0700594 int ret;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700595 u8 buf[2];
596
Nick Dyer8efaa5e2014-07-23 12:45:49 -0700597 if (unlock) {
598 buf[0] = MXT_UNLOCK_CMD_LSB;
599 buf[1] = MXT_UNLOCK_CMD_MSB;
600 } else {
601 buf[0] = 0x01;
602 buf[1] = 0x01;
603 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700604
Nick Dyerf28a8422014-05-18 23:10:49 -0700605 ret = mxt_bootloader_write(data, buf, 2);
606 if (ret)
607 return ret;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700608
609 return 0;
610}
611
Iiro Valkonen7686b102011-02-02 23:21:58 -0800612static int __mxt_read_reg(struct i2c_client *client,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700613 u16 reg, u16 len, void *val)
614{
615 struct i2c_msg xfer[2];
616 u8 buf[2];
Daniel Kurtz771733e2012-06-28 21:08:11 +0800617 int ret;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700618
619 buf[0] = reg & 0xff;
620 buf[1] = (reg >> 8) & 0xff;
621
622 /* Write register */
623 xfer[0].addr = client->addr;
624 xfer[0].flags = 0;
625 xfer[0].len = 2;
626 xfer[0].buf = buf;
627
628 /* Read data */
629 xfer[1].addr = client->addr;
630 xfer[1].flags = I2C_M_RD;
631 xfer[1].len = len;
632 xfer[1].buf = val;
633
Daniel Kurtz771733e2012-06-28 21:08:11 +0800634 ret = i2c_transfer(client->adapter, xfer, 2);
635 if (ret == 2) {
636 ret = 0;
637 } else {
638 if (ret >= 0)
639 ret = -EIO;
640 dev_err(&client->dev, "%s: i2c transfer failed (%d)\n",
641 __func__, ret);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700642 }
643
Daniel Kurtz771733e2012-06-28 21:08:11 +0800644 return ret;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700645}
646
Daniel Kurtz9638ab72012-06-28 21:08:12 +0800647static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
648 const void *val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700649{
Daniel Kurtz9638ab72012-06-28 21:08:12 +0800650 u8 *buf;
651 size_t count;
Daniel Kurtz771733e2012-06-28 21:08:11 +0800652 int ret;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700653
Daniel Kurtz9638ab72012-06-28 21:08:12 +0800654 count = len + 2;
655 buf = kmalloc(count, GFP_KERNEL);
656 if (!buf)
657 return -ENOMEM;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700658
659 buf[0] = reg & 0xff;
660 buf[1] = (reg >> 8) & 0xff;
Daniel Kurtz9638ab72012-06-28 21:08:12 +0800661 memcpy(&buf[2], val, len);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700662
Daniel Kurtz9638ab72012-06-28 21:08:12 +0800663 ret = i2c_master_send(client, buf, count);
664 if (ret == count) {
Daniel Kurtz771733e2012-06-28 21:08:11 +0800665 ret = 0;
666 } else {
667 if (ret >= 0)
668 ret = -EIO;
669 dev_err(&client->dev, "%s: i2c send failed (%d)\n",
670 __func__, ret);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700671 }
672
Daniel Kurtz9638ab72012-06-28 21:08:12 +0800673 kfree(buf);
Daniel Kurtz771733e2012-06-28 21:08:11 +0800674 return ret;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700675}
676
Daniel Kurtz9638ab72012-06-28 21:08:12 +0800677static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700678{
Daniel Kurtz9638ab72012-06-28 21:08:12 +0800679 return __mxt_write_reg(client, reg, 1, &val);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700680}
681
Iiro Valkonen7686b102011-02-02 23:21:58 -0800682static struct mxt_object *
683mxt_get_object(struct mxt_data *data, u8 type)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700684{
Iiro Valkonen7686b102011-02-02 23:21:58 -0800685 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700686 int i;
687
688 for (i = 0; i < data->info.object_num; i++) {
689 object = data->object_table + i;
690 if (object->type == type)
691 return object;
692 }
693
Nick Dyer50a77c62014-07-23 12:38:48 -0700694 dev_warn(&data->client->dev, "Invalid object type T%u\n", type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700695 return NULL;
696}
697
Nick Dyer497767d2014-07-23 12:47:50 -0700698static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg)
699{
700 struct device *dev = &data->client->dev;
701 u8 status = msg[1];
702 u32 crc = msg[2] | (msg[3] << 8) | (msg[4] << 16);
703
704 complete(&data->crc_completion);
705
706 if (crc != data->config_crc) {
707 data->config_crc = crc;
708 dev_dbg(dev, "T6 Config Checksum: 0x%06X\n", crc);
709 }
710
711 /* Detect reset */
712 if (status & MXT_T6_STATUS_RESET)
713 complete(&data->reset_completion);
714
715 /* Output debug if status has changed */
716 if (status != data->t6_status)
717 dev_dbg(dev, "T6 Status 0x%02X%s%s%s%s%s%s%s\n",
718 status,
719 status == 0 ? " OK" : "",
720 status & MXT_T6_STATUS_RESET ? " RESET" : "",
721 status & MXT_T6_STATUS_OFL ? " OFL" : "",
722 status & MXT_T6_STATUS_SIGERR ? " SIGERR" : "",
723 status & MXT_T6_STATUS_CAL ? " CAL" : "",
724 status & MXT_T6_STATUS_CFGERR ? " CFGERR" : "",
725 status & MXT_T6_STATUS_COMSERR ? " COMSERR" : "");
726
727 /* Save current status */
728 data->t6_status = status;
729}
730
Linus Torvalds7f405482014-12-31 12:59:34 -0800731static int mxt_write_object(struct mxt_data *data,
732 u8 type, u8 offset, u8 val)
733{
734 struct mxt_object *object;
735 u16 reg;
736
737 object = mxt_get_object(data, type);
738 if (!object || offset >= mxt_obj_size(object))
739 return -EINVAL;
740
741 reg = object->start_address;
742 return mxt_write_reg(data->client, reg + offset, val);
743}
744
Nick Dyer5f3f9bc2014-07-23 12:46:55 -0700745static void mxt_input_button(struct mxt_data *data, u8 *message)
Daniel Kurtz22dfab72013-03-07 19:43:33 -0800746{
747 struct input_dev *input = data->input_dev;
Nick Dyerfb5e4c3e2014-05-18 23:00:15 -0700748 const struct mxt_platform_data *pdata = data->pdata;
Daniel Kurtz22dfab72013-03-07 19:43:33 -0800749 int i;
750
Nick Dyerfb5e4c3e2014-05-18 23:00:15 -0700751 for (i = 0; i < pdata->t19_num_keys; i++) {
752 if (pdata->t19_keymap[i] == KEY_RESERVED)
Daniel Kurtz22dfab72013-03-07 19:43:33 -0800753 continue;
Dmitry Torokhovc37f6d32015-04-15 10:31:10 -0700754
755 /* Active-low switch */
756 input_report_key(input, pdata->t19_keymap[i],
757 !(message[1] & BIT(i)));
Daniel Kurtz22dfab72013-03-07 19:43:33 -0800758 }
759}
760
Benson Leungb735fbe2014-07-23 12:22:27 -0700761static void mxt_input_sync(struct mxt_data *data)
Nick Dyereef820d2014-05-18 23:22:22 -0700762{
Benson Leungb735fbe2014-07-23 12:22:27 -0700763 input_mt_report_pointer_emulation(data->input_dev,
764 data->pdata->t19_num_keys);
765 input_sync(data->input_dev);
Nick Dyereef820d2014-05-18 23:22:22 -0700766}
767
Nick Dyerb9b05a82014-07-23 12:48:13 -0700768static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700769{
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700770 struct device *dev = &data->client->dev;
Daniel Kurtzfba5bc32012-06-28 21:08:17 +0800771 struct input_dev *input_dev = data->input_dev;
Nick Dyer5f3f9bc2014-07-23 12:46:55 -0700772 int id;
773 u8 status;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700774 int x;
775 int y;
776 int area;
Nick Dyerfea9e462014-05-18 23:21:48 -0700777 int amplitude;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700778
Nick Dyer5f3f9bc2014-07-23 12:46:55 -0700779 id = message[0] - data->T9_reportid_min;
780 status = message[1];
781 x = (message[2] << 4) | ((message[4] >> 4) & 0xf);
782 y = (message[3] << 4) | ((message[4] & 0xf));
Nick Dyereef820d2014-05-18 23:22:22 -0700783
784 /* Handle 10/12 bit switching */
Joonyoung Shim910d8052011-04-12 23:14:38 -0700785 if (data->max_x < 1024)
Nick Dyereef820d2014-05-18 23:22:22 -0700786 x >>= 2;
Joonyoung Shim910d8052011-04-12 23:14:38 -0700787 if (data->max_y < 1024)
Nick Dyereef820d2014-05-18 23:22:22 -0700788 y >>= 2;
Joonyoung Shim910d8052011-04-12 23:14:38 -0700789
Nick Dyer5f3f9bc2014-07-23 12:46:55 -0700790 area = message[5];
791 amplitude = message[6];
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700792
Daniel Kurtzb2e459b2012-06-28 21:08:18 +0800793 dev_dbg(dev,
794 "[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u\n",
795 id,
Nick Dyerf3889ed2014-05-18 23:22:04 -0700796 (status & MXT_T9_DETECT) ? 'D' : '.',
797 (status & MXT_T9_PRESS) ? 'P' : '.',
798 (status & MXT_T9_RELEASE) ? 'R' : '.',
799 (status & MXT_T9_MOVE) ? 'M' : '.',
800 (status & MXT_T9_VECTOR) ? 'V' : '.',
801 (status & MXT_T9_AMP) ? 'A' : '.',
802 (status & MXT_T9_SUPPRESS) ? 'S' : '.',
803 (status & MXT_T9_UNGRIP) ? 'U' : '.',
Nick Dyerfea9e462014-05-18 23:21:48 -0700804 x, y, area, amplitude);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700805
Daniel Kurtzfba5bc32012-06-28 21:08:17 +0800806 input_mt_slot(input_dev, id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700807
Nick Dyerf3889ed2014-05-18 23:22:04 -0700808 if (status & MXT_T9_DETECT) {
Nick Dyereef820d2014-05-18 23:22:22 -0700809 /*
810 * Multiple bits may be set if the host is slow to read
811 * the status messages, indicating all the events that
812 * have happened.
813 */
814 if (status & MXT_T9_RELEASE) {
815 input_mt_report_slot_state(input_dev,
816 MT_TOOL_FINGER, 0);
Benson Leungb735fbe2014-07-23 12:22:27 -0700817 mxt_input_sync(data);
Nick Dyereef820d2014-05-18 23:22:22 -0700818 }
819
820 /* Touch active */
821 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1);
Daniel Kurtzfba5bc32012-06-28 21:08:17 +0800822 input_report_abs(input_dev, ABS_MT_POSITION_X, x);
823 input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
Nick Dyerfea9e462014-05-18 23:21:48 -0700824 input_report_abs(input_dev, ABS_MT_PRESSURE, amplitude);
Daniel Kurtzfba5bc32012-06-28 21:08:17 +0800825 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, area);
Nick Dyereef820d2014-05-18 23:22:22 -0700826 } else {
827 /* Touch no longer active, close out slot */
828 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 0);
Daniel Kurtzfba5bc32012-06-28 21:08:17 +0800829 }
Nick Dyerb9b05a82014-07-23 12:48:13 -0700830
831 data->update_input = true;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -0700832}
833
Nick Dyerb23157d2015-04-06 11:25:13 -0700834static void mxt_proc_t100_message(struct mxt_data *data, u8 *message)
835{
836 struct device *dev = &data->client->dev;
837 struct input_dev *input_dev = data->input_dev;
838 int id;
839 u8 status;
840 u8 type = 0;
841 u16 x;
842 u16 y;
843 int distance = 0;
844 int tool = 0;
845 u8 major = 0;
846 u8 pressure = 0;
847 u8 orientation = 0;
848
849 id = message[0] - data->T100_reportid_min - 2;
850
851 /* ignore SCRSTATUS events */
852 if (id < 0)
853 return;
854
855 status = message[1];
856 x = get_unaligned_le16(&message[2]);
857 y = get_unaligned_le16(&message[4]);
858
859 if (status & MXT_T100_DETECT) {
860 type = (status & MXT_T100_TYPE_MASK) >> 4;
861
862 switch (type) {
863 case MXT_T100_TYPE_HOVERING_FINGER:
864 tool = MT_TOOL_FINGER;
865 distance = MXT_DISTANCE_HOVERING;
866
867 if (data->t100_aux_vect)
868 orientation = message[data->t100_aux_vect];
869
870 break;
871
872 case MXT_T100_TYPE_FINGER:
873 case MXT_T100_TYPE_GLOVE:
874 tool = MT_TOOL_FINGER;
875 distance = MXT_DISTANCE_ACTIVE_TOUCH;
876
877 if (data->t100_aux_area)
878 major = message[data->t100_aux_area];
879
880 if (data->t100_aux_ampl)
881 pressure = message[data->t100_aux_ampl];
882
883 if (data->t100_aux_vect)
884 orientation = message[data->t100_aux_vect];
885
886 break;
887
888 case MXT_T100_TYPE_PASSIVE_STYLUS:
889 tool = MT_TOOL_PEN;
890
891 /*
892 * Passive stylus is reported with size zero so
893 * hardcode.
894 */
895 major = MXT_TOUCH_MAJOR_DEFAULT;
896
897 if (data->t100_aux_ampl)
898 pressure = message[data->t100_aux_ampl];
899
900 break;
901
902 case MXT_T100_TYPE_LARGE_TOUCH:
903 /* Ignore suppressed touch */
904 break;
905
906 default:
907 dev_dbg(dev, "Unexpected T100 type\n");
908 return;
909 }
910 }
911
912 /*
913 * Values reported should be non-zero if tool is touching the
914 * device
915 */
916 if (!pressure && type != MXT_T100_TYPE_HOVERING_FINGER)
917 pressure = MXT_PRESSURE_DEFAULT;
918
919 input_mt_slot(input_dev, id);
920
921 if (status & MXT_T100_DETECT) {
922 dev_dbg(dev, "[%u] type:%u x:%u y:%u a:%02X p:%02X v:%02X\n",
923 id, type, x, y, major, pressure, orientation);
924
925 input_mt_report_slot_state(input_dev, tool, 1);
926 input_report_abs(input_dev, ABS_MT_POSITION_X, x);
927 input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
928 input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, major);
929 input_report_abs(input_dev, ABS_MT_PRESSURE, pressure);
930 input_report_abs(input_dev, ABS_MT_DISTANCE, distance);
931 input_report_abs(input_dev, ABS_MT_ORIENTATION, orientation);
932 } else {
933 dev_dbg(dev, "[%u] release\n", id);
934
935 /* close out slot */
936 input_mt_report_slot_state(input_dev, 0, 0);
937 }
938
939 data->update_input = true;
940}
941
Nick Dyerb9b05a82014-07-23 12:48:13 -0700942static int mxt_proc_message(struct mxt_data *data, u8 *message)
Daniel Kurtz04a79182012-06-28 21:08:21 +0800943{
Nick Dyerb9b05a82014-07-23 12:48:13 -0700944 u8 report_id = message[0];
945
946 if (report_id == MXT_RPTID_NOMSG)
947 return 0;
948
949 if (report_id == data->T6_reportid) {
950 mxt_proc_t6_messages(data, message);
951 } else if (!data->input_dev) {
952 /*
953 * Do not report events if input device
954 * is not yet registered.
955 */
956 mxt_dump_message(data, message);
Nick Dyerb23157d2015-04-06 11:25:13 -0700957 } else if (report_id >= data->T9_reportid_min &&
958 report_id <= data->T9_reportid_max) {
Nick Dyerb9b05a82014-07-23 12:48:13 -0700959 mxt_proc_t9_message(data, message);
Nick Dyerb23157d2015-04-06 11:25:13 -0700960 } else if (report_id >= data->T100_reportid_min &&
961 report_id <= data->T100_reportid_max) {
962 mxt_proc_t100_message(data, message);
Nick Dyerb9b05a82014-07-23 12:48:13 -0700963 } else if (report_id == data->T19_reportid) {
964 mxt_input_button(data, message);
965 data->update_input = true;
966 } else {
967 mxt_dump_message(data, message);
968 }
969
970 return 1;
971}
972
Nick Dyer9d8dc3e2014-07-23 12:49:04 -0700973static int mxt_read_and_process_messages(struct mxt_data *data, u8 count)
Nick Dyerb9b05a82014-07-23 12:48:13 -0700974{
975 struct device *dev = &data->client->dev;
976 int ret;
Nick Dyer9d8dc3e2014-07-23 12:49:04 -0700977 int i;
978 u8 num_valid = 0;
Nick Dyerb9b05a82014-07-23 12:48:13 -0700979
Nick Dyer9d8dc3e2014-07-23 12:49:04 -0700980 /* Safety check for msg_buf */
981 if (count > data->max_reportid)
982 return -EINVAL;
983
984 /* Process remaining messages if necessary */
Nick Dyerb9b05a82014-07-23 12:48:13 -0700985 ret = __mxt_read_reg(data->client, data->T5_address,
Nick Dyer9d8dc3e2014-07-23 12:49:04 -0700986 data->T5_msg_size * count, data->msg_buf);
Nick Dyerb9b05a82014-07-23 12:48:13 -0700987 if (ret) {
Nick Dyer9d8dc3e2014-07-23 12:49:04 -0700988 dev_err(dev, "Failed to read %u messages (%d)\n", count, ret);
Nick Dyerb9b05a82014-07-23 12:48:13 -0700989 return ret;
990 }
991
Nick Dyer9d8dc3e2014-07-23 12:49:04 -0700992 for (i = 0; i < count; i++) {
993 ret = mxt_proc_message(data,
994 data->msg_buf + data->T5_msg_size * i);
995
996 if (ret == 1)
997 num_valid++;
998 }
999
1000 /* return number of messages read */
1001 return num_valid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001002}
1003
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001004static irqreturn_t mxt_process_messages_t44(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001005{
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001006 struct device *dev = &data->client->dev;
Nick Dyerb9b05a82014-07-23 12:48:13 -07001007 int ret;
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001008 u8 count, num_left;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001009
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001010 /* Read T44 and T5 together */
1011 ret = __mxt_read_reg(data->client, data->T44_address,
1012 data->T5_msg_size + 1, data->msg_buf);
1013 if (ret) {
1014 dev_err(dev, "Failed to read T44 and T5 (%d)\n", ret);
1015 return IRQ_NONE;
1016 }
1017
1018 count = data->msg_buf[0];
1019
Nick Dyer507584e2015-08-04 16:58:05 -07001020 /*
1021 * This condition may be caused by the CHG line being configured in
1022 * Mode 0. It results in unnecessary I2C operations but it is benign.
1023 */
1024 if (count == 0)
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001025 return IRQ_NONE;
Nick Dyer507584e2015-08-04 16:58:05 -07001026
1027 if (count > data->max_reportid) {
1028 dev_warn(dev, "T44 count %d exceeded max report id\n", count);
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001029 count = data->max_reportid;
1030 }
1031
1032 /* Process first message */
1033 ret = mxt_proc_message(data, data->msg_buf + 1);
1034 if (ret < 0) {
1035 dev_warn(dev, "Unexpected invalid message\n");
1036 return IRQ_NONE;
1037 }
1038
1039 num_left = count - 1;
1040
1041 /* Process remaining messages if necessary */
1042 if (num_left) {
1043 ret = mxt_read_and_process_messages(data, num_left);
Nick Dyerb9b05a82014-07-23 12:48:13 -07001044 if (ret < 0)
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001045 goto end;
1046 else if (ret != num_left)
1047 dev_warn(dev, "Unexpected invalid message\n");
1048 }
1049
1050end:
1051 if (data->update_input) {
1052 mxt_input_sync(data);
1053 data->update_input = false;
1054 }
1055
1056 return IRQ_HANDLED;
1057}
1058
1059static int mxt_process_messages_until_invalid(struct mxt_data *data)
1060{
1061 struct device *dev = &data->client->dev;
1062 int count, read;
1063 u8 tries = 2;
1064
1065 count = data->max_reportid;
1066
1067 /* Read messages until we force an invalid */
1068 do {
1069 read = mxt_read_and_process_messages(data, count);
1070 if (read < count)
1071 return 0;
1072 } while (--tries);
1073
1074 if (data->update_input) {
1075 mxt_input_sync(data);
1076 data->update_input = false;
1077 }
1078
1079 dev_err(dev, "CHG pin isn't cleared\n");
1080 return -EBUSY;
1081}
1082
1083static irqreturn_t mxt_process_messages(struct mxt_data *data)
1084{
1085 int total_handled, num_handled;
1086 u8 count = data->last_message_count;
1087
1088 if (count < 1 || count > data->max_reportid)
1089 count = 1;
1090
1091 /* include final invalid message */
1092 total_handled = mxt_read_and_process_messages(data, count + 1);
1093 if (total_handled < 0)
1094 return IRQ_NONE;
1095 /* if there were invalid messages, then we are done */
1096 else if (total_handled <= count)
1097 goto update_count;
1098
1099 /* keep reading two msgs until one is invalid or reportid limit */
1100 do {
1101 num_handled = mxt_read_and_process_messages(data, 2);
1102 if (num_handled < 0)
Nick Dyer8d4e1632014-05-18 23:00:56 -07001103 return IRQ_NONE;
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001104
1105 total_handled += num_handled;
1106
1107 if (num_handled < 2)
1108 break;
1109 } while (total_handled < data->num_touchids);
1110
1111update_count:
1112 data->last_message_count = total_handled;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001113
Nick Dyerb9b05a82014-07-23 12:48:13 -07001114 if (data->update_input) {
Benson Leungb735fbe2014-07-23 12:22:27 -07001115 mxt_input_sync(data);
Nick Dyerb9b05a82014-07-23 12:48:13 -07001116 data->update_input = false;
1117 }
Daniel Kurtz64464ae2012-06-28 21:08:23 +08001118
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001119 return IRQ_HANDLED;
1120}
1121
Benson Leungd79e7e42014-05-18 23:02:52 -07001122static irqreturn_t mxt_interrupt(int irq, void *dev_id)
1123{
1124 struct mxt_data *data = dev_id;
1125
1126 if (data->in_bootloader) {
1127 /* bootloader state transition completion */
1128 complete(&data->bl_completion);
1129 return IRQ_HANDLED;
1130 }
1131
Nick Dyerdd24dcf2014-07-23 11:25:55 -07001132 if (!data->object_table)
1133 return IRQ_HANDLED;
1134
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001135 if (data->T44_address) {
1136 return mxt_process_messages_t44(data);
1137 } else {
1138 return mxt_process_messages(data);
1139 }
Benson Leungd79e7e42014-05-18 23:02:52 -07001140}
1141
Iiro Valkonena4a2ef42014-05-18 23:03:44 -07001142static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset,
1143 u8 value, bool wait)
1144{
1145 u16 reg;
1146 u8 command_register;
1147 int timeout_counter = 0;
1148 int ret;
1149
1150 reg = data->T6_address + cmd_offset;
1151
1152 ret = mxt_write_reg(data->client, reg, value);
1153 if (ret)
1154 return ret;
1155
1156 if (!wait)
1157 return 0;
1158
1159 do {
1160 msleep(20);
1161 ret = __mxt_read_reg(data->client, reg, 1, &command_register);
1162 if (ret)
1163 return ret;
1164 } while (command_register != 0 && timeout_counter++ <= 100);
1165
1166 if (timeout_counter > 100) {
1167 dev_err(&data->client->dev, "Command failed!\n");
1168 return -EIO;
1169 }
1170
1171 return 0;
1172}
1173
Nick Dyereb433352016-04-25 14:18:52 -07001174static int mxt_acquire_irq(struct mxt_data *data)
1175{
1176 int error;
1177
1178 enable_irq(data->irq);
1179
1180 error = mxt_process_messages_until_invalid(data);
1181 if (error)
1182 return error;
1183
1184 return 0;
1185}
1186
Iiro Valkonena4a2ef42014-05-18 23:03:44 -07001187static int mxt_soft_reset(struct mxt_data *data)
1188{
1189 struct device *dev = &data->client->dev;
1190 int ret = 0;
1191
Nick Dyer885f3fb2015-08-04 16:57:25 -07001192 dev_info(dev, "Resetting device\n");
1193
1194 disable_irq(data->irq);
Iiro Valkonena4a2ef42014-05-18 23:03:44 -07001195
1196 reinit_completion(&data->reset_completion);
1197
1198 ret = mxt_t6_command(data, MXT_COMMAND_RESET, MXT_RESET_VALUE, false);
1199 if (ret)
1200 return ret;
1201
Nick Dyer885f3fb2015-08-04 16:57:25 -07001202 /* Ignore CHG line for 100ms after reset */
1203 msleep(100);
1204
Nick Dyereb433352016-04-25 14:18:52 -07001205 mxt_acquire_irq(data);
Nick Dyer885f3fb2015-08-04 16:57:25 -07001206
Iiro Valkonena4a2ef42014-05-18 23:03:44 -07001207 ret = mxt_wait_for_completion(data, &data->reset_completion,
1208 MXT_RESET_TIMEOUT);
1209 if (ret)
1210 return ret;
1211
1212 return 0;
1213}
1214
Nick Dyerc3f78042014-05-18 23:04:46 -07001215static void mxt_update_crc(struct mxt_data *data, u8 cmd, u8 value)
1216{
1217 /*
1218 * On failure, CRC is set to 0 and config will always be
1219 * downloaded.
1220 */
1221 data->config_crc = 0;
1222 reinit_completion(&data->crc_completion);
1223
1224 mxt_t6_command(data, cmd, value, true);
1225
1226 /*
1227 * Wait for crc message. On failure, CRC is set to 0 and config will
1228 * always be downloaded.
1229 */
1230 mxt_wait_for_completion(data, &data->crc_completion, MXT_CRC_TIMEOUT);
1231}
1232
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001233static void mxt_calc_crc24(u32 *crc, u8 firstbyte, u8 secondbyte)
1234{
1235 static const unsigned int crcpoly = 0x80001B;
1236 u32 result;
1237 u32 data_word;
1238
1239 data_word = (secondbyte << 8) | firstbyte;
1240 result = ((*crc << 1) ^ data_word);
1241
1242 if (result & 0x1000000)
1243 result ^= crcpoly;
1244
1245 *crc = result;
1246}
1247
1248static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off)
1249{
1250 u32 crc = 0;
1251 u8 *ptr = base + start_off;
1252 u8 *last_val = base + end_off - 1;
1253
1254 if (end_off < start_off)
1255 return -EINVAL;
1256
1257 while (ptr < last_val) {
1258 mxt_calc_crc24(&crc, *ptr, *(ptr + 1));
1259 ptr += 2;
1260 }
1261
1262 /* if len is odd, fill the last byte with 0 */
1263 if (ptr == last_val)
1264 mxt_calc_crc24(&crc, *ptr, 0);
1265
1266 /* Mask to 24-bit */
1267 crc &= 0x00FFFFFF;
1268
1269 return crc;
1270}
1271
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001272static int mxt_prepare_cfg_mem(struct mxt_data *data,
1273 const struct firmware *cfg,
1274 unsigned int data_pos,
1275 unsigned int cfg_start_ofs,
1276 u8 *config_mem,
1277 size_t config_mem_size)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001278{
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001279 struct device *dev = &data->client->dev;
Nick Dyer50a77c62014-07-23 12:38:48 -07001280 struct mxt_object *object;
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001281 unsigned int type, instance, size, byte_offset;
Nick Dyer50a77c62014-07-23 12:38:48 -07001282 int offset;
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001283 int ret;
Nick Dyer50a77c62014-07-23 12:38:48 -07001284 int i;
Nick Dyer50a77c62014-07-23 12:38:48 -07001285 u16 reg;
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001286 u8 val;
Nick Dyer50a77c62014-07-23 12:38:48 -07001287
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001288 while (data_pos < cfg->size) {
Nick Dyer50a77c62014-07-23 12:38:48 -07001289 /* Read type, instance, length */
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001290 ret = sscanf(cfg->data + data_pos, "%x %x %x%n",
Nick Dyer50a77c62014-07-23 12:38:48 -07001291 &type, &instance, &size, &offset);
1292 if (ret == 0) {
1293 /* EOF */
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001294 break;
Nick Dyer50a77c62014-07-23 12:38:48 -07001295 } else if (ret != 3) {
1296 dev_err(dev, "Bad format: failed to parse object\n");
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001297 return -EINVAL;
Nick Dyer50a77c62014-07-23 12:38:48 -07001298 }
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001299 data_pos += offset;
Nick Dyer50a77c62014-07-23 12:38:48 -07001300
1301 object = mxt_get_object(data, type);
1302 if (!object) {
1303 /* Skip object */
1304 for (i = 0; i < size; i++) {
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001305 ret = sscanf(cfg->data + data_pos, "%hhx%n",
Dmitry Torokhov041fa152014-08-11 10:58:29 -07001306 &val, &offset);
1307 if (ret != 1) {
1308 dev_err(dev, "Bad format in T%d at %d\n",
1309 type, i);
1310 return -EINVAL;
1311 }
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001312 data_pos += offset;
Nick Dyer50a77c62014-07-23 12:38:48 -07001313 }
1314 continue;
1315 }
1316
1317 if (size > mxt_obj_size(object)) {
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001318 /*
1319 * Either we are in fallback mode due to wrong
1320 * config or config from a later fw version,
1321 * or the file is corrupt or hand-edited.
1322 */
1323 dev_warn(dev, "Discarding %zu byte(s) in T%u\n",
1324 size - mxt_obj_size(object), type);
1325 } else if (mxt_obj_size(object) > size) {
1326 /*
1327 * If firmware is upgraded, new bytes may be added to
1328 * end of objects. It is generally forward compatible
1329 * to zero these bytes - previous behaviour will be
1330 * retained. However this does invalidate the CRC and
1331 * will force fallback mode until the configuration is
1332 * updated. We warn here but do nothing else - the
1333 * malloc has zeroed the entire configuration.
1334 */
1335 dev_warn(dev, "Zeroing %zu byte(s) in T%d\n",
1336 mxt_obj_size(object) - size, type);
Nick Dyer50a77c62014-07-23 12:38:48 -07001337 }
1338
1339 if (instance >= mxt_obj_instances(object)) {
1340 dev_err(dev, "Object instances exceeded!\n");
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001341 return -EINVAL;
Nick Dyer50a77c62014-07-23 12:38:48 -07001342 }
1343
1344 reg = object->start_address + mxt_obj_size(object) * instance;
1345
1346 for (i = 0; i < size; i++) {
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001347 ret = sscanf(cfg->data + data_pos, "%hhx%n",
Nick Dyer50a77c62014-07-23 12:38:48 -07001348 &val,
1349 &offset);
1350 if (ret != 1) {
Dmitry Torokhov041fa152014-08-11 10:58:29 -07001351 dev_err(dev, "Bad format in T%d at %d\n",
1352 type, i);
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001353 return -EINVAL;
Nick Dyer50a77c62014-07-23 12:38:48 -07001354 }
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001355 data_pos += offset;
Nick Dyer50a77c62014-07-23 12:38:48 -07001356
1357 if (i > mxt_obj_size(object))
1358 continue;
1359
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001360 byte_offset = reg + i - cfg_start_ofs;
Nick Dyer50a77c62014-07-23 12:38:48 -07001361
Dmitry Torokhov041fa152014-08-11 10:58:29 -07001362 if (byte_offset >= 0 && byte_offset < config_mem_size) {
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001363 *(config_mem + byte_offset) = val;
1364 } else {
1365 dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n",
1366 reg, object->type, byte_offset);
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001367 return -EINVAL;
Nick Dyer50a77c62014-07-23 12:38:48 -07001368 }
1369 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001370 }
1371
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001372 return 0;
1373}
1374
1375static int mxt_upload_cfg_mem(struct mxt_data *data, unsigned int cfg_start,
1376 u8 *config_mem, size_t config_mem_size)
1377{
1378 unsigned int byte_offset = 0;
1379 int error;
1380
1381 /* Write configuration as blocks */
1382 while (byte_offset < config_mem_size) {
1383 unsigned int size = config_mem_size - byte_offset;
1384
1385 if (size > MXT_MAX_BLOCK_WRITE)
1386 size = MXT_MAX_BLOCK_WRITE;
1387
1388 error = __mxt_write_reg(data->client,
1389 cfg_start + byte_offset,
1390 size, config_mem + byte_offset);
1391 if (error) {
1392 dev_err(&data->client->dev,
1393 "Config write error, ret=%d\n", error);
1394 return error;
1395 }
1396
1397 byte_offset += size;
1398 }
1399
1400 return 0;
1401}
1402
Nick Dyer7f3884f72015-08-04 16:36:29 -07001403static int mxt_init_t7_power_cfg(struct mxt_data *data);
1404
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001405/*
1406 * mxt_update_cfg - download configuration to chip
1407 *
1408 * Atmel Raw Config File Format
1409 *
1410 * The first four lines of the raw config file contain:
1411 * 1) Version
1412 * 2) Chip ID Information (first 7 bytes of device memory)
1413 * 3) Chip Information Block 24-bit CRC Checksum
1414 * 4) Chip Configuration 24-bit CRC Checksum
1415 *
1416 * The rest of the file consists of one line per object instance:
1417 * <TYPE> <INSTANCE> <SIZE> <CONTENTS>
1418 *
1419 * <TYPE> - 2-byte object type as hex
1420 * <INSTANCE> - 2-byte object instance number as hex
1421 * <SIZE> - 2-byte object size as hex
1422 * <CONTENTS> - array of <SIZE> 1-byte hex values
1423 */
1424static int mxt_update_cfg(struct mxt_data *data, const struct firmware *cfg)
1425{
1426 struct device *dev = &data->client->dev;
1427 struct mxt_info cfg_info;
1428 int ret;
1429 int offset;
1430 int data_pos;
1431 int i;
1432 int cfg_start_ofs;
1433 u32 info_crc, config_crc, calculated_crc;
1434 u8 *config_mem;
1435 size_t config_mem_size;
1436
1437 mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1);
1438
1439 if (strncmp(cfg->data, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) {
1440 dev_err(dev, "Unrecognised config file\n");
1441 return -EINVAL;
1442 }
1443
1444 data_pos = strlen(MXT_CFG_MAGIC);
1445
1446 /* Load information block and check */
1447 for (i = 0; i < sizeof(struct mxt_info); i++) {
1448 ret = sscanf(cfg->data + data_pos, "%hhx%n",
1449 (unsigned char *)&cfg_info + i,
1450 &offset);
1451 if (ret != 1) {
1452 dev_err(dev, "Bad format\n");
1453 return -EINVAL;
1454 }
1455
1456 data_pos += offset;
1457 }
1458
1459 if (cfg_info.family_id != data->info.family_id) {
1460 dev_err(dev, "Family ID mismatch!\n");
1461 return -EINVAL;
1462 }
1463
1464 if (cfg_info.variant_id != data->info.variant_id) {
1465 dev_err(dev, "Variant ID mismatch!\n");
1466 return -EINVAL;
1467 }
1468
1469 /* Read CRCs */
1470 ret = sscanf(cfg->data + data_pos, "%x%n", &info_crc, &offset);
1471 if (ret != 1) {
1472 dev_err(dev, "Bad format: failed to parse Info CRC\n");
1473 return -EINVAL;
1474 }
1475 data_pos += offset;
1476
1477 ret = sscanf(cfg->data + data_pos, "%x%n", &config_crc, &offset);
1478 if (ret != 1) {
1479 dev_err(dev, "Bad format: failed to parse Config CRC\n");
1480 return -EINVAL;
1481 }
1482 data_pos += offset;
1483
1484 /*
1485 * The Info Block CRC is calculated over mxt_info and the object
1486 * table. If it does not match then we are trying to load the
1487 * configuration from a different chip or firmware version, so
1488 * the configuration CRC is invalid anyway.
1489 */
1490 if (info_crc == data->info_crc) {
1491 if (config_crc == 0 || data->config_crc == 0) {
1492 dev_info(dev, "CRC zero, attempting to apply config\n");
1493 } else if (config_crc == data->config_crc) {
1494 dev_dbg(dev, "Config CRC 0x%06X: OK\n",
1495 data->config_crc);
1496 return 0;
1497 } else {
1498 dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n",
1499 data->config_crc, config_crc);
1500 }
1501 } else {
1502 dev_warn(dev,
1503 "Warning: Info CRC error - device=0x%06X file=0x%06X\n",
1504 data->info_crc, info_crc);
1505 }
1506
1507 /* Malloc memory to store configuration */
1508 cfg_start_ofs = MXT_OBJECT_START +
1509 data->info.object_num * sizeof(struct mxt_object) +
1510 MXT_INFO_CHECKSUM_SIZE;
1511 config_mem_size = data->mem_size - cfg_start_ofs;
1512 config_mem = kzalloc(config_mem_size, GFP_KERNEL);
1513 if (!config_mem) {
1514 dev_err(dev, "Failed to allocate memory\n");
1515 return -ENOMEM;
1516 }
1517
1518 ret = mxt_prepare_cfg_mem(data, cfg, data_pos, cfg_start_ofs,
1519 config_mem, config_mem_size);
1520 if (ret)
1521 goto release_mem;
1522
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001523 /* Calculate crc of the received configs (not the raw config file) */
1524 if (data->T7_address < cfg_start_ofs) {
1525 dev_err(dev, "Bad T7 address, T7addr = %x, config offset %x\n",
1526 data->T7_address, cfg_start_ofs);
1527 ret = 0;
1528 goto release_mem;
1529 }
1530
1531 calculated_crc = mxt_calculate_crc(config_mem,
1532 data->T7_address - cfg_start_ofs,
1533 config_mem_size);
1534
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001535 if (config_crc > 0 && config_crc != calculated_crc)
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001536 dev_warn(dev, "Config CRC error, calculated=%06X, file=%06X\n",
1537 calculated_crc, config_crc);
1538
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07001539 ret = mxt_upload_cfg_mem(data, cfg_start_ofs,
1540 config_mem, config_mem_size);
1541 if (ret)
1542 goto release_mem;
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001543
Nick Dyerc3f78042014-05-18 23:04:46 -07001544 mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
1545
1546 ret = mxt_soft_reset(data);
1547 if (ret)
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001548 goto release_mem;
Nick Dyerc3f78042014-05-18 23:04:46 -07001549
1550 dev_info(dev, "Config successfully updated\n");
1551
Nick Dyer7f3884f72015-08-04 16:36:29 -07001552 /* T7 config may have changed */
1553 mxt_init_t7_power_cfg(data);
1554
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001555release_mem:
1556 kfree(config_mem);
Nick Dyer50a77c62014-07-23 12:38:48 -07001557 return ret;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001558}
1559
Iiro Valkonen7686b102011-02-02 23:21:58 -08001560static int mxt_get_info(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001561{
1562 struct i2c_client *client = data->client;
Iiro Valkonen7686b102011-02-02 23:21:58 -08001563 struct mxt_info *info = &data->info;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001564 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001565
Daniel Kurtz23003a842012-06-28 21:08:14 +08001566 /* Read 7-byte info block starting at address 0 */
Nick Dyer146c6a62015-08-04 16:49:34 -07001567 error = __mxt_read_reg(client, 0, sizeof(*info), info);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001568 if (error)
1569 return error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001570
1571 return 0;
1572}
1573
Stephen Warren58e4aeee2014-09-10 10:01:10 -07001574static void mxt_free_input_device(struct mxt_data *data)
1575{
1576 if (data->input_dev) {
1577 input_unregister_device(data->input_dev);
1578 data->input_dev = NULL;
1579 }
1580}
1581
Nick Dyer5f3f9bc2014-07-23 12:46:55 -07001582static void mxt_free_object_table(struct mxt_data *data)
1583{
Nick Dyerecfdd7e2016-07-18 18:10:32 -03001584#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37
1585 video_unregister_device(&data->dbg.vdev);
1586 v4l2_device_unregister(&data->dbg.v4l2);
1587#endif
1588
Nick Dyer5f3f9bc2014-07-23 12:46:55 -07001589 kfree(data->object_table);
1590 data->object_table = NULL;
1591 kfree(data->msg_buf);
1592 data->msg_buf = NULL;
Nick Dyerb9b05a82014-07-23 12:48:13 -07001593 data->T5_address = 0;
Nick Dyer5f3f9bc2014-07-23 12:46:55 -07001594 data->T5_msg_size = 0;
1595 data->T6_reportid = 0;
1596 data->T7_address = 0;
1597 data->T9_reportid_min = 0;
1598 data->T9_reportid_max = 0;
1599 data->T19_reportid = 0;
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001600 data->T44_address = 0;
Nick Dyerb23157d2015-04-06 11:25:13 -07001601 data->T100_reportid_min = 0;
1602 data->T100_reportid_max = 0;
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001603 data->max_reportid = 0;
Nick Dyer5f3f9bc2014-07-23 12:46:55 -07001604}
1605
Iiro Valkonen7686b102011-02-02 23:21:58 -08001606static int mxt_get_object_table(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001607{
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001608 struct i2c_client *client = data->client;
1609 size_t table_size;
Nick Dyerdd24dcf2014-07-23 11:25:55 -07001610 struct mxt_object *object_table;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001611 int error;
1612 int i;
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001613 u8 reportid;
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001614 u16 end_address;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001615
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001616 table_size = data->info.object_num * sizeof(struct mxt_object);
Nick Dyerdd24dcf2014-07-23 11:25:55 -07001617 object_table = kzalloc(table_size, GFP_KERNEL);
1618 if (!object_table) {
1619 dev_err(&data->client->dev, "Failed to allocate memory\n");
1620 return -ENOMEM;
1621 }
1622
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001623 error = __mxt_read_reg(client, MXT_OBJECT_START, table_size,
Nick Dyerdd24dcf2014-07-23 11:25:55 -07001624 object_table);
1625 if (error) {
1626 kfree(object_table);
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001627 return error;
Nick Dyerdd24dcf2014-07-23 11:25:55 -07001628 }
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001629
1630 /* Valid Report IDs start counting from 1 */
1631 reportid = 1;
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001632 data->mem_size = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001633 for (i = 0; i < data->info.object_num; i++) {
Nick Dyerdd24dcf2014-07-23 11:25:55 -07001634 struct mxt_object *object = object_table + i;
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001635 u8 min_id, max_id;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001636
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001637 le16_to_cpus(&object->start_address);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001638
1639 if (object->num_report_ids) {
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001640 min_id = reportid;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001641 reportid += object->num_report_ids *
Daniel Kurtz1e0c0c52014-05-18 23:01:12 -07001642 mxt_obj_instances(object);
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001643 max_id = reportid - 1;
1644 } else {
1645 min_id = 0;
1646 max_id = 0;
1647 }
1648
1649 dev_dbg(&data->client->dev,
Nick Dyer7bed6802014-05-18 23:04:09 -07001650 "T%u Start:%u Size:%zu Instances:%zu Report IDs:%u-%u\n",
Daniel Kurtz1e0c0c52014-05-18 23:01:12 -07001651 object->type, object->start_address,
1652 mxt_obj_size(object), mxt_obj_instances(object),
1653 min_id, max_id);
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001654
1655 switch (object->type) {
Nick Dyer5f3f9bc2014-07-23 12:46:55 -07001656 case MXT_GEN_MESSAGE_T5:
Nick Dyer437d4f32014-08-07 09:56:01 -07001657 if (data->info.family_id == 0x80 &&
1658 data->info.version < 0x20) {
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001659 /*
Nick Dyer437d4f32014-08-07 09:56:01 -07001660 * On mXT224 firmware versions prior to V2.0
1661 * read and discard unused CRC byte otherwise
1662 * DMA reads are misaligned.
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001663 */
1664 data->T5_msg_size = mxt_obj_size(object);
1665 } else {
1666 /* CRC not enabled, so skip last byte */
1667 data->T5_msg_size = mxt_obj_size(object) - 1;
1668 }
Nick Dyerb9b05a82014-07-23 12:48:13 -07001669 data->T5_address = object->start_address;
Dmitry Torokhov041fa152014-08-11 10:58:29 -07001670 break;
Daniel Kurtzfdf804212012-06-28 21:08:24 +08001671 case MXT_GEN_COMMAND_T6:
1672 data->T6_reportid = min_id;
Iiro Valkonena4a2ef42014-05-18 23:03:44 -07001673 data->T6_address = object->start_address;
Daniel Kurtzfdf804212012-06-28 21:08:24 +08001674 break;
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001675 case MXT_GEN_POWER_T7:
1676 data->T7_address = object->start_address;
1677 break;
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001678 case MXT_TOUCH_MULTI_T9:
Nick Dyerb23157d2015-04-06 11:25:13 -07001679 data->multitouch = MXT_TOUCH_MULTI_T9;
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001680 data->T9_reportid_min = min_id;
1681 data->T9_reportid_max = max_id;
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001682 data->num_touchids = object->num_report_ids
1683 * mxt_obj_instances(object);
1684 break;
1685 case MXT_SPT_MESSAGECOUNT_T44:
1686 data->T44_address = object->start_address;
Daniel Kurtz333e5a92012-06-28 21:08:20 +08001687 break;
Daniel Kurtz22dfab72013-03-07 19:43:33 -08001688 case MXT_SPT_GPIOPWM_T19:
1689 data->T19_reportid = min_id;
1690 break;
Nick Dyerb23157d2015-04-06 11:25:13 -07001691 case MXT_TOUCH_MULTITOUCHSCREEN_T100:
1692 data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100;
1693 data->T100_reportid_min = min_id;
1694 data->T100_reportid_max = max_id;
1695 /* first two report IDs reserved */
1696 data->num_touchids = object->num_report_ids - 2;
1697 break;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001698 }
Nick Dyer4ce6fa02014-07-23 12:40:09 -07001699
1700 end_address = object->start_address
1701 + mxt_obj_size(object) * mxt_obj_instances(object) - 1;
1702
1703 if (end_address >= data->mem_size)
1704 data->mem_size = end_address + 1;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001705 }
1706
Nick Dyer9d8dc3e2014-07-23 12:49:04 -07001707 /* Store maximum reportid */
1708 data->max_reportid = reportid;
1709
1710 /* If T44 exists, T5 position has to be directly after */
1711 if (data->T44_address && (data->T5_address != data->T44_address + 1)) {
1712 dev_err(&client->dev, "Invalid T44 position\n");
1713 error = -EINVAL;
1714 goto free_object_table;
1715 }
1716
1717 data->msg_buf = kcalloc(data->max_reportid,
1718 data->T5_msg_size, GFP_KERNEL);
Nick Dyer5f3f9bc2014-07-23 12:46:55 -07001719 if (!data->msg_buf) {
1720 dev_err(&client->dev, "Failed to allocate message buffer\n");
1721 error = -ENOMEM;
1722 goto free_object_table;
1723 }
1724
Nick Dyerdd24dcf2014-07-23 11:25:55 -07001725 data->object_table = object_table;
1726
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001727 return 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07001728
Nick Dyer5f3f9bc2014-07-23 12:46:55 -07001729free_object_table:
1730 mxt_free_object_table(data);
1731 return error;
Daniel Kurtz7d4fa102012-06-28 21:08:19 +08001732}
1733
Nick Dyer61dc1ab2014-05-18 23:16:49 -07001734static int mxt_read_t9_resolution(struct mxt_data *data)
1735{
1736 struct i2c_client *client = data->client;
1737 int error;
1738 struct t9_range range;
1739 unsigned char orient;
1740 struct mxt_object *object;
1741
1742 object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1743 if (!object)
1744 return -EINVAL;
1745
1746 error = __mxt_read_reg(client,
Nick Dyer27864892016-07-18 18:10:33 -03001747 object->start_address + MXT_T9_XSIZE,
1748 sizeof(data->xsize), &data->xsize);
1749 if (error)
1750 return error;
1751
1752 error = __mxt_read_reg(client,
1753 object->start_address + MXT_T9_YSIZE,
1754 sizeof(data->ysize), &data->ysize);
1755 if (error)
1756 return error;
1757
1758 error = __mxt_read_reg(client,
Nick Dyer61dc1ab2014-05-18 23:16:49 -07001759 object->start_address + MXT_T9_RANGE,
1760 sizeof(range), &range);
1761 if (error)
1762 return error;
1763
Nick Dyer1c0276d2016-01-10 18:29:34 -08001764 data->max_x = get_unaligned_le16(&range.x);
1765 data->max_y = get_unaligned_le16(&range.y);
Nick Dyer61dc1ab2014-05-18 23:16:49 -07001766
1767 error = __mxt_read_reg(client,
1768 object->start_address + MXT_T9_ORIENT,
1769 1, &orient);
1770 if (error)
1771 return error;
1772
Nick Dyer1c0276d2016-01-10 18:29:34 -08001773 data->xy_switch = orient & MXT_T9_ORIENT_SWITCH;
Nick Dyerde601f72016-07-18 18:10:34 -03001774 data->invertx = orient & MXT_T9_ORIENT_INVERTX;
1775 data->inverty = orient & MXT_T9_ORIENT_INVERTY;
Nick Dyer61dc1ab2014-05-18 23:16:49 -07001776
1777 return 0;
1778}
1779
Nick Dyerb23157d2015-04-06 11:25:13 -07001780static int mxt_read_t100_config(struct mxt_data *data)
1781{
1782 struct i2c_client *client = data->client;
1783 int error;
1784 struct mxt_object *object;
1785 u16 range_x, range_y;
1786 u8 cfg, tchaux;
1787 u8 aux;
1788
1789 object = mxt_get_object(data, MXT_TOUCH_MULTITOUCHSCREEN_T100);
1790 if (!object)
1791 return -EINVAL;
1792
Nick Dyer1c0276d2016-01-10 18:29:34 -08001793 /* read touchscreen dimensions */
Nick Dyerb23157d2015-04-06 11:25:13 -07001794 error = __mxt_read_reg(client,
1795 object->start_address + MXT_T100_XRANGE,
1796 sizeof(range_x), &range_x);
1797 if (error)
1798 return error;
1799
Nick Dyer1c0276d2016-01-10 18:29:34 -08001800 data->max_x = get_unaligned_le16(&range_x);
Nick Dyerb23157d2015-04-06 11:25:13 -07001801
1802 error = __mxt_read_reg(client,
1803 object->start_address + MXT_T100_YRANGE,
1804 sizeof(range_y), &range_y);
1805 if (error)
1806 return error;
1807
Nick Dyer1c0276d2016-01-10 18:29:34 -08001808 data->max_y = get_unaligned_le16(&range_y);
Nick Dyerb23157d2015-04-06 11:25:13 -07001809
Nick Dyer27864892016-07-18 18:10:33 -03001810 error = __mxt_read_reg(client,
1811 object->start_address + MXT_T100_XSIZE,
1812 sizeof(data->xsize), &data->xsize);
1813 if (error)
1814 return error;
1815
1816 error = __mxt_read_reg(client,
1817 object->start_address + MXT_T100_YSIZE,
1818 sizeof(data->ysize), &data->ysize);
1819 if (error)
1820 return error;
1821
Nick Dyer1c0276d2016-01-10 18:29:34 -08001822 /* read orientation config */
Nick Dyerb23157d2015-04-06 11:25:13 -07001823 error = __mxt_read_reg(client,
1824 object->start_address + MXT_T100_CFG1,
1825 1, &cfg);
1826 if (error)
1827 return error;
1828
Nick Dyer1c0276d2016-01-10 18:29:34 -08001829 data->xy_switch = cfg & MXT_T100_CFG_SWITCHXY;
Nick Dyerde601f72016-07-18 18:10:34 -03001830 data->invertx = cfg & MXT_T100_CFG_INVERTX;
1831 data->inverty = cfg & MXT_T100_CFG_INVERTY;
Nick Dyer1c0276d2016-01-10 18:29:34 -08001832
1833 /* allocate aux bytes */
Nick Dyerb23157d2015-04-06 11:25:13 -07001834 error = __mxt_read_reg(client,
1835 object->start_address + MXT_T100_TCHAUX,
1836 1, &tchaux);
1837 if (error)
1838 return error;
1839
Nick Dyerb23157d2015-04-06 11:25:13 -07001840 aux = 6;
1841
1842 if (tchaux & MXT_T100_TCHAUX_VECT)
1843 data->t100_aux_vect = aux++;
1844
1845 if (tchaux & MXT_T100_TCHAUX_AMPL)
1846 data->t100_aux_ampl = aux++;
1847
1848 if (tchaux & MXT_T100_TCHAUX_AREA)
1849 data->t100_aux_area = aux++;
1850
1851 dev_dbg(&client->dev,
1852 "T100 aux mappings vect:%u ampl:%u area:%u\n",
1853 data->t100_aux_vect, data->t100_aux_ampl, data->t100_aux_area);
1854
Nick Dyerb23157d2015-04-06 11:25:13 -07001855 return 0;
1856}
1857
Nick Dyer7a53d602014-07-23 12:21:26 -07001858static int mxt_input_open(struct input_dev *dev);
1859static void mxt_input_close(struct input_dev *dev);
1860
Sjoerd Simonsb6d2d322015-04-06 13:10:30 -07001861static void mxt_set_up_as_touchpad(struct input_dev *input_dev,
1862 struct mxt_data *data)
1863{
1864 const struct mxt_platform_data *pdata = data->pdata;
1865 int i;
1866
1867 input_dev->name = "Atmel maXTouch Touchpad";
1868
1869 __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
1870
1871 input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM);
1872 input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM);
1873 input_abs_set_res(input_dev, ABS_MT_POSITION_X,
1874 MXT_PIXELS_PER_MM);
1875 input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
1876 MXT_PIXELS_PER_MM);
1877
1878 for (i = 0; i < pdata->t19_num_keys; i++)
1879 if (pdata->t19_keymap[i] != KEY_RESERVED)
1880 input_set_capability(input_dev, EV_KEY,
1881 pdata->t19_keymap[i]);
1882}
1883
Nick Dyerb23157d2015-04-06 11:25:13 -07001884static int mxt_initialize_input_device(struct mxt_data *data)
Nick Dyer7a53d602014-07-23 12:21:26 -07001885{
Nick Dyer7a53d602014-07-23 12:21:26 -07001886 const struct mxt_platform_data *pdata = data->pdata;
Sjoerd Simonsb6d2d322015-04-06 13:10:30 -07001887 struct device *dev = &data->client->dev;
Nick Dyer7a53d602014-07-23 12:21:26 -07001888 struct input_dev *input_dev;
1889 int error;
1890 unsigned int num_mt_slots;
1891 unsigned int mt_flags = 0;
Nick Dyer7a53d602014-07-23 12:21:26 -07001892
Nick Dyerb23157d2015-04-06 11:25:13 -07001893 switch (data->multitouch) {
1894 case MXT_TOUCH_MULTI_T9:
1895 num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
1896 error = mxt_read_t9_resolution(data);
1897 if (error)
1898 dev_warn(dev, "Failed to initialize T9 resolution\n");
1899 break;
1900
1901 case MXT_TOUCH_MULTITOUCHSCREEN_T100:
1902 num_mt_slots = data->num_touchids;
1903 error = mxt_read_t100_config(data);
1904 if (error)
1905 dev_warn(dev, "Failed to read T100 config\n");
1906 break;
1907
1908 default:
1909 dev_err(dev, "Invalid multitouch object\n");
1910 return -EINVAL;
1911 }
Nick Dyer7a53d602014-07-23 12:21:26 -07001912
Nick Dyer1c0276d2016-01-10 18:29:34 -08001913 /* Handle default values and orientation switch */
1914 if (data->max_x == 0)
1915 data->max_x = 1023;
1916
1917 if (data->max_y == 0)
1918 data->max_y = 1023;
1919
1920 if (data->xy_switch)
1921 swap(data->max_x, data->max_y);
1922
1923 dev_info(dev, "Touchscreen size X%uY%u\n", data->max_x, data->max_y);
1924
1925 /* Register input device */
Nick Dyer7a53d602014-07-23 12:21:26 -07001926 input_dev = input_allocate_device();
1927 if (!input_dev) {
1928 dev_err(dev, "Failed to allocate memory\n");
1929 return -ENOMEM;
1930 }
1931
1932 input_dev->name = "Atmel maXTouch Touchscreen";
1933 input_dev->phys = data->phys;
1934 input_dev->id.bustype = BUS_I2C;
1935 input_dev->dev.parent = dev;
1936 input_dev->open = mxt_input_open;
1937 input_dev->close = mxt_input_close;
1938
Nick Dyerb23157d2015-04-06 11:25:13 -07001939 input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
Nick Dyer7a53d602014-07-23 12:21:26 -07001940
Nick Dyer7a53d602014-07-23 12:21:26 -07001941 /* For single touch */
Nick Dyerb23157d2015-04-06 11:25:13 -07001942 input_set_abs_params(input_dev, ABS_X, 0, data->max_x, 0, 0);
1943 input_set_abs_params(input_dev, ABS_Y, 0, data->max_y, 0, 0);
1944
1945 if (data->multitouch == MXT_TOUCH_MULTI_T9 ||
1946 (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
1947 data->t100_aux_ampl)) {
1948 input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
1949 }
Nick Dyer7a53d602014-07-23 12:21:26 -07001950
Sjoerd Simonsb6d2d322015-04-06 13:10:30 -07001951 /* If device has buttons we assume it is a touchpad */
1952 if (pdata->t19_num_keys) {
1953 mxt_set_up_as_touchpad(input_dev, data);
1954 mt_flags |= INPUT_MT_POINTER;
Nick Dyereafc0c82015-08-04 16:57:40 -07001955 } else {
1956 mt_flags |= INPUT_MT_DIRECT;
Sjoerd Simonsb6d2d322015-04-06 13:10:30 -07001957 }
1958
Nick Dyer7a53d602014-07-23 12:21:26 -07001959 /* For multi touch */
Nick Dyer7a53d602014-07-23 12:21:26 -07001960 error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags);
1961 if (error) {
1962 dev_err(dev, "Error %d initialising slots\n", error);
1963 goto err_free_mem;
1964 }
1965
Nick Dyerb23157d2015-04-06 11:25:13 -07001966 if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) {
1967 input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
1968 0, MT_TOOL_MAX, 0, 0);
1969 input_set_abs_params(input_dev, ABS_MT_DISTANCE,
1970 MXT_DISTANCE_ACTIVE_TOUCH,
1971 MXT_DISTANCE_HOVERING,
1972 0, 0);
1973 }
1974
Nick Dyer7a53d602014-07-23 12:21:26 -07001975 input_set_abs_params(input_dev, ABS_MT_POSITION_X,
1976 0, data->max_x, 0, 0);
1977 input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
1978 0, data->max_y, 0, 0);
Nick Dyerb23157d2015-04-06 11:25:13 -07001979
1980 if (data->multitouch == MXT_TOUCH_MULTI_T9 ||
1981 (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
1982 data->t100_aux_area)) {
1983 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
1984 0, MXT_MAX_AREA, 0, 0);
1985 }
1986
1987 if (data->multitouch == MXT_TOUCH_MULTI_T9 ||
1988 (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
1989 data->t100_aux_ampl)) {
1990 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
1991 0, 255, 0, 0);
1992 }
1993
1994 if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
1995 data->t100_aux_vect) {
1996 input_set_abs_params(input_dev, ABS_MT_ORIENTATION,
1997 0, 255, 0, 0);
1998 }
1999
2000 if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
2001 data->t100_aux_ampl) {
2002 input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2003 0, 255, 0, 0);
2004 }
2005
2006 if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
2007 data->t100_aux_vect) {
2008 input_set_abs_params(input_dev, ABS_MT_ORIENTATION,
2009 0, 255, 0, 0);
2010 }
Nick Dyer7a53d602014-07-23 12:21:26 -07002011
2012 input_set_drvdata(input_dev, data);
2013
2014 error = input_register_device(input_dev);
2015 if (error) {
2016 dev_err(dev, "Error %d registering input device\n", error);
2017 goto err_free_mem;
2018 }
2019
2020 data->input_dev = input_dev;
2021
2022 return 0;
2023
2024err_free_mem:
2025 input_free_device(input_dev);
2026 return error;
2027}
2028
Nick Dyer50a77c62014-07-23 12:38:48 -07002029static int mxt_configure_objects(struct mxt_data *data,
2030 const struct firmware *cfg);
2031
2032static void mxt_config_cb(const struct firmware *cfg, void *ctx)
2033{
2034 mxt_configure_objects(ctx, cfg);
Dmitry Torokhovefdbd7a2014-08-08 09:29:06 -07002035 release_firmware(cfg);
Nick Dyer50a77c62014-07-23 12:38:48 -07002036}
2037
Iiro Valkonen7686b102011-02-02 23:21:58 -08002038static int mxt_initialize(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002039{
2040 struct i2c_client *client = data->client;
Dmitry Torokhov6cd1ab02014-08-08 09:28:45 -07002041 int recovery_attempts = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002042 int error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002043
Dmitry Torokhov6cd1ab02014-08-08 09:28:45 -07002044 while (1) {
2045 error = mxt_get_info(data);
2046 if (!error)
2047 break;
2048
2049 /* Check bootloader state */
2050 error = mxt_probe_bootloader(data, false);
Nick Dyer8efaa5e2014-07-23 12:45:49 -07002051 if (error) {
Dmitry Torokhov6cd1ab02014-08-08 09:28:45 -07002052 dev_info(&client->dev, "Trying alternate bootloader address\n");
2053 error = mxt_probe_bootloader(data, true);
2054 if (error) {
Nick Dyer8efaa5e2014-07-23 12:45:49 -07002055 /* Chip is not in appmode or bootloader mode */
2056 return error;
2057 }
Nick Dyer8efaa5e2014-07-23 12:45:49 -07002058 }
Dmitry Torokhov6cd1ab02014-08-08 09:28:45 -07002059
2060 /* OK, we are in bootloader, see if we can recover */
2061 if (++recovery_attempts > 1) {
2062 dev_err(&client->dev, "Could not recover from bootloader mode\n");
2063 /*
2064 * We can reflash from this state, so do not
2065 * abort initialization.
2066 */
2067 data->in_bootloader = true;
2068 return 0;
2069 }
2070
2071 /* Attempt to exit bootloader into app mode */
2072 mxt_send_bootloader_cmd(data, false);
2073 msleep(MXT_FW_RESET_TIME);
Nick Dyera9fdd1e2014-07-23 12:41:58 -07002074 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002075
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002076 /* Get object table information */
Iiro Valkonen7686b102011-02-02 23:21:58 -08002077 error = mxt_get_object_table(data);
Nick Dyer7bed6802014-05-18 23:04:09 -07002078 if (error) {
2079 dev_err(&client->dev, "Error %d reading object table\n", error);
Nick Dyerdd24dcf2014-07-23 11:25:55 -07002080 return error;
Nick Dyer7bed6802014-05-18 23:04:09 -07002081 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002082
Dmitry Torokhov041fa152014-08-11 10:58:29 -07002083 error = mxt_acquire_irq(data);
Nick Dyerdd24dcf2014-07-23 11:25:55 -07002084 if (error)
2085 goto err_free_object_table;
2086
Dmitry Torokhov6cd1ab02014-08-08 09:28:45 -07002087 error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME,
2088 &client->dev, GFP_KERNEL, data,
2089 mxt_config_cb);
2090 if (error) {
2091 dev_err(&client->dev, "Failed to invoke firmware loader: %d\n",
2092 error);
2093 goto err_free_object_table;
2094 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002095
2096 return 0;
Daniel Kurtz7d4fa102012-06-28 21:08:19 +08002097
2098err_free_object_table:
2099 mxt_free_object_table(data);
2100 return error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002101}
2102
Nick Dyer7f3884f72015-08-04 16:36:29 -07002103static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep)
2104{
2105 struct device *dev = &data->client->dev;
2106 int error;
2107 struct t7_config *new_config;
2108 struct t7_config deepsleep = { .active = 0, .idle = 0 };
2109
2110 if (sleep == MXT_POWER_CFG_DEEPSLEEP)
2111 new_config = &deepsleep;
2112 else
2113 new_config = &data->t7_cfg;
2114
2115 error = __mxt_write_reg(data->client, data->T7_address,
2116 sizeof(data->t7_cfg), new_config);
2117 if (error)
2118 return error;
2119
2120 dev_dbg(dev, "Set T7 ACTV:%d IDLE:%d\n",
2121 new_config->active, new_config->idle);
2122
2123 return 0;
2124}
2125
2126static int mxt_init_t7_power_cfg(struct mxt_data *data)
2127{
2128 struct device *dev = &data->client->dev;
2129 int error;
2130 bool retry = false;
2131
2132recheck:
2133 error = __mxt_read_reg(data->client, data->T7_address,
2134 sizeof(data->t7_cfg), &data->t7_cfg);
2135 if (error)
2136 return error;
2137
2138 if (data->t7_cfg.active == 0 || data->t7_cfg.idle == 0) {
2139 if (!retry) {
2140 dev_dbg(dev, "T7 cfg zero, resetting\n");
2141 mxt_soft_reset(data);
2142 retry = true;
2143 goto recheck;
2144 } else {
2145 dev_dbg(dev, "T7 cfg zero after reset, overriding\n");
2146 data->t7_cfg.active = 20;
2147 data->t7_cfg.idle = 100;
2148 return mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
2149 }
2150 }
2151
2152 dev_dbg(dev, "Initialized power cfg: ACTV %d, IDLE %d\n",
2153 data->t7_cfg.active, data->t7_cfg.idle);
2154 return 0;
2155}
2156
Nick Dyerd6a39402016-07-18 18:10:31 -03002157#ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37
2158static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x,
2159 unsigned int y)
2160{
Nick Dyer566d5332016-07-18 18:10:35 -03002161 struct mxt_info *info = &data->info;
Nick Dyerd6a39402016-07-18 18:10:31 -03002162 struct mxt_dbg *dbg = &data->dbg;
2163 unsigned int ofs, page;
Nick Dyer566d5332016-07-18 18:10:35 -03002164 unsigned int col = 0;
2165 unsigned int col_width;
Nick Dyerd6a39402016-07-18 18:10:31 -03002166
Nick Dyer566d5332016-07-18 18:10:35 -03002167 if (info->family_id == MXT_FAMILY_1386) {
2168 col_width = info->matrix_ysize / MXT1386_COLUMNS;
2169 col = y / col_width;
2170 y = y % col_width;
2171 } else {
2172 col_width = info->matrix_ysize;
2173 }
2174
2175 ofs = (y + (x * col_width)) * sizeof(u16);
Nick Dyerd6a39402016-07-18 18:10:31 -03002176 page = ofs / MXT_DIAGNOSTIC_SIZE;
2177 ofs %= MXT_DIAGNOSTIC_SIZE;
2178
Nick Dyer566d5332016-07-18 18:10:35 -03002179 if (info->family_id == MXT_FAMILY_1386)
2180 page += col * MXT1386_PAGES_PER_COLUMN;
2181
Nick Dyerd6a39402016-07-18 18:10:31 -03002182 return get_unaligned_le16(&dbg->t37_buf[page].data[ofs]);
2183}
2184
2185static int mxt_convert_debug_pages(struct mxt_data *data, u16 *outbuf)
2186{
2187 struct mxt_dbg *dbg = &data->dbg;
2188 unsigned int x = 0;
2189 unsigned int y = 0;
Nick Dyerde601f72016-07-18 18:10:34 -03002190 unsigned int i, rx, ry;
Nick Dyerd6a39402016-07-18 18:10:31 -03002191
2192 for (i = 0; i < dbg->t37_nodes; i++) {
Nick Dyerde601f72016-07-18 18:10:34 -03002193 /* Handle orientation */
2194 rx = data->xy_switch ? y : x;
2195 ry = data->xy_switch ? x : y;
2196 rx = data->invertx ? (data->xsize - 1 - rx) : rx;
2197 ry = data->inverty ? (data->ysize - 1 - ry) : ry;
2198
2199 outbuf[i] = mxt_get_debug_value(data, rx, ry);
Nick Dyerd6a39402016-07-18 18:10:31 -03002200
2201 /* Next value */
Nick Dyerde601f72016-07-18 18:10:34 -03002202 if (++x >= (data->xy_switch ? data->ysize : data->xsize)) {
Nick Dyerd6a39402016-07-18 18:10:31 -03002203 x = 0;
2204 y++;
2205 }
2206 }
2207
2208 return 0;
2209}
2210
2211static int mxt_read_diagnostic_debug(struct mxt_data *data, u8 mode,
2212 u16 *outbuf)
2213{
2214 struct mxt_dbg *dbg = &data->dbg;
2215 int retries = 0;
2216 int page;
2217 int ret;
2218 u8 cmd = mode;
2219 struct t37_debug *p;
2220 u8 cmd_poll;
2221
2222 for (page = 0; page < dbg->t37_pages; page++) {
2223 p = dbg->t37_buf + page;
2224
2225 ret = mxt_write_reg(data->client, dbg->diag_cmd_address,
2226 cmd);
2227 if (ret)
2228 return ret;
2229
2230 retries = 0;
2231 msleep(20);
2232wait_cmd:
2233 /* Read back command byte */
2234 ret = __mxt_read_reg(data->client, dbg->diag_cmd_address,
2235 sizeof(cmd_poll), &cmd_poll);
2236 if (ret)
2237 return ret;
2238
2239 /* Field is cleared once the command has been processed */
2240 if (cmd_poll) {
2241 if (retries++ > 100)
2242 return -EINVAL;
2243
2244 msleep(20);
2245 goto wait_cmd;
2246 }
2247
2248 /* Read T37 page */
2249 ret = __mxt_read_reg(data->client, dbg->t37_address,
2250 sizeof(struct t37_debug), p);
2251 if (ret)
2252 return ret;
2253
2254 if (p->mode != mode || p->page != page) {
2255 dev_err(&data->client->dev, "T37 page mismatch\n");
2256 return -EINVAL;
2257 }
2258
2259 dev_dbg(&data->client->dev, "%s page:%d retries:%d\n",
2260 __func__, page, retries);
2261
2262 /* For remaining pages, write PAGEUP rather than mode */
2263 cmd = MXT_DIAGNOSTIC_PAGEUP;
2264 }
2265
2266 return mxt_convert_debug_pages(data, outbuf);
2267}
2268
Nick Dyerecfdd7e2016-07-18 18:10:32 -03002269static int mxt_queue_setup(struct vb2_queue *q,
2270 unsigned int *nbuffers, unsigned int *nplanes,
2271 unsigned int sizes[], struct device *alloc_devs[])
2272{
2273 struct mxt_data *data = q->drv_priv;
2274 size_t size = data->dbg.t37_nodes * sizeof(u16);
2275
2276 if (*nplanes)
2277 return sizes[0] < size ? -EINVAL : 0;
2278
2279 *nplanes = 1;
2280 sizes[0] = size;
2281
2282 return 0;
2283}
2284
2285static void mxt_buffer_queue(struct vb2_buffer *vb)
2286{
2287 struct mxt_data *data = vb2_get_drv_priv(vb->vb2_queue);
2288 u16 *ptr;
2289 int ret;
Nick Dyer06b3d3f2016-07-18 18:10:36 -03002290 u8 mode;
Nick Dyerecfdd7e2016-07-18 18:10:32 -03002291
2292 ptr = vb2_plane_vaddr(vb, 0);
2293 if (!ptr) {
2294 dev_err(&data->client->dev, "Error acquiring frame ptr\n");
2295 goto fault;
2296 }
2297
Nick Dyer06b3d3f2016-07-18 18:10:36 -03002298 switch (data->dbg.input) {
2299 case MXT_V4L_INPUT_DELTAS:
2300 default:
2301 mode = MXT_DIAGNOSTIC_DELTAS;
2302 break;
2303
2304 case MXT_V4L_INPUT_REFS:
2305 mode = MXT_DIAGNOSTIC_REFS;
2306 break;
2307 }
2308
2309 ret = mxt_read_diagnostic_debug(data, mode, ptr);
Nick Dyerecfdd7e2016-07-18 18:10:32 -03002310 if (ret)
2311 goto fault;
2312
2313 vb2_set_plane_payload(vb, 0, data->dbg.t37_nodes * sizeof(u16));
2314 vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
2315 return;
2316
2317fault:
2318 vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
2319}
2320
2321/* V4L2 structures */
2322static const struct vb2_ops mxt_queue_ops = {
2323 .queue_setup = mxt_queue_setup,
2324 .buf_queue = mxt_buffer_queue,
2325 .wait_prepare = vb2_ops_wait_prepare,
2326 .wait_finish = vb2_ops_wait_finish,
2327};
2328
2329static const struct vb2_queue mxt_queue = {
2330 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
2331 .io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ,
2332 .buf_struct_size = sizeof(struct mxt_vb2_buffer),
2333 .ops = &mxt_queue_ops,
2334 .mem_ops = &vb2_vmalloc_memops,
2335 .timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC,
2336 .min_buffers_needed = 1,
2337};
2338
2339static int mxt_vidioc_querycap(struct file *file, void *priv,
2340 struct v4l2_capability *cap)
2341{
2342 struct mxt_data *data = video_drvdata(file);
2343
2344 strlcpy(cap->driver, "atmel_mxt_ts", sizeof(cap->driver));
2345 strlcpy(cap->card, "atmel_mxt_ts touch", sizeof(cap->card));
2346 snprintf(cap->bus_info, sizeof(cap->bus_info),
2347 "I2C:%s", dev_name(&data->client->dev));
2348 return 0;
2349}
2350
2351static int mxt_vidioc_enum_input(struct file *file, void *priv,
2352 struct v4l2_input *i)
2353{
Nick Dyer06b3d3f2016-07-18 18:10:36 -03002354 if (i->index >= MXT_V4L_INPUT_MAX)
Nick Dyerecfdd7e2016-07-18 18:10:32 -03002355 return -EINVAL;
2356
2357 i->type = V4L2_INPUT_TYPE_TOUCH;
Nick Dyer06b3d3f2016-07-18 18:10:36 -03002358
2359 switch (i->index) {
2360 case MXT_V4L_INPUT_REFS:
2361 strlcpy(i->name, "Mutual Capacitance References",
2362 sizeof(i->name));
2363 break;
2364 case MXT_V4L_INPUT_DELTAS:
2365 strlcpy(i->name, "Mutual Capacitance Deltas", sizeof(i->name));
2366 break;
2367 }
2368
Nick Dyerecfdd7e2016-07-18 18:10:32 -03002369 return 0;
2370}
2371
2372static int mxt_set_input(struct mxt_data *data, unsigned int i)
2373{
2374 struct v4l2_pix_format *f = &data->dbg.format;
2375
Nick Dyer06b3d3f2016-07-18 18:10:36 -03002376 if (i >= MXT_V4L_INPUT_MAX)
Nick Dyerecfdd7e2016-07-18 18:10:32 -03002377 return -EINVAL;
2378
Nick Dyer06b3d3f2016-07-18 18:10:36 -03002379 if (i == MXT_V4L_INPUT_DELTAS)
2380 f->pixelformat = V4L2_TCH_FMT_DELTA_TD16;
2381 else
2382 f->pixelformat = V4L2_TCH_FMT_TU16;
2383
Nick Dyerde601f72016-07-18 18:10:34 -03002384 f->width = data->xy_switch ? data->ysize : data->xsize;
2385 f->height = data->xy_switch ? data->xsize : data->ysize;
Nick Dyerecfdd7e2016-07-18 18:10:32 -03002386 f->field = V4L2_FIELD_NONE;
2387 f->colorspace = V4L2_COLORSPACE_RAW;
2388 f->bytesperline = f->width * sizeof(u16);
2389 f->sizeimage = f->width * f->height * sizeof(u16);
2390
2391 data->dbg.input = i;
2392
2393 return 0;
2394}
2395
2396static int mxt_vidioc_s_input(struct file *file, void *priv, unsigned int i)
2397{
2398 return mxt_set_input(video_drvdata(file), i);
2399}
2400
2401static int mxt_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
2402{
2403 struct mxt_data *data = video_drvdata(file);
2404
2405 *i = data->dbg.input;
2406
2407 return 0;
2408}
2409
2410static int mxt_vidioc_fmt(struct file *file, void *priv, struct v4l2_format *f)
2411{
2412 struct mxt_data *data = video_drvdata(file);
2413
2414 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2415 f->fmt.pix = data->dbg.format;
2416
2417 return 0;
2418}
2419
2420static int mxt_vidioc_enum_fmt(struct file *file, void *priv,
2421 struct v4l2_fmtdesc *fmt)
2422{
2423 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2424 return -EINVAL;
2425
Nick Dyer06b3d3f2016-07-18 18:10:36 -03002426 switch (fmt->index) {
2427 case 0:
2428 fmt->pixelformat = V4L2_TCH_FMT_TU16;
2429 break;
2430
2431 case 1:
2432 fmt->pixelformat = V4L2_TCH_FMT_DELTA_TD16;
2433 break;
2434
2435 default:
2436 return -EINVAL;
2437 }
2438
Nick Dyerecfdd7e2016-07-18 18:10:32 -03002439 return 0;
2440}
2441
2442static int mxt_vidioc_g_parm(struct file *file, void *fh,
2443 struct v4l2_streamparm *a)
2444{
2445 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2446 return -EINVAL;
2447
2448 a->parm.capture.readbuffers = 1;
2449 a->parm.capture.timeperframe.numerator = 1;
2450 a->parm.capture.timeperframe.denominator = 10;
2451 return 0;
2452}
2453
2454static const struct v4l2_ioctl_ops mxt_video_ioctl_ops = {
2455 .vidioc_querycap = mxt_vidioc_querycap,
2456
2457 .vidioc_enum_fmt_vid_cap = mxt_vidioc_enum_fmt,
2458 .vidioc_s_fmt_vid_cap = mxt_vidioc_fmt,
2459 .vidioc_g_fmt_vid_cap = mxt_vidioc_fmt,
2460 .vidioc_try_fmt_vid_cap = mxt_vidioc_fmt,
2461 .vidioc_g_parm = mxt_vidioc_g_parm,
2462
2463 .vidioc_enum_input = mxt_vidioc_enum_input,
2464 .vidioc_g_input = mxt_vidioc_g_input,
2465 .vidioc_s_input = mxt_vidioc_s_input,
2466
2467 .vidioc_reqbufs = vb2_ioctl_reqbufs,
2468 .vidioc_create_bufs = vb2_ioctl_create_bufs,
2469 .vidioc_querybuf = vb2_ioctl_querybuf,
2470 .vidioc_qbuf = vb2_ioctl_qbuf,
2471 .vidioc_dqbuf = vb2_ioctl_dqbuf,
2472 .vidioc_expbuf = vb2_ioctl_expbuf,
2473
2474 .vidioc_streamon = vb2_ioctl_streamon,
2475 .vidioc_streamoff = vb2_ioctl_streamoff,
2476};
2477
2478static const struct video_device mxt_video_device = {
2479 .name = "Atmel maxTouch",
2480 .fops = &mxt_video_fops,
2481 .ioctl_ops = &mxt_video_ioctl_ops,
2482 .release = video_device_release_empty,
2483 .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TOUCH |
2484 V4L2_CAP_READWRITE | V4L2_CAP_STREAMING,
2485};
2486
Nick Dyerd6a39402016-07-18 18:10:31 -03002487static void mxt_debug_init(struct mxt_data *data)
2488{
Nick Dyer566d5332016-07-18 18:10:35 -03002489 struct mxt_info *info = &data->info;
Nick Dyerd6a39402016-07-18 18:10:31 -03002490 struct mxt_dbg *dbg = &data->dbg;
2491 struct mxt_object *object;
Nick Dyerecfdd7e2016-07-18 18:10:32 -03002492 int error;
Nick Dyerd6a39402016-07-18 18:10:31 -03002493
2494 object = mxt_get_object(data, MXT_GEN_COMMAND_T6);
2495 if (!object)
2496 goto error;
2497
2498 dbg->diag_cmd_address = object->start_address + MXT_COMMAND_DIAGNOSTIC;
2499
2500 object = mxt_get_object(data, MXT_DEBUG_DIAGNOSTIC_T37);
2501 if (!object)
2502 goto error;
2503
2504 if (mxt_obj_size(object) != sizeof(struct t37_debug)) {
2505 dev_warn(&data->client->dev, "Bad T37 size");
2506 goto error;
2507 }
2508
2509 dbg->t37_address = object->start_address;
2510
2511 /* Calculate size of data and allocate buffer */
Nick Dyer27864892016-07-18 18:10:33 -03002512 dbg->t37_nodes = data->xsize * data->ysize;
Nick Dyer566d5332016-07-18 18:10:35 -03002513
2514 if (info->family_id == MXT_FAMILY_1386)
2515 dbg->t37_pages = MXT1386_COLUMNS * MXT1386_PAGES_PER_COLUMN;
2516 else
2517 dbg->t37_pages = DIV_ROUND_UP(data->xsize *
Guenter Roeckd7ddf152017-01-21 23:46:47 -08002518 info->matrix_ysize *
Nick Dyer566d5332016-07-18 18:10:35 -03002519 sizeof(u16),
2520 sizeof(dbg->t37_buf->data));
Nick Dyerd6a39402016-07-18 18:10:31 -03002521
2522 dbg->t37_buf = devm_kmalloc_array(&data->client->dev, dbg->t37_pages,
2523 sizeof(struct t37_debug), GFP_KERNEL);
2524 if (!dbg->t37_buf)
2525 goto error;
2526
Nick Dyerecfdd7e2016-07-18 18:10:32 -03002527 /* init channel to zero */
2528 mxt_set_input(data, 0);
2529
2530 /* register video device */
2531 snprintf(dbg->v4l2.name, sizeof(dbg->v4l2.name), "%s", "atmel_mxt_ts");
2532 error = v4l2_device_register(&data->client->dev, &dbg->v4l2);
2533 if (error)
2534 goto error;
2535
2536 /* initialize the queue */
2537 mutex_init(&dbg->lock);
2538 dbg->queue = mxt_queue;
2539 dbg->queue.drv_priv = data;
2540 dbg->queue.lock = &dbg->lock;
2541 dbg->queue.dev = &data->client->dev;
2542
2543 error = vb2_queue_init(&dbg->queue);
2544 if (error)
2545 goto error_unreg_v4l2;
2546
2547 dbg->vdev = mxt_video_device;
2548 dbg->vdev.v4l2_dev = &dbg->v4l2;
2549 dbg->vdev.lock = &dbg->lock;
2550 dbg->vdev.vfl_dir = VFL_DIR_RX;
2551 dbg->vdev.queue = &dbg->queue;
2552 video_set_drvdata(&dbg->vdev, data);
2553
2554 error = video_register_device(&dbg->vdev, VFL_TYPE_TOUCH, -1);
2555 if (error)
2556 goto error_unreg_v4l2;
2557
Nick Dyerd6a39402016-07-18 18:10:31 -03002558 return;
2559
Nick Dyerecfdd7e2016-07-18 18:10:32 -03002560error_unreg_v4l2:
2561 v4l2_device_unregister(&dbg->v4l2);
Nick Dyerd6a39402016-07-18 18:10:31 -03002562error:
2563 dev_warn(&data->client->dev, "Error initializing T37\n");
2564}
2565#else
2566static void mxt_debug_init(struct mxt_data *data)
2567{
2568}
2569#endif
2570
Nick Dyer50a77c62014-07-23 12:38:48 -07002571static int mxt_configure_objects(struct mxt_data *data,
2572 const struct firmware *cfg)
2573{
2574 struct device *dev = &data->client->dev;
2575 struct mxt_info *info = &data->info;
2576 int error;
2577
Nick Dyer7f3884f72015-08-04 16:36:29 -07002578 error = mxt_init_t7_power_cfg(data);
2579 if (error) {
2580 dev_err(dev, "Failed to initialize power cfg\n");
2581 return error;
2582 }
2583
Nick Dyer50a77c62014-07-23 12:38:48 -07002584 if (cfg) {
2585 error = mxt_update_cfg(data, cfg);
2586 if (error)
2587 dev_warn(dev, "Error %d updating config\n", error);
2588 }
2589
Nick Dyerb23157d2015-04-06 11:25:13 -07002590 if (data->multitouch) {
2591 error = mxt_initialize_input_device(data);
2592 if (error)
2593 return error;
2594 } else {
2595 dev_warn(dev, "No touch object detected\n");
2596 }
Nick Dyer50a77c62014-07-23 12:38:48 -07002597
Nick Dyerd6a39402016-07-18 18:10:31 -03002598 mxt_debug_init(data);
2599
Nick Dyer50a77c62014-07-23 12:38:48 -07002600 dev_info(dev,
2601 "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
2602 info->family_id, info->variant_id, info->version >> 4,
2603 info->version & 0xf, info->build, info->object_num);
2604
2605 return 0;
2606}
2607
Daniel Kurtzb19fc9e2012-06-28 21:08:16 +08002608/* Firmware Version is returned as Major.Minor.Build */
2609static ssize_t mxt_fw_version_show(struct device *dev,
2610 struct device_attribute *attr, char *buf)
2611{
2612 struct mxt_data *data = dev_get_drvdata(dev);
2613 struct mxt_info *info = &data->info;
2614 return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n",
2615 info->version >> 4, info->version & 0xf, info->build);
2616}
2617
2618/* Hardware Version is returned as FamilyID.VariantID */
2619static ssize_t mxt_hw_version_show(struct device *dev,
2620 struct device_attribute *attr, char *buf)
2621{
2622 struct mxt_data *data = dev_get_drvdata(dev);
2623 struct mxt_info *info = &data->info;
2624 return scnprintf(buf, PAGE_SIZE, "%u.%u\n",
2625 info->family_id, info->variant_id);
2626}
2627
Daniel Kurtz794eb672012-06-28 21:08:10 +08002628static ssize_t mxt_show_instance(char *buf, int count,
2629 struct mxt_object *object, int instance,
2630 const u8 *val)
2631{
2632 int i;
2633
Daniel Kurtz1e0c0c52014-05-18 23:01:12 -07002634 if (mxt_obj_instances(object) > 1)
Daniel Kurtz794eb672012-06-28 21:08:10 +08002635 count += scnprintf(buf + count, PAGE_SIZE - count,
2636 "Instance %u\n", instance);
2637
Daniel Kurtz1e0c0c52014-05-18 23:01:12 -07002638 for (i = 0; i < mxt_obj_size(object); i++)
Daniel Kurtz794eb672012-06-28 21:08:10 +08002639 count += scnprintf(buf + count, PAGE_SIZE - count,
2640 "\t[%2u]: %02x (%d)\n", i, val[i], val[i]);
2641 count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
2642
2643 return count;
2644}
2645
Iiro Valkonen7686b102011-02-02 23:21:58 -08002646static ssize_t mxt_object_show(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002647 struct device_attribute *attr, char *buf)
2648{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002649 struct mxt_data *data = dev_get_drvdata(dev);
2650 struct mxt_object *object;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002651 int count = 0;
2652 int i, j;
2653 int error;
Daniel Kurtz43a91d52012-06-28 21:08:08 +08002654 u8 *obuf;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002655
Daniel Kurtz43a91d52012-06-28 21:08:08 +08002656 /* Pre-allocate buffer large enough to hold max sized object. */
2657 obuf = kmalloc(256, GFP_KERNEL);
2658 if (!obuf)
2659 return -ENOMEM;
2660
2661 error = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002662 for (i = 0; i < data->info.object_num; i++) {
2663 object = data->object_table + i;
2664
Daniel Kurtz91630952012-06-28 21:08:09 +08002665 if (!mxt_object_readable(object->type))
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002666 continue;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002667
Daniel Kurtz91630952012-06-28 21:08:09 +08002668 count += scnprintf(buf + count, PAGE_SIZE - count,
2669 "T%u:\n", object->type);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002670
Daniel Kurtz1e0c0c52014-05-18 23:01:12 -07002671 for (j = 0; j < mxt_obj_instances(object); j++) {
2672 u16 size = mxt_obj_size(object);
Daniel Kurtz794eb672012-06-28 21:08:10 +08002673 u16 addr = object->start_address + j * size;
Daniel Kurtz43a91d52012-06-28 21:08:08 +08002674
Daniel Kurtz794eb672012-06-28 21:08:10 +08002675 error = __mxt_read_reg(data->client, addr, size, obuf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002676 if (error)
Daniel Kurtz794eb672012-06-28 21:08:10 +08002677 goto done;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002678
Daniel Kurtz794eb672012-06-28 21:08:10 +08002679 count = mxt_show_instance(buf, count, object, j, obuf);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002680 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002681 }
2682
Daniel Kurtz794eb672012-06-28 21:08:10 +08002683done:
Daniel Kurtz43a91d52012-06-28 21:08:08 +08002684 kfree(obuf);
2685 return error ?: count;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002686}
2687
Nick Dyerf2ac6cb2014-05-18 23:15:01 -07002688static int mxt_check_firmware_format(struct device *dev,
2689 const struct firmware *fw)
2690{
2691 unsigned int pos = 0;
2692 char c;
2693
2694 while (pos < fw->size) {
2695 c = *(fw->data + pos);
2696
2697 if (c < '0' || (c > '9' && c < 'A') || c > 'F')
2698 return 0;
2699
2700 pos++;
2701 }
2702
2703 /*
2704 * To convert file try:
2705 * xxd -r -p mXTXXX__APP_VX-X-XX.enc > maxtouch.fw
2706 */
2707 dev_err(dev, "Aborting: firmware file must be in binary format\n");
2708
2709 return -EINVAL;
2710}
2711
Iiro Valkonen7686b102011-02-02 23:21:58 -08002712static int mxt_load_fw(struct device *dev, const char *fn)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002713{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002714 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002715 const struct firmware *fw = NULL;
2716 unsigned int frame_size;
2717 unsigned int pos = 0;
Nick Dyerf943c742014-05-18 23:14:20 -07002718 unsigned int retry = 0;
Nick Dyerf477c752014-05-18 23:14:45 -07002719 unsigned int frame = 0;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002720 int ret;
2721
2722 ret = request_firmware(&fw, fn, dev);
2723 if (ret) {
2724 dev_err(dev, "Unable to open firmware %s\n", fn);
2725 return ret;
2726 }
2727
Nick Dyerf2ac6cb2014-05-18 23:15:01 -07002728 /* Check for incorrect enc file */
2729 ret = mxt_check_firmware_format(dev, fw);
2730 if (ret)
2731 goto release_firmware;
2732
Nick Dyera9fdd1e2014-07-23 12:41:58 -07002733 if (!data->in_bootloader) {
2734 /* Change to the bootloader mode */
2735 data->in_bootloader = true;
Benson Leungd79e7e42014-05-18 23:02:52 -07002736
Nick Dyera9fdd1e2014-07-23 12:41:58 -07002737 ret = mxt_t6_command(data, MXT_COMMAND_RESET,
2738 MXT_BOOT_VALUE, false);
2739 if (ret)
2740 goto release_firmware;
Iiro Valkonena4a2ef42014-05-18 23:03:44 -07002741
Nick Dyera9fdd1e2014-07-23 12:41:58 -07002742 msleep(MXT_RESET_TIME);
Nick Dyer8efaa5e2014-07-23 12:45:49 -07002743
2744 /* Do not need to scan since we know family ID */
2745 ret = mxt_lookup_bootloader_address(data, 0);
2746 if (ret)
2747 goto release_firmware;
Stephen Warren58e4aeee2014-09-10 10:01:10 -07002748
2749 mxt_free_input_device(data);
2750 mxt_free_object_table(data);
Nick Dyer8efaa5e2014-07-23 12:45:49 -07002751 } else {
2752 enable_irq(data->irq);
Nick Dyera9fdd1e2014-07-23 12:41:58 -07002753 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002754
Benson Leungd79e7e42014-05-18 23:02:52 -07002755 reinit_completion(&data->bl_completion);
2756
Nick Dyer385deb92014-07-23 12:42:40 -07002757 ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false);
2758 if (ret) {
2759 /* Bootloader may still be unlocked from previous attempt */
2760 ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, false);
2761 if (ret)
2762 goto disable_irq;
2763 } else {
2764 dev_info(dev, "Unlocking bootloader\n");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002765
Nick Dyer385deb92014-07-23 12:42:40 -07002766 /* Unlock bootloader */
Nick Dyer8efaa5e2014-07-23 12:45:49 -07002767 ret = mxt_send_bootloader_cmd(data, true);
Nick Dyer385deb92014-07-23 12:42:40 -07002768 if (ret)
2769 goto disable_irq;
2770 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002771
2772 while (pos < fw->size) {
Nick Dyer385deb92014-07-23 12:42:40 -07002773 ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, true);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002774 if (ret)
Benson Leungd79e7e42014-05-18 23:02:52 -07002775 goto disable_irq;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002776
2777 frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
2778
Nick Dyerf943c742014-05-18 23:14:20 -07002779 /* Take account of CRC bytes */
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002780 frame_size += 2;
2781
2782 /* Write one frame to device */
Nick Dyerf28a8422014-05-18 23:10:49 -07002783 ret = mxt_bootloader_write(data, fw->data + pos, frame_size);
2784 if (ret)
2785 goto disable_irq;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002786
Nick Dyer385deb92014-07-23 12:42:40 -07002787 ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS, true);
Nick Dyerf943c742014-05-18 23:14:20 -07002788 if (ret) {
2789 retry++;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002790
Nick Dyerf943c742014-05-18 23:14:20 -07002791 /* Back off by 20ms per retry */
2792 msleep(retry * 20);
2793
2794 if (retry > 20) {
2795 dev_err(dev, "Retry count exceeded\n");
2796 goto disable_irq;
2797 }
2798 } else {
2799 retry = 0;
2800 pos += frame_size;
Nick Dyerf477c752014-05-18 23:14:45 -07002801 frame++;
Nick Dyerf943c742014-05-18 23:14:20 -07002802 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002803
Nick Dyerf477c752014-05-18 23:14:45 -07002804 if (frame % 50 == 0)
2805 dev_dbg(dev, "Sent %d frames, %d/%zd bytes\n",
2806 frame, pos, fw->size);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002807 }
2808
Benson Leunga0434b72014-05-18 23:03:09 -07002809 /* Wait for flash. */
Iiro Valkonena4a2ef42014-05-18 23:03:44 -07002810 ret = mxt_wait_for_completion(data, &data->bl_completion,
2811 MXT_FW_RESET_TIME);
Benson Leunga0434b72014-05-18 23:03:09 -07002812 if (ret)
2813 goto disable_irq;
2814
Nick Dyerf477c752014-05-18 23:14:45 -07002815 dev_dbg(dev, "Sent %d frames, %d bytes\n", frame, pos);
2816
Benson Leunga0434b72014-05-18 23:03:09 -07002817 /*
2818 * Wait for device to reset. Some bootloader versions do not assert
2819 * the CHG line after bootloading has finished, so ignore potential
2820 * errors.
2821 */
Iiro Valkonena4a2ef42014-05-18 23:03:44 -07002822 mxt_wait_for_completion(data, &data->bl_completion, MXT_FW_RESET_TIME);
Benson Leunga0434b72014-05-18 23:03:09 -07002823
Benson Leungd79e7e42014-05-18 23:02:52 -07002824 data->in_bootloader = false;
2825
2826disable_irq:
2827 disable_irq(data->irq);
Iiro Valkonena4a2ef42014-05-18 23:03:44 -07002828release_firmware:
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002829 release_firmware(fw);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002830 return ret;
2831}
2832
Iiro Valkonen7686b102011-02-02 23:21:58 -08002833static ssize_t mxt_update_fw_store(struct device *dev,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002834 struct device_attribute *attr,
2835 const char *buf, size_t count)
2836{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002837 struct mxt_data *data = dev_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002838 int error;
2839
Iiro Valkonen7686b102011-02-02 23:21:58 -08002840 error = mxt_load_fw(dev, MXT_FW_NAME);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002841 if (error) {
2842 dev_err(dev, "The firmware update failed(%d)\n", error);
2843 count = error;
2844 } else {
Nick Dyer7bed6802014-05-18 23:04:09 -07002845 dev_info(dev, "The firmware update succeeded\n");
2846
Nick Dyerdd24dcf2014-07-23 11:25:55 -07002847 error = mxt_initialize(data);
Benson Leungd79e7e42014-05-18 23:02:52 -07002848 if (error)
2849 return error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002850 }
2851
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002852 return count;
2853}
2854
Daniel Kurtzb19fc9e2012-06-28 21:08:16 +08002855static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
2856static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
Daniel Kurtz71b3e932012-05-08 22:30:14 -07002857static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
2858static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002859
Iiro Valkonen7686b102011-02-02 23:21:58 -08002860static struct attribute *mxt_attrs[] = {
Daniel Kurtzb19fc9e2012-06-28 21:08:16 +08002861 &dev_attr_fw_version.attr,
2862 &dev_attr_hw_version.attr,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002863 &dev_attr_object.attr,
2864 &dev_attr_update_fw.attr,
2865 NULL
2866};
2867
Iiro Valkonen7686b102011-02-02 23:21:58 -08002868static const struct attribute_group mxt_attr_group = {
2869 .attrs = mxt_attrs,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002870};
2871
Iiro Valkonen7686b102011-02-02 23:21:58 -08002872static void mxt_start(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002873{
Dmitry Torokhovd80808e2018-03-20 15:31:25 -07002874 switch (data->suspend_mode) {
Nick Dyer7f3884f72015-08-04 16:36:29 -07002875 case MXT_SUSPEND_T9_CTRL:
2876 mxt_soft_reset(data);
2877
2878 /* Touch enable */
2879 /* 0x83 = SCANEN | RPTEN | ENABLE */
2880 mxt_write_object(data,
2881 MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0x83);
2882 break;
2883
2884 case MXT_SUSPEND_DEEP_SLEEP:
2885 default:
2886 mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
2887
2888 /* Recalibrate since chip has been in deep sleep */
2889 mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false);
2890 break;
2891 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002892}
2893
Iiro Valkonen7686b102011-02-02 23:21:58 -08002894static void mxt_stop(struct mxt_data *data)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002895{
Dmitry Torokhovd80808e2018-03-20 15:31:25 -07002896 switch (data->suspend_mode) {
Nick Dyer7f3884f72015-08-04 16:36:29 -07002897 case MXT_SUSPEND_T9_CTRL:
2898 /* Touch disable */
2899 mxt_write_object(data,
2900 MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0);
2901 break;
2902
2903 case MXT_SUSPEND_DEEP_SLEEP:
2904 default:
2905 mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP);
2906 break;
2907 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002908}
2909
Iiro Valkonen7686b102011-02-02 23:21:58 -08002910static int mxt_input_open(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002911{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002912 struct mxt_data *data = input_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002913
Iiro Valkonen7686b102011-02-02 23:21:58 -08002914 mxt_start(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002915
2916 return 0;
2917}
2918
Iiro Valkonen7686b102011-02-02 23:21:58 -08002919static void mxt_input_close(struct input_dev *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002920{
Iiro Valkonen7686b102011-02-02 23:21:58 -08002921 struct mxt_data *data = input_get_drvdata(dev);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002922
Iiro Valkonen7686b102011-02-02 23:21:58 -08002923 mxt_stop(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07002924}
2925
Dmitry Torokhov93afb1d2018-03-20 15:31:26 -07002926static const struct mxt_platform_data *
2927mxt_parse_device_properties(struct i2c_client *client)
Stephen Warren78188be2014-07-23 12:23:23 -07002928{
Dmitry Torokhov93afb1d2018-03-20 15:31:26 -07002929 static const char keymap_property[] = "linux,gpio-keymap";
Stephen Warren78188be2014-07-23 12:23:23 -07002930 struct mxt_platform_data *pdata;
2931 u32 *keymap;
Dmitry Torokhov93afb1d2018-03-20 15:31:26 -07002932 int n_keys;
2933 int error;
Stephen Warren78188be2014-07-23 12:23:23 -07002934
2935 pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
2936 if (!pdata)
2937 return ERR_PTR(-ENOMEM);
2938
Dmitry Torokhov93afb1d2018-03-20 15:31:26 -07002939 if (device_property_present(&client->dev, keymap_property)) {
2940 n_keys = device_property_read_u32_array(&client->dev,
2941 keymap_property,
2942 NULL, 0);
2943 if (n_keys <= 0) {
2944 error = n_keys < 0 ? n_keys : -EINVAL;
2945 dev_err(&client->dev,
2946 "invalid/malformed '%s' property: %d\n",
2947 keymap_property, error);
2948 return ERR_PTR(error);
2949 }
Stephen Warren78188be2014-07-23 12:23:23 -07002950
Dmitry Torokhov93afb1d2018-03-20 15:31:26 -07002951 keymap = devm_kmalloc_array(&client->dev, n_keys, sizeof(u32),
2952 GFP_KERNEL);
Stephen Warren78188be2014-07-23 12:23:23 -07002953 if (!keymap)
2954 return ERR_PTR(-ENOMEM);
2955
Dmitry Torokhov93afb1d2018-03-20 15:31:26 -07002956 error = device_property_read_u32_array(&client->dev,
2957 keymap_property,
2958 keymap, n_keys);
2959 if (error) {
2960 dev_err(&client->dev,
2961 "failed to parse '%s' property: %d\n",
2962 keymap_property, error);
2963 return ERR_PTR(error);
2964 }
Stephen Warren78188be2014-07-23 12:23:23 -07002965
2966 pdata->t19_keymap = keymap;
Dmitry Torokhov93afb1d2018-03-20 15:31:26 -07002967 pdata->t19_num_keys = n_keys;
Stephen Warren78188be2014-07-23 12:23:23 -07002968 }
2969
2970 return pdata;
2971}
Stephen Warren78188be2014-07-23 12:23:23 -07002972
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07002973#ifdef CONFIG_ACPI
2974
2975struct mxt_acpi_platform_data {
2976 const char *hid;
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07002977 const struct property_entry *props;
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07002978};
2979
2980static unsigned int samus_touchpad_buttons[] = {
2981 KEY_RESERVED,
2982 KEY_RESERVED,
2983 KEY_RESERVED,
2984 BTN_LEFT
2985};
2986
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07002987static const struct property_entry samus_touchpad_props[] = {
2988 PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", samus_touchpad_buttons),
2989 { }
2990};
2991
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07002992static struct mxt_acpi_platform_data samus_platform_data[] = {
2993 {
2994 /* Touchpad */
2995 .hid = "ATML0000",
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07002996 .props = samus_touchpad_props,
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07002997 },
2998 {
2999 /* Touchscreen */
3000 .hid = "ATML0001",
3001 },
3002 { }
3003};
3004
Dmitry Torokhovc67566c2015-11-20 10:58:07 -08003005static unsigned int chromebook_tp_buttons[] = {
3006 KEY_RESERVED,
3007 KEY_RESERVED,
3008 KEY_RESERVED,
3009 KEY_RESERVED,
3010 KEY_RESERVED,
3011 BTN_LEFT
3012};
3013
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003014static const struct property_entry chromebook_tp_props[] = {
3015 PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", chromebook_tp_buttons),
3016 { }
3017};
3018
Dmitry Torokhovc67566c2015-11-20 10:58:07 -08003019static struct mxt_acpi_platform_data chromebook_platform_data[] = {
3020 {
3021 /* Touchpad */
3022 .hid = "ATML0000",
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003023 .props = chromebook_tp_props,
Dmitry Torokhovc67566c2015-11-20 10:58:07 -08003024 },
3025 {
3026 /* Touchscreen */
3027 .hid = "ATML0001",
3028 },
3029 { }
3030};
3031
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003032static const struct dmi_system_id mxt_dmi_table[] = {
3033 {
3034 /* 2015 Google Pixel */
3035 .ident = "Chromebook Pixel 2",
3036 .matches = {
3037 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
3038 DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
3039 },
3040 .driver_data = samus_platform_data,
3041 },
Dmitry Torokhovc67566c2015-11-20 10:58:07 -08003042 {
3043 /* Other Google Chromebooks */
3044 .ident = "Chromebook",
3045 .matches = {
3046 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
3047 },
3048 .driver_data = chromebook_platform_data,
3049 },
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003050 { }
3051};
3052
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003053static int mxt_acpi_probe(struct i2c_client *client)
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003054{
3055 struct acpi_device *adev;
3056 const struct dmi_system_id *system_id;
3057 const struct mxt_acpi_platform_data *acpi_pdata;
3058
3059 /*
3060 * Ignore ACPI devices representing bootloader mode.
3061 *
3062 * This is a bit of a hack: Google Chromebook BIOS creates ACPI
3063 * devices for both application and bootloader modes, but we are
3064 * interested in application mode only (if device is in bootloader
3065 * mode we'll end up switching into application anyway). So far
3066 * application mode addresses were all above 0x40, so we'll use it
3067 * as a threshold.
3068 */
3069 if (client->addr < 0x40)
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003070 return -ENXIO;
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003071
3072 adev = ACPI_COMPANION(&client->dev);
3073 if (!adev)
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003074 return -ENOENT;
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003075
3076 system_id = dmi_first_match(mxt_dmi_table);
3077 if (!system_id)
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003078 return -ENOENT;
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003079
3080 acpi_pdata = system_id->driver_data;
3081 if (!acpi_pdata)
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003082 return -ENOENT;
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003083
3084 while (acpi_pdata->hid) {
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003085 if (!strcmp(acpi_device_hid(adev), acpi_pdata->hid)) {
3086 /*
3087 * Remove previously installed properties if we
3088 * are probing this device not for the very first
3089 * time.
3090 */
3091 device_remove_properties(&client->dev);
3092
3093 /*
3094 * Now install the platform-specific properties
3095 * that are missing from ACPI.
3096 */
3097 device_add_properties(&client->dev, acpi_pdata->props);
3098 break;
3099 }
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003100
3101 acpi_pdata++;
3102 }
3103
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003104 return 0;
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003105}
3106#else
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003107static int mxt_acpi_probe(struct i2c_client *client)
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003108{
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003109 return -ENOENT;
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003110}
3111#endif
3112
3113static const struct mxt_platform_data *
3114mxt_get_platform_data(struct i2c_client *client)
3115{
3116 const struct mxt_platform_data *pdata;
3117
3118 pdata = dev_get_platdata(&client->dev);
3119 if (pdata)
3120 return pdata;
3121
Dmitry Torokhov93afb1d2018-03-20 15:31:26 -07003122 return mxt_parse_device_properties(client);
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003123}
3124
Dmitry Torokhovd80808e2018-03-20 15:31:25 -07003125static const struct dmi_system_id chromebook_T9_suspend_dmi[] = {
3126 {
3127 .matches = {
3128 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
3129 DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
3130 },
3131 },
3132 {
3133 .matches = {
3134 DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
3135 },
3136 },
3137 { }
3138};
3139
Stephen Warren78188be2014-07-23 12:23:23 -07003140static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003141{
Iiro Valkonen7686b102011-02-02 23:21:58 -08003142 struct mxt_data *data;
Stephen Warren78188be2014-07-23 12:23:23 -07003143 const struct mxt_platform_data *pdata;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003144 int error;
3145
Dmitry Torokhovd3f810c2018-03-20 15:31:27 -07003146 error = mxt_acpi_probe(client);
3147 if (error && error != -ENOENT)
3148 return error;
3149
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003150 pdata = mxt_get_platform_data(client);
3151 if (IS_ERR(pdata))
3152 return PTR_ERR(pdata);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003153
Sebastian Reichel8cc84462017-07-25 14:08:48 -07003154 data = devm_kzalloc(&client->dev, sizeof(struct mxt_data), GFP_KERNEL);
3155 if (!data)
Nick Dyer7a53d602014-07-23 12:21:26 -07003156 return -ENOMEM;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003157
Daniel Kurtzec02ac22012-06-28 21:08:02 +08003158 snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
3159 client->adapter->nr, client->addr);
Daniel Kurtz22dfab72013-03-07 19:43:33 -08003160
Joonyoung Shim910d8052011-04-12 23:14:38 -07003161 data->client = client;
Joonyoung Shim910d8052011-04-12 23:14:38 -07003162 data->pdata = pdata;
3163 data->irq = client->irq;
Nick Dyer7a53d602014-07-23 12:21:26 -07003164 i2c_set_clientdata(client, data);
Joonyoung Shim910d8052011-04-12 23:14:38 -07003165
Benson Leungd79e7e42014-05-18 23:02:52 -07003166 init_completion(&data->bl_completion);
Iiro Valkonena4a2ef42014-05-18 23:03:44 -07003167 init_completion(&data->reset_completion);
Nick Dyerc3f78042014-05-18 23:04:46 -07003168 init_completion(&data->crc_completion);
Benson Leungd79e7e42014-05-18 23:02:52 -07003169
Dmitry Torokhovd80808e2018-03-20 15:31:25 -07003170 data->suspend_mode = dmi_check_system(chromebook_T9_suspend_dmi) ?
3171 MXT_SUSPEND_T9_CTRL : MXT_SUSPEND_DEEP_SLEEP;
3172
Sebastian Reichelf657b002017-07-25 14:11:34 -07003173 data->reset_gpio = devm_gpiod_get_optional(&client->dev,
3174 "reset", GPIOD_OUT_LOW);
3175 if (IS_ERR(data->reset_gpio)) {
3176 error = PTR_ERR(data->reset_gpio);
3177 dev_err(&client->dev, "Failed to get reset gpio: %d\n", error);
3178 return error;
3179 }
3180
Sebastian Reichel8cc84462017-07-25 14:08:48 -07003181 error = devm_request_threaded_irq(&client->dev, client->irq,
3182 NULL, mxt_interrupt,
3183 pdata->irqflags | IRQF_ONESHOT,
3184 client->name, data);
Nick Dyerdd24dcf2014-07-23 11:25:55 -07003185 if (error) {
3186 dev_err(&client->dev, "Failed to register interrupt\n");
Sebastian Reichel8cc84462017-07-25 14:08:48 -07003187 return error;
Nick Dyerdd24dcf2014-07-23 11:25:55 -07003188 }
3189
Sebastian Reichelf657b002017-07-25 14:11:34 -07003190 if (data->reset_gpio) {
3191 data->in_bootloader = true;
3192 msleep(MXT_RESET_TIME);
3193 reinit_completion(&data->bl_completion);
3194 gpiod_set_value(data->reset_gpio, 1);
3195 error = mxt_wait_for_completion(data, &data->bl_completion,
3196 MXT_RESET_TIMEOUT);
3197 if (error)
3198 return error;
3199 data->in_bootloader = false;
3200 }
3201
Nick Dyerdd24dcf2014-07-23 11:25:55 -07003202 disable_irq(client->irq);
3203
Daniel Kurtzcb159112012-06-28 21:08:22 +08003204 error = mxt_initialize(data);
3205 if (error)
Sebastian Reichel8cc84462017-07-25 14:08:48 -07003206 return error;
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003207
Iiro Valkonen7686b102011-02-02 23:21:58 -08003208 error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
Nick Dyer7bed6802014-05-18 23:04:09 -07003209 if (error) {
3210 dev_err(&client->dev, "Failure %d creating sysfs group\n",
3211 error);
Nick Dyer7a53d602014-07-23 12:21:26 -07003212 goto err_free_object;
Nick Dyer7bed6802014-05-18 23:04:09 -07003213 }
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003214
3215 return 0;
3216
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003217err_free_object:
Stephen Warren58e4aeee2014-09-10 10:01:10 -07003218 mxt_free_input_device(data);
Nick Dyer5f3f9bc2014-07-23 12:46:55 -07003219 mxt_free_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003220 return error;
3221}
3222
Bill Pembertone2619cf2012-11-23 21:50:47 -08003223static int mxt_remove(struct i2c_client *client)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003224{
Iiro Valkonen7686b102011-02-02 23:21:58 -08003225 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003226
Sebastian Reichel8cc84462017-07-25 14:08:48 -07003227 disable_irq(data->irq);
Iiro Valkonen7686b102011-02-02 23:21:58 -08003228 sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
Stephen Warren58e4aeee2014-09-10 10:01:10 -07003229 mxt_free_input_device(data);
Nick Dyer5f3f9bc2014-07-23 12:46:55 -07003230 mxt_free_object_table(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003231
3232 return 0;
3233}
3234
Jingoo Han02b6a582014-11-02 00:04:14 -07003235static int __maybe_unused mxt_suspend(struct device *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003236{
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08003237 struct i2c_client *client = to_i2c_client(dev);
Iiro Valkonen7686b102011-02-02 23:21:58 -08003238 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003239 struct input_dev *input_dev = data->input_dev;
3240
Pan Xinhui50fabb02015-08-04 16:53:04 -07003241 if (!input_dev)
3242 return 0;
3243
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003244 mutex_lock(&input_dev->mutex);
3245
3246 if (input_dev->users)
Iiro Valkonen7686b102011-02-02 23:21:58 -08003247 mxt_stop(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003248
3249 mutex_unlock(&input_dev->mutex);
3250
3251 return 0;
3252}
3253
Jingoo Han02b6a582014-11-02 00:04:14 -07003254static int __maybe_unused mxt_resume(struct device *dev)
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003255{
Dmitry Torokhov8b5fce02010-11-18 00:14:03 -08003256 struct i2c_client *client = to_i2c_client(dev);
Iiro Valkonen7686b102011-02-02 23:21:58 -08003257 struct mxt_data *data = i2c_get_clientdata(client);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003258 struct input_dev *input_dev = data->input_dev;
3259
Pan Xinhui50fabb02015-08-04 16:53:04 -07003260 if (!input_dev)
3261 return 0;
3262
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003263 mutex_lock(&input_dev->mutex);
3264
3265 if (input_dev->users)
Iiro Valkonen7686b102011-02-02 23:21:58 -08003266 mxt_start(data);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003267
3268 mutex_unlock(&input_dev->mutex);
3269
3270 return 0;
3271}
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003272
Daniel Kurtz3a73c812012-05-08 22:29:14 -07003273static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);
3274
Stephen Warren78188be2014-07-23 12:23:23 -07003275static const struct of_device_id mxt_of_match[] = {
3276 { .compatible = "atmel,maxtouch", },
3277 {},
3278};
3279MODULE_DEVICE_TABLE(of, mxt_of_match);
3280
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003281#ifdef CONFIG_ACPI
3282static const struct acpi_device_id mxt_acpi_id[] = {
3283 { "ATML0000", 0 }, /* Touchpad */
3284 { "ATML0001", 0 }, /* Touchscreen */
3285 { }
3286};
3287MODULE_DEVICE_TABLE(acpi, mxt_acpi_id);
3288#endif
3289
Iiro Valkonen7686b102011-02-02 23:21:58 -08003290static const struct i2c_device_id mxt_id[] = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003291 { "qt602240_ts", 0 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08003292 { "atmel_mxt_ts", 0 },
Daniel Kurtz22dfab72013-03-07 19:43:33 -08003293 { "atmel_mxt_tp", 0 },
Javier Martinez Canillasb7d21052015-12-11 13:22:39 -08003294 { "maxtouch", 0 },
Chris Leech46ee2a02011-02-15 13:36:52 -08003295 { "mXT224", 0 },
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003296 { }
3297};
Iiro Valkonen7686b102011-02-02 23:21:58 -08003298MODULE_DEVICE_TABLE(i2c, mxt_id);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003299
Iiro Valkonen7686b102011-02-02 23:21:58 -08003300static struct i2c_driver mxt_driver = {
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003301 .driver = {
Iiro Valkonen7686b102011-02-02 23:21:58 -08003302 .name = "atmel_mxt_ts",
Stephen Warren78188be2014-07-23 12:23:23 -07003303 .of_match_table = of_match_ptr(mxt_of_match),
Dmitry Torokhov4f8d8082015-04-07 16:30:01 -07003304 .acpi_match_table = ACPI_PTR(mxt_acpi_id),
Iiro Valkonen7686b102011-02-02 23:21:58 -08003305 .pm = &mxt_pm_ops,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003306 },
Iiro Valkonen7686b102011-02-02 23:21:58 -08003307 .probe = mxt_probe,
Bill Pemberton1cb0aa82012-11-23 21:27:39 -08003308 .remove = mxt_remove,
Iiro Valkonen7686b102011-02-02 23:21:58 -08003309 .id_table = mxt_id,
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003310};
3311
Axel Lin1b92c1c2012-03-16 23:05:41 -07003312module_i2c_driver(mxt_driver);
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003313
3314/* Module information */
3315MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
Iiro Valkonen7686b102011-02-02 23:21:58 -08003316MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
Joonyoung Shim4cf51c32010-07-14 21:55:30 -07003317MODULE_LICENSE("GPL");