1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Atmel maXTouch Touchscreen driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2010 Samsung Electronics Co.Ltd
6*4882a593Smuzhiyun * Copyright (C) 2011-2014 Atmel Corporation
7*4882a593Smuzhiyun * Copyright (C) 2012 Google, Inc.
8*4882a593Smuzhiyun * Copyright (C) 2016 Zodiac Inflight Innovations
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Author: Joonyoung Shim <jy0922.shim@samsung.com>
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include <linux/acpi.h>
14*4882a593Smuzhiyun #include <linux/dmi.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/init.h>
17*4882a593Smuzhiyun #include <linux/completion.h>
18*4882a593Smuzhiyun #include <linux/delay.h>
19*4882a593Smuzhiyun #include <linux/firmware.h>
20*4882a593Smuzhiyun #include <linux/i2c.h>
21*4882a593Smuzhiyun #include <linux/input/mt.h>
22*4882a593Smuzhiyun #include <linux/interrupt.h>
23*4882a593Smuzhiyun #include <linux/irq.h>
24*4882a593Smuzhiyun #include <linux/of.h>
25*4882a593Smuzhiyun #include <linux/property.h>
26*4882a593Smuzhiyun #include <linux/slab.h>
27*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
28*4882a593Smuzhiyun #include <asm/unaligned.h>
29*4882a593Smuzhiyun #include <media/v4l2-device.h>
30*4882a593Smuzhiyun #include <media/v4l2-ioctl.h>
31*4882a593Smuzhiyun #include <media/videobuf2-v4l2.h>
32*4882a593Smuzhiyun #include <media/videobuf2-vmalloc.h>
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun /* Firmware files */
35*4882a593Smuzhiyun #define MXT_FW_NAME "maxtouch.fw"
36*4882a593Smuzhiyun #define MXT_CFG_NAME "maxtouch.cfg"
37*4882a593Smuzhiyun #define MXT_CFG_MAGIC "OBP_RAW V1"
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /* Registers */
40*4882a593Smuzhiyun #define MXT_OBJECT_START 0x07
41*4882a593Smuzhiyun #define MXT_OBJECT_SIZE 6
42*4882a593Smuzhiyun #define MXT_INFO_CHECKSUM_SIZE 3
43*4882a593Smuzhiyun #define MXT_MAX_BLOCK_WRITE 256
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /* Object types */
46*4882a593Smuzhiyun #define MXT_DEBUG_DIAGNOSTIC_T37 37
47*4882a593Smuzhiyun #define MXT_GEN_MESSAGE_T5 5
48*4882a593Smuzhiyun #define MXT_GEN_COMMAND_T6 6
49*4882a593Smuzhiyun #define MXT_GEN_POWER_T7 7
50*4882a593Smuzhiyun #define MXT_GEN_ACQUIRE_T8 8
51*4882a593Smuzhiyun #define MXT_GEN_DATASOURCE_T53 53
52*4882a593Smuzhiyun #define MXT_TOUCH_MULTI_T9 9
53*4882a593Smuzhiyun #define MXT_TOUCH_KEYARRAY_T15 15
54*4882a593Smuzhiyun #define MXT_TOUCH_PROXIMITY_T23 23
55*4882a593Smuzhiyun #define MXT_TOUCH_PROXKEY_T52 52
56*4882a593Smuzhiyun #define MXT_PROCI_GRIPFACE_T20 20
57*4882a593Smuzhiyun #define MXT_PROCG_NOISE_T22 22
58*4882a593Smuzhiyun #define MXT_PROCI_ONETOUCH_T24 24
59*4882a593Smuzhiyun #define MXT_PROCI_TWOTOUCH_T27 27
60*4882a593Smuzhiyun #define MXT_PROCI_GRIP_T40 40
61*4882a593Smuzhiyun #define MXT_PROCI_PALM_T41 41
62*4882a593Smuzhiyun #define MXT_PROCI_TOUCHSUPPRESSION_T42 42
63*4882a593Smuzhiyun #define MXT_PROCI_STYLUS_T47 47
64*4882a593Smuzhiyun #define MXT_PROCG_NOISESUPPRESSION_T48 48
65*4882a593Smuzhiyun #define MXT_SPT_COMMSCONFIG_T18 18
66*4882a593Smuzhiyun #define MXT_SPT_GPIOPWM_T19 19
67*4882a593Smuzhiyun #define MXT_SPT_SELFTEST_T25 25
68*4882a593Smuzhiyun #define MXT_SPT_CTECONFIG_T28 28
69*4882a593Smuzhiyun #define MXT_SPT_USERDATA_T38 38
70*4882a593Smuzhiyun #define MXT_SPT_DIGITIZER_T43 43
71*4882a593Smuzhiyun #define MXT_SPT_MESSAGECOUNT_T44 44
72*4882a593Smuzhiyun #define MXT_SPT_CTECONFIG_T46 46
73*4882a593Smuzhiyun #define MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71 71
74*4882a593Smuzhiyun #define MXT_TOUCH_MULTITOUCHSCREEN_T100 100
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /* MXT_GEN_MESSAGE_T5 object */
77*4882a593Smuzhiyun #define MXT_RPTID_NOMSG 0xff
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun /* MXT_GEN_COMMAND_T6 field */
80*4882a593Smuzhiyun #define MXT_COMMAND_RESET 0
81*4882a593Smuzhiyun #define MXT_COMMAND_BACKUPNV 1
82*4882a593Smuzhiyun #define MXT_COMMAND_CALIBRATE 2
83*4882a593Smuzhiyun #define MXT_COMMAND_REPORTALL 3
84*4882a593Smuzhiyun #define MXT_COMMAND_DIAGNOSTIC 5
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun /* Define for T6 status byte */
87*4882a593Smuzhiyun #define MXT_T6_STATUS_RESET BIT(7)
88*4882a593Smuzhiyun #define MXT_T6_STATUS_OFL BIT(6)
89*4882a593Smuzhiyun #define MXT_T6_STATUS_SIGERR BIT(5)
90*4882a593Smuzhiyun #define MXT_T6_STATUS_CAL BIT(4)
91*4882a593Smuzhiyun #define MXT_T6_STATUS_CFGERR BIT(3)
92*4882a593Smuzhiyun #define MXT_T6_STATUS_COMSERR BIT(2)
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /* MXT_GEN_POWER_T7 field */
95*4882a593Smuzhiyun struct t7_config {
96*4882a593Smuzhiyun u8 idle;
97*4882a593Smuzhiyun u8 active;
98*4882a593Smuzhiyun } __packed;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun #define MXT_POWER_CFG_RUN 0
101*4882a593Smuzhiyun #define MXT_POWER_CFG_DEEPSLEEP 1
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun /* MXT_TOUCH_MULTI_T9 field */
104*4882a593Smuzhiyun #define MXT_T9_CTRL 0
105*4882a593Smuzhiyun #define MXT_T9_XSIZE 3
106*4882a593Smuzhiyun #define MXT_T9_YSIZE 4
107*4882a593Smuzhiyun #define MXT_T9_ORIENT 9
108*4882a593Smuzhiyun #define MXT_T9_RANGE 18
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /* MXT_TOUCH_MULTI_T9 status */
111*4882a593Smuzhiyun #define MXT_T9_UNGRIP BIT(0)
112*4882a593Smuzhiyun #define MXT_T9_SUPPRESS BIT(1)
113*4882a593Smuzhiyun #define MXT_T9_AMP BIT(2)
114*4882a593Smuzhiyun #define MXT_T9_VECTOR BIT(3)
115*4882a593Smuzhiyun #define MXT_T9_MOVE BIT(4)
116*4882a593Smuzhiyun #define MXT_T9_RELEASE BIT(5)
117*4882a593Smuzhiyun #define MXT_T9_PRESS BIT(6)
118*4882a593Smuzhiyun #define MXT_T9_DETECT BIT(7)
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun struct t9_range {
121*4882a593Smuzhiyun __le16 x;
122*4882a593Smuzhiyun __le16 y;
123*4882a593Smuzhiyun } __packed;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun /* MXT_TOUCH_MULTI_T9 orient */
126*4882a593Smuzhiyun #define MXT_T9_ORIENT_SWITCH BIT(0)
127*4882a593Smuzhiyun #define MXT_T9_ORIENT_INVERTX BIT(1)
128*4882a593Smuzhiyun #define MXT_T9_ORIENT_INVERTY BIT(2)
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun /* MXT_SPT_COMMSCONFIG_T18 */
131*4882a593Smuzhiyun #define MXT_COMMS_CTRL 0
132*4882a593Smuzhiyun #define MXT_COMMS_CMD 1
133*4882a593Smuzhiyun #define MXT_COMMS_RETRIGEN BIT(6)
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun /* MXT_DEBUG_DIAGNOSTIC_T37 */
136*4882a593Smuzhiyun #define MXT_DIAGNOSTIC_PAGEUP 0x01
137*4882a593Smuzhiyun #define MXT_DIAGNOSTIC_DELTAS 0x10
138*4882a593Smuzhiyun #define MXT_DIAGNOSTIC_REFS 0x11
139*4882a593Smuzhiyun #define MXT_DIAGNOSTIC_SIZE 128
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun #define MXT_FAMILY_1386 160
142*4882a593Smuzhiyun #define MXT1386_COLUMNS 3
143*4882a593Smuzhiyun #define MXT1386_PAGES_PER_COLUMN 8
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun struct t37_debug {
146*4882a593Smuzhiyun #ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37
147*4882a593Smuzhiyun u8 mode;
148*4882a593Smuzhiyun u8 page;
149*4882a593Smuzhiyun u8 data[MXT_DIAGNOSTIC_SIZE];
150*4882a593Smuzhiyun #endif
151*4882a593Smuzhiyun };
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /* Define for MXT_GEN_COMMAND_T6 */
154*4882a593Smuzhiyun #define MXT_BOOT_VALUE 0xa5
155*4882a593Smuzhiyun #define MXT_RESET_VALUE 0x01
156*4882a593Smuzhiyun #define MXT_BACKUP_VALUE 0x55
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /* T100 Multiple Touch Touchscreen */
159*4882a593Smuzhiyun #define MXT_T100_CTRL 0
160*4882a593Smuzhiyun #define MXT_T100_CFG1 1
161*4882a593Smuzhiyun #define MXT_T100_TCHAUX 3
162*4882a593Smuzhiyun #define MXT_T100_XSIZE 9
163*4882a593Smuzhiyun #define MXT_T100_XRANGE 13
164*4882a593Smuzhiyun #define MXT_T100_YSIZE 20
165*4882a593Smuzhiyun #define MXT_T100_YRANGE 24
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun #define MXT_T100_CFG_SWITCHXY BIT(5)
168*4882a593Smuzhiyun #define MXT_T100_CFG_INVERTY BIT(6)
169*4882a593Smuzhiyun #define MXT_T100_CFG_INVERTX BIT(7)
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun #define MXT_T100_TCHAUX_VECT BIT(0)
172*4882a593Smuzhiyun #define MXT_T100_TCHAUX_AMPL BIT(1)
173*4882a593Smuzhiyun #define MXT_T100_TCHAUX_AREA BIT(2)
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun #define MXT_T100_DETECT BIT(7)
176*4882a593Smuzhiyun #define MXT_T100_TYPE_MASK 0x70
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun enum t100_type {
179*4882a593Smuzhiyun MXT_T100_TYPE_FINGER = 1,
180*4882a593Smuzhiyun MXT_T100_TYPE_PASSIVE_STYLUS = 2,
181*4882a593Smuzhiyun MXT_T100_TYPE_HOVERING_FINGER = 4,
182*4882a593Smuzhiyun MXT_T100_TYPE_GLOVE = 5,
183*4882a593Smuzhiyun MXT_T100_TYPE_LARGE_TOUCH = 6,
184*4882a593Smuzhiyun };
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun #define MXT_DISTANCE_ACTIVE_TOUCH 0
187*4882a593Smuzhiyun #define MXT_DISTANCE_HOVERING 1
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun #define MXT_TOUCH_MAJOR_DEFAULT 1
190*4882a593Smuzhiyun #define MXT_PRESSURE_DEFAULT 1
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun /* Delay times */
193*4882a593Smuzhiyun #define MXT_BACKUP_TIME 50 /* msec */
194*4882a593Smuzhiyun #define MXT_RESET_GPIO_TIME 20 /* msec */
195*4882a593Smuzhiyun #define MXT_RESET_INVALID_CHG 100 /* msec */
196*4882a593Smuzhiyun #define MXT_RESET_TIME 200 /* msec */
197*4882a593Smuzhiyun #define MXT_RESET_TIMEOUT 3000 /* msec */
198*4882a593Smuzhiyun #define MXT_CRC_TIMEOUT 1000 /* msec */
199*4882a593Smuzhiyun #define MXT_FW_RESET_TIME 3000 /* msec */
200*4882a593Smuzhiyun #define MXT_FW_CHG_TIMEOUT 300 /* msec */
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /* Command to unlock bootloader */
203*4882a593Smuzhiyun #define MXT_UNLOCK_CMD_MSB 0xaa
204*4882a593Smuzhiyun #define MXT_UNLOCK_CMD_LSB 0xdc
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun /* Bootloader mode status */
207*4882a593Smuzhiyun #define MXT_WAITING_BOOTLOAD_CMD 0xc0 /* valid 7 6 bit only */
208*4882a593Smuzhiyun #define MXT_WAITING_FRAME_DATA 0x80 /* valid 7 6 bit only */
209*4882a593Smuzhiyun #define MXT_FRAME_CRC_CHECK 0x02
210*4882a593Smuzhiyun #define MXT_FRAME_CRC_FAIL 0x03
211*4882a593Smuzhiyun #define MXT_FRAME_CRC_PASS 0x04
212*4882a593Smuzhiyun #define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
213*4882a593Smuzhiyun #define MXT_BOOT_STATUS_MASK 0x3f
214*4882a593Smuzhiyun #define MXT_BOOT_EXTENDED_ID BIT(5)
215*4882a593Smuzhiyun #define MXT_BOOT_ID_MASK 0x1f
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /* Touchscreen absolute values */
218*4882a593Smuzhiyun #define MXT_MAX_AREA 0xff
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun #define MXT_PIXELS_PER_MM 20
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun struct mxt_info {
223*4882a593Smuzhiyun u8 family_id;
224*4882a593Smuzhiyun u8 variant_id;
225*4882a593Smuzhiyun u8 version;
226*4882a593Smuzhiyun u8 build;
227*4882a593Smuzhiyun u8 matrix_xsize;
228*4882a593Smuzhiyun u8 matrix_ysize;
229*4882a593Smuzhiyun u8 object_num;
230*4882a593Smuzhiyun };
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun struct mxt_object {
233*4882a593Smuzhiyun u8 type;
234*4882a593Smuzhiyun u16 start_address;
235*4882a593Smuzhiyun u8 size_minus_one;
236*4882a593Smuzhiyun u8 instances_minus_one;
237*4882a593Smuzhiyun u8 num_report_ids;
238*4882a593Smuzhiyun } __packed;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun struct mxt_dbg {
241*4882a593Smuzhiyun u16 t37_address;
242*4882a593Smuzhiyun u16 diag_cmd_address;
243*4882a593Smuzhiyun struct t37_debug *t37_buf;
244*4882a593Smuzhiyun unsigned int t37_pages;
245*4882a593Smuzhiyun unsigned int t37_nodes;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun struct v4l2_device v4l2;
248*4882a593Smuzhiyun struct v4l2_pix_format format;
249*4882a593Smuzhiyun struct video_device vdev;
250*4882a593Smuzhiyun struct vb2_queue queue;
251*4882a593Smuzhiyun struct mutex lock;
252*4882a593Smuzhiyun int input;
253*4882a593Smuzhiyun };
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun enum v4l_dbg_inputs {
256*4882a593Smuzhiyun MXT_V4L_INPUT_DELTAS,
257*4882a593Smuzhiyun MXT_V4L_INPUT_REFS,
258*4882a593Smuzhiyun MXT_V4L_INPUT_MAX,
259*4882a593Smuzhiyun };
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun enum mxt_suspend_mode {
262*4882a593Smuzhiyun MXT_SUSPEND_DEEP_SLEEP = 0,
263*4882a593Smuzhiyun MXT_SUSPEND_T9_CTRL = 1,
264*4882a593Smuzhiyun };
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun /* Config update context */
267*4882a593Smuzhiyun struct mxt_cfg {
268*4882a593Smuzhiyun u8 *raw;
269*4882a593Smuzhiyun size_t raw_size;
270*4882a593Smuzhiyun off_t raw_pos;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun u8 *mem;
273*4882a593Smuzhiyun size_t mem_size;
274*4882a593Smuzhiyun int start_ofs;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun struct mxt_info info;
277*4882a593Smuzhiyun };
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun /* Each client has this additional data */
280*4882a593Smuzhiyun struct mxt_data {
281*4882a593Smuzhiyun struct i2c_client *client;
282*4882a593Smuzhiyun struct input_dev *input_dev;
283*4882a593Smuzhiyun char phys[64]; /* device physical location */
284*4882a593Smuzhiyun struct mxt_object *object_table;
285*4882a593Smuzhiyun struct mxt_info *info;
286*4882a593Smuzhiyun void *raw_info_block;
287*4882a593Smuzhiyun unsigned int irq;
288*4882a593Smuzhiyun unsigned int max_x;
289*4882a593Smuzhiyun unsigned int max_y;
290*4882a593Smuzhiyun bool invertx;
291*4882a593Smuzhiyun bool inverty;
292*4882a593Smuzhiyun bool xy_switch;
293*4882a593Smuzhiyun u8 xsize;
294*4882a593Smuzhiyun u8 ysize;
295*4882a593Smuzhiyun bool in_bootloader;
296*4882a593Smuzhiyun u16 mem_size;
297*4882a593Smuzhiyun u8 t100_aux_ampl;
298*4882a593Smuzhiyun u8 t100_aux_area;
299*4882a593Smuzhiyun u8 t100_aux_vect;
300*4882a593Smuzhiyun u8 max_reportid;
301*4882a593Smuzhiyun u32 config_crc;
302*4882a593Smuzhiyun u32 info_crc;
303*4882a593Smuzhiyun u8 bootloader_addr;
304*4882a593Smuzhiyun u8 *msg_buf;
305*4882a593Smuzhiyun u8 t6_status;
306*4882a593Smuzhiyun bool update_input;
307*4882a593Smuzhiyun u8 last_message_count;
308*4882a593Smuzhiyun u8 num_touchids;
309*4882a593Smuzhiyun u8 multitouch;
310*4882a593Smuzhiyun struct t7_config t7_cfg;
311*4882a593Smuzhiyun struct mxt_dbg dbg;
312*4882a593Smuzhiyun struct gpio_desc *reset_gpio;
313*4882a593Smuzhiyun bool use_retrigen_workaround;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun /* Cached parameters from object table */
316*4882a593Smuzhiyun u16 T5_address;
317*4882a593Smuzhiyun u8 T5_msg_size;
318*4882a593Smuzhiyun u8 T6_reportid;
319*4882a593Smuzhiyun u16 T6_address;
320*4882a593Smuzhiyun u16 T7_address;
321*4882a593Smuzhiyun u16 T71_address;
322*4882a593Smuzhiyun u8 T9_reportid_min;
323*4882a593Smuzhiyun u8 T9_reportid_max;
324*4882a593Smuzhiyun u16 T18_address;
325*4882a593Smuzhiyun u8 T19_reportid;
326*4882a593Smuzhiyun u16 T44_address;
327*4882a593Smuzhiyun u8 T100_reportid_min;
328*4882a593Smuzhiyun u8 T100_reportid_max;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun /* for fw update in bootloader */
331*4882a593Smuzhiyun struct completion bl_completion;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun /* for reset handling */
334*4882a593Smuzhiyun struct completion reset_completion;
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun /* for config update handling */
337*4882a593Smuzhiyun struct completion crc_completion;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun u32 *t19_keymap;
340*4882a593Smuzhiyun unsigned int t19_num_keys;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun enum mxt_suspend_mode suspend_mode;
343*4882a593Smuzhiyun };
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun struct mxt_vb2_buffer {
346*4882a593Smuzhiyun struct vb2_buffer vb;
347*4882a593Smuzhiyun struct list_head list;
348*4882a593Smuzhiyun };
349*4882a593Smuzhiyun
mxt_obj_size(const struct mxt_object * obj)350*4882a593Smuzhiyun static size_t mxt_obj_size(const struct mxt_object *obj)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun return obj->size_minus_one + 1;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
mxt_obj_instances(const struct mxt_object * obj)355*4882a593Smuzhiyun static size_t mxt_obj_instances(const struct mxt_object *obj)
356*4882a593Smuzhiyun {
357*4882a593Smuzhiyun return obj->instances_minus_one + 1;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun
mxt_object_readable(unsigned int type)360*4882a593Smuzhiyun static bool mxt_object_readable(unsigned int type)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun switch (type) {
363*4882a593Smuzhiyun case MXT_GEN_COMMAND_T6:
364*4882a593Smuzhiyun case MXT_GEN_POWER_T7:
365*4882a593Smuzhiyun case MXT_GEN_ACQUIRE_T8:
366*4882a593Smuzhiyun case MXT_GEN_DATASOURCE_T53:
367*4882a593Smuzhiyun case MXT_TOUCH_MULTI_T9:
368*4882a593Smuzhiyun case MXT_TOUCH_KEYARRAY_T15:
369*4882a593Smuzhiyun case MXT_TOUCH_PROXIMITY_T23:
370*4882a593Smuzhiyun case MXT_TOUCH_PROXKEY_T52:
371*4882a593Smuzhiyun case MXT_TOUCH_MULTITOUCHSCREEN_T100:
372*4882a593Smuzhiyun case MXT_PROCI_GRIPFACE_T20:
373*4882a593Smuzhiyun case MXT_PROCG_NOISE_T22:
374*4882a593Smuzhiyun case MXT_PROCI_ONETOUCH_T24:
375*4882a593Smuzhiyun case MXT_PROCI_TWOTOUCH_T27:
376*4882a593Smuzhiyun case MXT_PROCI_GRIP_T40:
377*4882a593Smuzhiyun case MXT_PROCI_PALM_T41:
378*4882a593Smuzhiyun case MXT_PROCI_TOUCHSUPPRESSION_T42:
379*4882a593Smuzhiyun case MXT_PROCI_STYLUS_T47:
380*4882a593Smuzhiyun case MXT_PROCG_NOISESUPPRESSION_T48:
381*4882a593Smuzhiyun case MXT_SPT_COMMSCONFIG_T18:
382*4882a593Smuzhiyun case MXT_SPT_GPIOPWM_T19:
383*4882a593Smuzhiyun case MXT_SPT_SELFTEST_T25:
384*4882a593Smuzhiyun case MXT_SPT_CTECONFIG_T28:
385*4882a593Smuzhiyun case MXT_SPT_USERDATA_T38:
386*4882a593Smuzhiyun case MXT_SPT_DIGITIZER_T43:
387*4882a593Smuzhiyun case MXT_SPT_CTECONFIG_T46:
388*4882a593Smuzhiyun case MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71:
389*4882a593Smuzhiyun return true;
390*4882a593Smuzhiyun default:
391*4882a593Smuzhiyun return false;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun
mxt_dump_message(struct mxt_data * data,u8 * message)395*4882a593Smuzhiyun static void mxt_dump_message(struct mxt_data *data, u8 *message)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun dev_dbg(&data->client->dev, "message: %*ph\n",
398*4882a593Smuzhiyun data->T5_msg_size, message);
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
mxt_wait_for_completion(struct mxt_data * data,struct completion * comp,unsigned int timeout_ms)401*4882a593Smuzhiyun static int mxt_wait_for_completion(struct mxt_data *data,
402*4882a593Smuzhiyun struct completion *comp,
403*4882a593Smuzhiyun unsigned int timeout_ms)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun struct device *dev = &data->client->dev;
406*4882a593Smuzhiyun unsigned long timeout = msecs_to_jiffies(timeout_ms);
407*4882a593Smuzhiyun long ret;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun ret = wait_for_completion_interruptible_timeout(comp, timeout);
410*4882a593Smuzhiyun if (ret < 0) {
411*4882a593Smuzhiyun return ret;
412*4882a593Smuzhiyun } else if (ret == 0) {
413*4882a593Smuzhiyun dev_err(dev, "Wait for completion timed out.\n");
414*4882a593Smuzhiyun return -ETIMEDOUT;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun return 0;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
mxt_bootloader_read(struct mxt_data * data,u8 * val,unsigned int count)419*4882a593Smuzhiyun static int mxt_bootloader_read(struct mxt_data *data,
420*4882a593Smuzhiyun u8 *val, unsigned int count)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun int ret;
423*4882a593Smuzhiyun struct i2c_msg msg;
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun msg.addr = data->bootloader_addr;
426*4882a593Smuzhiyun msg.flags = data->client->flags & I2C_M_TEN;
427*4882a593Smuzhiyun msg.flags |= I2C_M_RD;
428*4882a593Smuzhiyun msg.len = count;
429*4882a593Smuzhiyun msg.buf = val;
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun ret = i2c_transfer(data->client->adapter, &msg, 1);
432*4882a593Smuzhiyun if (ret == 1) {
433*4882a593Smuzhiyun ret = 0;
434*4882a593Smuzhiyun } else {
435*4882a593Smuzhiyun ret = ret < 0 ? ret : -EIO;
436*4882a593Smuzhiyun dev_err(&data->client->dev, "%s: i2c recv failed (%d)\n",
437*4882a593Smuzhiyun __func__, ret);
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun return ret;
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
mxt_bootloader_write(struct mxt_data * data,const u8 * const val,unsigned int count)443*4882a593Smuzhiyun static int mxt_bootloader_write(struct mxt_data *data,
444*4882a593Smuzhiyun const u8 * const val, unsigned int count)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun int ret;
447*4882a593Smuzhiyun struct i2c_msg msg;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun msg.addr = data->bootloader_addr;
450*4882a593Smuzhiyun msg.flags = data->client->flags & I2C_M_TEN;
451*4882a593Smuzhiyun msg.len = count;
452*4882a593Smuzhiyun msg.buf = (u8 *)val;
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun ret = i2c_transfer(data->client->adapter, &msg, 1);
455*4882a593Smuzhiyun if (ret == 1) {
456*4882a593Smuzhiyun ret = 0;
457*4882a593Smuzhiyun } else {
458*4882a593Smuzhiyun ret = ret < 0 ? ret : -EIO;
459*4882a593Smuzhiyun dev_err(&data->client->dev, "%s: i2c send failed (%d)\n",
460*4882a593Smuzhiyun __func__, ret);
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun return ret;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
mxt_lookup_bootloader_address(struct mxt_data * data,bool retry)466*4882a593Smuzhiyun static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun u8 appmode = data->client->addr;
469*4882a593Smuzhiyun u8 bootloader;
470*4882a593Smuzhiyun u8 family_id = data->info ? data->info->family_id : 0;
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun switch (appmode) {
473*4882a593Smuzhiyun case 0x4a:
474*4882a593Smuzhiyun case 0x4b:
475*4882a593Smuzhiyun /* Chips after 1664S use different scheme */
476*4882a593Smuzhiyun if (retry || family_id >= 0xa2) {
477*4882a593Smuzhiyun bootloader = appmode - 0x24;
478*4882a593Smuzhiyun break;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun fallthrough; /* for normal case */
481*4882a593Smuzhiyun case 0x4c:
482*4882a593Smuzhiyun case 0x4d:
483*4882a593Smuzhiyun case 0x5a:
484*4882a593Smuzhiyun case 0x5b:
485*4882a593Smuzhiyun bootloader = appmode - 0x26;
486*4882a593Smuzhiyun break;
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun default:
489*4882a593Smuzhiyun dev_err(&data->client->dev,
490*4882a593Smuzhiyun "Appmode i2c address 0x%02x not found\n",
491*4882a593Smuzhiyun appmode);
492*4882a593Smuzhiyun return -EINVAL;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun data->bootloader_addr = bootloader;
496*4882a593Smuzhiyun return 0;
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun
mxt_probe_bootloader(struct mxt_data * data,bool alt_address)499*4882a593Smuzhiyun static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address)
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun struct device *dev = &data->client->dev;
502*4882a593Smuzhiyun int error;
503*4882a593Smuzhiyun u8 val;
504*4882a593Smuzhiyun bool crc_failure;
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun error = mxt_lookup_bootloader_address(data, alt_address);
507*4882a593Smuzhiyun if (error)
508*4882a593Smuzhiyun return error;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun error = mxt_bootloader_read(data, &val, 1);
511*4882a593Smuzhiyun if (error)
512*4882a593Smuzhiyun return error;
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun /* Check app crc fail mode */
515*4882a593Smuzhiyun crc_failure = (val & ~MXT_BOOT_STATUS_MASK) == MXT_APP_CRC_FAIL;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun dev_err(dev, "Detected bootloader, status:%02X%s\n",
518*4882a593Smuzhiyun val, crc_failure ? ", APP_CRC_FAIL" : "");
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun return 0;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun
mxt_get_bootloader_version(struct mxt_data * data,u8 val)523*4882a593Smuzhiyun static u8 mxt_get_bootloader_version(struct mxt_data *data, u8 val)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun struct device *dev = &data->client->dev;
526*4882a593Smuzhiyun u8 buf[3];
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun if (val & MXT_BOOT_EXTENDED_ID) {
529*4882a593Smuzhiyun if (mxt_bootloader_read(data, &buf[0], 3) != 0) {
530*4882a593Smuzhiyun dev_err(dev, "%s: i2c failure\n", __func__);
531*4882a593Smuzhiyun return val;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun dev_dbg(dev, "Bootloader ID:%d Version:%d\n", buf[1], buf[2]);
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun return buf[0];
537*4882a593Smuzhiyun } else {
538*4882a593Smuzhiyun dev_dbg(dev, "Bootloader ID:%d\n", val & MXT_BOOT_ID_MASK);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun return val;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun
mxt_check_bootloader(struct mxt_data * data,unsigned int state,bool wait)544*4882a593Smuzhiyun static int mxt_check_bootloader(struct mxt_data *data, unsigned int state,
545*4882a593Smuzhiyun bool wait)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun struct device *dev = &data->client->dev;
548*4882a593Smuzhiyun u8 val;
549*4882a593Smuzhiyun int ret;
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun recheck:
552*4882a593Smuzhiyun if (wait) {
553*4882a593Smuzhiyun /*
554*4882a593Smuzhiyun * In application update mode, the interrupt
555*4882a593Smuzhiyun * line signals state transitions. We must wait for the
556*4882a593Smuzhiyun * CHG assertion before reading the status byte.
557*4882a593Smuzhiyun * Once the status byte has been read, the line is deasserted.
558*4882a593Smuzhiyun */
559*4882a593Smuzhiyun ret = mxt_wait_for_completion(data, &data->bl_completion,
560*4882a593Smuzhiyun MXT_FW_CHG_TIMEOUT);
561*4882a593Smuzhiyun if (ret) {
562*4882a593Smuzhiyun /*
563*4882a593Smuzhiyun * TODO: handle -ERESTARTSYS better by terminating
564*4882a593Smuzhiyun * fw update process before returning to userspace
565*4882a593Smuzhiyun * by writing length 0x000 to device (iff we are in
566*4882a593Smuzhiyun * WAITING_FRAME_DATA state).
567*4882a593Smuzhiyun */
568*4882a593Smuzhiyun dev_err(dev, "Update wait error %d\n", ret);
569*4882a593Smuzhiyun return ret;
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun ret = mxt_bootloader_read(data, &val, 1);
574*4882a593Smuzhiyun if (ret)
575*4882a593Smuzhiyun return ret;
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun if (state == MXT_WAITING_BOOTLOAD_CMD)
578*4882a593Smuzhiyun val = mxt_get_bootloader_version(data, val);
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun switch (state) {
581*4882a593Smuzhiyun case MXT_WAITING_BOOTLOAD_CMD:
582*4882a593Smuzhiyun case MXT_WAITING_FRAME_DATA:
583*4882a593Smuzhiyun case MXT_APP_CRC_FAIL:
584*4882a593Smuzhiyun val &= ~MXT_BOOT_STATUS_MASK;
585*4882a593Smuzhiyun break;
586*4882a593Smuzhiyun case MXT_FRAME_CRC_PASS:
587*4882a593Smuzhiyun if (val == MXT_FRAME_CRC_CHECK) {
588*4882a593Smuzhiyun goto recheck;
589*4882a593Smuzhiyun } else if (val == MXT_FRAME_CRC_FAIL) {
590*4882a593Smuzhiyun dev_err(dev, "Bootloader CRC fail\n");
591*4882a593Smuzhiyun return -EINVAL;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun break;
594*4882a593Smuzhiyun default:
595*4882a593Smuzhiyun return -EINVAL;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun if (val != state) {
599*4882a593Smuzhiyun dev_err(dev, "Invalid bootloader state %02X != %02X\n",
600*4882a593Smuzhiyun val, state);
601*4882a593Smuzhiyun return -EINVAL;
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun return 0;
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
mxt_send_bootloader_cmd(struct mxt_data * data,bool unlock)607*4882a593Smuzhiyun static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun int ret;
610*4882a593Smuzhiyun u8 buf[2];
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun if (unlock) {
613*4882a593Smuzhiyun buf[0] = MXT_UNLOCK_CMD_LSB;
614*4882a593Smuzhiyun buf[1] = MXT_UNLOCK_CMD_MSB;
615*4882a593Smuzhiyun } else {
616*4882a593Smuzhiyun buf[0] = 0x01;
617*4882a593Smuzhiyun buf[1] = 0x01;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun ret = mxt_bootloader_write(data, buf, 2);
621*4882a593Smuzhiyun if (ret)
622*4882a593Smuzhiyun return ret;
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun return 0;
625*4882a593Smuzhiyun }
626*4882a593Smuzhiyun
__mxt_read_reg(struct i2c_client * client,u16 reg,u16 len,void * val)627*4882a593Smuzhiyun static int __mxt_read_reg(struct i2c_client *client,
628*4882a593Smuzhiyun u16 reg, u16 len, void *val)
629*4882a593Smuzhiyun {
630*4882a593Smuzhiyun struct i2c_msg xfer[2];
631*4882a593Smuzhiyun u8 buf[2];
632*4882a593Smuzhiyun int ret;
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun buf[0] = reg & 0xff;
635*4882a593Smuzhiyun buf[1] = (reg >> 8) & 0xff;
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun /* Write register */
638*4882a593Smuzhiyun xfer[0].addr = client->addr;
639*4882a593Smuzhiyun xfer[0].flags = 0;
640*4882a593Smuzhiyun xfer[0].len = 2;
641*4882a593Smuzhiyun xfer[0].buf = buf;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun /* Read data */
644*4882a593Smuzhiyun xfer[1].addr = client->addr;
645*4882a593Smuzhiyun xfer[1].flags = I2C_M_RD;
646*4882a593Smuzhiyun xfer[1].len = len;
647*4882a593Smuzhiyun xfer[1].buf = val;
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun ret = i2c_transfer(client->adapter, xfer, 2);
650*4882a593Smuzhiyun if (ret == 2) {
651*4882a593Smuzhiyun ret = 0;
652*4882a593Smuzhiyun } else {
653*4882a593Smuzhiyun if (ret >= 0)
654*4882a593Smuzhiyun ret = -EIO;
655*4882a593Smuzhiyun dev_err(&client->dev, "%s: i2c transfer failed (%d)\n",
656*4882a593Smuzhiyun __func__, ret);
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun return ret;
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun
__mxt_write_reg(struct i2c_client * client,u16 reg,u16 len,const void * val)662*4882a593Smuzhiyun static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
663*4882a593Smuzhiyun const void *val)
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun u8 *buf;
666*4882a593Smuzhiyun size_t count;
667*4882a593Smuzhiyun int ret;
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun count = len + 2;
670*4882a593Smuzhiyun buf = kmalloc(count, GFP_KERNEL);
671*4882a593Smuzhiyun if (!buf)
672*4882a593Smuzhiyun return -ENOMEM;
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun buf[0] = reg & 0xff;
675*4882a593Smuzhiyun buf[1] = (reg >> 8) & 0xff;
676*4882a593Smuzhiyun memcpy(&buf[2], val, len);
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun ret = i2c_master_send(client, buf, count);
679*4882a593Smuzhiyun if (ret == count) {
680*4882a593Smuzhiyun ret = 0;
681*4882a593Smuzhiyun } else {
682*4882a593Smuzhiyun if (ret >= 0)
683*4882a593Smuzhiyun ret = -EIO;
684*4882a593Smuzhiyun dev_err(&client->dev, "%s: i2c send failed (%d)\n",
685*4882a593Smuzhiyun __func__, ret);
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun kfree(buf);
689*4882a593Smuzhiyun return ret;
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun
mxt_write_reg(struct i2c_client * client,u16 reg,u8 val)692*4882a593Smuzhiyun static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
693*4882a593Smuzhiyun {
694*4882a593Smuzhiyun return __mxt_write_reg(client, reg, 1, &val);
695*4882a593Smuzhiyun }
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun static struct mxt_object *
mxt_get_object(struct mxt_data * data,u8 type)698*4882a593Smuzhiyun mxt_get_object(struct mxt_data *data, u8 type)
699*4882a593Smuzhiyun {
700*4882a593Smuzhiyun struct mxt_object *object;
701*4882a593Smuzhiyun int i;
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun for (i = 0; i < data->info->object_num; i++) {
704*4882a593Smuzhiyun object = data->object_table + i;
705*4882a593Smuzhiyun if (object->type == type)
706*4882a593Smuzhiyun return object;
707*4882a593Smuzhiyun }
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun dev_warn(&data->client->dev, "Invalid object type T%u\n", type);
710*4882a593Smuzhiyun return NULL;
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun
mxt_proc_t6_messages(struct mxt_data * data,u8 * msg)713*4882a593Smuzhiyun static void mxt_proc_t6_messages(struct mxt_data *data, u8 *msg)
714*4882a593Smuzhiyun {
715*4882a593Smuzhiyun struct device *dev = &data->client->dev;
716*4882a593Smuzhiyun u8 status = msg[1];
717*4882a593Smuzhiyun u32 crc = msg[2] | (msg[3] << 8) | (msg[4] << 16);
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun if (crc != data->config_crc) {
720*4882a593Smuzhiyun data->config_crc = crc;
721*4882a593Smuzhiyun dev_dbg(dev, "T6 Config Checksum: 0x%06X\n", crc);
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun complete(&data->crc_completion);
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun /* Detect reset */
727*4882a593Smuzhiyun if (status & MXT_T6_STATUS_RESET)
728*4882a593Smuzhiyun complete(&data->reset_completion);
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun /* Output debug if status has changed */
731*4882a593Smuzhiyun if (status != data->t6_status)
732*4882a593Smuzhiyun dev_dbg(dev, "T6 Status 0x%02X%s%s%s%s%s%s%s\n",
733*4882a593Smuzhiyun status,
734*4882a593Smuzhiyun status == 0 ? " OK" : "",
735*4882a593Smuzhiyun status & MXT_T6_STATUS_RESET ? " RESET" : "",
736*4882a593Smuzhiyun status & MXT_T6_STATUS_OFL ? " OFL" : "",
737*4882a593Smuzhiyun status & MXT_T6_STATUS_SIGERR ? " SIGERR" : "",
738*4882a593Smuzhiyun status & MXT_T6_STATUS_CAL ? " CAL" : "",
739*4882a593Smuzhiyun status & MXT_T6_STATUS_CFGERR ? " CFGERR" : "",
740*4882a593Smuzhiyun status & MXT_T6_STATUS_COMSERR ? " COMSERR" : "");
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun /* Save current status */
743*4882a593Smuzhiyun data->t6_status = status;
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun
mxt_write_object(struct mxt_data * data,u8 type,u8 offset,u8 val)746*4882a593Smuzhiyun static int mxt_write_object(struct mxt_data *data,
747*4882a593Smuzhiyun u8 type, u8 offset, u8 val)
748*4882a593Smuzhiyun {
749*4882a593Smuzhiyun struct mxt_object *object;
750*4882a593Smuzhiyun u16 reg;
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun object = mxt_get_object(data, type);
753*4882a593Smuzhiyun if (!object || offset >= mxt_obj_size(object))
754*4882a593Smuzhiyun return -EINVAL;
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun reg = object->start_address;
757*4882a593Smuzhiyun return mxt_write_reg(data->client, reg + offset, val);
758*4882a593Smuzhiyun }
759*4882a593Smuzhiyun
mxt_input_button(struct mxt_data * data,u8 * message)760*4882a593Smuzhiyun static void mxt_input_button(struct mxt_data *data, u8 *message)
761*4882a593Smuzhiyun {
762*4882a593Smuzhiyun struct input_dev *input = data->input_dev;
763*4882a593Smuzhiyun int i;
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun for (i = 0; i < data->t19_num_keys; i++) {
766*4882a593Smuzhiyun if (data->t19_keymap[i] == KEY_RESERVED)
767*4882a593Smuzhiyun continue;
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun /* Active-low switch */
770*4882a593Smuzhiyun input_report_key(input, data->t19_keymap[i],
771*4882a593Smuzhiyun !(message[1] & BIT(i)));
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun
mxt_input_sync(struct mxt_data * data)775*4882a593Smuzhiyun static void mxt_input_sync(struct mxt_data *data)
776*4882a593Smuzhiyun {
777*4882a593Smuzhiyun input_mt_report_pointer_emulation(data->input_dev,
778*4882a593Smuzhiyun data->t19_num_keys);
779*4882a593Smuzhiyun input_sync(data->input_dev);
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun
mxt_proc_t9_message(struct mxt_data * data,u8 * message)782*4882a593Smuzhiyun static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)
783*4882a593Smuzhiyun {
784*4882a593Smuzhiyun struct device *dev = &data->client->dev;
785*4882a593Smuzhiyun struct input_dev *input_dev = data->input_dev;
786*4882a593Smuzhiyun int id;
787*4882a593Smuzhiyun u8 status;
788*4882a593Smuzhiyun int x;
789*4882a593Smuzhiyun int y;
790*4882a593Smuzhiyun int area;
791*4882a593Smuzhiyun int amplitude;
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun id = message[0] - data->T9_reportid_min;
794*4882a593Smuzhiyun status = message[1];
795*4882a593Smuzhiyun x = (message[2] << 4) | ((message[4] >> 4) & 0xf);
796*4882a593Smuzhiyun y = (message[3] << 4) | ((message[4] & 0xf));
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun /* Handle 10/12 bit switching */
799*4882a593Smuzhiyun if (data->max_x < 1024)
800*4882a593Smuzhiyun x >>= 2;
801*4882a593Smuzhiyun if (data->max_y < 1024)
802*4882a593Smuzhiyun y >>= 2;
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun area = message[5];
805*4882a593Smuzhiyun amplitude = message[6];
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun dev_dbg(dev,
808*4882a593Smuzhiyun "[%u] %c%c%c%c%c%c%c%c x: %5u y: %5u area: %3u amp: %3u\n",
809*4882a593Smuzhiyun id,
810*4882a593Smuzhiyun (status & MXT_T9_DETECT) ? 'D' : '.',
811*4882a593Smuzhiyun (status & MXT_T9_PRESS) ? 'P' : '.',
812*4882a593Smuzhiyun (status & MXT_T9_RELEASE) ? 'R' : '.',
813*4882a593Smuzhiyun (status & MXT_T9_MOVE) ? 'M' : '.',
814*4882a593Smuzhiyun (status & MXT_T9_VECTOR) ? 'V' : '.',
815*4882a593Smuzhiyun (status & MXT_T9_AMP) ? 'A' : '.',
816*4882a593Smuzhiyun (status & MXT_T9_SUPPRESS) ? 'S' : '.',
817*4882a593Smuzhiyun (status & MXT_T9_UNGRIP) ? 'U' : '.',
818*4882a593Smuzhiyun x, y, area, amplitude);
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun input_mt_slot(input_dev, id);
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun if (status & MXT_T9_DETECT) {
823*4882a593Smuzhiyun /*
824*4882a593Smuzhiyun * Multiple bits may be set if the host is slow to read
825*4882a593Smuzhiyun * the status messages, indicating all the events that
826*4882a593Smuzhiyun * have happened.
827*4882a593Smuzhiyun */
828*4882a593Smuzhiyun if (status & MXT_T9_RELEASE) {
829*4882a593Smuzhiyun input_mt_report_slot_inactive(input_dev);
830*4882a593Smuzhiyun mxt_input_sync(data);
831*4882a593Smuzhiyun }
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun /* if active, pressure must be non-zero */
834*4882a593Smuzhiyun if (!amplitude)
835*4882a593Smuzhiyun amplitude = MXT_PRESSURE_DEFAULT;
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun /* Touch active */
838*4882a593Smuzhiyun input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, 1);
839*4882a593Smuzhiyun input_report_abs(input_dev, ABS_MT_POSITION_X, x);
840*4882a593Smuzhiyun input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
841*4882a593Smuzhiyun input_report_abs(input_dev, ABS_MT_PRESSURE, amplitude);
842*4882a593Smuzhiyun input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, area);
843*4882a593Smuzhiyun } else {
844*4882a593Smuzhiyun /* Touch no longer active, close out slot */
845*4882a593Smuzhiyun input_mt_report_slot_inactive(input_dev);
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun data->update_input = true;
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun
mxt_proc_t100_message(struct mxt_data * data,u8 * message)851*4882a593Smuzhiyun static void mxt_proc_t100_message(struct mxt_data *data, u8 *message)
852*4882a593Smuzhiyun {
853*4882a593Smuzhiyun struct device *dev = &data->client->dev;
854*4882a593Smuzhiyun struct input_dev *input_dev = data->input_dev;
855*4882a593Smuzhiyun int id;
856*4882a593Smuzhiyun u8 status;
857*4882a593Smuzhiyun u8 type = 0;
858*4882a593Smuzhiyun u16 x;
859*4882a593Smuzhiyun u16 y;
860*4882a593Smuzhiyun int distance = 0;
861*4882a593Smuzhiyun int tool = 0;
862*4882a593Smuzhiyun u8 major = 0;
863*4882a593Smuzhiyun u8 pressure = 0;
864*4882a593Smuzhiyun u8 orientation = 0;
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun id = message[0] - data->T100_reportid_min - 2;
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun /* ignore SCRSTATUS events */
869*4882a593Smuzhiyun if (id < 0)
870*4882a593Smuzhiyun return;
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun status = message[1];
873*4882a593Smuzhiyun x = get_unaligned_le16(&message[2]);
874*4882a593Smuzhiyun y = get_unaligned_le16(&message[4]);
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun if (status & MXT_T100_DETECT) {
877*4882a593Smuzhiyun type = (status & MXT_T100_TYPE_MASK) >> 4;
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun switch (type) {
880*4882a593Smuzhiyun case MXT_T100_TYPE_HOVERING_FINGER:
881*4882a593Smuzhiyun tool = MT_TOOL_FINGER;
882*4882a593Smuzhiyun distance = MXT_DISTANCE_HOVERING;
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun if (data->t100_aux_vect)
885*4882a593Smuzhiyun orientation = message[data->t100_aux_vect];
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun break;
888*4882a593Smuzhiyun
889*4882a593Smuzhiyun case MXT_T100_TYPE_FINGER:
890*4882a593Smuzhiyun case MXT_T100_TYPE_GLOVE:
891*4882a593Smuzhiyun tool = MT_TOOL_FINGER;
892*4882a593Smuzhiyun distance = MXT_DISTANCE_ACTIVE_TOUCH;
893*4882a593Smuzhiyun
894*4882a593Smuzhiyun if (data->t100_aux_area)
895*4882a593Smuzhiyun major = message[data->t100_aux_area];
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun if (data->t100_aux_ampl)
898*4882a593Smuzhiyun pressure = message[data->t100_aux_ampl];
899*4882a593Smuzhiyun
900*4882a593Smuzhiyun if (data->t100_aux_vect)
901*4882a593Smuzhiyun orientation = message[data->t100_aux_vect];
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun break;
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun case MXT_T100_TYPE_PASSIVE_STYLUS:
906*4882a593Smuzhiyun tool = MT_TOOL_PEN;
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun /*
909*4882a593Smuzhiyun * Passive stylus is reported with size zero so
910*4882a593Smuzhiyun * hardcode.
911*4882a593Smuzhiyun */
912*4882a593Smuzhiyun major = MXT_TOUCH_MAJOR_DEFAULT;
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun if (data->t100_aux_ampl)
915*4882a593Smuzhiyun pressure = message[data->t100_aux_ampl];
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun break;
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun case MXT_T100_TYPE_LARGE_TOUCH:
920*4882a593Smuzhiyun /* Ignore suppressed touch */
921*4882a593Smuzhiyun break;
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun default:
924*4882a593Smuzhiyun dev_dbg(dev, "Unexpected T100 type\n");
925*4882a593Smuzhiyun return;
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun }
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun /*
930*4882a593Smuzhiyun * Values reported should be non-zero if tool is touching the
931*4882a593Smuzhiyun * device
932*4882a593Smuzhiyun */
933*4882a593Smuzhiyun if (!pressure && type != MXT_T100_TYPE_HOVERING_FINGER)
934*4882a593Smuzhiyun pressure = MXT_PRESSURE_DEFAULT;
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun input_mt_slot(input_dev, id);
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun if (status & MXT_T100_DETECT) {
939*4882a593Smuzhiyun dev_dbg(dev, "[%u] type:%u x:%u y:%u a:%02X p:%02X v:%02X\n",
940*4882a593Smuzhiyun id, type, x, y, major, pressure, orientation);
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun input_mt_report_slot_state(input_dev, tool, 1);
943*4882a593Smuzhiyun input_report_abs(input_dev, ABS_MT_POSITION_X, x);
944*4882a593Smuzhiyun input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
945*4882a593Smuzhiyun input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, major);
946*4882a593Smuzhiyun input_report_abs(input_dev, ABS_MT_PRESSURE, pressure);
947*4882a593Smuzhiyun input_report_abs(input_dev, ABS_MT_DISTANCE, distance);
948*4882a593Smuzhiyun input_report_abs(input_dev, ABS_MT_ORIENTATION, orientation);
949*4882a593Smuzhiyun } else {
950*4882a593Smuzhiyun dev_dbg(dev, "[%u] release\n", id);
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun /* close out slot */
953*4882a593Smuzhiyun input_mt_report_slot_inactive(input_dev);
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun
956*4882a593Smuzhiyun data->update_input = true;
957*4882a593Smuzhiyun }
958*4882a593Smuzhiyun
mxt_proc_message(struct mxt_data * data,u8 * message)959*4882a593Smuzhiyun static int mxt_proc_message(struct mxt_data *data, u8 *message)
960*4882a593Smuzhiyun {
961*4882a593Smuzhiyun u8 report_id = message[0];
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun if (report_id == MXT_RPTID_NOMSG)
964*4882a593Smuzhiyun return 0;
965*4882a593Smuzhiyun
966*4882a593Smuzhiyun if (report_id == data->T6_reportid) {
967*4882a593Smuzhiyun mxt_proc_t6_messages(data, message);
968*4882a593Smuzhiyun } else if (!data->input_dev) {
969*4882a593Smuzhiyun /*
970*4882a593Smuzhiyun * Do not report events if input device
971*4882a593Smuzhiyun * is not yet registered.
972*4882a593Smuzhiyun */
973*4882a593Smuzhiyun mxt_dump_message(data, message);
974*4882a593Smuzhiyun } else if (report_id >= data->T9_reportid_min &&
975*4882a593Smuzhiyun report_id <= data->T9_reportid_max) {
976*4882a593Smuzhiyun mxt_proc_t9_message(data, message);
977*4882a593Smuzhiyun } else if (report_id >= data->T100_reportid_min &&
978*4882a593Smuzhiyun report_id <= data->T100_reportid_max) {
979*4882a593Smuzhiyun mxt_proc_t100_message(data, message);
980*4882a593Smuzhiyun } else if (report_id == data->T19_reportid) {
981*4882a593Smuzhiyun mxt_input_button(data, message);
982*4882a593Smuzhiyun data->update_input = true;
983*4882a593Smuzhiyun } else {
984*4882a593Smuzhiyun mxt_dump_message(data, message);
985*4882a593Smuzhiyun }
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun return 1;
988*4882a593Smuzhiyun }
989*4882a593Smuzhiyun
mxt_read_and_process_messages(struct mxt_data * data,u8 count)990*4882a593Smuzhiyun static int mxt_read_and_process_messages(struct mxt_data *data, u8 count)
991*4882a593Smuzhiyun {
992*4882a593Smuzhiyun struct device *dev = &data->client->dev;
993*4882a593Smuzhiyun int ret;
994*4882a593Smuzhiyun int i;
995*4882a593Smuzhiyun u8 num_valid = 0;
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun /* Safety check for msg_buf */
998*4882a593Smuzhiyun if (count > data->max_reportid)
999*4882a593Smuzhiyun return -EINVAL;
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun /* Process remaining messages if necessary */
1002*4882a593Smuzhiyun ret = __mxt_read_reg(data->client, data->T5_address,
1003*4882a593Smuzhiyun data->T5_msg_size * count, data->msg_buf);
1004*4882a593Smuzhiyun if (ret) {
1005*4882a593Smuzhiyun dev_err(dev, "Failed to read %u messages (%d)\n", count, ret);
1006*4882a593Smuzhiyun return ret;
1007*4882a593Smuzhiyun }
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun for (i = 0; i < count; i++) {
1010*4882a593Smuzhiyun ret = mxt_proc_message(data,
1011*4882a593Smuzhiyun data->msg_buf + data->T5_msg_size * i);
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun if (ret == 1)
1014*4882a593Smuzhiyun num_valid++;
1015*4882a593Smuzhiyun }
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun /* return number of messages read */
1018*4882a593Smuzhiyun return num_valid;
1019*4882a593Smuzhiyun }
1020*4882a593Smuzhiyun
mxt_process_messages_t44(struct mxt_data * data)1021*4882a593Smuzhiyun static irqreturn_t mxt_process_messages_t44(struct mxt_data *data)
1022*4882a593Smuzhiyun {
1023*4882a593Smuzhiyun struct device *dev = &data->client->dev;
1024*4882a593Smuzhiyun int ret;
1025*4882a593Smuzhiyun u8 count, num_left;
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun /* Read T44 and T5 together */
1028*4882a593Smuzhiyun ret = __mxt_read_reg(data->client, data->T44_address,
1029*4882a593Smuzhiyun data->T5_msg_size + 1, data->msg_buf);
1030*4882a593Smuzhiyun if (ret) {
1031*4882a593Smuzhiyun dev_err(dev, "Failed to read T44 and T5 (%d)\n", ret);
1032*4882a593Smuzhiyun return IRQ_NONE;
1033*4882a593Smuzhiyun }
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun count = data->msg_buf[0];
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun /*
1038*4882a593Smuzhiyun * This condition may be caused by the CHG line being configured in
1039*4882a593Smuzhiyun * Mode 0. It results in unnecessary I2C operations but it is benign.
1040*4882a593Smuzhiyun */
1041*4882a593Smuzhiyun if (count == 0)
1042*4882a593Smuzhiyun return IRQ_NONE;
1043*4882a593Smuzhiyun
1044*4882a593Smuzhiyun if (count > data->max_reportid) {
1045*4882a593Smuzhiyun dev_warn(dev, "T44 count %d exceeded max report id\n", count);
1046*4882a593Smuzhiyun count = data->max_reportid;
1047*4882a593Smuzhiyun }
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun /* Process first message */
1050*4882a593Smuzhiyun ret = mxt_proc_message(data, data->msg_buf + 1);
1051*4882a593Smuzhiyun if (ret < 0) {
1052*4882a593Smuzhiyun dev_warn(dev, "Unexpected invalid message\n");
1053*4882a593Smuzhiyun return IRQ_NONE;
1054*4882a593Smuzhiyun }
1055*4882a593Smuzhiyun
1056*4882a593Smuzhiyun num_left = count - 1;
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun /* Process remaining messages if necessary */
1059*4882a593Smuzhiyun if (num_left) {
1060*4882a593Smuzhiyun ret = mxt_read_and_process_messages(data, num_left);
1061*4882a593Smuzhiyun if (ret < 0)
1062*4882a593Smuzhiyun goto end;
1063*4882a593Smuzhiyun else if (ret != num_left)
1064*4882a593Smuzhiyun dev_warn(dev, "Unexpected invalid message\n");
1065*4882a593Smuzhiyun }
1066*4882a593Smuzhiyun
1067*4882a593Smuzhiyun end:
1068*4882a593Smuzhiyun if (data->update_input) {
1069*4882a593Smuzhiyun mxt_input_sync(data);
1070*4882a593Smuzhiyun data->update_input = false;
1071*4882a593Smuzhiyun }
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun return IRQ_HANDLED;
1074*4882a593Smuzhiyun }
1075*4882a593Smuzhiyun
mxt_process_messages_until_invalid(struct mxt_data * data)1076*4882a593Smuzhiyun static int mxt_process_messages_until_invalid(struct mxt_data *data)
1077*4882a593Smuzhiyun {
1078*4882a593Smuzhiyun struct device *dev = &data->client->dev;
1079*4882a593Smuzhiyun int count, read;
1080*4882a593Smuzhiyun u8 tries = 2;
1081*4882a593Smuzhiyun
1082*4882a593Smuzhiyun count = data->max_reportid;
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun /* Read messages until we force an invalid */
1085*4882a593Smuzhiyun do {
1086*4882a593Smuzhiyun read = mxt_read_and_process_messages(data, count);
1087*4882a593Smuzhiyun if (read < count)
1088*4882a593Smuzhiyun return 0;
1089*4882a593Smuzhiyun } while (--tries);
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun if (data->update_input) {
1092*4882a593Smuzhiyun mxt_input_sync(data);
1093*4882a593Smuzhiyun data->update_input = false;
1094*4882a593Smuzhiyun }
1095*4882a593Smuzhiyun
1096*4882a593Smuzhiyun dev_err(dev, "CHG pin isn't cleared\n");
1097*4882a593Smuzhiyun return -EBUSY;
1098*4882a593Smuzhiyun }
1099*4882a593Smuzhiyun
mxt_process_messages(struct mxt_data * data)1100*4882a593Smuzhiyun static irqreturn_t mxt_process_messages(struct mxt_data *data)
1101*4882a593Smuzhiyun {
1102*4882a593Smuzhiyun int total_handled, num_handled;
1103*4882a593Smuzhiyun u8 count = data->last_message_count;
1104*4882a593Smuzhiyun
1105*4882a593Smuzhiyun if (count < 1 || count > data->max_reportid)
1106*4882a593Smuzhiyun count = 1;
1107*4882a593Smuzhiyun
1108*4882a593Smuzhiyun /* include final invalid message */
1109*4882a593Smuzhiyun total_handled = mxt_read_and_process_messages(data, count + 1);
1110*4882a593Smuzhiyun if (total_handled < 0)
1111*4882a593Smuzhiyun return IRQ_NONE;
1112*4882a593Smuzhiyun /* if there were invalid messages, then we are done */
1113*4882a593Smuzhiyun else if (total_handled <= count)
1114*4882a593Smuzhiyun goto update_count;
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun /* keep reading two msgs until one is invalid or reportid limit */
1117*4882a593Smuzhiyun do {
1118*4882a593Smuzhiyun num_handled = mxt_read_and_process_messages(data, 2);
1119*4882a593Smuzhiyun if (num_handled < 0)
1120*4882a593Smuzhiyun return IRQ_NONE;
1121*4882a593Smuzhiyun
1122*4882a593Smuzhiyun total_handled += num_handled;
1123*4882a593Smuzhiyun
1124*4882a593Smuzhiyun if (num_handled < 2)
1125*4882a593Smuzhiyun break;
1126*4882a593Smuzhiyun } while (total_handled < data->num_touchids);
1127*4882a593Smuzhiyun
1128*4882a593Smuzhiyun update_count:
1129*4882a593Smuzhiyun data->last_message_count = total_handled;
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun if (data->update_input) {
1132*4882a593Smuzhiyun mxt_input_sync(data);
1133*4882a593Smuzhiyun data->update_input = false;
1134*4882a593Smuzhiyun }
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun return IRQ_HANDLED;
1137*4882a593Smuzhiyun }
1138*4882a593Smuzhiyun
mxt_interrupt(int irq,void * dev_id)1139*4882a593Smuzhiyun static irqreturn_t mxt_interrupt(int irq, void *dev_id)
1140*4882a593Smuzhiyun {
1141*4882a593Smuzhiyun struct mxt_data *data = dev_id;
1142*4882a593Smuzhiyun
1143*4882a593Smuzhiyun if (data->in_bootloader) {
1144*4882a593Smuzhiyun /* bootloader state transition completion */
1145*4882a593Smuzhiyun complete(&data->bl_completion);
1146*4882a593Smuzhiyun return IRQ_HANDLED;
1147*4882a593Smuzhiyun }
1148*4882a593Smuzhiyun
1149*4882a593Smuzhiyun if (!data->object_table)
1150*4882a593Smuzhiyun return IRQ_HANDLED;
1151*4882a593Smuzhiyun
1152*4882a593Smuzhiyun if (data->T44_address) {
1153*4882a593Smuzhiyun return mxt_process_messages_t44(data);
1154*4882a593Smuzhiyun } else {
1155*4882a593Smuzhiyun return mxt_process_messages(data);
1156*4882a593Smuzhiyun }
1157*4882a593Smuzhiyun }
1158*4882a593Smuzhiyun
mxt_t6_command(struct mxt_data * data,u16 cmd_offset,u8 value,bool wait)1159*4882a593Smuzhiyun static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset,
1160*4882a593Smuzhiyun u8 value, bool wait)
1161*4882a593Smuzhiyun {
1162*4882a593Smuzhiyun u16 reg;
1163*4882a593Smuzhiyun u8 command_register;
1164*4882a593Smuzhiyun int timeout_counter = 0;
1165*4882a593Smuzhiyun int ret;
1166*4882a593Smuzhiyun
1167*4882a593Smuzhiyun reg = data->T6_address + cmd_offset;
1168*4882a593Smuzhiyun
1169*4882a593Smuzhiyun ret = mxt_write_reg(data->client, reg, value);
1170*4882a593Smuzhiyun if (ret)
1171*4882a593Smuzhiyun return ret;
1172*4882a593Smuzhiyun
1173*4882a593Smuzhiyun if (!wait)
1174*4882a593Smuzhiyun return 0;
1175*4882a593Smuzhiyun
1176*4882a593Smuzhiyun do {
1177*4882a593Smuzhiyun msleep(20);
1178*4882a593Smuzhiyun ret = __mxt_read_reg(data->client, reg, 1, &command_register);
1179*4882a593Smuzhiyun if (ret)
1180*4882a593Smuzhiyun return ret;
1181*4882a593Smuzhiyun } while (command_register != 0 && timeout_counter++ <= 100);
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun if (timeout_counter > 100) {
1184*4882a593Smuzhiyun dev_err(&data->client->dev, "Command failed!\n");
1185*4882a593Smuzhiyun return -EIO;
1186*4882a593Smuzhiyun }
1187*4882a593Smuzhiyun
1188*4882a593Smuzhiyun return 0;
1189*4882a593Smuzhiyun }
1190*4882a593Smuzhiyun
mxt_acquire_irq(struct mxt_data * data)1191*4882a593Smuzhiyun static int mxt_acquire_irq(struct mxt_data *data)
1192*4882a593Smuzhiyun {
1193*4882a593Smuzhiyun int error;
1194*4882a593Smuzhiyun
1195*4882a593Smuzhiyun enable_irq(data->irq);
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun if (data->use_retrigen_workaround) {
1198*4882a593Smuzhiyun error = mxt_process_messages_until_invalid(data);
1199*4882a593Smuzhiyun if (error)
1200*4882a593Smuzhiyun return error;
1201*4882a593Smuzhiyun }
1202*4882a593Smuzhiyun
1203*4882a593Smuzhiyun return 0;
1204*4882a593Smuzhiyun }
1205*4882a593Smuzhiyun
mxt_soft_reset(struct mxt_data * data)1206*4882a593Smuzhiyun static int mxt_soft_reset(struct mxt_data *data)
1207*4882a593Smuzhiyun {
1208*4882a593Smuzhiyun struct device *dev = &data->client->dev;
1209*4882a593Smuzhiyun int ret = 0;
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun dev_info(dev, "Resetting device\n");
1212*4882a593Smuzhiyun
1213*4882a593Smuzhiyun disable_irq(data->irq);
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun reinit_completion(&data->reset_completion);
1216*4882a593Smuzhiyun
1217*4882a593Smuzhiyun ret = mxt_t6_command(data, MXT_COMMAND_RESET, MXT_RESET_VALUE, false);
1218*4882a593Smuzhiyun if (ret)
1219*4882a593Smuzhiyun return ret;
1220*4882a593Smuzhiyun
1221*4882a593Smuzhiyun /* Ignore CHG line for 100ms after reset */
1222*4882a593Smuzhiyun msleep(MXT_RESET_INVALID_CHG);
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun mxt_acquire_irq(data);
1225*4882a593Smuzhiyun
1226*4882a593Smuzhiyun ret = mxt_wait_for_completion(data, &data->reset_completion,
1227*4882a593Smuzhiyun MXT_RESET_TIMEOUT);
1228*4882a593Smuzhiyun if (ret)
1229*4882a593Smuzhiyun return ret;
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun return 0;
1232*4882a593Smuzhiyun }
1233*4882a593Smuzhiyun
mxt_update_crc(struct mxt_data * data,u8 cmd,u8 value)1234*4882a593Smuzhiyun static void mxt_update_crc(struct mxt_data *data, u8 cmd, u8 value)
1235*4882a593Smuzhiyun {
1236*4882a593Smuzhiyun /*
1237*4882a593Smuzhiyun * On failure, CRC is set to 0 and config will always be
1238*4882a593Smuzhiyun * downloaded.
1239*4882a593Smuzhiyun */
1240*4882a593Smuzhiyun data->config_crc = 0;
1241*4882a593Smuzhiyun reinit_completion(&data->crc_completion);
1242*4882a593Smuzhiyun
1243*4882a593Smuzhiyun mxt_t6_command(data, cmd, value, true);
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyun /*
1246*4882a593Smuzhiyun * Wait for crc message. On failure, CRC is set to 0 and config will
1247*4882a593Smuzhiyun * always be downloaded.
1248*4882a593Smuzhiyun */
1249*4882a593Smuzhiyun mxt_wait_for_completion(data, &data->crc_completion, MXT_CRC_TIMEOUT);
1250*4882a593Smuzhiyun }
1251*4882a593Smuzhiyun
mxt_calc_crc24(u32 * crc,u8 firstbyte,u8 secondbyte)1252*4882a593Smuzhiyun static void mxt_calc_crc24(u32 *crc, u8 firstbyte, u8 secondbyte)
1253*4882a593Smuzhiyun {
1254*4882a593Smuzhiyun static const unsigned int crcpoly = 0x80001B;
1255*4882a593Smuzhiyun u32 result;
1256*4882a593Smuzhiyun u32 data_word;
1257*4882a593Smuzhiyun
1258*4882a593Smuzhiyun data_word = (secondbyte << 8) | firstbyte;
1259*4882a593Smuzhiyun result = ((*crc << 1) ^ data_word);
1260*4882a593Smuzhiyun
1261*4882a593Smuzhiyun if (result & 0x1000000)
1262*4882a593Smuzhiyun result ^= crcpoly;
1263*4882a593Smuzhiyun
1264*4882a593Smuzhiyun *crc = result;
1265*4882a593Smuzhiyun }
1266*4882a593Smuzhiyun
mxt_calculate_crc(u8 * base,off_t start_off,off_t end_off)1267*4882a593Smuzhiyun static u32 mxt_calculate_crc(u8 *base, off_t start_off, off_t end_off)
1268*4882a593Smuzhiyun {
1269*4882a593Smuzhiyun u32 crc = 0;
1270*4882a593Smuzhiyun u8 *ptr = base + start_off;
1271*4882a593Smuzhiyun u8 *last_val = base + end_off - 1;
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun if (end_off < start_off)
1274*4882a593Smuzhiyun return -EINVAL;
1275*4882a593Smuzhiyun
1276*4882a593Smuzhiyun while (ptr < last_val) {
1277*4882a593Smuzhiyun mxt_calc_crc24(&crc, *ptr, *(ptr + 1));
1278*4882a593Smuzhiyun ptr += 2;
1279*4882a593Smuzhiyun }
1280*4882a593Smuzhiyun
1281*4882a593Smuzhiyun /* if len is odd, fill the last byte with 0 */
1282*4882a593Smuzhiyun if (ptr == last_val)
1283*4882a593Smuzhiyun mxt_calc_crc24(&crc, *ptr, 0);
1284*4882a593Smuzhiyun
1285*4882a593Smuzhiyun /* Mask to 24-bit */
1286*4882a593Smuzhiyun crc &= 0x00FFFFFF;
1287*4882a593Smuzhiyun
1288*4882a593Smuzhiyun return crc;
1289*4882a593Smuzhiyun }
1290*4882a593Smuzhiyun
mxt_check_retrigen(struct mxt_data * data)1291*4882a593Smuzhiyun static int mxt_check_retrigen(struct mxt_data *data)
1292*4882a593Smuzhiyun {
1293*4882a593Smuzhiyun struct i2c_client *client = data->client;
1294*4882a593Smuzhiyun int error;
1295*4882a593Smuzhiyun int val;
1296*4882a593Smuzhiyun struct irq_data *irqd;
1297*4882a593Smuzhiyun
1298*4882a593Smuzhiyun data->use_retrigen_workaround = false;
1299*4882a593Smuzhiyun
1300*4882a593Smuzhiyun irqd = irq_get_irq_data(data->irq);
1301*4882a593Smuzhiyun if (!irqd)
1302*4882a593Smuzhiyun return -EINVAL;
1303*4882a593Smuzhiyun
1304*4882a593Smuzhiyun if (irqd_is_level_type(irqd))
1305*4882a593Smuzhiyun return 0;
1306*4882a593Smuzhiyun
1307*4882a593Smuzhiyun if (data->T18_address) {
1308*4882a593Smuzhiyun error = __mxt_read_reg(client,
1309*4882a593Smuzhiyun data->T18_address + MXT_COMMS_CTRL,
1310*4882a593Smuzhiyun 1, &val);
1311*4882a593Smuzhiyun if (error)
1312*4882a593Smuzhiyun return error;
1313*4882a593Smuzhiyun
1314*4882a593Smuzhiyun if (val & MXT_COMMS_RETRIGEN)
1315*4882a593Smuzhiyun return 0;
1316*4882a593Smuzhiyun }
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun dev_warn(&client->dev, "Enabling RETRIGEN workaround\n");
1319*4882a593Smuzhiyun data->use_retrigen_workaround = true;
1320*4882a593Smuzhiyun return 0;
1321*4882a593Smuzhiyun }
1322*4882a593Smuzhiyun
mxt_prepare_cfg_mem(struct mxt_data * data,struct mxt_cfg * cfg)1323*4882a593Smuzhiyun static int mxt_prepare_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg)
1324*4882a593Smuzhiyun {
1325*4882a593Smuzhiyun struct device *dev = &data->client->dev;
1326*4882a593Smuzhiyun struct mxt_object *object;
1327*4882a593Smuzhiyun unsigned int type, instance, size, byte_offset;
1328*4882a593Smuzhiyun int offset;
1329*4882a593Smuzhiyun int ret;
1330*4882a593Smuzhiyun int i;
1331*4882a593Smuzhiyun u16 reg;
1332*4882a593Smuzhiyun u8 val;
1333*4882a593Smuzhiyun
1334*4882a593Smuzhiyun while (cfg->raw_pos < cfg->raw_size) {
1335*4882a593Smuzhiyun /* Read type, instance, length */
1336*4882a593Smuzhiyun ret = sscanf(cfg->raw + cfg->raw_pos, "%x %x %x%n",
1337*4882a593Smuzhiyun &type, &instance, &size, &offset);
1338*4882a593Smuzhiyun if (ret == 0) {
1339*4882a593Smuzhiyun /* EOF */
1340*4882a593Smuzhiyun break;
1341*4882a593Smuzhiyun } else if (ret != 3) {
1342*4882a593Smuzhiyun dev_err(dev, "Bad format: failed to parse object\n");
1343*4882a593Smuzhiyun return -EINVAL;
1344*4882a593Smuzhiyun }
1345*4882a593Smuzhiyun cfg->raw_pos += offset;
1346*4882a593Smuzhiyun
1347*4882a593Smuzhiyun object = mxt_get_object(data, type);
1348*4882a593Smuzhiyun if (!object) {
1349*4882a593Smuzhiyun /* Skip object */
1350*4882a593Smuzhiyun for (i = 0; i < size; i++) {
1351*4882a593Smuzhiyun ret = sscanf(cfg->raw + cfg->raw_pos, "%hhx%n",
1352*4882a593Smuzhiyun &val, &offset);
1353*4882a593Smuzhiyun if (ret != 1) {
1354*4882a593Smuzhiyun dev_err(dev, "Bad format in T%d at %d\n",
1355*4882a593Smuzhiyun type, i);
1356*4882a593Smuzhiyun return -EINVAL;
1357*4882a593Smuzhiyun }
1358*4882a593Smuzhiyun cfg->raw_pos += offset;
1359*4882a593Smuzhiyun }
1360*4882a593Smuzhiyun continue;
1361*4882a593Smuzhiyun }
1362*4882a593Smuzhiyun
1363*4882a593Smuzhiyun if (size > mxt_obj_size(object)) {
1364*4882a593Smuzhiyun /*
1365*4882a593Smuzhiyun * Either we are in fallback mode due to wrong
1366*4882a593Smuzhiyun * config or config from a later fw version,
1367*4882a593Smuzhiyun * or the file is corrupt or hand-edited.
1368*4882a593Smuzhiyun */
1369*4882a593Smuzhiyun dev_warn(dev, "Discarding %zu byte(s) in T%u\n",
1370*4882a593Smuzhiyun size - mxt_obj_size(object), type);
1371*4882a593Smuzhiyun } else if (mxt_obj_size(object) > size) {
1372*4882a593Smuzhiyun /*
1373*4882a593Smuzhiyun * If firmware is upgraded, new bytes may be added to
1374*4882a593Smuzhiyun * end of objects. It is generally forward compatible
1375*4882a593Smuzhiyun * to zero these bytes - previous behaviour will be
1376*4882a593Smuzhiyun * retained. However this does invalidate the CRC and
1377*4882a593Smuzhiyun * will force fallback mode until the configuration is
1378*4882a593Smuzhiyun * updated. We warn here but do nothing else - the
1379*4882a593Smuzhiyun * malloc has zeroed the entire configuration.
1380*4882a593Smuzhiyun */
1381*4882a593Smuzhiyun dev_warn(dev, "Zeroing %zu byte(s) in T%d\n",
1382*4882a593Smuzhiyun mxt_obj_size(object) - size, type);
1383*4882a593Smuzhiyun }
1384*4882a593Smuzhiyun
1385*4882a593Smuzhiyun if (instance >= mxt_obj_instances(object)) {
1386*4882a593Smuzhiyun dev_err(dev, "Object instances exceeded!\n");
1387*4882a593Smuzhiyun return -EINVAL;
1388*4882a593Smuzhiyun }
1389*4882a593Smuzhiyun
1390*4882a593Smuzhiyun reg = object->start_address + mxt_obj_size(object) * instance;
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun for (i = 0; i < size; i++) {
1393*4882a593Smuzhiyun ret = sscanf(cfg->raw + cfg->raw_pos, "%hhx%n",
1394*4882a593Smuzhiyun &val,
1395*4882a593Smuzhiyun &offset);
1396*4882a593Smuzhiyun if (ret != 1) {
1397*4882a593Smuzhiyun dev_err(dev, "Bad format in T%d at %d\n",
1398*4882a593Smuzhiyun type, i);
1399*4882a593Smuzhiyun return -EINVAL;
1400*4882a593Smuzhiyun }
1401*4882a593Smuzhiyun cfg->raw_pos += offset;
1402*4882a593Smuzhiyun
1403*4882a593Smuzhiyun if (i > mxt_obj_size(object))
1404*4882a593Smuzhiyun continue;
1405*4882a593Smuzhiyun
1406*4882a593Smuzhiyun byte_offset = reg + i - cfg->start_ofs;
1407*4882a593Smuzhiyun
1408*4882a593Smuzhiyun if (byte_offset >= 0 && byte_offset < cfg->mem_size) {
1409*4882a593Smuzhiyun *(cfg->mem + byte_offset) = val;
1410*4882a593Smuzhiyun } else {
1411*4882a593Smuzhiyun dev_err(dev, "Bad object: reg:%d, T%d, ofs=%d\n",
1412*4882a593Smuzhiyun reg, object->type, byte_offset);
1413*4882a593Smuzhiyun return -EINVAL;
1414*4882a593Smuzhiyun }
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun }
1417*4882a593Smuzhiyun
1418*4882a593Smuzhiyun return 0;
1419*4882a593Smuzhiyun }
1420*4882a593Smuzhiyun
mxt_upload_cfg_mem(struct mxt_data * data,struct mxt_cfg * cfg)1421*4882a593Smuzhiyun static int mxt_upload_cfg_mem(struct mxt_data *data, struct mxt_cfg *cfg)
1422*4882a593Smuzhiyun {
1423*4882a593Smuzhiyun unsigned int byte_offset = 0;
1424*4882a593Smuzhiyun int error;
1425*4882a593Smuzhiyun
1426*4882a593Smuzhiyun /* Write configuration as blocks */
1427*4882a593Smuzhiyun while (byte_offset < cfg->mem_size) {
1428*4882a593Smuzhiyun unsigned int size = cfg->mem_size - byte_offset;
1429*4882a593Smuzhiyun
1430*4882a593Smuzhiyun if (size > MXT_MAX_BLOCK_WRITE)
1431*4882a593Smuzhiyun size = MXT_MAX_BLOCK_WRITE;
1432*4882a593Smuzhiyun
1433*4882a593Smuzhiyun error = __mxt_write_reg(data->client,
1434*4882a593Smuzhiyun cfg->start_ofs + byte_offset,
1435*4882a593Smuzhiyun size, cfg->mem + byte_offset);
1436*4882a593Smuzhiyun if (error) {
1437*4882a593Smuzhiyun dev_err(&data->client->dev,
1438*4882a593Smuzhiyun "Config write error, ret=%d\n", error);
1439*4882a593Smuzhiyun return error;
1440*4882a593Smuzhiyun }
1441*4882a593Smuzhiyun
1442*4882a593Smuzhiyun byte_offset += size;
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun
1445*4882a593Smuzhiyun return 0;
1446*4882a593Smuzhiyun }
1447*4882a593Smuzhiyun
1448*4882a593Smuzhiyun static int mxt_init_t7_power_cfg(struct mxt_data *data);
1449*4882a593Smuzhiyun
1450*4882a593Smuzhiyun /*
1451*4882a593Smuzhiyun * mxt_update_cfg - download configuration to chip
1452*4882a593Smuzhiyun *
1453*4882a593Smuzhiyun * Atmel Raw Config File Format
1454*4882a593Smuzhiyun *
1455*4882a593Smuzhiyun * The first four lines of the raw config file contain:
1456*4882a593Smuzhiyun * 1) Version
1457*4882a593Smuzhiyun * 2) Chip ID Information (first 7 bytes of device memory)
1458*4882a593Smuzhiyun * 3) Chip Information Block 24-bit CRC Checksum
1459*4882a593Smuzhiyun * 4) Chip Configuration 24-bit CRC Checksum
1460*4882a593Smuzhiyun *
1461*4882a593Smuzhiyun * The rest of the file consists of one line per object instance:
1462*4882a593Smuzhiyun * <TYPE> <INSTANCE> <SIZE> <CONTENTS>
1463*4882a593Smuzhiyun *
1464*4882a593Smuzhiyun * <TYPE> - 2-byte object type as hex
1465*4882a593Smuzhiyun * <INSTANCE> - 2-byte object instance number as hex
1466*4882a593Smuzhiyun * <SIZE> - 2-byte object size as hex
1467*4882a593Smuzhiyun * <CONTENTS> - array of <SIZE> 1-byte hex values
1468*4882a593Smuzhiyun */
mxt_update_cfg(struct mxt_data * data,const struct firmware * fw)1469*4882a593Smuzhiyun static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
1470*4882a593Smuzhiyun {
1471*4882a593Smuzhiyun struct device *dev = &data->client->dev;
1472*4882a593Smuzhiyun struct mxt_cfg cfg;
1473*4882a593Smuzhiyun int ret;
1474*4882a593Smuzhiyun int offset;
1475*4882a593Smuzhiyun int i;
1476*4882a593Smuzhiyun u32 info_crc, config_crc, calculated_crc;
1477*4882a593Smuzhiyun u16 crc_start = 0;
1478*4882a593Smuzhiyun
1479*4882a593Smuzhiyun /* Make zero terminated copy of the OBP_RAW file */
1480*4882a593Smuzhiyun cfg.raw = kmemdup_nul(fw->data, fw->size, GFP_KERNEL);
1481*4882a593Smuzhiyun if (!cfg.raw)
1482*4882a593Smuzhiyun return -ENOMEM;
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun cfg.raw_size = fw->size;
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1);
1487*4882a593Smuzhiyun
1488*4882a593Smuzhiyun if (strncmp(cfg.raw, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) {
1489*4882a593Smuzhiyun dev_err(dev, "Unrecognised config file\n");
1490*4882a593Smuzhiyun ret = -EINVAL;
1491*4882a593Smuzhiyun goto release_raw;
1492*4882a593Smuzhiyun }
1493*4882a593Smuzhiyun
1494*4882a593Smuzhiyun cfg.raw_pos = strlen(MXT_CFG_MAGIC);
1495*4882a593Smuzhiyun
1496*4882a593Smuzhiyun /* Load information block and check */
1497*4882a593Smuzhiyun for (i = 0; i < sizeof(struct mxt_info); i++) {
1498*4882a593Smuzhiyun ret = sscanf(cfg.raw + cfg.raw_pos, "%hhx%n",
1499*4882a593Smuzhiyun (unsigned char *)&cfg.info + i,
1500*4882a593Smuzhiyun &offset);
1501*4882a593Smuzhiyun if (ret != 1) {
1502*4882a593Smuzhiyun dev_err(dev, "Bad format\n");
1503*4882a593Smuzhiyun ret = -EINVAL;
1504*4882a593Smuzhiyun goto release_raw;
1505*4882a593Smuzhiyun }
1506*4882a593Smuzhiyun
1507*4882a593Smuzhiyun cfg.raw_pos += offset;
1508*4882a593Smuzhiyun }
1509*4882a593Smuzhiyun
1510*4882a593Smuzhiyun if (cfg.info.family_id != data->info->family_id) {
1511*4882a593Smuzhiyun dev_err(dev, "Family ID mismatch!\n");
1512*4882a593Smuzhiyun ret = -EINVAL;
1513*4882a593Smuzhiyun goto release_raw;
1514*4882a593Smuzhiyun }
1515*4882a593Smuzhiyun
1516*4882a593Smuzhiyun if (cfg.info.variant_id != data->info->variant_id) {
1517*4882a593Smuzhiyun dev_err(dev, "Variant ID mismatch!\n");
1518*4882a593Smuzhiyun ret = -EINVAL;
1519*4882a593Smuzhiyun goto release_raw;
1520*4882a593Smuzhiyun }
1521*4882a593Smuzhiyun
1522*4882a593Smuzhiyun /* Read CRCs */
1523*4882a593Smuzhiyun ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &info_crc, &offset);
1524*4882a593Smuzhiyun if (ret != 1) {
1525*4882a593Smuzhiyun dev_err(dev, "Bad format: failed to parse Info CRC\n");
1526*4882a593Smuzhiyun ret = -EINVAL;
1527*4882a593Smuzhiyun goto release_raw;
1528*4882a593Smuzhiyun }
1529*4882a593Smuzhiyun cfg.raw_pos += offset;
1530*4882a593Smuzhiyun
1531*4882a593Smuzhiyun ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &config_crc, &offset);
1532*4882a593Smuzhiyun if (ret != 1) {
1533*4882a593Smuzhiyun dev_err(dev, "Bad format: failed to parse Config CRC\n");
1534*4882a593Smuzhiyun ret = -EINVAL;
1535*4882a593Smuzhiyun goto release_raw;
1536*4882a593Smuzhiyun }
1537*4882a593Smuzhiyun cfg.raw_pos += offset;
1538*4882a593Smuzhiyun
1539*4882a593Smuzhiyun /*
1540*4882a593Smuzhiyun * The Info Block CRC is calculated over mxt_info and the object
1541*4882a593Smuzhiyun * table. If it does not match then we are trying to load the
1542*4882a593Smuzhiyun * configuration from a different chip or firmware version, so
1543*4882a593Smuzhiyun * the configuration CRC is invalid anyway.
1544*4882a593Smuzhiyun */
1545*4882a593Smuzhiyun if (info_crc == data->info_crc) {
1546*4882a593Smuzhiyun if (config_crc == 0 || data->config_crc == 0) {
1547*4882a593Smuzhiyun dev_info(dev, "CRC zero, attempting to apply config\n");
1548*4882a593Smuzhiyun } else if (config_crc == data->config_crc) {
1549*4882a593Smuzhiyun dev_dbg(dev, "Config CRC 0x%06X: OK\n",
1550*4882a593Smuzhiyun data->config_crc);
1551*4882a593Smuzhiyun ret = 0;
1552*4882a593Smuzhiyun goto release_raw;
1553*4882a593Smuzhiyun } else {
1554*4882a593Smuzhiyun dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n",
1555*4882a593Smuzhiyun data->config_crc, config_crc);
1556*4882a593Smuzhiyun }
1557*4882a593Smuzhiyun } else {
1558*4882a593Smuzhiyun dev_warn(dev,
1559*4882a593Smuzhiyun "Warning: Info CRC error - device=0x%06X file=0x%06X\n",
1560*4882a593Smuzhiyun data->info_crc, info_crc);
1561*4882a593Smuzhiyun }
1562*4882a593Smuzhiyun
1563*4882a593Smuzhiyun /* Malloc memory to store configuration */
1564*4882a593Smuzhiyun cfg.start_ofs = MXT_OBJECT_START +
1565*4882a593Smuzhiyun data->info->object_num * sizeof(struct mxt_object) +
1566*4882a593Smuzhiyun MXT_INFO_CHECKSUM_SIZE;
1567*4882a593Smuzhiyun cfg.mem_size = data->mem_size - cfg.start_ofs;
1568*4882a593Smuzhiyun cfg.mem = kzalloc(cfg.mem_size, GFP_KERNEL);
1569*4882a593Smuzhiyun if (!cfg.mem) {
1570*4882a593Smuzhiyun ret = -ENOMEM;
1571*4882a593Smuzhiyun goto release_raw;
1572*4882a593Smuzhiyun }
1573*4882a593Smuzhiyun
1574*4882a593Smuzhiyun ret = mxt_prepare_cfg_mem(data, &cfg);
1575*4882a593Smuzhiyun if (ret)
1576*4882a593Smuzhiyun goto release_mem;
1577*4882a593Smuzhiyun
1578*4882a593Smuzhiyun /* Calculate crc of the received configs (not the raw config file) */
1579*4882a593Smuzhiyun if (data->T71_address)
1580*4882a593Smuzhiyun crc_start = data->T71_address;
1581*4882a593Smuzhiyun else if (data->T7_address)
1582*4882a593Smuzhiyun crc_start = data->T7_address;
1583*4882a593Smuzhiyun else
1584*4882a593Smuzhiyun dev_warn(dev, "Could not find CRC start\n");
1585*4882a593Smuzhiyun
1586*4882a593Smuzhiyun if (crc_start > cfg.start_ofs) {
1587*4882a593Smuzhiyun calculated_crc = mxt_calculate_crc(cfg.mem,
1588*4882a593Smuzhiyun crc_start - cfg.start_ofs,
1589*4882a593Smuzhiyun cfg.mem_size);
1590*4882a593Smuzhiyun
1591*4882a593Smuzhiyun if (config_crc > 0 && config_crc != calculated_crc)
1592*4882a593Smuzhiyun dev_warn(dev, "Config CRC in file inconsistent, calculated=%06X, file=%06X\n",
1593*4882a593Smuzhiyun calculated_crc, config_crc);
1594*4882a593Smuzhiyun }
1595*4882a593Smuzhiyun
1596*4882a593Smuzhiyun ret = mxt_upload_cfg_mem(data, &cfg);
1597*4882a593Smuzhiyun if (ret)
1598*4882a593Smuzhiyun goto release_mem;
1599*4882a593Smuzhiyun
1600*4882a593Smuzhiyun mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
1601*4882a593Smuzhiyun
1602*4882a593Smuzhiyun ret = mxt_check_retrigen(data);
1603*4882a593Smuzhiyun if (ret)
1604*4882a593Smuzhiyun goto release_mem;
1605*4882a593Smuzhiyun
1606*4882a593Smuzhiyun ret = mxt_soft_reset(data);
1607*4882a593Smuzhiyun if (ret)
1608*4882a593Smuzhiyun goto release_mem;
1609*4882a593Smuzhiyun
1610*4882a593Smuzhiyun dev_info(dev, "Config successfully updated\n");
1611*4882a593Smuzhiyun
1612*4882a593Smuzhiyun /* T7 config may have changed */
1613*4882a593Smuzhiyun mxt_init_t7_power_cfg(data);
1614*4882a593Smuzhiyun
1615*4882a593Smuzhiyun release_mem:
1616*4882a593Smuzhiyun kfree(cfg.mem);
1617*4882a593Smuzhiyun release_raw:
1618*4882a593Smuzhiyun kfree(cfg.raw);
1619*4882a593Smuzhiyun return ret;
1620*4882a593Smuzhiyun }
1621*4882a593Smuzhiyun
mxt_free_input_device(struct mxt_data * data)1622*4882a593Smuzhiyun static void mxt_free_input_device(struct mxt_data *data)
1623*4882a593Smuzhiyun {
1624*4882a593Smuzhiyun if (data->input_dev) {
1625*4882a593Smuzhiyun input_unregister_device(data->input_dev);
1626*4882a593Smuzhiyun data->input_dev = NULL;
1627*4882a593Smuzhiyun }
1628*4882a593Smuzhiyun }
1629*4882a593Smuzhiyun
mxt_free_object_table(struct mxt_data * data)1630*4882a593Smuzhiyun static void mxt_free_object_table(struct mxt_data *data)
1631*4882a593Smuzhiyun {
1632*4882a593Smuzhiyun #ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37
1633*4882a593Smuzhiyun video_unregister_device(&data->dbg.vdev);
1634*4882a593Smuzhiyun v4l2_device_unregister(&data->dbg.v4l2);
1635*4882a593Smuzhiyun #endif
1636*4882a593Smuzhiyun data->object_table = NULL;
1637*4882a593Smuzhiyun data->info = NULL;
1638*4882a593Smuzhiyun kfree(data->raw_info_block);
1639*4882a593Smuzhiyun data->raw_info_block = NULL;
1640*4882a593Smuzhiyun kfree(data->msg_buf);
1641*4882a593Smuzhiyun data->msg_buf = NULL;
1642*4882a593Smuzhiyun data->T5_address = 0;
1643*4882a593Smuzhiyun data->T5_msg_size = 0;
1644*4882a593Smuzhiyun data->T6_reportid = 0;
1645*4882a593Smuzhiyun data->T7_address = 0;
1646*4882a593Smuzhiyun data->T71_address = 0;
1647*4882a593Smuzhiyun data->T9_reportid_min = 0;
1648*4882a593Smuzhiyun data->T9_reportid_max = 0;
1649*4882a593Smuzhiyun data->T18_address = 0;
1650*4882a593Smuzhiyun data->T19_reportid = 0;
1651*4882a593Smuzhiyun data->T44_address = 0;
1652*4882a593Smuzhiyun data->T100_reportid_min = 0;
1653*4882a593Smuzhiyun data->T100_reportid_max = 0;
1654*4882a593Smuzhiyun data->max_reportid = 0;
1655*4882a593Smuzhiyun }
1656*4882a593Smuzhiyun
mxt_parse_object_table(struct mxt_data * data,struct mxt_object * object_table)1657*4882a593Smuzhiyun static int mxt_parse_object_table(struct mxt_data *data,
1658*4882a593Smuzhiyun struct mxt_object *object_table)
1659*4882a593Smuzhiyun {
1660*4882a593Smuzhiyun struct i2c_client *client = data->client;
1661*4882a593Smuzhiyun int i;
1662*4882a593Smuzhiyun u8 reportid;
1663*4882a593Smuzhiyun u16 end_address;
1664*4882a593Smuzhiyun
1665*4882a593Smuzhiyun /* Valid Report IDs start counting from 1 */
1666*4882a593Smuzhiyun reportid = 1;
1667*4882a593Smuzhiyun data->mem_size = 0;
1668*4882a593Smuzhiyun for (i = 0; i < data->info->object_num; i++) {
1669*4882a593Smuzhiyun struct mxt_object *object = object_table + i;
1670*4882a593Smuzhiyun u8 min_id, max_id;
1671*4882a593Smuzhiyun
1672*4882a593Smuzhiyun le16_to_cpus(&object->start_address);
1673*4882a593Smuzhiyun
1674*4882a593Smuzhiyun if (object->num_report_ids) {
1675*4882a593Smuzhiyun min_id = reportid;
1676*4882a593Smuzhiyun reportid += object->num_report_ids *
1677*4882a593Smuzhiyun mxt_obj_instances(object);
1678*4882a593Smuzhiyun max_id = reportid - 1;
1679*4882a593Smuzhiyun } else {
1680*4882a593Smuzhiyun min_id = 0;
1681*4882a593Smuzhiyun max_id = 0;
1682*4882a593Smuzhiyun }
1683*4882a593Smuzhiyun
1684*4882a593Smuzhiyun dev_dbg(&data->client->dev,
1685*4882a593Smuzhiyun "T%u Start:%u Size:%zu Instances:%zu Report IDs:%u-%u\n",
1686*4882a593Smuzhiyun object->type, object->start_address,
1687*4882a593Smuzhiyun mxt_obj_size(object), mxt_obj_instances(object),
1688*4882a593Smuzhiyun min_id, max_id);
1689*4882a593Smuzhiyun
1690*4882a593Smuzhiyun switch (object->type) {
1691*4882a593Smuzhiyun case MXT_GEN_MESSAGE_T5:
1692*4882a593Smuzhiyun if (data->info->family_id == 0x80 &&
1693*4882a593Smuzhiyun data->info->version < 0x20) {
1694*4882a593Smuzhiyun /*
1695*4882a593Smuzhiyun * On mXT224 firmware versions prior to V2.0
1696*4882a593Smuzhiyun * read and discard unused CRC byte otherwise
1697*4882a593Smuzhiyun * DMA reads are misaligned.
1698*4882a593Smuzhiyun */
1699*4882a593Smuzhiyun data->T5_msg_size = mxt_obj_size(object);
1700*4882a593Smuzhiyun } else {
1701*4882a593Smuzhiyun /* CRC not enabled, so skip last byte */
1702*4882a593Smuzhiyun data->T5_msg_size = mxt_obj_size(object) - 1;
1703*4882a593Smuzhiyun }
1704*4882a593Smuzhiyun data->T5_address = object->start_address;
1705*4882a593Smuzhiyun break;
1706*4882a593Smuzhiyun case MXT_GEN_COMMAND_T6:
1707*4882a593Smuzhiyun data->T6_reportid = min_id;
1708*4882a593Smuzhiyun data->T6_address = object->start_address;
1709*4882a593Smuzhiyun break;
1710*4882a593Smuzhiyun case MXT_GEN_POWER_T7:
1711*4882a593Smuzhiyun data->T7_address = object->start_address;
1712*4882a593Smuzhiyun break;
1713*4882a593Smuzhiyun case MXT_SPT_DYNAMICCONFIGURATIONCONTAINER_T71:
1714*4882a593Smuzhiyun data->T71_address = object->start_address;
1715*4882a593Smuzhiyun break;
1716*4882a593Smuzhiyun case MXT_TOUCH_MULTI_T9:
1717*4882a593Smuzhiyun data->multitouch = MXT_TOUCH_MULTI_T9;
1718*4882a593Smuzhiyun /* Only handle messages from first T9 instance */
1719*4882a593Smuzhiyun data->T9_reportid_min = min_id;
1720*4882a593Smuzhiyun data->T9_reportid_max = min_id +
1721*4882a593Smuzhiyun object->num_report_ids - 1;
1722*4882a593Smuzhiyun data->num_touchids = object->num_report_ids;
1723*4882a593Smuzhiyun break;
1724*4882a593Smuzhiyun case MXT_SPT_COMMSCONFIG_T18:
1725*4882a593Smuzhiyun data->T18_address = object->start_address;
1726*4882a593Smuzhiyun break;
1727*4882a593Smuzhiyun case MXT_SPT_MESSAGECOUNT_T44:
1728*4882a593Smuzhiyun data->T44_address = object->start_address;
1729*4882a593Smuzhiyun break;
1730*4882a593Smuzhiyun case MXT_SPT_GPIOPWM_T19:
1731*4882a593Smuzhiyun data->T19_reportid = min_id;
1732*4882a593Smuzhiyun break;
1733*4882a593Smuzhiyun case MXT_TOUCH_MULTITOUCHSCREEN_T100:
1734*4882a593Smuzhiyun data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100;
1735*4882a593Smuzhiyun data->T100_reportid_min = min_id;
1736*4882a593Smuzhiyun data->T100_reportid_max = max_id;
1737*4882a593Smuzhiyun /* first two report IDs reserved */
1738*4882a593Smuzhiyun data->num_touchids = object->num_report_ids - 2;
1739*4882a593Smuzhiyun break;
1740*4882a593Smuzhiyun }
1741*4882a593Smuzhiyun
1742*4882a593Smuzhiyun end_address = object->start_address
1743*4882a593Smuzhiyun + mxt_obj_size(object) * mxt_obj_instances(object) - 1;
1744*4882a593Smuzhiyun
1745*4882a593Smuzhiyun if (end_address >= data->mem_size)
1746*4882a593Smuzhiyun data->mem_size = end_address + 1;
1747*4882a593Smuzhiyun }
1748*4882a593Smuzhiyun
1749*4882a593Smuzhiyun /* Store maximum reportid */
1750*4882a593Smuzhiyun data->max_reportid = reportid;
1751*4882a593Smuzhiyun
1752*4882a593Smuzhiyun /* If T44 exists, T5 position has to be directly after */
1753*4882a593Smuzhiyun if (data->T44_address && (data->T5_address != data->T44_address + 1)) {
1754*4882a593Smuzhiyun dev_err(&client->dev, "Invalid T44 position\n");
1755*4882a593Smuzhiyun return -EINVAL;
1756*4882a593Smuzhiyun }
1757*4882a593Smuzhiyun
1758*4882a593Smuzhiyun data->msg_buf = kcalloc(data->max_reportid,
1759*4882a593Smuzhiyun data->T5_msg_size, GFP_KERNEL);
1760*4882a593Smuzhiyun if (!data->msg_buf)
1761*4882a593Smuzhiyun return -ENOMEM;
1762*4882a593Smuzhiyun
1763*4882a593Smuzhiyun return 0;
1764*4882a593Smuzhiyun }
1765*4882a593Smuzhiyun
mxt_read_info_block(struct mxt_data * data)1766*4882a593Smuzhiyun static int mxt_read_info_block(struct mxt_data *data)
1767*4882a593Smuzhiyun {
1768*4882a593Smuzhiyun struct i2c_client *client = data->client;
1769*4882a593Smuzhiyun int error;
1770*4882a593Smuzhiyun size_t size;
1771*4882a593Smuzhiyun void *id_buf, *buf;
1772*4882a593Smuzhiyun uint8_t num_objects;
1773*4882a593Smuzhiyun u32 calculated_crc;
1774*4882a593Smuzhiyun u8 *crc_ptr;
1775*4882a593Smuzhiyun
1776*4882a593Smuzhiyun /* If info block already allocated, free it */
1777*4882a593Smuzhiyun if (data->raw_info_block)
1778*4882a593Smuzhiyun mxt_free_object_table(data);
1779*4882a593Smuzhiyun
1780*4882a593Smuzhiyun /* Read 7-byte ID information block starting at address 0 */
1781*4882a593Smuzhiyun size = sizeof(struct mxt_info);
1782*4882a593Smuzhiyun id_buf = kzalloc(size, GFP_KERNEL);
1783*4882a593Smuzhiyun if (!id_buf)
1784*4882a593Smuzhiyun return -ENOMEM;
1785*4882a593Smuzhiyun
1786*4882a593Smuzhiyun error = __mxt_read_reg(client, 0, size, id_buf);
1787*4882a593Smuzhiyun if (error)
1788*4882a593Smuzhiyun goto err_free_mem;
1789*4882a593Smuzhiyun
1790*4882a593Smuzhiyun /* Resize buffer to give space for rest of info block */
1791*4882a593Smuzhiyun num_objects = ((struct mxt_info *)id_buf)->object_num;
1792*4882a593Smuzhiyun size += (num_objects * sizeof(struct mxt_object))
1793*4882a593Smuzhiyun + MXT_INFO_CHECKSUM_SIZE;
1794*4882a593Smuzhiyun
1795*4882a593Smuzhiyun buf = krealloc(id_buf, size, GFP_KERNEL);
1796*4882a593Smuzhiyun if (!buf) {
1797*4882a593Smuzhiyun error = -ENOMEM;
1798*4882a593Smuzhiyun goto err_free_mem;
1799*4882a593Smuzhiyun }
1800*4882a593Smuzhiyun id_buf = buf;
1801*4882a593Smuzhiyun
1802*4882a593Smuzhiyun /* Read rest of info block */
1803*4882a593Smuzhiyun error = __mxt_read_reg(client, MXT_OBJECT_START,
1804*4882a593Smuzhiyun size - MXT_OBJECT_START,
1805*4882a593Smuzhiyun id_buf + MXT_OBJECT_START);
1806*4882a593Smuzhiyun if (error)
1807*4882a593Smuzhiyun goto err_free_mem;
1808*4882a593Smuzhiyun
1809*4882a593Smuzhiyun /* Extract & calculate checksum */
1810*4882a593Smuzhiyun crc_ptr = id_buf + size - MXT_INFO_CHECKSUM_SIZE;
1811*4882a593Smuzhiyun data->info_crc = crc_ptr[0] | (crc_ptr[1] << 8) | (crc_ptr[2] << 16);
1812*4882a593Smuzhiyun
1813*4882a593Smuzhiyun calculated_crc = mxt_calculate_crc(id_buf, 0,
1814*4882a593Smuzhiyun size - MXT_INFO_CHECKSUM_SIZE);
1815*4882a593Smuzhiyun
1816*4882a593Smuzhiyun /*
1817*4882a593Smuzhiyun * CRC mismatch can be caused by data corruption due to I2C comms
1818*4882a593Smuzhiyun * issue or else device is not using Object Based Protocol (eg i2c-hid)
1819*4882a593Smuzhiyun */
1820*4882a593Smuzhiyun if ((data->info_crc == 0) || (data->info_crc != calculated_crc)) {
1821*4882a593Smuzhiyun dev_err(&client->dev,
1822*4882a593Smuzhiyun "Info Block CRC error calculated=0x%06X read=0x%06X\n",
1823*4882a593Smuzhiyun calculated_crc, data->info_crc);
1824*4882a593Smuzhiyun error = -EIO;
1825*4882a593Smuzhiyun goto err_free_mem;
1826*4882a593Smuzhiyun }
1827*4882a593Smuzhiyun
1828*4882a593Smuzhiyun data->raw_info_block = id_buf;
1829*4882a593Smuzhiyun data->info = (struct mxt_info *)id_buf;
1830*4882a593Smuzhiyun
1831*4882a593Smuzhiyun dev_info(&client->dev,
1832*4882a593Smuzhiyun "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n",
1833*4882a593Smuzhiyun data->info->family_id, data->info->variant_id,
1834*4882a593Smuzhiyun data->info->version >> 4, data->info->version & 0xf,
1835*4882a593Smuzhiyun data->info->build, data->info->object_num);
1836*4882a593Smuzhiyun
1837*4882a593Smuzhiyun /* Parse object table information */
1838*4882a593Smuzhiyun error = mxt_parse_object_table(data, id_buf + MXT_OBJECT_START);
1839*4882a593Smuzhiyun if (error) {
1840*4882a593Smuzhiyun dev_err(&client->dev, "Error %d parsing object table\n", error);
1841*4882a593Smuzhiyun mxt_free_object_table(data);
1842*4882a593Smuzhiyun return error;
1843*4882a593Smuzhiyun }
1844*4882a593Smuzhiyun
1845*4882a593Smuzhiyun data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START);
1846*4882a593Smuzhiyun
1847*4882a593Smuzhiyun return 0;
1848*4882a593Smuzhiyun
1849*4882a593Smuzhiyun err_free_mem:
1850*4882a593Smuzhiyun kfree(id_buf);
1851*4882a593Smuzhiyun return error;
1852*4882a593Smuzhiyun }
1853*4882a593Smuzhiyun
mxt_read_t9_resolution(struct mxt_data * data)1854*4882a593Smuzhiyun static int mxt_read_t9_resolution(struct mxt_data *data)
1855*4882a593Smuzhiyun {
1856*4882a593Smuzhiyun struct i2c_client *client = data->client;
1857*4882a593Smuzhiyun int error;
1858*4882a593Smuzhiyun struct t9_range range;
1859*4882a593Smuzhiyun unsigned char orient;
1860*4882a593Smuzhiyun struct mxt_object *object;
1861*4882a593Smuzhiyun
1862*4882a593Smuzhiyun object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
1863*4882a593Smuzhiyun if (!object)
1864*4882a593Smuzhiyun return -EINVAL;
1865*4882a593Smuzhiyun
1866*4882a593Smuzhiyun error = __mxt_read_reg(client,
1867*4882a593Smuzhiyun object->start_address + MXT_T9_XSIZE,
1868*4882a593Smuzhiyun sizeof(data->xsize), &data->xsize);
1869*4882a593Smuzhiyun if (error)
1870*4882a593Smuzhiyun return error;
1871*4882a593Smuzhiyun
1872*4882a593Smuzhiyun error = __mxt_read_reg(client,
1873*4882a593Smuzhiyun object->start_address + MXT_T9_YSIZE,
1874*4882a593Smuzhiyun sizeof(data->ysize), &data->ysize);
1875*4882a593Smuzhiyun if (error)
1876*4882a593Smuzhiyun return error;
1877*4882a593Smuzhiyun
1878*4882a593Smuzhiyun error = __mxt_read_reg(client,
1879*4882a593Smuzhiyun object->start_address + MXT_T9_RANGE,
1880*4882a593Smuzhiyun sizeof(range), &range);
1881*4882a593Smuzhiyun if (error)
1882*4882a593Smuzhiyun return error;
1883*4882a593Smuzhiyun
1884*4882a593Smuzhiyun data->max_x = get_unaligned_le16(&range.x);
1885*4882a593Smuzhiyun data->max_y = get_unaligned_le16(&range.y);
1886*4882a593Smuzhiyun
1887*4882a593Smuzhiyun error = __mxt_read_reg(client,
1888*4882a593Smuzhiyun object->start_address + MXT_T9_ORIENT,
1889*4882a593Smuzhiyun 1, &orient);
1890*4882a593Smuzhiyun if (error)
1891*4882a593Smuzhiyun return error;
1892*4882a593Smuzhiyun
1893*4882a593Smuzhiyun data->xy_switch = orient & MXT_T9_ORIENT_SWITCH;
1894*4882a593Smuzhiyun data->invertx = orient & MXT_T9_ORIENT_INVERTX;
1895*4882a593Smuzhiyun data->inverty = orient & MXT_T9_ORIENT_INVERTY;
1896*4882a593Smuzhiyun
1897*4882a593Smuzhiyun return 0;
1898*4882a593Smuzhiyun }
1899*4882a593Smuzhiyun
mxt_read_t100_config(struct mxt_data * data)1900*4882a593Smuzhiyun static int mxt_read_t100_config(struct mxt_data *data)
1901*4882a593Smuzhiyun {
1902*4882a593Smuzhiyun struct i2c_client *client = data->client;
1903*4882a593Smuzhiyun int error;
1904*4882a593Smuzhiyun struct mxt_object *object;
1905*4882a593Smuzhiyun u16 range_x, range_y;
1906*4882a593Smuzhiyun u8 cfg, tchaux;
1907*4882a593Smuzhiyun u8 aux;
1908*4882a593Smuzhiyun
1909*4882a593Smuzhiyun object = mxt_get_object(data, MXT_TOUCH_MULTITOUCHSCREEN_T100);
1910*4882a593Smuzhiyun if (!object)
1911*4882a593Smuzhiyun return -EINVAL;
1912*4882a593Smuzhiyun
1913*4882a593Smuzhiyun /* read touchscreen dimensions */
1914*4882a593Smuzhiyun error = __mxt_read_reg(client,
1915*4882a593Smuzhiyun object->start_address + MXT_T100_XRANGE,
1916*4882a593Smuzhiyun sizeof(range_x), &range_x);
1917*4882a593Smuzhiyun if (error)
1918*4882a593Smuzhiyun return error;
1919*4882a593Smuzhiyun
1920*4882a593Smuzhiyun data->max_x = get_unaligned_le16(&range_x);
1921*4882a593Smuzhiyun
1922*4882a593Smuzhiyun error = __mxt_read_reg(client,
1923*4882a593Smuzhiyun object->start_address + MXT_T100_YRANGE,
1924*4882a593Smuzhiyun sizeof(range_y), &range_y);
1925*4882a593Smuzhiyun if (error)
1926*4882a593Smuzhiyun return error;
1927*4882a593Smuzhiyun
1928*4882a593Smuzhiyun data->max_y = get_unaligned_le16(&range_y);
1929*4882a593Smuzhiyun
1930*4882a593Smuzhiyun error = __mxt_read_reg(client,
1931*4882a593Smuzhiyun object->start_address + MXT_T100_XSIZE,
1932*4882a593Smuzhiyun sizeof(data->xsize), &data->xsize);
1933*4882a593Smuzhiyun if (error)
1934*4882a593Smuzhiyun return error;
1935*4882a593Smuzhiyun
1936*4882a593Smuzhiyun error = __mxt_read_reg(client,
1937*4882a593Smuzhiyun object->start_address + MXT_T100_YSIZE,
1938*4882a593Smuzhiyun sizeof(data->ysize), &data->ysize);
1939*4882a593Smuzhiyun if (error)
1940*4882a593Smuzhiyun return error;
1941*4882a593Smuzhiyun
1942*4882a593Smuzhiyun /* read orientation config */
1943*4882a593Smuzhiyun error = __mxt_read_reg(client,
1944*4882a593Smuzhiyun object->start_address + MXT_T100_CFG1,
1945*4882a593Smuzhiyun 1, &cfg);
1946*4882a593Smuzhiyun if (error)
1947*4882a593Smuzhiyun return error;
1948*4882a593Smuzhiyun
1949*4882a593Smuzhiyun data->xy_switch = cfg & MXT_T100_CFG_SWITCHXY;
1950*4882a593Smuzhiyun data->invertx = cfg & MXT_T100_CFG_INVERTX;
1951*4882a593Smuzhiyun data->inverty = cfg & MXT_T100_CFG_INVERTY;
1952*4882a593Smuzhiyun
1953*4882a593Smuzhiyun /* allocate aux bytes */
1954*4882a593Smuzhiyun error = __mxt_read_reg(client,
1955*4882a593Smuzhiyun object->start_address + MXT_T100_TCHAUX,
1956*4882a593Smuzhiyun 1, &tchaux);
1957*4882a593Smuzhiyun if (error)
1958*4882a593Smuzhiyun return error;
1959*4882a593Smuzhiyun
1960*4882a593Smuzhiyun aux = 6;
1961*4882a593Smuzhiyun
1962*4882a593Smuzhiyun if (tchaux & MXT_T100_TCHAUX_VECT)
1963*4882a593Smuzhiyun data->t100_aux_vect = aux++;
1964*4882a593Smuzhiyun
1965*4882a593Smuzhiyun if (tchaux & MXT_T100_TCHAUX_AMPL)
1966*4882a593Smuzhiyun data->t100_aux_ampl = aux++;
1967*4882a593Smuzhiyun
1968*4882a593Smuzhiyun if (tchaux & MXT_T100_TCHAUX_AREA)
1969*4882a593Smuzhiyun data->t100_aux_area = aux++;
1970*4882a593Smuzhiyun
1971*4882a593Smuzhiyun dev_dbg(&client->dev,
1972*4882a593Smuzhiyun "T100 aux mappings vect:%u ampl:%u area:%u\n",
1973*4882a593Smuzhiyun data->t100_aux_vect, data->t100_aux_ampl, data->t100_aux_area);
1974*4882a593Smuzhiyun
1975*4882a593Smuzhiyun return 0;
1976*4882a593Smuzhiyun }
1977*4882a593Smuzhiyun
1978*4882a593Smuzhiyun static int mxt_input_open(struct input_dev *dev);
1979*4882a593Smuzhiyun static void mxt_input_close(struct input_dev *dev);
1980*4882a593Smuzhiyun
mxt_set_up_as_touchpad(struct input_dev * input_dev,struct mxt_data * data)1981*4882a593Smuzhiyun static void mxt_set_up_as_touchpad(struct input_dev *input_dev,
1982*4882a593Smuzhiyun struct mxt_data *data)
1983*4882a593Smuzhiyun {
1984*4882a593Smuzhiyun int i;
1985*4882a593Smuzhiyun
1986*4882a593Smuzhiyun input_dev->name = "Atmel maXTouch Touchpad";
1987*4882a593Smuzhiyun
1988*4882a593Smuzhiyun __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
1989*4882a593Smuzhiyun
1990*4882a593Smuzhiyun input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM);
1991*4882a593Smuzhiyun input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM);
1992*4882a593Smuzhiyun input_abs_set_res(input_dev, ABS_MT_POSITION_X,
1993*4882a593Smuzhiyun MXT_PIXELS_PER_MM);
1994*4882a593Smuzhiyun input_abs_set_res(input_dev, ABS_MT_POSITION_Y,
1995*4882a593Smuzhiyun MXT_PIXELS_PER_MM);
1996*4882a593Smuzhiyun
1997*4882a593Smuzhiyun for (i = 0; i < data->t19_num_keys; i++)
1998*4882a593Smuzhiyun if (data->t19_keymap[i] != KEY_RESERVED)
1999*4882a593Smuzhiyun input_set_capability(input_dev, EV_KEY,
2000*4882a593Smuzhiyun data->t19_keymap[i]);
2001*4882a593Smuzhiyun }
2002*4882a593Smuzhiyun
mxt_initialize_input_device(struct mxt_data * data)2003*4882a593Smuzhiyun static int mxt_initialize_input_device(struct mxt_data *data)
2004*4882a593Smuzhiyun {
2005*4882a593Smuzhiyun struct device *dev = &data->client->dev;
2006*4882a593Smuzhiyun struct input_dev *input_dev;
2007*4882a593Smuzhiyun int error;
2008*4882a593Smuzhiyun unsigned int num_mt_slots;
2009*4882a593Smuzhiyun unsigned int mt_flags = 0;
2010*4882a593Smuzhiyun
2011*4882a593Smuzhiyun switch (data->multitouch) {
2012*4882a593Smuzhiyun case MXT_TOUCH_MULTI_T9:
2013*4882a593Smuzhiyun num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
2014*4882a593Smuzhiyun error = mxt_read_t9_resolution(data);
2015*4882a593Smuzhiyun if (error)
2016*4882a593Smuzhiyun dev_warn(dev, "Failed to initialize T9 resolution\n");
2017*4882a593Smuzhiyun break;
2018*4882a593Smuzhiyun
2019*4882a593Smuzhiyun case MXT_TOUCH_MULTITOUCHSCREEN_T100:
2020*4882a593Smuzhiyun num_mt_slots = data->num_touchids;
2021*4882a593Smuzhiyun error = mxt_read_t100_config(data);
2022*4882a593Smuzhiyun if (error)
2023*4882a593Smuzhiyun dev_warn(dev, "Failed to read T100 config\n");
2024*4882a593Smuzhiyun break;
2025*4882a593Smuzhiyun
2026*4882a593Smuzhiyun default:
2027*4882a593Smuzhiyun dev_err(dev, "Invalid multitouch object\n");
2028*4882a593Smuzhiyun return -EINVAL;
2029*4882a593Smuzhiyun }
2030*4882a593Smuzhiyun
2031*4882a593Smuzhiyun /* Handle default values and orientation switch */
2032*4882a593Smuzhiyun if (data->max_x == 0)
2033*4882a593Smuzhiyun data->max_x = 1023;
2034*4882a593Smuzhiyun
2035*4882a593Smuzhiyun if (data->max_y == 0)
2036*4882a593Smuzhiyun data->max_y = 1023;
2037*4882a593Smuzhiyun
2038*4882a593Smuzhiyun if (data->xy_switch)
2039*4882a593Smuzhiyun swap(data->max_x, data->max_y);
2040*4882a593Smuzhiyun
2041*4882a593Smuzhiyun dev_info(dev, "Touchscreen size X%uY%u\n", data->max_x, data->max_y);
2042*4882a593Smuzhiyun
2043*4882a593Smuzhiyun /* Register input device */
2044*4882a593Smuzhiyun input_dev = input_allocate_device();
2045*4882a593Smuzhiyun if (!input_dev)
2046*4882a593Smuzhiyun return -ENOMEM;
2047*4882a593Smuzhiyun
2048*4882a593Smuzhiyun input_dev->name = "Atmel maXTouch Touchscreen";
2049*4882a593Smuzhiyun input_dev->phys = data->phys;
2050*4882a593Smuzhiyun input_dev->id.bustype = BUS_I2C;
2051*4882a593Smuzhiyun input_dev->dev.parent = dev;
2052*4882a593Smuzhiyun input_dev->open = mxt_input_open;
2053*4882a593Smuzhiyun input_dev->close = mxt_input_close;
2054*4882a593Smuzhiyun
2055*4882a593Smuzhiyun input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
2056*4882a593Smuzhiyun
2057*4882a593Smuzhiyun /* For single touch */
2058*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_X, 0, data->max_x, 0, 0);
2059*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_Y, 0, data->max_y, 0, 0);
2060*4882a593Smuzhiyun
2061*4882a593Smuzhiyun if (data->multitouch == MXT_TOUCH_MULTI_T9 ||
2062*4882a593Smuzhiyun (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
2063*4882a593Smuzhiyun data->t100_aux_ampl)) {
2064*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);
2065*4882a593Smuzhiyun }
2066*4882a593Smuzhiyun
2067*4882a593Smuzhiyun /* If device has buttons we assume it is a touchpad */
2068*4882a593Smuzhiyun if (data->t19_num_keys) {
2069*4882a593Smuzhiyun mxt_set_up_as_touchpad(input_dev, data);
2070*4882a593Smuzhiyun mt_flags |= INPUT_MT_POINTER;
2071*4882a593Smuzhiyun } else {
2072*4882a593Smuzhiyun mt_flags |= INPUT_MT_DIRECT;
2073*4882a593Smuzhiyun }
2074*4882a593Smuzhiyun
2075*4882a593Smuzhiyun /* For multi touch */
2076*4882a593Smuzhiyun error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags);
2077*4882a593Smuzhiyun if (error) {
2078*4882a593Smuzhiyun dev_err(dev, "Error %d initialising slots\n", error);
2079*4882a593Smuzhiyun goto err_free_mem;
2080*4882a593Smuzhiyun }
2081*4882a593Smuzhiyun
2082*4882a593Smuzhiyun if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) {
2083*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
2084*4882a593Smuzhiyun 0, MT_TOOL_MAX, 0, 0);
2085*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_MT_DISTANCE,
2086*4882a593Smuzhiyun MXT_DISTANCE_ACTIVE_TOUCH,
2087*4882a593Smuzhiyun MXT_DISTANCE_HOVERING,
2088*4882a593Smuzhiyun 0, 0);
2089*4882a593Smuzhiyun }
2090*4882a593Smuzhiyun
2091*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_MT_POSITION_X,
2092*4882a593Smuzhiyun 0, data->max_x, 0, 0);
2093*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
2094*4882a593Smuzhiyun 0, data->max_y, 0, 0);
2095*4882a593Smuzhiyun
2096*4882a593Smuzhiyun if (data->multitouch == MXT_TOUCH_MULTI_T9 ||
2097*4882a593Smuzhiyun (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
2098*4882a593Smuzhiyun data->t100_aux_area)) {
2099*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
2100*4882a593Smuzhiyun 0, MXT_MAX_AREA, 0, 0);
2101*4882a593Smuzhiyun }
2102*4882a593Smuzhiyun
2103*4882a593Smuzhiyun if (data->multitouch == MXT_TOUCH_MULTI_T9 ||
2104*4882a593Smuzhiyun (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
2105*4882a593Smuzhiyun data->t100_aux_ampl)) {
2106*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_MT_PRESSURE,
2107*4882a593Smuzhiyun 0, 255, 0, 0);
2108*4882a593Smuzhiyun }
2109*4882a593Smuzhiyun
2110*4882a593Smuzhiyun if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
2111*4882a593Smuzhiyun data->t100_aux_vect) {
2112*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_MT_ORIENTATION,
2113*4882a593Smuzhiyun 0, 255, 0, 0);
2114*4882a593Smuzhiyun }
2115*4882a593Smuzhiyun
2116*4882a593Smuzhiyun if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 &&
2117*4882a593Smuzhiyun data->t100_aux_vect) {
2118*4882a593Smuzhiyun input_set_abs_params(input_dev, ABS_MT_ORIENTATION,
2119*4882a593Smuzhiyun 0, 255, 0, 0);
2120*4882a593Smuzhiyun }
2121*4882a593Smuzhiyun
2122*4882a593Smuzhiyun input_set_drvdata(input_dev, data);
2123*4882a593Smuzhiyun
2124*4882a593Smuzhiyun error = input_register_device(input_dev);
2125*4882a593Smuzhiyun if (error) {
2126*4882a593Smuzhiyun dev_err(dev, "Error %d registering input device\n", error);
2127*4882a593Smuzhiyun goto err_free_mem;
2128*4882a593Smuzhiyun }
2129*4882a593Smuzhiyun
2130*4882a593Smuzhiyun data->input_dev = input_dev;
2131*4882a593Smuzhiyun
2132*4882a593Smuzhiyun return 0;
2133*4882a593Smuzhiyun
2134*4882a593Smuzhiyun err_free_mem:
2135*4882a593Smuzhiyun input_free_device(input_dev);
2136*4882a593Smuzhiyun return error;
2137*4882a593Smuzhiyun }
2138*4882a593Smuzhiyun
2139*4882a593Smuzhiyun static int mxt_configure_objects(struct mxt_data *data,
2140*4882a593Smuzhiyun const struct firmware *cfg);
2141*4882a593Smuzhiyun
mxt_config_cb(const struct firmware * cfg,void * ctx)2142*4882a593Smuzhiyun static void mxt_config_cb(const struct firmware *cfg, void *ctx)
2143*4882a593Smuzhiyun {
2144*4882a593Smuzhiyun mxt_configure_objects(ctx, cfg);
2145*4882a593Smuzhiyun release_firmware(cfg);
2146*4882a593Smuzhiyun }
2147*4882a593Smuzhiyun
mxt_initialize(struct mxt_data * data)2148*4882a593Smuzhiyun static int mxt_initialize(struct mxt_data *data)
2149*4882a593Smuzhiyun {
2150*4882a593Smuzhiyun struct i2c_client *client = data->client;
2151*4882a593Smuzhiyun int recovery_attempts = 0;
2152*4882a593Smuzhiyun int error;
2153*4882a593Smuzhiyun
2154*4882a593Smuzhiyun while (1) {
2155*4882a593Smuzhiyun error = mxt_read_info_block(data);
2156*4882a593Smuzhiyun if (!error)
2157*4882a593Smuzhiyun break;
2158*4882a593Smuzhiyun
2159*4882a593Smuzhiyun /* Check bootloader state */
2160*4882a593Smuzhiyun error = mxt_probe_bootloader(data, false);
2161*4882a593Smuzhiyun if (error) {
2162*4882a593Smuzhiyun dev_info(&client->dev, "Trying alternate bootloader address\n");
2163*4882a593Smuzhiyun error = mxt_probe_bootloader(data, true);
2164*4882a593Smuzhiyun if (error) {
2165*4882a593Smuzhiyun /* Chip is not in appmode or bootloader mode */
2166*4882a593Smuzhiyun return error;
2167*4882a593Smuzhiyun }
2168*4882a593Smuzhiyun }
2169*4882a593Smuzhiyun
2170*4882a593Smuzhiyun /* OK, we are in bootloader, see if we can recover */
2171*4882a593Smuzhiyun if (++recovery_attempts > 1) {
2172*4882a593Smuzhiyun dev_err(&client->dev, "Could not recover from bootloader mode\n");
2173*4882a593Smuzhiyun /*
2174*4882a593Smuzhiyun * We can reflash from this state, so do not
2175*4882a593Smuzhiyun * abort initialization.
2176*4882a593Smuzhiyun */
2177*4882a593Smuzhiyun data->in_bootloader = true;
2178*4882a593Smuzhiyun return 0;
2179*4882a593Smuzhiyun }
2180*4882a593Smuzhiyun
2181*4882a593Smuzhiyun /* Attempt to exit bootloader into app mode */
2182*4882a593Smuzhiyun mxt_send_bootloader_cmd(data, false);
2183*4882a593Smuzhiyun msleep(MXT_FW_RESET_TIME);
2184*4882a593Smuzhiyun }
2185*4882a593Smuzhiyun
2186*4882a593Smuzhiyun error = mxt_check_retrigen(data);
2187*4882a593Smuzhiyun if (error)
2188*4882a593Smuzhiyun return error;
2189*4882a593Smuzhiyun
2190*4882a593Smuzhiyun error = mxt_acquire_irq(data);
2191*4882a593Smuzhiyun if (error)
2192*4882a593Smuzhiyun return error;
2193*4882a593Smuzhiyun
2194*4882a593Smuzhiyun error = request_firmware_nowait(THIS_MODULE, true, MXT_CFG_NAME,
2195*4882a593Smuzhiyun &client->dev, GFP_KERNEL, data,
2196*4882a593Smuzhiyun mxt_config_cb);
2197*4882a593Smuzhiyun if (error) {
2198*4882a593Smuzhiyun dev_err(&client->dev, "Failed to invoke firmware loader: %d\n",
2199*4882a593Smuzhiyun error);
2200*4882a593Smuzhiyun return error;
2201*4882a593Smuzhiyun }
2202*4882a593Smuzhiyun
2203*4882a593Smuzhiyun return 0;
2204*4882a593Smuzhiyun }
2205*4882a593Smuzhiyun
mxt_set_t7_power_cfg(struct mxt_data * data,u8 sleep)2206*4882a593Smuzhiyun static int mxt_set_t7_power_cfg(struct mxt_data *data, u8 sleep)
2207*4882a593Smuzhiyun {
2208*4882a593Smuzhiyun struct device *dev = &data->client->dev;
2209*4882a593Smuzhiyun int error;
2210*4882a593Smuzhiyun struct t7_config *new_config;
2211*4882a593Smuzhiyun struct t7_config deepsleep = { .active = 0, .idle = 0 };
2212*4882a593Smuzhiyun
2213*4882a593Smuzhiyun if (sleep == MXT_POWER_CFG_DEEPSLEEP)
2214*4882a593Smuzhiyun new_config = &deepsleep;
2215*4882a593Smuzhiyun else
2216*4882a593Smuzhiyun new_config = &data->t7_cfg;
2217*4882a593Smuzhiyun
2218*4882a593Smuzhiyun error = __mxt_write_reg(data->client, data->T7_address,
2219*4882a593Smuzhiyun sizeof(data->t7_cfg), new_config);
2220*4882a593Smuzhiyun if (error)
2221*4882a593Smuzhiyun return error;
2222*4882a593Smuzhiyun
2223*4882a593Smuzhiyun dev_dbg(dev, "Set T7 ACTV:%d IDLE:%d\n",
2224*4882a593Smuzhiyun new_config->active, new_config->idle);
2225*4882a593Smuzhiyun
2226*4882a593Smuzhiyun return 0;
2227*4882a593Smuzhiyun }
2228*4882a593Smuzhiyun
mxt_init_t7_power_cfg(struct mxt_data * data)2229*4882a593Smuzhiyun static int mxt_init_t7_power_cfg(struct mxt_data *data)
2230*4882a593Smuzhiyun {
2231*4882a593Smuzhiyun struct device *dev = &data->client->dev;
2232*4882a593Smuzhiyun int error;
2233*4882a593Smuzhiyun bool retry = false;
2234*4882a593Smuzhiyun
2235*4882a593Smuzhiyun recheck:
2236*4882a593Smuzhiyun error = __mxt_read_reg(data->client, data->T7_address,
2237*4882a593Smuzhiyun sizeof(data->t7_cfg), &data->t7_cfg);
2238*4882a593Smuzhiyun if (error)
2239*4882a593Smuzhiyun return error;
2240*4882a593Smuzhiyun
2241*4882a593Smuzhiyun if (data->t7_cfg.active == 0 || data->t7_cfg.idle == 0) {
2242*4882a593Smuzhiyun if (!retry) {
2243*4882a593Smuzhiyun dev_dbg(dev, "T7 cfg zero, resetting\n");
2244*4882a593Smuzhiyun mxt_soft_reset(data);
2245*4882a593Smuzhiyun retry = true;
2246*4882a593Smuzhiyun goto recheck;
2247*4882a593Smuzhiyun } else {
2248*4882a593Smuzhiyun dev_dbg(dev, "T7 cfg zero after reset, overriding\n");
2249*4882a593Smuzhiyun data->t7_cfg.active = 20;
2250*4882a593Smuzhiyun data->t7_cfg.idle = 100;
2251*4882a593Smuzhiyun return mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
2252*4882a593Smuzhiyun }
2253*4882a593Smuzhiyun }
2254*4882a593Smuzhiyun
2255*4882a593Smuzhiyun dev_dbg(dev, "Initialized power cfg: ACTV %d, IDLE %d\n",
2256*4882a593Smuzhiyun data->t7_cfg.active, data->t7_cfg.idle);
2257*4882a593Smuzhiyun return 0;
2258*4882a593Smuzhiyun }
2259*4882a593Smuzhiyun
2260*4882a593Smuzhiyun #ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT_T37
2261*4882a593Smuzhiyun static const struct v4l2_file_operations mxt_video_fops = {
2262*4882a593Smuzhiyun .owner = THIS_MODULE,
2263*4882a593Smuzhiyun .open = v4l2_fh_open,
2264*4882a593Smuzhiyun .release = vb2_fop_release,
2265*4882a593Smuzhiyun .unlocked_ioctl = video_ioctl2,
2266*4882a593Smuzhiyun .read = vb2_fop_read,
2267*4882a593Smuzhiyun .mmap = vb2_fop_mmap,
2268*4882a593Smuzhiyun .poll = vb2_fop_poll,
2269*4882a593Smuzhiyun };
2270*4882a593Smuzhiyun
mxt_get_debug_value(struct mxt_data * data,unsigned int x,unsigned int y)2271*4882a593Smuzhiyun static u16 mxt_get_debug_value(struct mxt_data *data, unsigned int x,
2272*4882a593Smuzhiyun unsigned int y)
2273*4882a593Smuzhiyun {
2274*4882a593Smuzhiyun struct mxt_info *info = data->info;
2275*4882a593Smuzhiyun struct mxt_dbg *dbg = &data->dbg;
2276*4882a593Smuzhiyun unsigned int ofs, page;
2277*4882a593Smuzhiyun unsigned int col = 0;
2278*4882a593Smuzhiyun unsigned int col_width;
2279*4882a593Smuzhiyun
2280*4882a593Smuzhiyun if (info->family_id == MXT_FAMILY_1386) {
2281*4882a593Smuzhiyun col_width = info->matrix_ysize / MXT1386_COLUMNS;
2282*4882a593Smuzhiyun col = y / col_width;
2283*4882a593Smuzhiyun y = y % col_width;
2284*4882a593Smuzhiyun } else {
2285*4882a593Smuzhiyun col_width = info->matrix_ysize;
2286*4882a593Smuzhiyun }
2287*4882a593Smuzhiyun
2288*4882a593Smuzhiyun ofs = (y + (x * col_width)) * sizeof(u16);
2289*4882a593Smuzhiyun page = ofs / MXT_DIAGNOSTIC_SIZE;
2290*4882a593Smuzhiyun ofs %= MXT_DIAGNOSTIC_SIZE;
2291*4882a593Smuzhiyun
2292*4882a593Smuzhiyun if (info->family_id == MXT_FAMILY_1386)
2293*4882a593Smuzhiyun page += col * MXT1386_PAGES_PER_COLUMN;
2294*4882a593Smuzhiyun
2295*4882a593Smuzhiyun return get_unaligned_le16(&dbg->t37_buf[page].data[ofs]);
2296*4882a593Smuzhiyun }
2297*4882a593Smuzhiyun
mxt_convert_debug_pages(struct mxt_data * data,u16 * outbuf)2298*4882a593Smuzhiyun static int mxt_convert_debug_pages(struct mxt_data *data, u16 *outbuf)
2299*4882a593Smuzhiyun {
2300*4882a593Smuzhiyun struct mxt_dbg *dbg = &data->dbg;
2301*4882a593Smuzhiyun unsigned int x = 0;
2302*4882a593Smuzhiyun unsigned int y = 0;
2303*4882a593Smuzhiyun unsigned int i, rx, ry;
2304*4882a593Smuzhiyun
2305*4882a593Smuzhiyun for (i = 0; i < dbg->t37_nodes; i++) {
2306*4882a593Smuzhiyun /* Handle orientation */
2307*4882a593Smuzhiyun rx = data->xy_switch ? y : x;
2308*4882a593Smuzhiyun ry = data->xy_switch ? x : y;
2309*4882a593Smuzhiyun rx = data->invertx ? (data->xsize - 1 - rx) : rx;
2310*4882a593Smuzhiyun ry = data->inverty ? (data->ysize - 1 - ry) : ry;
2311*4882a593Smuzhiyun
2312*4882a593Smuzhiyun outbuf[i] = mxt_get_debug_value(data, rx, ry);
2313*4882a593Smuzhiyun
2314*4882a593Smuzhiyun /* Next value */
2315*4882a593Smuzhiyun if (++x >= (data->xy_switch ? data->ysize : data->xsize)) {
2316*4882a593Smuzhiyun x = 0;
2317*4882a593Smuzhiyun y++;
2318*4882a593Smuzhiyun }
2319*4882a593Smuzhiyun }
2320*4882a593Smuzhiyun
2321*4882a593Smuzhiyun return 0;
2322*4882a593Smuzhiyun }
2323*4882a593Smuzhiyun
mxt_read_diagnostic_debug(struct mxt_data * data,u8 mode,u16 * outbuf)2324*4882a593Smuzhiyun static int mxt_read_diagnostic_debug(struct mxt_data *data, u8 mode,
2325*4882a593Smuzhiyun u16 *outbuf)
2326*4882a593Smuzhiyun {
2327*4882a593Smuzhiyun struct mxt_dbg *dbg = &data->dbg;
2328*4882a593Smuzhiyun int retries = 0;
2329*4882a593Smuzhiyun int page;
2330*4882a593Smuzhiyun int ret;
2331*4882a593Smuzhiyun u8 cmd = mode;
2332*4882a593Smuzhiyun struct t37_debug *p;
2333*4882a593Smuzhiyun u8 cmd_poll;
2334*4882a593Smuzhiyun
2335*4882a593Smuzhiyun for (page = 0; page < dbg->t37_pages; page++) {
2336*4882a593Smuzhiyun p = dbg->t37_buf + page;
2337*4882a593Smuzhiyun
2338*4882a593Smuzhiyun ret = mxt_write_reg(data->client, dbg->diag_cmd_address,
2339*4882a593Smuzhiyun cmd);
2340*4882a593Smuzhiyun if (ret)
2341*4882a593Smuzhiyun return ret;
2342*4882a593Smuzhiyun
2343*4882a593Smuzhiyun retries = 0;
2344*4882a593Smuzhiyun msleep(20);
2345*4882a593Smuzhiyun wait_cmd:
2346*4882a593Smuzhiyun /* Read back command byte */
2347*4882a593Smuzhiyun ret = __mxt_read_reg(data->client, dbg->diag_cmd_address,
2348*4882a593Smuzhiyun sizeof(cmd_poll), &cmd_poll);
2349*4882a593Smuzhiyun if (ret)
2350*4882a593Smuzhiyun return ret;
2351*4882a593Smuzhiyun
2352*4882a593Smuzhiyun /* Field is cleared once the command has been processed */
2353*4882a593Smuzhiyun if (cmd_poll) {
2354*4882a593Smuzhiyun if (retries++ > 100)
2355*4882a593Smuzhiyun return -EINVAL;
2356*4882a593Smuzhiyun
2357*4882a593Smuzhiyun msleep(20);
2358*4882a593Smuzhiyun goto wait_cmd;
2359*4882a593Smuzhiyun }
2360*4882a593Smuzhiyun
2361*4882a593Smuzhiyun /* Read T37 page */
2362*4882a593Smuzhiyun ret = __mxt_read_reg(data->client, dbg->t37_address,
2363*4882a593Smuzhiyun sizeof(struct t37_debug), p);
2364*4882a593Smuzhiyun if (ret)
2365*4882a593Smuzhiyun return ret;
2366*4882a593Smuzhiyun
2367*4882a593Smuzhiyun if (p->mode != mode || p->page != page) {
2368*4882a593Smuzhiyun dev_err(&data->client->dev, "T37 page mismatch\n");
2369*4882a593Smuzhiyun return -EINVAL;
2370*4882a593Smuzhiyun }
2371*4882a593Smuzhiyun
2372*4882a593Smuzhiyun dev_dbg(&data->client->dev, "%s page:%d retries:%d\n",
2373*4882a593Smuzhiyun __func__, page, retries);
2374*4882a593Smuzhiyun
2375*4882a593Smuzhiyun /* For remaining pages, write PAGEUP rather than mode */
2376*4882a593Smuzhiyun cmd = MXT_DIAGNOSTIC_PAGEUP;
2377*4882a593Smuzhiyun }
2378*4882a593Smuzhiyun
2379*4882a593Smuzhiyun return mxt_convert_debug_pages(data, outbuf);
2380*4882a593Smuzhiyun }
2381*4882a593Smuzhiyun
mxt_queue_setup(struct vb2_queue * q,unsigned int * nbuffers,unsigned int * nplanes,unsigned int sizes[],struct device * alloc_devs[])2382*4882a593Smuzhiyun static int mxt_queue_setup(struct vb2_queue *q,
2383*4882a593Smuzhiyun unsigned int *nbuffers, unsigned int *nplanes,
2384*4882a593Smuzhiyun unsigned int sizes[], struct device *alloc_devs[])
2385*4882a593Smuzhiyun {
2386*4882a593Smuzhiyun struct mxt_data *data = q->drv_priv;
2387*4882a593Smuzhiyun size_t size = data->dbg.t37_nodes * sizeof(u16);
2388*4882a593Smuzhiyun
2389*4882a593Smuzhiyun if (*nplanes)
2390*4882a593Smuzhiyun return sizes[0] < size ? -EINVAL : 0;
2391*4882a593Smuzhiyun
2392*4882a593Smuzhiyun *nplanes = 1;
2393*4882a593Smuzhiyun sizes[0] = size;
2394*4882a593Smuzhiyun
2395*4882a593Smuzhiyun return 0;
2396*4882a593Smuzhiyun }
2397*4882a593Smuzhiyun
mxt_buffer_queue(struct vb2_buffer * vb)2398*4882a593Smuzhiyun static void mxt_buffer_queue(struct vb2_buffer *vb)
2399*4882a593Smuzhiyun {
2400*4882a593Smuzhiyun struct mxt_data *data = vb2_get_drv_priv(vb->vb2_queue);
2401*4882a593Smuzhiyun u16 *ptr;
2402*4882a593Smuzhiyun int ret;
2403*4882a593Smuzhiyun u8 mode;
2404*4882a593Smuzhiyun
2405*4882a593Smuzhiyun ptr = vb2_plane_vaddr(vb, 0);
2406*4882a593Smuzhiyun if (!ptr) {
2407*4882a593Smuzhiyun dev_err(&data->client->dev, "Error acquiring frame ptr\n");
2408*4882a593Smuzhiyun goto fault;
2409*4882a593Smuzhiyun }
2410*4882a593Smuzhiyun
2411*4882a593Smuzhiyun switch (data->dbg.input) {
2412*4882a593Smuzhiyun case MXT_V4L_INPUT_DELTAS:
2413*4882a593Smuzhiyun default:
2414*4882a593Smuzhiyun mode = MXT_DIAGNOSTIC_DELTAS;
2415*4882a593Smuzhiyun break;
2416*4882a593Smuzhiyun
2417*4882a593Smuzhiyun case MXT_V4L_INPUT_REFS:
2418*4882a593Smuzhiyun mode = MXT_DIAGNOSTIC_REFS;
2419*4882a593Smuzhiyun break;
2420*4882a593Smuzhiyun }
2421*4882a593Smuzhiyun
2422*4882a593Smuzhiyun ret = mxt_read_diagnostic_debug(data, mode, ptr);
2423*4882a593Smuzhiyun if (ret)
2424*4882a593Smuzhiyun goto fault;
2425*4882a593Smuzhiyun
2426*4882a593Smuzhiyun vb2_set_plane_payload(vb, 0, data->dbg.t37_nodes * sizeof(u16));
2427*4882a593Smuzhiyun vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
2428*4882a593Smuzhiyun return;
2429*4882a593Smuzhiyun
2430*4882a593Smuzhiyun fault:
2431*4882a593Smuzhiyun vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
2432*4882a593Smuzhiyun }
2433*4882a593Smuzhiyun
2434*4882a593Smuzhiyun /* V4L2 structures */
2435*4882a593Smuzhiyun static const struct vb2_ops mxt_queue_ops = {
2436*4882a593Smuzhiyun .queue_setup = mxt_queue_setup,
2437*4882a593Smuzhiyun .buf_queue = mxt_buffer_queue,
2438*4882a593Smuzhiyun .wait_prepare = vb2_ops_wait_prepare,
2439*4882a593Smuzhiyun .wait_finish = vb2_ops_wait_finish,
2440*4882a593Smuzhiyun };
2441*4882a593Smuzhiyun
2442*4882a593Smuzhiyun static const struct vb2_queue mxt_queue = {
2443*4882a593Smuzhiyun .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
2444*4882a593Smuzhiyun .io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ,
2445*4882a593Smuzhiyun .buf_struct_size = sizeof(struct mxt_vb2_buffer),
2446*4882a593Smuzhiyun .ops = &mxt_queue_ops,
2447*4882a593Smuzhiyun .mem_ops = &vb2_vmalloc_memops,
2448*4882a593Smuzhiyun .timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC,
2449*4882a593Smuzhiyun .min_buffers_needed = 1,
2450*4882a593Smuzhiyun };
2451*4882a593Smuzhiyun
mxt_vidioc_querycap(struct file * file,void * priv,struct v4l2_capability * cap)2452*4882a593Smuzhiyun static int mxt_vidioc_querycap(struct file *file, void *priv,
2453*4882a593Smuzhiyun struct v4l2_capability *cap)
2454*4882a593Smuzhiyun {
2455*4882a593Smuzhiyun struct mxt_data *data = video_drvdata(file);
2456*4882a593Smuzhiyun
2457*4882a593Smuzhiyun strlcpy(cap->driver, "atmel_mxt_ts", sizeof(cap->driver));
2458*4882a593Smuzhiyun strlcpy(cap->card, "atmel_mxt_ts touch", sizeof(cap->card));
2459*4882a593Smuzhiyun snprintf(cap->bus_info, sizeof(cap->bus_info),
2460*4882a593Smuzhiyun "I2C:%s", dev_name(&data->client->dev));
2461*4882a593Smuzhiyun return 0;
2462*4882a593Smuzhiyun }
2463*4882a593Smuzhiyun
mxt_vidioc_enum_input(struct file * file,void * priv,struct v4l2_input * i)2464*4882a593Smuzhiyun static int mxt_vidioc_enum_input(struct file *file, void *priv,
2465*4882a593Smuzhiyun struct v4l2_input *i)
2466*4882a593Smuzhiyun {
2467*4882a593Smuzhiyun if (i->index >= MXT_V4L_INPUT_MAX)
2468*4882a593Smuzhiyun return -EINVAL;
2469*4882a593Smuzhiyun
2470*4882a593Smuzhiyun i->type = V4L2_INPUT_TYPE_TOUCH;
2471*4882a593Smuzhiyun
2472*4882a593Smuzhiyun switch (i->index) {
2473*4882a593Smuzhiyun case MXT_V4L_INPUT_REFS:
2474*4882a593Smuzhiyun strlcpy(i->name, "Mutual Capacitance References",
2475*4882a593Smuzhiyun sizeof(i->name));
2476*4882a593Smuzhiyun break;
2477*4882a593Smuzhiyun case MXT_V4L_INPUT_DELTAS:
2478*4882a593Smuzhiyun strlcpy(i->name, "Mutual Capacitance Deltas", sizeof(i->name));
2479*4882a593Smuzhiyun break;
2480*4882a593Smuzhiyun }
2481*4882a593Smuzhiyun
2482*4882a593Smuzhiyun return 0;
2483*4882a593Smuzhiyun }
2484*4882a593Smuzhiyun
mxt_set_input(struct mxt_data * data,unsigned int i)2485*4882a593Smuzhiyun static int mxt_set_input(struct mxt_data *data, unsigned int i)
2486*4882a593Smuzhiyun {
2487*4882a593Smuzhiyun struct v4l2_pix_format *f = &data->dbg.format;
2488*4882a593Smuzhiyun
2489*4882a593Smuzhiyun if (i >= MXT_V4L_INPUT_MAX)
2490*4882a593Smuzhiyun return -EINVAL;
2491*4882a593Smuzhiyun
2492*4882a593Smuzhiyun if (i == MXT_V4L_INPUT_DELTAS)
2493*4882a593Smuzhiyun f->pixelformat = V4L2_TCH_FMT_DELTA_TD16;
2494*4882a593Smuzhiyun else
2495*4882a593Smuzhiyun f->pixelformat = V4L2_TCH_FMT_TU16;
2496*4882a593Smuzhiyun
2497*4882a593Smuzhiyun f->width = data->xy_switch ? data->ysize : data->xsize;
2498*4882a593Smuzhiyun f->height = data->xy_switch ? data->xsize : data->ysize;
2499*4882a593Smuzhiyun f->field = V4L2_FIELD_NONE;
2500*4882a593Smuzhiyun f->colorspace = V4L2_COLORSPACE_RAW;
2501*4882a593Smuzhiyun f->bytesperline = f->width * sizeof(u16);
2502*4882a593Smuzhiyun f->sizeimage = f->width * f->height * sizeof(u16);
2503*4882a593Smuzhiyun
2504*4882a593Smuzhiyun data->dbg.input = i;
2505*4882a593Smuzhiyun
2506*4882a593Smuzhiyun return 0;
2507*4882a593Smuzhiyun }
2508*4882a593Smuzhiyun
mxt_vidioc_s_input(struct file * file,void * priv,unsigned int i)2509*4882a593Smuzhiyun static int mxt_vidioc_s_input(struct file *file, void *priv, unsigned int i)
2510*4882a593Smuzhiyun {
2511*4882a593Smuzhiyun return mxt_set_input(video_drvdata(file), i);
2512*4882a593Smuzhiyun }
2513*4882a593Smuzhiyun
mxt_vidioc_g_input(struct file * file,void * priv,unsigned int * i)2514*4882a593Smuzhiyun static int mxt_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
2515*4882a593Smuzhiyun {
2516*4882a593Smuzhiyun struct mxt_data *data = video_drvdata(file);
2517*4882a593Smuzhiyun
2518*4882a593Smuzhiyun *i = data->dbg.input;
2519*4882a593Smuzhiyun
2520*4882a593Smuzhiyun return 0;
2521*4882a593Smuzhiyun }
2522*4882a593Smuzhiyun
mxt_vidioc_fmt(struct file * file,void * priv,struct v4l2_format * f)2523*4882a593Smuzhiyun static int mxt_vidioc_fmt(struct file *file, void *priv, struct v4l2_format *f)
2524*4882a593Smuzhiyun {
2525*4882a593Smuzhiyun struct mxt_data *data = video_drvdata(file);
2526*4882a593Smuzhiyun
2527*4882a593Smuzhiyun f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2528*4882a593Smuzhiyun f->fmt.pix = data->dbg.format;
2529*4882a593Smuzhiyun
2530*4882a593Smuzhiyun return 0;
2531*4882a593Smuzhiyun }
2532*4882a593Smuzhiyun
mxt_vidioc_enum_fmt(struct file * file,void * priv,struct v4l2_fmtdesc * fmt)2533*4882a593Smuzhiyun static int mxt_vidioc_enum_fmt(struct file *file, void *priv,
2534*4882a593Smuzhiyun struct v4l2_fmtdesc *fmt)
2535*4882a593Smuzhiyun {
2536*4882a593Smuzhiyun if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2537*4882a593Smuzhiyun return -EINVAL;
2538*4882a593Smuzhiyun
2539*4882a593Smuzhiyun switch (fmt->index) {
2540*4882a593Smuzhiyun case 0:
2541*4882a593Smuzhiyun fmt->pixelformat = V4L2_TCH_FMT_TU16;
2542*4882a593Smuzhiyun break;
2543*4882a593Smuzhiyun
2544*4882a593Smuzhiyun case 1:
2545*4882a593Smuzhiyun fmt->pixelformat = V4L2_TCH_FMT_DELTA_TD16;
2546*4882a593Smuzhiyun break;
2547*4882a593Smuzhiyun
2548*4882a593Smuzhiyun default:
2549*4882a593Smuzhiyun return -EINVAL;
2550*4882a593Smuzhiyun }
2551*4882a593Smuzhiyun
2552*4882a593Smuzhiyun return 0;
2553*4882a593Smuzhiyun }
2554*4882a593Smuzhiyun
mxt_vidioc_g_parm(struct file * file,void * fh,struct v4l2_streamparm * a)2555*4882a593Smuzhiyun static int mxt_vidioc_g_parm(struct file *file, void *fh,
2556*4882a593Smuzhiyun struct v4l2_streamparm *a)
2557*4882a593Smuzhiyun {
2558*4882a593Smuzhiyun if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
2559*4882a593Smuzhiyun return -EINVAL;
2560*4882a593Smuzhiyun
2561*4882a593Smuzhiyun a->parm.capture.readbuffers = 1;
2562*4882a593Smuzhiyun a->parm.capture.timeperframe.numerator = 1;
2563*4882a593Smuzhiyun a->parm.capture.timeperframe.denominator = 10;
2564*4882a593Smuzhiyun return 0;
2565*4882a593Smuzhiyun }
2566*4882a593Smuzhiyun
2567*4882a593Smuzhiyun static const struct v4l2_ioctl_ops mxt_video_ioctl_ops = {
2568*4882a593Smuzhiyun .vidioc_querycap = mxt_vidioc_querycap,
2569*4882a593Smuzhiyun
2570*4882a593Smuzhiyun .vidioc_enum_fmt_vid_cap = mxt_vidioc_enum_fmt,
2571*4882a593Smuzhiyun .vidioc_s_fmt_vid_cap = mxt_vidioc_fmt,
2572*4882a593Smuzhiyun .vidioc_g_fmt_vid_cap = mxt_vidioc_fmt,
2573*4882a593Smuzhiyun .vidioc_try_fmt_vid_cap = mxt_vidioc_fmt,
2574*4882a593Smuzhiyun .vidioc_g_parm = mxt_vidioc_g_parm,
2575*4882a593Smuzhiyun
2576*4882a593Smuzhiyun .vidioc_enum_input = mxt_vidioc_enum_input,
2577*4882a593Smuzhiyun .vidioc_g_input = mxt_vidioc_g_input,
2578*4882a593Smuzhiyun .vidioc_s_input = mxt_vidioc_s_input,
2579*4882a593Smuzhiyun
2580*4882a593Smuzhiyun .vidioc_reqbufs = vb2_ioctl_reqbufs,
2581*4882a593Smuzhiyun .vidioc_create_bufs = vb2_ioctl_create_bufs,
2582*4882a593Smuzhiyun .vidioc_querybuf = vb2_ioctl_querybuf,
2583*4882a593Smuzhiyun .vidioc_qbuf = vb2_ioctl_qbuf,
2584*4882a593Smuzhiyun .vidioc_dqbuf = vb2_ioctl_dqbuf,
2585*4882a593Smuzhiyun .vidioc_expbuf = vb2_ioctl_expbuf,
2586*4882a593Smuzhiyun
2587*4882a593Smuzhiyun .vidioc_streamon = vb2_ioctl_streamon,
2588*4882a593Smuzhiyun .vidioc_streamoff = vb2_ioctl_streamoff,
2589*4882a593Smuzhiyun };
2590*4882a593Smuzhiyun
2591*4882a593Smuzhiyun static const struct video_device mxt_video_device = {
2592*4882a593Smuzhiyun .name = "Atmel maxTouch",
2593*4882a593Smuzhiyun .fops = &mxt_video_fops,
2594*4882a593Smuzhiyun .ioctl_ops = &mxt_video_ioctl_ops,
2595*4882a593Smuzhiyun .release = video_device_release_empty,
2596*4882a593Smuzhiyun .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TOUCH |
2597*4882a593Smuzhiyun V4L2_CAP_READWRITE | V4L2_CAP_STREAMING,
2598*4882a593Smuzhiyun };
2599*4882a593Smuzhiyun
mxt_debug_init(struct mxt_data * data)2600*4882a593Smuzhiyun static void mxt_debug_init(struct mxt_data *data)
2601*4882a593Smuzhiyun {
2602*4882a593Smuzhiyun struct mxt_info *info = data->info;
2603*4882a593Smuzhiyun struct mxt_dbg *dbg = &data->dbg;
2604*4882a593Smuzhiyun struct mxt_object *object;
2605*4882a593Smuzhiyun int error;
2606*4882a593Smuzhiyun
2607*4882a593Smuzhiyun object = mxt_get_object(data, MXT_GEN_COMMAND_T6);
2608*4882a593Smuzhiyun if (!object)
2609*4882a593Smuzhiyun goto error;
2610*4882a593Smuzhiyun
2611*4882a593Smuzhiyun dbg->diag_cmd_address = object->start_address + MXT_COMMAND_DIAGNOSTIC;
2612*4882a593Smuzhiyun
2613*4882a593Smuzhiyun object = mxt_get_object(data, MXT_DEBUG_DIAGNOSTIC_T37);
2614*4882a593Smuzhiyun if (!object)
2615*4882a593Smuzhiyun goto error;
2616*4882a593Smuzhiyun
2617*4882a593Smuzhiyun if (mxt_obj_size(object) != sizeof(struct t37_debug)) {
2618*4882a593Smuzhiyun dev_warn(&data->client->dev, "Bad T37 size");
2619*4882a593Smuzhiyun goto error;
2620*4882a593Smuzhiyun }
2621*4882a593Smuzhiyun
2622*4882a593Smuzhiyun dbg->t37_address = object->start_address;
2623*4882a593Smuzhiyun
2624*4882a593Smuzhiyun /* Calculate size of data and allocate buffer */
2625*4882a593Smuzhiyun dbg->t37_nodes = data->xsize * data->ysize;
2626*4882a593Smuzhiyun
2627*4882a593Smuzhiyun if (info->family_id == MXT_FAMILY_1386)
2628*4882a593Smuzhiyun dbg->t37_pages = MXT1386_COLUMNS * MXT1386_PAGES_PER_COLUMN;
2629*4882a593Smuzhiyun else
2630*4882a593Smuzhiyun dbg->t37_pages = DIV_ROUND_UP(data->xsize *
2631*4882a593Smuzhiyun info->matrix_ysize *
2632*4882a593Smuzhiyun sizeof(u16),
2633*4882a593Smuzhiyun sizeof(dbg->t37_buf->data));
2634*4882a593Smuzhiyun
2635*4882a593Smuzhiyun dbg->t37_buf = devm_kmalloc_array(&data->client->dev, dbg->t37_pages,
2636*4882a593Smuzhiyun sizeof(struct t37_debug), GFP_KERNEL);
2637*4882a593Smuzhiyun if (!dbg->t37_buf)
2638*4882a593Smuzhiyun goto error;
2639*4882a593Smuzhiyun
2640*4882a593Smuzhiyun /* init channel to zero */
2641*4882a593Smuzhiyun mxt_set_input(data, 0);
2642*4882a593Smuzhiyun
2643*4882a593Smuzhiyun /* register video device */
2644*4882a593Smuzhiyun snprintf(dbg->v4l2.name, sizeof(dbg->v4l2.name), "%s", "atmel_mxt_ts");
2645*4882a593Smuzhiyun error = v4l2_device_register(&data->client->dev, &dbg->v4l2);
2646*4882a593Smuzhiyun if (error)
2647*4882a593Smuzhiyun goto error;
2648*4882a593Smuzhiyun
2649*4882a593Smuzhiyun /* initialize the queue */
2650*4882a593Smuzhiyun mutex_init(&dbg->lock);
2651*4882a593Smuzhiyun dbg->queue = mxt_queue;
2652*4882a593Smuzhiyun dbg->queue.drv_priv = data;
2653*4882a593Smuzhiyun dbg->queue.lock = &dbg->lock;
2654*4882a593Smuzhiyun dbg->queue.dev = &data->client->dev;
2655*4882a593Smuzhiyun
2656*4882a593Smuzhiyun error = vb2_queue_init(&dbg->queue);
2657*4882a593Smuzhiyun if (error)
2658*4882a593Smuzhiyun goto error_unreg_v4l2;
2659*4882a593Smuzhiyun
2660*4882a593Smuzhiyun dbg->vdev = mxt_video_device;
2661*4882a593Smuzhiyun dbg->vdev.v4l2_dev = &dbg->v4l2;
2662*4882a593Smuzhiyun dbg->vdev.lock = &dbg->lock;
2663*4882a593Smuzhiyun dbg->vdev.vfl_dir = VFL_DIR_RX;
2664*4882a593Smuzhiyun dbg->vdev.queue = &dbg->queue;
2665*4882a593Smuzhiyun video_set_drvdata(&dbg->vdev, data);
2666*4882a593Smuzhiyun
2667*4882a593Smuzhiyun error = video_register_device(&dbg->vdev, VFL_TYPE_TOUCH, -1);
2668*4882a593Smuzhiyun if (error)
2669*4882a593Smuzhiyun goto error_unreg_v4l2;
2670*4882a593Smuzhiyun
2671*4882a593Smuzhiyun return;
2672*4882a593Smuzhiyun
2673*4882a593Smuzhiyun error_unreg_v4l2:
2674*4882a593Smuzhiyun v4l2_device_unregister(&dbg->v4l2);
2675*4882a593Smuzhiyun error:
2676*4882a593Smuzhiyun dev_warn(&data->client->dev, "Error initializing T37\n");
2677*4882a593Smuzhiyun }
2678*4882a593Smuzhiyun #else
mxt_debug_init(struct mxt_data * data)2679*4882a593Smuzhiyun static void mxt_debug_init(struct mxt_data *data)
2680*4882a593Smuzhiyun {
2681*4882a593Smuzhiyun }
2682*4882a593Smuzhiyun #endif
2683*4882a593Smuzhiyun
mxt_configure_objects(struct mxt_data * data,const struct firmware * cfg)2684*4882a593Smuzhiyun static int mxt_configure_objects(struct mxt_data *data,
2685*4882a593Smuzhiyun const struct firmware *cfg)
2686*4882a593Smuzhiyun {
2687*4882a593Smuzhiyun struct device *dev = &data->client->dev;
2688*4882a593Smuzhiyun int error;
2689*4882a593Smuzhiyun
2690*4882a593Smuzhiyun error = mxt_init_t7_power_cfg(data);
2691*4882a593Smuzhiyun if (error) {
2692*4882a593Smuzhiyun dev_err(dev, "Failed to initialize power cfg\n");
2693*4882a593Smuzhiyun return error;
2694*4882a593Smuzhiyun }
2695*4882a593Smuzhiyun
2696*4882a593Smuzhiyun if (cfg) {
2697*4882a593Smuzhiyun error = mxt_update_cfg(data, cfg);
2698*4882a593Smuzhiyun if (error)
2699*4882a593Smuzhiyun dev_warn(dev, "Error %d updating config\n", error);
2700*4882a593Smuzhiyun }
2701*4882a593Smuzhiyun
2702*4882a593Smuzhiyun if (data->multitouch) {
2703*4882a593Smuzhiyun error = mxt_initialize_input_device(data);
2704*4882a593Smuzhiyun if (error)
2705*4882a593Smuzhiyun return error;
2706*4882a593Smuzhiyun } else {
2707*4882a593Smuzhiyun dev_warn(dev, "No touch object detected\n");
2708*4882a593Smuzhiyun }
2709*4882a593Smuzhiyun
2710*4882a593Smuzhiyun mxt_debug_init(data);
2711*4882a593Smuzhiyun
2712*4882a593Smuzhiyun return 0;
2713*4882a593Smuzhiyun }
2714*4882a593Smuzhiyun
2715*4882a593Smuzhiyun /* Firmware Version is returned as Major.Minor.Build */
mxt_fw_version_show(struct device * dev,struct device_attribute * attr,char * buf)2716*4882a593Smuzhiyun static ssize_t mxt_fw_version_show(struct device *dev,
2717*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
2718*4882a593Smuzhiyun {
2719*4882a593Smuzhiyun struct mxt_data *data = dev_get_drvdata(dev);
2720*4882a593Smuzhiyun struct mxt_info *info = data->info;
2721*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "%u.%u.%02X\n",
2722*4882a593Smuzhiyun info->version >> 4, info->version & 0xf, info->build);
2723*4882a593Smuzhiyun }
2724*4882a593Smuzhiyun
2725*4882a593Smuzhiyun /* Hardware Version is returned as FamilyID.VariantID */
mxt_hw_version_show(struct device * dev,struct device_attribute * attr,char * buf)2726*4882a593Smuzhiyun static ssize_t mxt_hw_version_show(struct device *dev,
2727*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
2728*4882a593Smuzhiyun {
2729*4882a593Smuzhiyun struct mxt_data *data = dev_get_drvdata(dev);
2730*4882a593Smuzhiyun struct mxt_info *info = data->info;
2731*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "%u.%u\n",
2732*4882a593Smuzhiyun info->family_id, info->variant_id);
2733*4882a593Smuzhiyun }
2734*4882a593Smuzhiyun
mxt_show_instance(char * buf,int count,struct mxt_object * object,int instance,const u8 * val)2735*4882a593Smuzhiyun static ssize_t mxt_show_instance(char *buf, int count,
2736*4882a593Smuzhiyun struct mxt_object *object, int instance,
2737*4882a593Smuzhiyun const u8 *val)
2738*4882a593Smuzhiyun {
2739*4882a593Smuzhiyun int i;
2740*4882a593Smuzhiyun
2741*4882a593Smuzhiyun if (mxt_obj_instances(object) > 1)
2742*4882a593Smuzhiyun count += scnprintf(buf + count, PAGE_SIZE - count,
2743*4882a593Smuzhiyun "Instance %u\n", instance);
2744*4882a593Smuzhiyun
2745*4882a593Smuzhiyun for (i = 0; i < mxt_obj_size(object); i++)
2746*4882a593Smuzhiyun count += scnprintf(buf + count, PAGE_SIZE - count,
2747*4882a593Smuzhiyun "\t[%2u]: %02x (%d)\n", i, val[i], val[i]);
2748*4882a593Smuzhiyun count += scnprintf(buf + count, PAGE_SIZE - count, "\n");
2749*4882a593Smuzhiyun
2750*4882a593Smuzhiyun return count;
2751*4882a593Smuzhiyun }
2752*4882a593Smuzhiyun
mxt_object_show(struct device * dev,struct device_attribute * attr,char * buf)2753*4882a593Smuzhiyun static ssize_t mxt_object_show(struct device *dev,
2754*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
2755*4882a593Smuzhiyun {
2756*4882a593Smuzhiyun struct mxt_data *data = dev_get_drvdata(dev);
2757*4882a593Smuzhiyun struct mxt_object *object;
2758*4882a593Smuzhiyun int count = 0;
2759*4882a593Smuzhiyun int i, j;
2760*4882a593Smuzhiyun int error;
2761*4882a593Smuzhiyun u8 *obuf;
2762*4882a593Smuzhiyun
2763*4882a593Smuzhiyun /* Pre-allocate buffer large enough to hold max sized object. */
2764*4882a593Smuzhiyun obuf = kmalloc(256, GFP_KERNEL);
2765*4882a593Smuzhiyun if (!obuf)
2766*4882a593Smuzhiyun return -ENOMEM;
2767*4882a593Smuzhiyun
2768*4882a593Smuzhiyun error = 0;
2769*4882a593Smuzhiyun for (i = 0; i < data->info->object_num; i++) {
2770*4882a593Smuzhiyun object = data->object_table + i;
2771*4882a593Smuzhiyun
2772*4882a593Smuzhiyun if (!mxt_object_readable(object->type))
2773*4882a593Smuzhiyun continue;
2774*4882a593Smuzhiyun
2775*4882a593Smuzhiyun count += scnprintf(buf + count, PAGE_SIZE - count,
2776*4882a593Smuzhiyun "T%u:\n", object->type);
2777*4882a593Smuzhiyun
2778*4882a593Smuzhiyun for (j = 0; j < mxt_obj_instances(object); j++) {
2779*4882a593Smuzhiyun u16 size = mxt_obj_size(object);
2780*4882a593Smuzhiyun u16 addr = object->start_address + j * size;
2781*4882a593Smuzhiyun
2782*4882a593Smuzhiyun error = __mxt_read_reg(data->client, addr, size, obuf);
2783*4882a593Smuzhiyun if (error)
2784*4882a593Smuzhiyun goto done;
2785*4882a593Smuzhiyun
2786*4882a593Smuzhiyun count = mxt_show_instance(buf, count, object, j, obuf);
2787*4882a593Smuzhiyun }
2788*4882a593Smuzhiyun }
2789*4882a593Smuzhiyun
2790*4882a593Smuzhiyun done:
2791*4882a593Smuzhiyun kfree(obuf);
2792*4882a593Smuzhiyun return error ?: count;
2793*4882a593Smuzhiyun }
2794*4882a593Smuzhiyun
mxt_check_firmware_format(struct device * dev,const struct firmware * fw)2795*4882a593Smuzhiyun static int mxt_check_firmware_format(struct device *dev,
2796*4882a593Smuzhiyun const struct firmware *fw)
2797*4882a593Smuzhiyun {
2798*4882a593Smuzhiyun unsigned int pos = 0;
2799*4882a593Smuzhiyun char c;
2800*4882a593Smuzhiyun
2801*4882a593Smuzhiyun while (pos < fw->size) {
2802*4882a593Smuzhiyun c = *(fw->data + pos);
2803*4882a593Smuzhiyun
2804*4882a593Smuzhiyun if (c < '0' || (c > '9' && c < 'A') || c > 'F')
2805*4882a593Smuzhiyun return 0;
2806*4882a593Smuzhiyun
2807*4882a593Smuzhiyun pos++;
2808*4882a593Smuzhiyun }
2809*4882a593Smuzhiyun
2810*4882a593Smuzhiyun /*
2811*4882a593Smuzhiyun * To convert file try:
2812*4882a593Smuzhiyun * xxd -r -p mXTXXX__APP_VX-X-XX.enc > maxtouch.fw
2813*4882a593Smuzhiyun */
2814*4882a593Smuzhiyun dev_err(dev, "Aborting: firmware file must be in binary format\n");
2815*4882a593Smuzhiyun
2816*4882a593Smuzhiyun return -EINVAL;
2817*4882a593Smuzhiyun }
2818*4882a593Smuzhiyun
mxt_load_fw(struct device * dev,const char * fn)2819*4882a593Smuzhiyun static int mxt_load_fw(struct device *dev, const char *fn)
2820*4882a593Smuzhiyun {
2821*4882a593Smuzhiyun struct mxt_data *data = dev_get_drvdata(dev);
2822*4882a593Smuzhiyun const struct firmware *fw = NULL;
2823*4882a593Smuzhiyun unsigned int frame_size;
2824*4882a593Smuzhiyun unsigned int pos = 0;
2825*4882a593Smuzhiyun unsigned int retry = 0;
2826*4882a593Smuzhiyun unsigned int frame = 0;
2827*4882a593Smuzhiyun int ret;
2828*4882a593Smuzhiyun
2829*4882a593Smuzhiyun ret = request_firmware(&fw, fn, dev);
2830*4882a593Smuzhiyun if (ret) {
2831*4882a593Smuzhiyun dev_err(dev, "Unable to open firmware %s\n", fn);
2832*4882a593Smuzhiyun return ret;
2833*4882a593Smuzhiyun }
2834*4882a593Smuzhiyun
2835*4882a593Smuzhiyun /* Check for incorrect enc file */
2836*4882a593Smuzhiyun ret = mxt_check_firmware_format(dev, fw);
2837*4882a593Smuzhiyun if (ret)
2838*4882a593Smuzhiyun goto release_firmware;
2839*4882a593Smuzhiyun
2840*4882a593Smuzhiyun if (!data->in_bootloader) {
2841*4882a593Smuzhiyun /* Change to the bootloader mode */
2842*4882a593Smuzhiyun data->in_bootloader = true;
2843*4882a593Smuzhiyun
2844*4882a593Smuzhiyun ret = mxt_t6_command(data, MXT_COMMAND_RESET,
2845*4882a593Smuzhiyun MXT_BOOT_VALUE, false);
2846*4882a593Smuzhiyun if (ret)
2847*4882a593Smuzhiyun goto release_firmware;
2848*4882a593Smuzhiyun
2849*4882a593Smuzhiyun msleep(MXT_RESET_TIME);
2850*4882a593Smuzhiyun
2851*4882a593Smuzhiyun /* Do not need to scan since we know family ID */
2852*4882a593Smuzhiyun ret = mxt_lookup_bootloader_address(data, 0);
2853*4882a593Smuzhiyun if (ret)
2854*4882a593Smuzhiyun goto release_firmware;
2855*4882a593Smuzhiyun
2856*4882a593Smuzhiyun mxt_free_input_device(data);
2857*4882a593Smuzhiyun mxt_free_object_table(data);
2858*4882a593Smuzhiyun } else {
2859*4882a593Smuzhiyun enable_irq(data->irq);
2860*4882a593Smuzhiyun }
2861*4882a593Smuzhiyun
2862*4882a593Smuzhiyun reinit_completion(&data->bl_completion);
2863*4882a593Smuzhiyun
2864*4882a593Smuzhiyun ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false);
2865*4882a593Smuzhiyun if (ret) {
2866*4882a593Smuzhiyun /* Bootloader may still be unlocked from previous attempt */
2867*4882a593Smuzhiyun ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, false);
2868*4882a593Smuzhiyun if (ret)
2869*4882a593Smuzhiyun goto disable_irq;
2870*4882a593Smuzhiyun } else {
2871*4882a593Smuzhiyun dev_info(dev, "Unlocking bootloader\n");
2872*4882a593Smuzhiyun
2873*4882a593Smuzhiyun /* Unlock bootloader */
2874*4882a593Smuzhiyun ret = mxt_send_bootloader_cmd(data, true);
2875*4882a593Smuzhiyun if (ret)
2876*4882a593Smuzhiyun goto disable_irq;
2877*4882a593Smuzhiyun }
2878*4882a593Smuzhiyun
2879*4882a593Smuzhiyun while (pos < fw->size) {
2880*4882a593Smuzhiyun ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, true);
2881*4882a593Smuzhiyun if (ret)
2882*4882a593Smuzhiyun goto disable_irq;
2883*4882a593Smuzhiyun
2884*4882a593Smuzhiyun frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
2885*4882a593Smuzhiyun
2886*4882a593Smuzhiyun /* Take account of CRC bytes */
2887*4882a593Smuzhiyun frame_size += 2;
2888*4882a593Smuzhiyun
2889*4882a593Smuzhiyun /* Write one frame to device */
2890*4882a593Smuzhiyun ret = mxt_bootloader_write(data, fw->data + pos, frame_size);
2891*4882a593Smuzhiyun if (ret)
2892*4882a593Smuzhiyun goto disable_irq;
2893*4882a593Smuzhiyun
2894*4882a593Smuzhiyun ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS, true);
2895*4882a593Smuzhiyun if (ret) {
2896*4882a593Smuzhiyun retry++;
2897*4882a593Smuzhiyun
2898*4882a593Smuzhiyun /* Back off by 20ms per retry */
2899*4882a593Smuzhiyun msleep(retry * 20);
2900*4882a593Smuzhiyun
2901*4882a593Smuzhiyun if (retry > 20) {
2902*4882a593Smuzhiyun dev_err(dev, "Retry count exceeded\n");
2903*4882a593Smuzhiyun goto disable_irq;
2904*4882a593Smuzhiyun }
2905*4882a593Smuzhiyun } else {
2906*4882a593Smuzhiyun retry = 0;
2907*4882a593Smuzhiyun pos += frame_size;
2908*4882a593Smuzhiyun frame++;
2909*4882a593Smuzhiyun }
2910*4882a593Smuzhiyun
2911*4882a593Smuzhiyun if (frame % 50 == 0)
2912*4882a593Smuzhiyun dev_dbg(dev, "Sent %d frames, %d/%zd bytes\n",
2913*4882a593Smuzhiyun frame, pos, fw->size);
2914*4882a593Smuzhiyun }
2915*4882a593Smuzhiyun
2916*4882a593Smuzhiyun /* Wait for flash. */
2917*4882a593Smuzhiyun ret = mxt_wait_for_completion(data, &data->bl_completion,
2918*4882a593Smuzhiyun MXT_FW_RESET_TIME);
2919*4882a593Smuzhiyun if (ret)
2920*4882a593Smuzhiyun goto disable_irq;
2921*4882a593Smuzhiyun
2922*4882a593Smuzhiyun dev_dbg(dev, "Sent %d frames, %d bytes\n", frame, pos);
2923*4882a593Smuzhiyun
2924*4882a593Smuzhiyun /*
2925*4882a593Smuzhiyun * Wait for device to reset. Some bootloader versions do not assert
2926*4882a593Smuzhiyun * the CHG line after bootloading has finished, so ignore potential
2927*4882a593Smuzhiyun * errors.
2928*4882a593Smuzhiyun */
2929*4882a593Smuzhiyun mxt_wait_for_completion(data, &data->bl_completion, MXT_FW_RESET_TIME);
2930*4882a593Smuzhiyun
2931*4882a593Smuzhiyun data->in_bootloader = false;
2932*4882a593Smuzhiyun
2933*4882a593Smuzhiyun disable_irq:
2934*4882a593Smuzhiyun disable_irq(data->irq);
2935*4882a593Smuzhiyun release_firmware:
2936*4882a593Smuzhiyun release_firmware(fw);
2937*4882a593Smuzhiyun return ret;
2938*4882a593Smuzhiyun }
2939*4882a593Smuzhiyun
mxt_update_fw_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)2940*4882a593Smuzhiyun static ssize_t mxt_update_fw_store(struct device *dev,
2941*4882a593Smuzhiyun struct device_attribute *attr,
2942*4882a593Smuzhiyun const char *buf, size_t count)
2943*4882a593Smuzhiyun {
2944*4882a593Smuzhiyun struct mxt_data *data = dev_get_drvdata(dev);
2945*4882a593Smuzhiyun int error;
2946*4882a593Smuzhiyun
2947*4882a593Smuzhiyun error = mxt_load_fw(dev, MXT_FW_NAME);
2948*4882a593Smuzhiyun if (error) {
2949*4882a593Smuzhiyun dev_err(dev, "The firmware update failed(%d)\n", error);
2950*4882a593Smuzhiyun count = error;
2951*4882a593Smuzhiyun } else {
2952*4882a593Smuzhiyun dev_info(dev, "The firmware update succeeded\n");
2953*4882a593Smuzhiyun
2954*4882a593Smuzhiyun error = mxt_initialize(data);
2955*4882a593Smuzhiyun if (error)
2956*4882a593Smuzhiyun return error;
2957*4882a593Smuzhiyun }
2958*4882a593Smuzhiyun
2959*4882a593Smuzhiyun return count;
2960*4882a593Smuzhiyun }
2961*4882a593Smuzhiyun
2962*4882a593Smuzhiyun static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL);
2963*4882a593Smuzhiyun static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL);
2964*4882a593Smuzhiyun static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
2965*4882a593Smuzhiyun static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store);
2966*4882a593Smuzhiyun
2967*4882a593Smuzhiyun static struct attribute *mxt_attrs[] = {
2968*4882a593Smuzhiyun &dev_attr_fw_version.attr,
2969*4882a593Smuzhiyun &dev_attr_hw_version.attr,
2970*4882a593Smuzhiyun &dev_attr_object.attr,
2971*4882a593Smuzhiyun &dev_attr_update_fw.attr,
2972*4882a593Smuzhiyun NULL
2973*4882a593Smuzhiyun };
2974*4882a593Smuzhiyun
2975*4882a593Smuzhiyun static const struct attribute_group mxt_attr_group = {
2976*4882a593Smuzhiyun .attrs = mxt_attrs,
2977*4882a593Smuzhiyun };
2978*4882a593Smuzhiyun
mxt_start(struct mxt_data * data)2979*4882a593Smuzhiyun static void mxt_start(struct mxt_data *data)
2980*4882a593Smuzhiyun {
2981*4882a593Smuzhiyun switch (data->suspend_mode) {
2982*4882a593Smuzhiyun case MXT_SUSPEND_T9_CTRL:
2983*4882a593Smuzhiyun mxt_soft_reset(data);
2984*4882a593Smuzhiyun
2985*4882a593Smuzhiyun /* Touch enable */
2986*4882a593Smuzhiyun /* 0x83 = SCANEN | RPTEN | ENABLE */
2987*4882a593Smuzhiyun mxt_write_object(data,
2988*4882a593Smuzhiyun MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0x83);
2989*4882a593Smuzhiyun break;
2990*4882a593Smuzhiyun
2991*4882a593Smuzhiyun case MXT_SUSPEND_DEEP_SLEEP:
2992*4882a593Smuzhiyun default:
2993*4882a593Smuzhiyun mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
2994*4882a593Smuzhiyun
2995*4882a593Smuzhiyun /* Recalibrate since chip has been in deep sleep */
2996*4882a593Smuzhiyun mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false);
2997*4882a593Smuzhiyun break;
2998*4882a593Smuzhiyun }
2999*4882a593Smuzhiyun }
3000*4882a593Smuzhiyun
mxt_stop(struct mxt_data * data)3001*4882a593Smuzhiyun static void mxt_stop(struct mxt_data *data)
3002*4882a593Smuzhiyun {
3003*4882a593Smuzhiyun switch (data->suspend_mode) {
3004*4882a593Smuzhiyun case MXT_SUSPEND_T9_CTRL:
3005*4882a593Smuzhiyun /* Touch disable */
3006*4882a593Smuzhiyun mxt_write_object(data,
3007*4882a593Smuzhiyun MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0);
3008*4882a593Smuzhiyun break;
3009*4882a593Smuzhiyun
3010*4882a593Smuzhiyun case MXT_SUSPEND_DEEP_SLEEP:
3011*4882a593Smuzhiyun default:
3012*4882a593Smuzhiyun mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP);
3013*4882a593Smuzhiyun break;
3014*4882a593Smuzhiyun }
3015*4882a593Smuzhiyun }
3016*4882a593Smuzhiyun
mxt_input_open(struct input_dev * dev)3017*4882a593Smuzhiyun static int mxt_input_open(struct input_dev *dev)
3018*4882a593Smuzhiyun {
3019*4882a593Smuzhiyun struct mxt_data *data = input_get_drvdata(dev);
3020*4882a593Smuzhiyun
3021*4882a593Smuzhiyun mxt_start(data);
3022*4882a593Smuzhiyun
3023*4882a593Smuzhiyun return 0;
3024*4882a593Smuzhiyun }
3025*4882a593Smuzhiyun
mxt_input_close(struct input_dev * dev)3026*4882a593Smuzhiyun static void mxt_input_close(struct input_dev *dev)
3027*4882a593Smuzhiyun {
3028*4882a593Smuzhiyun struct mxt_data *data = input_get_drvdata(dev);
3029*4882a593Smuzhiyun
3030*4882a593Smuzhiyun mxt_stop(data);
3031*4882a593Smuzhiyun }
3032*4882a593Smuzhiyun
mxt_parse_device_properties(struct mxt_data * data)3033*4882a593Smuzhiyun static int mxt_parse_device_properties(struct mxt_data *data)
3034*4882a593Smuzhiyun {
3035*4882a593Smuzhiyun static const char keymap_property[] = "linux,gpio-keymap";
3036*4882a593Smuzhiyun struct device *dev = &data->client->dev;
3037*4882a593Smuzhiyun u32 *keymap;
3038*4882a593Smuzhiyun int n_keys;
3039*4882a593Smuzhiyun int error;
3040*4882a593Smuzhiyun
3041*4882a593Smuzhiyun if (device_property_present(dev, keymap_property)) {
3042*4882a593Smuzhiyun n_keys = device_property_count_u32(dev, keymap_property);
3043*4882a593Smuzhiyun if (n_keys <= 0) {
3044*4882a593Smuzhiyun error = n_keys < 0 ? n_keys : -EINVAL;
3045*4882a593Smuzhiyun dev_err(dev, "invalid/malformed '%s' property: %d\n",
3046*4882a593Smuzhiyun keymap_property, error);
3047*4882a593Smuzhiyun return error;
3048*4882a593Smuzhiyun }
3049*4882a593Smuzhiyun
3050*4882a593Smuzhiyun keymap = devm_kmalloc_array(dev, n_keys, sizeof(*keymap),
3051*4882a593Smuzhiyun GFP_KERNEL);
3052*4882a593Smuzhiyun if (!keymap)
3053*4882a593Smuzhiyun return -ENOMEM;
3054*4882a593Smuzhiyun
3055*4882a593Smuzhiyun error = device_property_read_u32_array(dev, keymap_property,
3056*4882a593Smuzhiyun keymap, n_keys);
3057*4882a593Smuzhiyun if (error) {
3058*4882a593Smuzhiyun dev_err(dev, "failed to parse '%s' property: %d\n",
3059*4882a593Smuzhiyun keymap_property, error);
3060*4882a593Smuzhiyun return error;
3061*4882a593Smuzhiyun }
3062*4882a593Smuzhiyun
3063*4882a593Smuzhiyun data->t19_keymap = keymap;
3064*4882a593Smuzhiyun data->t19_num_keys = n_keys;
3065*4882a593Smuzhiyun }
3066*4882a593Smuzhiyun
3067*4882a593Smuzhiyun return 0;
3068*4882a593Smuzhiyun }
3069*4882a593Smuzhiyun
3070*4882a593Smuzhiyun static const struct dmi_system_id chromebook_T9_suspend_dmi[] = {
3071*4882a593Smuzhiyun {
3072*4882a593Smuzhiyun .matches = {
3073*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
3074*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
3075*4882a593Smuzhiyun },
3076*4882a593Smuzhiyun },
3077*4882a593Smuzhiyun {
3078*4882a593Smuzhiyun .matches = {
3079*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
3080*4882a593Smuzhiyun },
3081*4882a593Smuzhiyun },
3082*4882a593Smuzhiyun { }
3083*4882a593Smuzhiyun };
3084*4882a593Smuzhiyun
mxt_probe(struct i2c_client * client,const struct i2c_device_id * id)3085*4882a593Smuzhiyun static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
3086*4882a593Smuzhiyun {
3087*4882a593Smuzhiyun struct mxt_data *data;
3088*4882a593Smuzhiyun int error;
3089*4882a593Smuzhiyun
3090*4882a593Smuzhiyun /*
3091*4882a593Smuzhiyun * Ignore devices that do not have device properties attached to
3092*4882a593Smuzhiyun * them, as we need help determining whether we are dealing with
3093*4882a593Smuzhiyun * touch screen or touchpad.
3094*4882a593Smuzhiyun *
3095*4882a593Smuzhiyun * So far on x86 the only users of Atmel touch controllers are
3096*4882a593Smuzhiyun * Chromebooks, and chromeos_laptop driver will ensure that
3097*4882a593Smuzhiyun * necessary properties are provided (if firmware does not do that).
3098*4882a593Smuzhiyun */
3099*4882a593Smuzhiyun if (!device_property_present(&client->dev, "compatible"))
3100*4882a593Smuzhiyun return -ENXIO;
3101*4882a593Smuzhiyun
3102*4882a593Smuzhiyun /*
3103*4882a593Smuzhiyun * Ignore ACPI devices representing bootloader mode.
3104*4882a593Smuzhiyun *
3105*4882a593Smuzhiyun * This is a bit of a hack: Google Chromebook BIOS creates ACPI
3106*4882a593Smuzhiyun * devices for both application and bootloader modes, but we are
3107*4882a593Smuzhiyun * interested in application mode only (if device is in bootloader
3108*4882a593Smuzhiyun * mode we'll end up switching into application anyway). So far
3109*4882a593Smuzhiyun * application mode addresses were all above 0x40, so we'll use it
3110*4882a593Smuzhiyun * as a threshold.
3111*4882a593Smuzhiyun */
3112*4882a593Smuzhiyun if (ACPI_COMPANION(&client->dev) && client->addr < 0x40)
3113*4882a593Smuzhiyun return -ENXIO;
3114*4882a593Smuzhiyun
3115*4882a593Smuzhiyun data = devm_kzalloc(&client->dev, sizeof(struct mxt_data), GFP_KERNEL);
3116*4882a593Smuzhiyun if (!data)
3117*4882a593Smuzhiyun return -ENOMEM;
3118*4882a593Smuzhiyun
3119*4882a593Smuzhiyun snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0",
3120*4882a593Smuzhiyun client->adapter->nr, client->addr);
3121*4882a593Smuzhiyun
3122*4882a593Smuzhiyun data->client = client;
3123*4882a593Smuzhiyun data->irq = client->irq;
3124*4882a593Smuzhiyun i2c_set_clientdata(client, data);
3125*4882a593Smuzhiyun
3126*4882a593Smuzhiyun init_completion(&data->bl_completion);
3127*4882a593Smuzhiyun init_completion(&data->reset_completion);
3128*4882a593Smuzhiyun init_completion(&data->crc_completion);
3129*4882a593Smuzhiyun
3130*4882a593Smuzhiyun data->suspend_mode = dmi_check_system(chromebook_T9_suspend_dmi) ?
3131*4882a593Smuzhiyun MXT_SUSPEND_T9_CTRL : MXT_SUSPEND_DEEP_SLEEP;
3132*4882a593Smuzhiyun
3133*4882a593Smuzhiyun error = mxt_parse_device_properties(data);
3134*4882a593Smuzhiyun if (error)
3135*4882a593Smuzhiyun return error;
3136*4882a593Smuzhiyun
3137*4882a593Smuzhiyun /* Request the RESET line as asserted so we go into reset */
3138*4882a593Smuzhiyun data->reset_gpio = devm_gpiod_get_optional(&client->dev,
3139*4882a593Smuzhiyun "reset", GPIOD_OUT_HIGH);
3140*4882a593Smuzhiyun if (IS_ERR(data->reset_gpio)) {
3141*4882a593Smuzhiyun error = PTR_ERR(data->reset_gpio);
3142*4882a593Smuzhiyun dev_err(&client->dev, "Failed to get reset gpio: %d\n", error);
3143*4882a593Smuzhiyun return error;
3144*4882a593Smuzhiyun }
3145*4882a593Smuzhiyun
3146*4882a593Smuzhiyun error = devm_request_threaded_irq(&client->dev, client->irq,
3147*4882a593Smuzhiyun NULL, mxt_interrupt, IRQF_ONESHOT,
3148*4882a593Smuzhiyun client->name, data);
3149*4882a593Smuzhiyun if (error) {
3150*4882a593Smuzhiyun dev_err(&client->dev, "Failed to register interrupt\n");
3151*4882a593Smuzhiyun return error;
3152*4882a593Smuzhiyun }
3153*4882a593Smuzhiyun
3154*4882a593Smuzhiyun disable_irq(client->irq);
3155*4882a593Smuzhiyun
3156*4882a593Smuzhiyun if (data->reset_gpio) {
3157*4882a593Smuzhiyun /* Wait a while and then de-assert the RESET GPIO line */
3158*4882a593Smuzhiyun msleep(MXT_RESET_GPIO_TIME);
3159*4882a593Smuzhiyun gpiod_set_value(data->reset_gpio, 0);
3160*4882a593Smuzhiyun msleep(MXT_RESET_INVALID_CHG);
3161*4882a593Smuzhiyun }
3162*4882a593Smuzhiyun
3163*4882a593Smuzhiyun error = mxt_initialize(data);
3164*4882a593Smuzhiyun if (error)
3165*4882a593Smuzhiyun return error;
3166*4882a593Smuzhiyun
3167*4882a593Smuzhiyun error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
3168*4882a593Smuzhiyun if (error) {
3169*4882a593Smuzhiyun dev_err(&client->dev, "Failure %d creating sysfs group\n",
3170*4882a593Smuzhiyun error);
3171*4882a593Smuzhiyun goto err_free_object;
3172*4882a593Smuzhiyun }
3173*4882a593Smuzhiyun
3174*4882a593Smuzhiyun return 0;
3175*4882a593Smuzhiyun
3176*4882a593Smuzhiyun err_free_object:
3177*4882a593Smuzhiyun mxt_free_input_device(data);
3178*4882a593Smuzhiyun mxt_free_object_table(data);
3179*4882a593Smuzhiyun return error;
3180*4882a593Smuzhiyun }
3181*4882a593Smuzhiyun
mxt_remove(struct i2c_client * client)3182*4882a593Smuzhiyun static int mxt_remove(struct i2c_client *client)
3183*4882a593Smuzhiyun {
3184*4882a593Smuzhiyun struct mxt_data *data = i2c_get_clientdata(client);
3185*4882a593Smuzhiyun
3186*4882a593Smuzhiyun disable_irq(data->irq);
3187*4882a593Smuzhiyun sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
3188*4882a593Smuzhiyun mxt_free_input_device(data);
3189*4882a593Smuzhiyun mxt_free_object_table(data);
3190*4882a593Smuzhiyun
3191*4882a593Smuzhiyun return 0;
3192*4882a593Smuzhiyun }
3193*4882a593Smuzhiyun
mxt_suspend(struct device * dev)3194*4882a593Smuzhiyun static int __maybe_unused mxt_suspend(struct device *dev)
3195*4882a593Smuzhiyun {
3196*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
3197*4882a593Smuzhiyun struct mxt_data *data = i2c_get_clientdata(client);
3198*4882a593Smuzhiyun struct input_dev *input_dev = data->input_dev;
3199*4882a593Smuzhiyun
3200*4882a593Smuzhiyun if (!input_dev)
3201*4882a593Smuzhiyun return 0;
3202*4882a593Smuzhiyun
3203*4882a593Smuzhiyun mutex_lock(&input_dev->mutex);
3204*4882a593Smuzhiyun
3205*4882a593Smuzhiyun if (input_dev->users)
3206*4882a593Smuzhiyun mxt_stop(data);
3207*4882a593Smuzhiyun
3208*4882a593Smuzhiyun mutex_unlock(&input_dev->mutex);
3209*4882a593Smuzhiyun
3210*4882a593Smuzhiyun disable_irq(data->irq);
3211*4882a593Smuzhiyun
3212*4882a593Smuzhiyun return 0;
3213*4882a593Smuzhiyun }
3214*4882a593Smuzhiyun
mxt_resume(struct device * dev)3215*4882a593Smuzhiyun static int __maybe_unused mxt_resume(struct device *dev)
3216*4882a593Smuzhiyun {
3217*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
3218*4882a593Smuzhiyun struct mxt_data *data = i2c_get_clientdata(client);
3219*4882a593Smuzhiyun struct input_dev *input_dev = data->input_dev;
3220*4882a593Smuzhiyun
3221*4882a593Smuzhiyun if (!input_dev)
3222*4882a593Smuzhiyun return 0;
3223*4882a593Smuzhiyun
3224*4882a593Smuzhiyun enable_irq(data->irq);
3225*4882a593Smuzhiyun
3226*4882a593Smuzhiyun mutex_lock(&input_dev->mutex);
3227*4882a593Smuzhiyun
3228*4882a593Smuzhiyun if (input_dev->users)
3229*4882a593Smuzhiyun mxt_start(data);
3230*4882a593Smuzhiyun
3231*4882a593Smuzhiyun mutex_unlock(&input_dev->mutex);
3232*4882a593Smuzhiyun
3233*4882a593Smuzhiyun return 0;
3234*4882a593Smuzhiyun }
3235*4882a593Smuzhiyun
3236*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume);
3237*4882a593Smuzhiyun
3238*4882a593Smuzhiyun static const struct of_device_id mxt_of_match[] = {
3239*4882a593Smuzhiyun { .compatible = "atmel,maxtouch", },
3240*4882a593Smuzhiyun /* Compatibles listed below are deprecated */
3241*4882a593Smuzhiyun { .compatible = "atmel,qt602240_ts", },
3242*4882a593Smuzhiyun { .compatible = "atmel,atmel_mxt_ts", },
3243*4882a593Smuzhiyun { .compatible = "atmel,atmel_mxt_tp", },
3244*4882a593Smuzhiyun { .compatible = "atmel,mXT224", },
3245*4882a593Smuzhiyun {},
3246*4882a593Smuzhiyun };
3247*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, mxt_of_match);
3248*4882a593Smuzhiyun
3249*4882a593Smuzhiyun #ifdef CONFIG_ACPI
3250*4882a593Smuzhiyun static const struct acpi_device_id mxt_acpi_id[] = {
3251*4882a593Smuzhiyun { "ATML0000", 0 }, /* Touchpad */
3252*4882a593Smuzhiyun { "ATML0001", 0 }, /* Touchscreen */
3253*4882a593Smuzhiyun { }
3254*4882a593Smuzhiyun };
3255*4882a593Smuzhiyun MODULE_DEVICE_TABLE(acpi, mxt_acpi_id);
3256*4882a593Smuzhiyun #endif
3257*4882a593Smuzhiyun
3258*4882a593Smuzhiyun static const struct i2c_device_id mxt_id[] = {
3259*4882a593Smuzhiyun { "qt602240_ts", 0 },
3260*4882a593Smuzhiyun { "atmel_mxt_ts", 0 },
3261*4882a593Smuzhiyun { "atmel_mxt_tp", 0 },
3262*4882a593Smuzhiyun { "maxtouch", 0 },
3263*4882a593Smuzhiyun { "mXT224", 0 },
3264*4882a593Smuzhiyun { }
3265*4882a593Smuzhiyun };
3266*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, mxt_id);
3267*4882a593Smuzhiyun
3268*4882a593Smuzhiyun static struct i2c_driver mxt_driver = {
3269*4882a593Smuzhiyun .driver = {
3270*4882a593Smuzhiyun .name = "atmel_mxt_ts",
3271*4882a593Smuzhiyun .of_match_table = mxt_of_match,
3272*4882a593Smuzhiyun .acpi_match_table = ACPI_PTR(mxt_acpi_id),
3273*4882a593Smuzhiyun .pm = &mxt_pm_ops,
3274*4882a593Smuzhiyun },
3275*4882a593Smuzhiyun .probe = mxt_probe,
3276*4882a593Smuzhiyun .remove = mxt_remove,
3277*4882a593Smuzhiyun .id_table = mxt_id,
3278*4882a593Smuzhiyun };
3279*4882a593Smuzhiyun
3280*4882a593Smuzhiyun module_i2c_driver(mxt_driver);
3281*4882a593Smuzhiyun
3282*4882a593Smuzhiyun /* Module information */
3283*4882a593Smuzhiyun MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
3284*4882a593Smuzhiyun MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
3285*4882a593Smuzhiyun MODULE_LICENSE("GPL");
3286