]>
Commit | Line | Data |
---|---|---|
9f1cd857 DD |
1 | /* |
2 | * Cypress APA trackpad with I2C interface | |
3 | * | |
4 | * Author: Dudley Du <dudl@cypress.com> | |
5 | * Further cleanup and restructuring by: | |
6 | * Daniel Kurtz <djkurtz@chromium.org> | |
7 | * Benson Leung <bleung@chromium.org> | |
8 | * | |
9 | * Copyright (C) 2011-2014 Cypress Semiconductor, Inc. | |
10 | * Copyright (C) 2011-2012 Google, Inc. | |
11 | * | |
12 | * This file is subject to the terms and conditions of the GNU General Public | |
13 | * License. See the file COPYING in the main directory of this archive for | |
14 | * more details. | |
15 | */ | |
16 | ||
17 | #include <linux/delay.h> | |
18 | #include <linux/i2c.h> | |
19 | #include <linux/input.h> | |
20 | #include <linux/input/mt.h> | |
21 | #include <linux/module.h> | |
22 | #include <linux/slab.h> | |
23 | #include "cyapa.h" | |
24 | ||
25 | ||
26 | #define GEN3_MAX_FINGERS 5 | |
27 | #define GEN3_FINGER_NUM(x) (((x) >> 4) & 0x07) | |
28 | ||
29 | #define BLK_HEAD_BYTES 32 | |
30 | ||
31 | /* Macro for register map group offset. */ | |
32 | #define PRODUCT_ID_SIZE 16 | |
33 | #define QUERY_DATA_SIZE 27 | |
34 | #define REG_PROTOCOL_GEN_QUERY_OFFSET 20 | |
35 | ||
36 | #define REG_OFFSET_DATA_BASE 0x0000 | |
37 | #define REG_OFFSET_COMMAND_BASE 0x0028 | |
38 | #define REG_OFFSET_QUERY_BASE 0x002a | |
39 | ||
40 | #define CYAPA_OFFSET_SOFT_RESET REG_OFFSET_COMMAND_BASE | |
41 | #define OP_RECALIBRATION_MASK 0x80 | |
42 | #define OP_REPORT_BASELINE_MASK 0x40 | |
43 | #define REG_OFFSET_MAX_BASELINE 0x0026 | |
44 | #define REG_OFFSET_MIN_BASELINE 0x0027 | |
45 | ||
46 | #define REG_OFFSET_POWER_MODE (REG_OFFSET_COMMAND_BASE + 1) | |
47 | #define SET_POWER_MODE_DELAY 10000 /* Unit: us */ | |
48 | #define SET_POWER_MODE_TRIES 5 | |
49 | ||
50 | #define GEN3_BL_CMD_CHECKSUM_SEED 0xff | |
51 | #define GEN3_BL_CMD_INITIATE_BL 0x38 | |
52 | #define GEN3_BL_CMD_WRITE_BLOCK 0x39 | |
53 | #define GEN3_BL_CMD_VERIFY_BLOCK 0x3a | |
54 | #define GEN3_BL_CMD_TERMINATE_BL 0x3b | |
55 | #define GEN3_BL_CMD_LAUNCH_APP 0xa5 | |
56 | ||
57 | /* | |
58 | * CYAPA trackpad device states. | |
59 | * Used in register 0x00, bit1-0, DeviceStatus field. | |
60 | * Other values indicate device is in an abnormal state and must be reset. | |
61 | */ | |
62 | #define CYAPA_DEV_NORMAL 0x03 | |
63 | #define CYAPA_DEV_BUSY 0x01 | |
64 | ||
65 | #define CYAPA_FW_BLOCK_SIZE 64 | |
66 | #define CYAPA_FW_READ_SIZE 16 | |
67 | #define CYAPA_FW_HDR_START 0x0780 | |
68 | #define CYAPA_FW_HDR_BLOCK_COUNT 2 | |
69 | #define CYAPA_FW_HDR_BLOCK_START (CYAPA_FW_HDR_START / CYAPA_FW_BLOCK_SIZE) | |
70 | #define CYAPA_FW_HDR_SIZE (CYAPA_FW_HDR_BLOCK_COUNT * \ | |
71 | CYAPA_FW_BLOCK_SIZE) | |
72 | #define CYAPA_FW_DATA_START 0x0800 | |
73 | #define CYAPA_FW_DATA_BLOCK_COUNT 480 | |
74 | #define CYAPA_FW_DATA_BLOCK_START (CYAPA_FW_DATA_START / CYAPA_FW_BLOCK_SIZE) | |
75 | #define CYAPA_FW_DATA_SIZE (CYAPA_FW_DATA_BLOCK_COUNT * \ | |
76 | CYAPA_FW_BLOCK_SIZE) | |
77 | #define CYAPA_FW_SIZE (CYAPA_FW_HDR_SIZE + CYAPA_FW_DATA_SIZE) | |
78 | #define CYAPA_CMD_LEN 16 | |
79 | ||
80 | #define GEN3_BL_IDLE_FW_MAJ_VER_OFFSET 0x0b | |
81 | #define GEN3_BL_IDLE_FW_MIN_VER_OFFSET (GEN3_BL_IDLE_FW_MAJ_VER_OFFSET + 1) | |
82 | ||
83 | ||
84 | struct cyapa_touch { | |
85 | /* | |
86 | * high bits or x/y position value | |
87 | * bit 7 - 4: high 4 bits of x position value | |
88 | * bit 3 - 0: high 4 bits of y position value | |
89 | */ | |
90 | u8 xy_hi; | |
91 | u8 x_lo; /* low 8 bits of x position value. */ | |
92 | u8 y_lo; /* low 8 bits of y position value. */ | |
93 | u8 pressure; | |
94 | /* id range is 1 - 15. It is incremented with every new touch. */ | |
95 | u8 id; | |
96 | } __packed; | |
97 | ||
98 | struct cyapa_reg_data { | |
99 | /* | |
100 | * bit 0 - 1: device status | |
101 | * bit 3 - 2: power mode | |
102 | * bit 6 - 4: reserved | |
103 | * bit 7: interrupt valid bit | |
104 | */ | |
105 | u8 device_status; | |
106 | /* | |
107 | * bit 7 - 4: number of fingers currently touching pad | |
108 | * bit 3: valid data check bit | |
109 | * bit 2: middle mechanism button state if exists | |
110 | * bit 1: right mechanism button state if exists | |
111 | * bit 0: left mechanism button state if exists | |
112 | */ | |
113 | u8 finger_btn; | |
114 | /* CYAPA reports up to 5 touches per packet. */ | |
115 | struct cyapa_touch touches[5]; | |
116 | } __packed; | |
117 | ||
118 | static const u8 bl_activate[] = { 0x00, 0xff, 0x38, 0x00, 0x01, 0x02, 0x03, | |
119 | 0x04, 0x05, 0x06, 0x07 }; | |
120 | static const u8 bl_deactivate[] = { 0x00, 0xff, 0x3b, 0x00, 0x01, 0x02, 0x03, | |
121 | 0x04, 0x05, 0x06, 0x07 }; | |
122 | static const u8 bl_exit[] = { 0x00, 0xff, 0xa5, 0x00, 0x01, 0x02, 0x03, 0x04, | |
123 | 0x05, 0x06, 0x07 }; | |
124 | ||
125 | ||
126 | /* for byte read/write command */ | |
127 | #define CMD_RESET 0 | |
128 | #define CMD_POWER_MODE 1 | |
129 | #define CMD_DEV_STATUS 2 | |
130 | #define CMD_REPORT_MAX_BASELINE 3 | |
131 | #define CMD_REPORT_MIN_BASELINE 4 | |
132 | #define SMBUS_BYTE_CMD(cmd) (((cmd) & 0x3f) << 1) | |
133 | #define CYAPA_SMBUS_RESET SMBUS_BYTE_CMD(CMD_RESET) | |
134 | #define CYAPA_SMBUS_POWER_MODE SMBUS_BYTE_CMD(CMD_POWER_MODE) | |
135 | #define CYAPA_SMBUS_DEV_STATUS SMBUS_BYTE_CMD(CMD_DEV_STATUS) | |
136 | #define CYAPA_SMBUS_MAX_BASELINE SMBUS_BYTE_CMD(CMD_REPORT_MAX_BASELINE) | |
137 | #define CYAPA_SMBUS_MIN_BASELINE SMBUS_BYTE_CMD(CMD_REPORT_MIN_BASELINE) | |
138 | ||
139 | /* for group registers read/write command */ | |
140 | #define REG_GROUP_DATA 0 | |
141 | #define REG_GROUP_CMD 2 | |
142 | #define REG_GROUP_QUERY 3 | |
143 | #define SMBUS_GROUP_CMD(grp) (0x80 | (((grp) & 0x07) << 3)) | |
144 | #define CYAPA_SMBUS_GROUP_DATA SMBUS_GROUP_CMD(REG_GROUP_DATA) | |
145 | #define CYAPA_SMBUS_GROUP_CMD SMBUS_GROUP_CMD(REG_GROUP_CMD) | |
146 | #define CYAPA_SMBUS_GROUP_QUERY SMBUS_GROUP_CMD(REG_GROUP_QUERY) | |
147 | ||
148 | /* for register block read/write command */ | |
149 | #define CMD_BL_STATUS 0 | |
150 | #define CMD_BL_HEAD 1 | |
151 | #define CMD_BL_CMD 2 | |
152 | #define CMD_BL_DATA 3 | |
153 | #define CMD_BL_ALL 4 | |
154 | #define CMD_BLK_PRODUCT_ID 5 | |
155 | #define CMD_BLK_HEAD 6 | |
156 | #define SMBUS_BLOCK_CMD(cmd) (0xc0 | (((cmd) & 0x1f) << 1)) | |
157 | ||
158 | /* register block read/write command in bootloader mode */ | |
159 | #define CYAPA_SMBUS_BL_STATUS SMBUS_BLOCK_CMD(CMD_BL_STATUS) | |
160 | #define CYAPA_SMBUS_BL_HEAD SMBUS_BLOCK_CMD(CMD_BL_HEAD) | |
161 | #define CYAPA_SMBUS_BL_CMD SMBUS_BLOCK_CMD(CMD_BL_CMD) | |
162 | #define CYAPA_SMBUS_BL_DATA SMBUS_BLOCK_CMD(CMD_BL_DATA) | |
163 | #define CYAPA_SMBUS_BL_ALL SMBUS_BLOCK_CMD(CMD_BL_ALL) | |
164 | ||
165 | /* register block read/write command in operational mode */ | |
166 | #define CYAPA_SMBUS_BLK_PRODUCT_ID SMBUS_BLOCK_CMD(CMD_BLK_PRODUCT_ID) | |
167 | #define CYAPA_SMBUS_BLK_HEAD SMBUS_BLOCK_CMD(CMD_BLK_HEAD) | |
168 | ||
169 | /* for byte read/write command */ | |
170 | #define CMD_RESET 0 | |
171 | #define CMD_POWER_MODE 1 | |
172 | #define CMD_DEV_STATUS 2 | |
173 | #define CMD_REPORT_MAX_BASELINE 3 | |
174 | #define CMD_REPORT_MIN_BASELINE 4 | |
175 | #define SMBUS_BYTE_CMD(cmd) (((cmd) & 0x3f) << 1) | |
176 | #define CYAPA_SMBUS_RESET SMBUS_BYTE_CMD(CMD_RESET) | |
177 | #define CYAPA_SMBUS_POWER_MODE SMBUS_BYTE_CMD(CMD_POWER_MODE) | |
178 | #define CYAPA_SMBUS_DEV_STATUS SMBUS_BYTE_CMD(CMD_DEV_STATUS) | |
179 | #define CYAPA_SMBUS_MAX_BASELINE SMBUS_BYTE_CMD(CMD_REPORT_MAX_BASELINE) | |
180 | #define CYAPA_SMBUS_MIN_BASELINE SMBUS_BYTE_CMD(CMD_REPORT_MIN_BASELINE) | |
181 | ||
182 | /* for group registers read/write command */ | |
183 | #define REG_GROUP_DATA 0 | |
184 | #define REG_GROUP_CMD 2 | |
185 | #define REG_GROUP_QUERY 3 | |
186 | #define SMBUS_GROUP_CMD(grp) (0x80 | (((grp) & 0x07) << 3)) | |
187 | #define CYAPA_SMBUS_GROUP_DATA SMBUS_GROUP_CMD(REG_GROUP_DATA) | |
188 | #define CYAPA_SMBUS_GROUP_CMD SMBUS_GROUP_CMD(REG_GROUP_CMD) | |
189 | #define CYAPA_SMBUS_GROUP_QUERY SMBUS_GROUP_CMD(REG_GROUP_QUERY) | |
190 | ||
191 | /* for register block read/write command */ | |
192 | #define CMD_BL_STATUS 0 | |
193 | #define CMD_BL_HEAD 1 | |
194 | #define CMD_BL_CMD 2 | |
195 | #define CMD_BL_DATA 3 | |
196 | #define CMD_BL_ALL 4 | |
197 | #define CMD_BLK_PRODUCT_ID 5 | |
198 | #define CMD_BLK_HEAD 6 | |
199 | #define SMBUS_BLOCK_CMD(cmd) (0xc0 | (((cmd) & 0x1f) << 1)) | |
200 | ||
201 | /* register block read/write command in bootloader mode */ | |
202 | #define CYAPA_SMBUS_BL_STATUS SMBUS_BLOCK_CMD(CMD_BL_STATUS) | |
203 | #define CYAPA_SMBUS_BL_HEAD SMBUS_BLOCK_CMD(CMD_BL_HEAD) | |
204 | #define CYAPA_SMBUS_BL_CMD SMBUS_BLOCK_CMD(CMD_BL_CMD) | |
205 | #define CYAPA_SMBUS_BL_DATA SMBUS_BLOCK_CMD(CMD_BL_DATA) | |
206 | #define CYAPA_SMBUS_BL_ALL SMBUS_BLOCK_CMD(CMD_BL_ALL) | |
207 | ||
208 | /* register block read/write command in operational mode */ | |
209 | #define CYAPA_SMBUS_BLK_PRODUCT_ID SMBUS_BLOCK_CMD(CMD_BLK_PRODUCT_ID) | |
210 | #define CYAPA_SMBUS_BLK_HEAD SMBUS_BLOCK_CMD(CMD_BLK_HEAD) | |
211 | ||
212 | struct cyapa_cmd_len { | |
213 | u8 cmd; | |
214 | u8 len; | |
215 | }; | |
216 | ||
217 | /* maps generic CYAPA_CMD_* code to the I2C equivalent */ | |
218 | static const struct cyapa_cmd_len cyapa_i2c_cmds[] = { | |
219 | { CYAPA_OFFSET_SOFT_RESET, 1 }, /* CYAPA_CMD_SOFT_RESET */ | |
220 | { REG_OFFSET_COMMAND_BASE + 1, 1 }, /* CYAPA_CMD_POWER_MODE */ | |
221 | { REG_OFFSET_DATA_BASE, 1 }, /* CYAPA_CMD_DEV_STATUS */ | |
222 | { REG_OFFSET_DATA_BASE, sizeof(struct cyapa_reg_data) }, | |
223 | /* CYAPA_CMD_GROUP_DATA */ | |
224 | { REG_OFFSET_COMMAND_BASE, 0 }, /* CYAPA_CMD_GROUP_CMD */ | |
225 | { REG_OFFSET_QUERY_BASE, QUERY_DATA_SIZE }, /* CYAPA_CMD_GROUP_QUERY */ | |
226 | { BL_HEAD_OFFSET, 3 }, /* CYAPA_CMD_BL_STATUS */ | |
227 | { BL_HEAD_OFFSET, 16 }, /* CYAPA_CMD_BL_HEAD */ | |
228 | { BL_HEAD_OFFSET, 16 }, /* CYAPA_CMD_BL_CMD */ | |
229 | { BL_DATA_OFFSET, 16 }, /* CYAPA_CMD_BL_DATA */ | |
230 | { BL_HEAD_OFFSET, 32 }, /* CYAPA_CMD_BL_ALL */ | |
231 | { REG_OFFSET_QUERY_BASE, PRODUCT_ID_SIZE }, | |
232 | /* CYAPA_CMD_BLK_PRODUCT_ID */ | |
233 | { REG_OFFSET_DATA_BASE, 32 }, /* CYAPA_CMD_BLK_HEAD */ | |
234 | { REG_OFFSET_MAX_BASELINE, 1 }, /* CYAPA_CMD_MAX_BASELINE */ | |
235 | { REG_OFFSET_MIN_BASELINE, 1 }, /* CYAPA_CMD_MIN_BASELINE */ | |
236 | }; | |
237 | ||
238 | static const struct cyapa_cmd_len cyapa_smbus_cmds[] = { | |
239 | { CYAPA_SMBUS_RESET, 1 }, /* CYAPA_CMD_SOFT_RESET */ | |
240 | { CYAPA_SMBUS_POWER_MODE, 1 }, /* CYAPA_CMD_POWER_MODE */ | |
241 | { CYAPA_SMBUS_DEV_STATUS, 1 }, /* CYAPA_CMD_DEV_STATUS */ | |
242 | { CYAPA_SMBUS_GROUP_DATA, sizeof(struct cyapa_reg_data) }, | |
243 | /* CYAPA_CMD_GROUP_DATA */ | |
244 | { CYAPA_SMBUS_GROUP_CMD, 2 }, /* CYAPA_CMD_GROUP_CMD */ | |
245 | { CYAPA_SMBUS_GROUP_QUERY, QUERY_DATA_SIZE }, | |
246 | /* CYAPA_CMD_GROUP_QUERY */ | |
247 | { CYAPA_SMBUS_BL_STATUS, 3 }, /* CYAPA_CMD_BL_STATUS */ | |
248 | { CYAPA_SMBUS_BL_HEAD, 16 }, /* CYAPA_CMD_BL_HEAD */ | |
249 | { CYAPA_SMBUS_BL_CMD, 16 }, /* CYAPA_CMD_BL_CMD */ | |
250 | { CYAPA_SMBUS_BL_DATA, 16 }, /* CYAPA_CMD_BL_DATA */ | |
251 | { CYAPA_SMBUS_BL_ALL, 32 }, /* CYAPA_CMD_BL_ALL */ | |
252 | { CYAPA_SMBUS_BLK_PRODUCT_ID, PRODUCT_ID_SIZE }, | |
253 | /* CYAPA_CMD_BLK_PRODUCT_ID */ | |
254 | { CYAPA_SMBUS_BLK_HEAD, 16 }, /* CYAPA_CMD_BLK_HEAD */ | |
255 | { CYAPA_SMBUS_MAX_BASELINE, 1 }, /* CYAPA_CMD_MAX_BASELINE */ | |
256 | { CYAPA_SMBUS_MIN_BASELINE, 1 }, /* CYAPA_CMD_MIN_BASELINE */ | |
257 | }; | |
258 | ||
259 | ||
260 | /* | |
261 | * cyapa_smbus_read_block - perform smbus block read command | |
262 | * @cyapa - private data structure of the driver | |
263 | * @cmd - the properly encoded smbus command | |
264 | * @len - expected length of smbus command result | |
265 | * @values - buffer to store smbus command result | |
266 | * | |
267 | * Returns negative errno, else the number of bytes written. | |
268 | * | |
269 | * Note: | |
270 | * In trackpad device, the memory block allocated for I2C register map | |
271 | * is 256 bytes, so the max read block for I2C bus is 256 bytes. | |
272 | */ | |
273 | ssize_t cyapa_smbus_read_block(struct cyapa *cyapa, u8 cmd, size_t len, | |
274 | u8 *values) | |
275 | { | |
276 | ssize_t ret; | |
277 | u8 index; | |
278 | u8 smbus_cmd; | |
279 | u8 *buf; | |
280 | struct i2c_client *client = cyapa->client; | |
281 | ||
282 | if (!(SMBUS_BYTE_BLOCK_CMD_MASK & cmd)) | |
283 | return -EINVAL; | |
284 | ||
285 | if (SMBUS_GROUP_BLOCK_CMD_MASK & cmd) { | |
286 | /* read specific block registers command. */ | |
287 | smbus_cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ); | |
288 | ret = i2c_smbus_read_block_data(client, smbus_cmd, values); | |
289 | goto out; | |
290 | } | |
291 | ||
292 | ret = 0; | |
293 | for (index = 0; index * I2C_SMBUS_BLOCK_MAX < len; index++) { | |
294 | smbus_cmd = SMBUS_ENCODE_IDX(cmd, index); | |
295 | smbus_cmd = SMBUS_ENCODE_RW(smbus_cmd, SMBUS_READ); | |
296 | buf = values + I2C_SMBUS_BLOCK_MAX * index; | |
297 | ret = i2c_smbus_read_block_data(client, smbus_cmd, buf); | |
298 | if (ret < 0) | |
299 | goto out; | |
300 | } | |
301 | ||
302 | out: | |
303 | return ret > 0 ? len : ret; | |
304 | } | |
305 | ||
306 | static s32 cyapa_read_byte(struct cyapa *cyapa, u8 cmd_idx) | |
307 | { | |
308 | u8 cmd; | |
309 | ||
310 | if (cyapa->smbus) { | |
311 | cmd = cyapa_smbus_cmds[cmd_idx].cmd; | |
312 | cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ); | |
313 | } else { | |
314 | cmd = cyapa_i2c_cmds[cmd_idx].cmd; | |
315 | } | |
316 | return i2c_smbus_read_byte_data(cyapa->client, cmd); | |
317 | } | |
318 | ||
319 | static s32 cyapa_write_byte(struct cyapa *cyapa, u8 cmd_idx, u8 value) | |
320 | { | |
321 | u8 cmd; | |
322 | ||
323 | if (cyapa->smbus) { | |
324 | cmd = cyapa_smbus_cmds[cmd_idx].cmd; | |
325 | cmd = SMBUS_ENCODE_RW(cmd, SMBUS_WRITE); | |
326 | } else { | |
327 | cmd = cyapa_i2c_cmds[cmd_idx].cmd; | |
328 | } | |
329 | return i2c_smbus_write_byte_data(cyapa->client, cmd, value); | |
330 | } | |
331 | ||
332 | ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len, | |
333 | u8 *values) | |
334 | { | |
335 | return i2c_smbus_read_i2c_block_data(cyapa->client, reg, len, values); | |
336 | } | |
337 | ||
338 | static ssize_t cyapa_i2c_reg_write_block(struct cyapa *cyapa, u8 reg, | |
339 | size_t len, const u8 *values) | |
340 | { | |
341 | return i2c_smbus_write_i2c_block_data(cyapa->client, reg, len, values); | |
342 | } | |
343 | ||
344 | ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values) | |
345 | { | |
346 | u8 cmd; | |
347 | size_t len; | |
348 | ||
349 | if (cyapa->smbus) { | |
350 | cmd = cyapa_smbus_cmds[cmd_idx].cmd; | |
351 | len = cyapa_smbus_cmds[cmd_idx].len; | |
352 | return cyapa_smbus_read_block(cyapa, cmd, len, values); | |
353 | } | |
354 | cmd = cyapa_i2c_cmds[cmd_idx].cmd; | |
355 | len = cyapa_i2c_cmds[cmd_idx].len; | |
356 | return cyapa_i2c_reg_read_block(cyapa, cmd, len, values); | |
357 | } | |
358 | ||
359 | /* | |
360 | * Determine the Gen3 trackpad device's current operating state. | |
361 | * | |
362 | */ | |
363 | static int cyapa_gen3_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) | |
364 | { | |
365 | cyapa->state = CYAPA_STATE_NO_DEVICE; | |
366 | ||
367 | /* Parse based on Gen3 characteristic registers and bits */ | |
368 | if (reg_data[REG_BL_FILE] == BL_FILE && | |
369 | reg_data[REG_BL_ERROR] == BL_ERROR_NO_ERR_IDLE && | |
370 | (reg_data[REG_BL_STATUS] == | |
371 | (BL_STATUS_RUNNING | BL_STATUS_CSUM_VALID) || | |
372 | reg_data[REG_BL_STATUS] == BL_STATUS_RUNNING)) { | |
373 | /* | |
374 | * Normal state after power on or reset, | |
375 | * REG_BL_STATUS == 0x11, firmware image checksum is valid. | |
376 | * REG_BL_STATUS == 0x10, firmware image checksum is invalid. | |
377 | */ | |
378 | cyapa->gen = CYAPA_GEN3; | |
379 | cyapa->state = CYAPA_STATE_BL_IDLE; | |
380 | } else if (reg_data[REG_BL_FILE] == BL_FILE && | |
381 | (reg_data[REG_BL_STATUS] & BL_STATUS_RUNNING) == | |
382 | BL_STATUS_RUNNING) { | |
383 | cyapa->gen = CYAPA_GEN3; | |
384 | if (reg_data[REG_BL_STATUS] & BL_STATUS_BUSY) { | |
385 | cyapa->state = CYAPA_STATE_BL_BUSY; | |
386 | } else { | |
387 | if ((reg_data[REG_BL_ERROR] & BL_ERROR_BOOTLOADING) == | |
388 | BL_ERROR_BOOTLOADING) | |
389 | cyapa->state = CYAPA_STATE_BL_ACTIVE; | |
390 | else | |
391 | cyapa->state = CYAPA_STATE_BL_IDLE; | |
392 | } | |
393 | } else if ((reg_data[REG_OP_STATUS] & OP_STATUS_SRC) && | |
394 | (reg_data[REG_OP_DATA1] & OP_DATA_VALID)) { | |
395 | /* | |
396 | * Normal state when running in operational mode, | |
397 | * may also not in full power state or | |
398 | * busying in command process. | |
399 | */ | |
400 | if (GEN3_FINGER_NUM(reg_data[REG_OP_DATA1]) <= | |
401 | GEN3_MAX_FINGERS) { | |
402 | /* Finger number data is valid. */ | |
403 | cyapa->gen = CYAPA_GEN3; | |
404 | cyapa->state = CYAPA_STATE_OP; | |
405 | } | |
406 | } else if (reg_data[REG_OP_STATUS] == 0x0C && | |
407 | reg_data[REG_OP_DATA1] == 0x08) { | |
408 | /* Op state when first two registers overwritten with 0x00 */ | |
409 | cyapa->gen = CYAPA_GEN3; | |
410 | cyapa->state = CYAPA_STATE_OP; | |
411 | } else if (reg_data[REG_BL_STATUS] & | |
412 | (BL_STATUS_RUNNING | BL_STATUS_BUSY)) { | |
413 | cyapa->gen = CYAPA_GEN3; | |
414 | cyapa->state = CYAPA_STATE_BL_BUSY; | |
415 | } | |
416 | ||
417 | if (cyapa->gen == CYAPA_GEN3 && (cyapa->state == CYAPA_STATE_OP || | |
418 | cyapa->state == CYAPA_STATE_BL_IDLE || | |
419 | cyapa->state == CYAPA_STATE_BL_ACTIVE || | |
420 | cyapa->state == CYAPA_STATE_BL_BUSY)) | |
421 | return 0; | |
422 | ||
423 | return -EAGAIN; | |
424 | } | |
425 | ||
426 | static int cyapa_gen3_bl_deactivate(struct cyapa *cyapa) | |
427 | { | |
428 | int error; | |
429 | ||
430 | error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_deactivate), | |
431 | bl_deactivate); | |
432 | if (error) | |
433 | return error; | |
434 | ||
435 | /* Wait for bootloader to switch to idle state; should take < 100ms */ | |
436 | msleep(100); | |
437 | error = cyapa_poll_state(cyapa, 500); | |
438 | if (error) | |
439 | return error; | |
440 | if (cyapa->state != CYAPA_STATE_BL_IDLE) | |
441 | return -EAGAIN; | |
442 | return 0; | |
443 | } | |
444 | ||
445 | /* | |
446 | * Exit bootloader | |
447 | * | |
448 | * Send bl_exit command, then wait 50 - 100 ms to let device transition to | |
449 | * operational mode. If this is the first time the device's firmware is | |
450 | * running, it can take up to 2 seconds to calibrate its sensors. So, poll | |
451 | * the device's new state for up to 2 seconds. | |
452 | * | |
453 | * Returns: | |
454 | * -EIO failure while reading from device | |
455 | * -EAGAIN device is stuck in bootloader, b/c it has invalid firmware | |
456 | * 0 device is supported and in operational mode | |
457 | */ | |
458 | static int cyapa_gen3_bl_exit(struct cyapa *cyapa) | |
459 | { | |
460 | int error; | |
461 | ||
462 | error = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_exit), bl_exit); | |
463 | if (error) | |
464 | return error; | |
465 | ||
466 | /* | |
467 | * Wait for bootloader to exit, and operation mode to start. | |
468 | * Normally, this takes at least 50 ms. | |
469 | */ | |
470 | usleep_range(50000, 100000); | |
471 | /* | |
472 | * In addition, when a device boots for the first time after being | |
473 | * updated to new firmware, it must first calibrate its sensors, which | |
474 | * can take up to an additional 2 seconds. If the device power is | |
475 | * running low, this may take even longer. | |
476 | */ | |
477 | error = cyapa_poll_state(cyapa, 4000); | |
478 | if (error < 0) | |
479 | return error; | |
480 | if (cyapa->state != CYAPA_STATE_OP) | |
481 | return -EAGAIN; | |
482 | ||
483 | return 0; | |
484 | } | |
485 | ||
486 | /* | |
487 | * cyapa_get_wait_time_for_pwr_cmd | |
488 | * | |
489 | * Compute the amount of time we need to wait after updating the touchpad | |
490 | * power mode. The touchpad needs to consume the incoming power mode set | |
491 | * command at the current clock rate. | |
492 | */ | |
493 | ||
494 | static u16 cyapa_get_wait_time_for_pwr_cmd(u8 pwr_mode) | |
495 | { | |
496 | switch (pwr_mode) { | |
497 | case PWR_MODE_FULL_ACTIVE: return 20; | |
498 | case PWR_MODE_BTN_ONLY: return 20; | |
499 | case PWR_MODE_OFF: return 20; | |
500 | default: return cyapa_pwr_cmd_to_sleep_time(pwr_mode) + 50; | |
501 | } | |
502 | } | |
503 | ||
504 | /* | |
505 | * Set device power mode | |
506 | * | |
507 | * Write to the field to configure power state. Power states include : | |
508 | * Full : Max scans and report rate. | |
509 | * Idle : Report rate set by user specified time. | |
510 | * ButtonOnly : No scans for fingers. When the button is triggered, | |
511 | * a slave interrupt is asserted to notify host to wake up. | |
512 | * Off : Only awake for i2c commands from host. No function for button | |
513 | * or touch sensors. | |
514 | * | |
515 | * The power_mode command should conform to the following : | |
516 | * Full : 0x3f | |
517 | * Idle : Configurable from 20 to 1000ms. See note below for | |
518 | * cyapa_sleep_time_to_pwr_cmd and cyapa_pwr_cmd_to_sleep_time | |
519 | * ButtonOnly : 0x01 | |
520 | * Off : 0x00 | |
521 | * | |
522 | * Device power mode can only be set when device is in operational mode. | |
523 | */ | |
524 | static int cyapa_gen3_set_power_mode(struct cyapa *cyapa, u8 power_mode, | |
525 | u16 always_unused) | |
526 | { | |
527 | int ret; | |
528 | u8 power; | |
529 | int tries; | |
530 | u16 sleep_time; | |
531 | ||
532 | always_unused = 0; | |
533 | if (cyapa->state != CYAPA_STATE_OP) | |
534 | return 0; | |
535 | ||
536 | tries = SET_POWER_MODE_TRIES; | |
537 | while (tries--) { | |
538 | ret = cyapa_read_byte(cyapa, CYAPA_CMD_POWER_MODE); | |
539 | if (ret >= 0) | |
540 | break; | |
541 | usleep_range(SET_POWER_MODE_DELAY, 2 * SET_POWER_MODE_DELAY); | |
542 | } | |
543 | if (ret < 0) | |
544 | return ret; | |
545 | ||
546 | /* | |
547 | * Return early if the power mode to set is the same as the current | |
548 | * one. | |
549 | */ | |
550 | if ((ret & PWR_MODE_MASK) == power_mode) | |
551 | return 0; | |
552 | ||
553 | sleep_time = cyapa_get_wait_time_for_pwr_cmd(ret & PWR_MODE_MASK); | |
554 | power = ret; | |
555 | power &= ~PWR_MODE_MASK; | |
556 | power |= power_mode & PWR_MODE_MASK; | |
557 | tries = SET_POWER_MODE_TRIES; | |
558 | while (tries--) { | |
559 | ret = cyapa_write_byte(cyapa, CYAPA_CMD_POWER_MODE, power); | |
560 | if (!ret) | |
561 | break; | |
562 | usleep_range(SET_POWER_MODE_DELAY, 2 * SET_POWER_MODE_DELAY); | |
563 | } | |
564 | ||
565 | /* | |
566 | * Wait for the newly set power command to go in at the previous | |
567 | * clock speed (scanrate) used by the touchpad firmware. Not | |
568 | * doing so before issuing the next command may result in errors | |
569 | * depending on the command's content. | |
570 | */ | |
571 | msleep(sleep_time); | |
572 | return ret; | |
573 | } | |
574 | ||
575 | static int cyapa_gen3_get_query_data(struct cyapa *cyapa) | |
576 | { | |
577 | u8 query_data[QUERY_DATA_SIZE]; | |
578 | int ret; | |
579 | ||
580 | if (cyapa->state != CYAPA_STATE_OP) | |
581 | return -EBUSY; | |
582 | ||
583 | ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_QUERY, query_data); | |
584 | if (ret != QUERY_DATA_SIZE) | |
585 | return (ret < 0) ? ret : -EIO; | |
586 | ||
587 | memcpy(&cyapa->product_id[0], &query_data[0], 5); | |
588 | cyapa->product_id[5] = '-'; | |
589 | memcpy(&cyapa->product_id[6], &query_data[5], 6); | |
590 | cyapa->product_id[12] = '-'; | |
591 | memcpy(&cyapa->product_id[13], &query_data[11], 2); | |
592 | cyapa->product_id[15] = '\0'; | |
593 | ||
594 | cyapa->fw_maj_ver = query_data[15]; | |
595 | cyapa->fw_min_ver = query_data[16]; | |
596 | ||
597 | cyapa->btn_capability = query_data[19] & CAPABILITY_BTN_MASK; | |
598 | ||
599 | cyapa->gen = query_data[20] & 0x0f; | |
600 | ||
601 | cyapa->max_abs_x = ((query_data[21] & 0xf0) << 4) | query_data[22]; | |
602 | cyapa->max_abs_y = ((query_data[21] & 0x0f) << 8) | query_data[23]; | |
603 | ||
604 | cyapa->physical_size_x = | |
605 | ((query_data[24] & 0xf0) << 4) | query_data[25]; | |
606 | cyapa->physical_size_y = | |
607 | ((query_data[24] & 0x0f) << 8) | query_data[26]; | |
608 | ||
609 | cyapa->max_z = 255; | |
610 | ||
611 | return 0; | |
612 | } | |
613 | ||
614 | static int cyapa_gen3_bl_query_data(struct cyapa *cyapa) | |
615 | { | |
616 | u8 bl_data[CYAPA_CMD_LEN]; | |
617 | int ret; | |
618 | ||
619 | ret = cyapa_i2c_reg_read_block(cyapa, 0, CYAPA_CMD_LEN, bl_data); | |
620 | if (ret != CYAPA_CMD_LEN) | |
621 | return (ret < 0) ? ret : -EIO; | |
622 | ||
623 | /* | |
624 | * This value will be updated again when entered application mode. | |
625 | * If TP failed to enter application mode, this fw version values | |
626 | * can be used as a reference. | |
627 | * This firmware version valid when fw image checksum is valid. | |
628 | */ | |
629 | if (bl_data[REG_BL_STATUS] == | |
630 | (BL_STATUS_RUNNING | BL_STATUS_CSUM_VALID)) { | |
631 | cyapa->fw_maj_ver = bl_data[GEN3_BL_IDLE_FW_MAJ_VER_OFFSET]; | |
632 | cyapa->fw_min_ver = bl_data[GEN3_BL_IDLE_FW_MIN_VER_OFFSET]; | |
633 | } | |
634 | ||
635 | return 0; | |
636 | } | |
637 | ||
638 | /* | |
639 | * Check if device is operational. | |
640 | * | |
641 | * An operational device is responding, has exited bootloader, and has | |
642 | * firmware supported by this driver. | |
643 | * | |
644 | * Returns: | |
645 | * -EBUSY no device or in bootloader | |
646 | * -EIO failure while reading from device | |
647 | * -EAGAIN device is still in bootloader | |
648 | * if ->state = CYAPA_STATE_BL_IDLE, device has invalid firmware | |
649 | * -EINVAL device is in operational mode, but not supported by this driver | |
650 | * 0 device is supported | |
651 | */ | |
652 | static int cyapa_gen3_do_operational_check(struct cyapa *cyapa) | |
653 | { | |
654 | struct device *dev = &cyapa->client->dev; | |
655 | int error; | |
656 | ||
657 | switch (cyapa->state) { | |
658 | case CYAPA_STATE_BL_ACTIVE: | |
659 | error = cyapa_gen3_bl_deactivate(cyapa); | |
660 | if (error) { | |
661 | dev_err(dev, "failed to bl_deactivate: %d\n", error); | |
662 | return error; | |
663 | } | |
664 | ||
665 | /* Fallthrough state */ | |
666 | case CYAPA_STATE_BL_IDLE: | |
667 | /* Try to get firmware version in bootloader mode. */ | |
668 | cyapa_gen3_bl_query_data(cyapa); | |
669 | ||
670 | error = cyapa_gen3_bl_exit(cyapa); | |
671 | if (error) { | |
672 | dev_err(dev, "failed to bl_exit: %d\n", error); | |
673 | return error; | |
674 | } | |
675 | ||
676 | /* Fallthrough state */ | |
677 | case CYAPA_STATE_OP: | |
678 | /* | |
679 | * Reading query data before going back to the full mode | |
680 | * may cause problems, so we set the power mode first here. | |
681 | */ | |
682 | error = cyapa_gen3_set_power_mode(cyapa, | |
683 | PWR_MODE_FULL_ACTIVE, 0); | |
684 | if (error) | |
685 | dev_err(dev, "%s: set full power mode failed: %d\n", | |
686 | __func__, error); | |
687 | error = cyapa_gen3_get_query_data(cyapa); | |
688 | if (error < 0) | |
689 | return error; | |
690 | ||
691 | /* Only support firmware protocol gen3 */ | |
692 | if (cyapa->gen != CYAPA_GEN3) { | |
693 | dev_err(dev, "unsupported protocol version (%d)", | |
694 | cyapa->gen); | |
695 | return -EINVAL; | |
696 | } | |
697 | ||
698 | /* Only support product ID starting with CYTRA */ | |
699 | if (memcmp(cyapa->product_id, product_id, | |
700 | strlen(product_id)) != 0) { | |
701 | dev_err(dev, "unsupported product ID (%s)\n", | |
702 | cyapa->product_id); | |
703 | return -EINVAL; | |
704 | } | |
705 | ||
706 | return 0; | |
707 | ||
708 | default: | |
709 | return -EIO; | |
710 | } | |
711 | return 0; | |
712 | } | |
713 | ||
714 | /* | |
715 | * Return false, do not continue process | |
716 | * Return true, continue process. | |
717 | */ | |
718 | static bool cyapa_gen3_irq_cmd_handler(struct cyapa *cyapa) | |
719 | { | |
720 | /* Not gen3 irq command response, skip for continue. */ | |
721 | if (cyapa->gen != CYAPA_GEN3) | |
722 | return true; | |
723 | ||
724 | if (cyapa->operational) | |
725 | return true; | |
726 | ||
727 | /* | |
728 | * Driver in detecting or other interface function processing, | |
729 | * so, stop cyapa_gen3_irq_handler to continue process to | |
730 | * avoid unwanted to error detecting and processing. | |
731 | * | |
732 | * And also, avoid the periodicly accerted interrupts to be processed | |
733 | * as touch inputs when gen3 failed to launch into application mode, | |
734 | * which will cause gen3 stays in bootloader mode. | |
735 | */ | |
736 | return false; | |
737 | } | |
738 | ||
739 | static int cyapa_gen3_irq_handler(struct cyapa *cyapa) | |
740 | { | |
741 | struct input_dev *input = cyapa->input; | |
742 | struct device *dev = &cyapa->client->dev; | |
743 | struct cyapa_reg_data data; | |
744 | int num_fingers; | |
745 | int ret; | |
746 | int i; | |
747 | ||
748 | ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_DATA, (u8 *)&data); | |
749 | if (ret != sizeof(data)) { | |
750 | dev_err(dev, "failed to read report data, (%d)\n", ret); | |
751 | return -EINVAL; | |
752 | } | |
753 | ||
754 | if ((data.device_status & OP_STATUS_SRC) != OP_STATUS_SRC || | |
755 | (data.device_status & OP_STATUS_DEV) != CYAPA_DEV_NORMAL || | |
756 | (data.finger_btn & OP_DATA_VALID) != OP_DATA_VALID) { | |
757 | dev_err(dev, "invalid device state bytes, %02x %02x\n", | |
758 | data.device_status, data.finger_btn); | |
759 | return -EINVAL; | |
760 | } | |
761 | ||
762 | num_fingers = (data.finger_btn >> 4) & 0x0f; | |
763 | for (i = 0; i < num_fingers; i++) { | |
764 | const struct cyapa_touch *touch = &data.touches[i]; | |
765 | /* Note: touch->id range is 1 to 15; slots are 0 to 14. */ | |
766 | int slot = touch->id - 1; | |
767 | ||
768 | input_mt_slot(input, slot); | |
769 | input_mt_report_slot_state(input, MT_TOOL_FINGER, true); | |
770 | input_report_abs(input, ABS_MT_POSITION_X, | |
771 | ((touch->xy_hi & 0xf0) << 4) | touch->x_lo); | |
772 | input_report_abs(input, ABS_MT_POSITION_Y, | |
773 | ((touch->xy_hi & 0x0f) << 8) | touch->y_lo); | |
774 | input_report_abs(input, ABS_MT_PRESSURE, touch->pressure); | |
775 | } | |
776 | ||
777 | input_mt_sync_frame(input); | |
778 | ||
779 | if (cyapa->btn_capability & CAPABILITY_LEFT_BTN_MASK) | |
780 | input_report_key(input, BTN_LEFT, | |
781 | !!(data.finger_btn & OP_DATA_LEFT_BTN)); | |
782 | if (cyapa->btn_capability & CAPABILITY_MIDDLE_BTN_MASK) | |
783 | input_report_key(input, BTN_MIDDLE, | |
784 | !!(data.finger_btn & OP_DATA_MIDDLE_BTN)); | |
785 | if (cyapa->btn_capability & CAPABILITY_RIGHT_BTN_MASK) | |
786 | input_report_key(input, BTN_RIGHT, | |
787 | !!(data.finger_btn & OP_DATA_RIGHT_BTN)); | |
788 | input_sync(input); | |
789 | ||
790 | return 0; | |
791 | } | |
792 | ||
793 | static int cyapa_gen3_initialize(struct cyapa *cyapa) { return 0; } | |
794 | static int cyapa_gen3_empty_output_data(struct cyapa *cyapa, | |
795 | u8 *buf, int *len, cb_sort func) { return 0; } | |
796 | ||
797 | const struct cyapa_dev_ops cyapa_gen3_ops = { | |
798 | .initialize = cyapa_gen3_initialize, | |
799 | ||
800 | .state_parse = cyapa_gen3_state_parse, | |
801 | .operational_check = cyapa_gen3_do_operational_check, | |
802 | ||
803 | .irq_handler = cyapa_gen3_irq_handler, | |
804 | .irq_cmd_handler = cyapa_gen3_irq_cmd_handler, | |
805 | .sort_empty_output_data = cyapa_gen3_empty_output_data, | |
806 | .set_power_mode = cyapa_gen3_set_power_mode, | |
807 | }; |