.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Elan I2C/SMBus Touchpad driver |
---|
3 | 4 | * |
---|
.. | .. |
---|
10 | 11 | * Based on cyapa driver: |
---|
11 | 12 | * copyright (c) 2011-2012 Cypress Semiconductor, Inc. |
---|
12 | 13 | * copyright (c) 2011-2012 Google, Inc. |
---|
13 | | - * |
---|
14 | | - * This program is free software; you can redistribute it and/or modify it |
---|
15 | | - * under the terms of the GNU General Public License version 2 as published |
---|
16 | | - * by the Free Software Foundation. |
---|
17 | 14 | * |
---|
18 | 15 | * Trademarks are the property of their respective owners. |
---|
19 | 16 | */ |
---|
.. | .. |
---|
37 | 34 | #include <linux/completion.h> |
---|
38 | 35 | #include <linux/of.h> |
---|
39 | 36 | #include <linux/property.h> |
---|
| 37 | +#include <linux/input/elan-i2c-ids.h> |
---|
40 | 38 | #include <linux/regulator/consumer.h> |
---|
41 | 39 | #include <asm/unaligned.h> |
---|
42 | 40 | |
---|
.. | .. |
---|
48 | 46 | #define ETP_FWIDTH_REDUCE 90 |
---|
49 | 47 | #define ETP_FINGER_WIDTH 15 |
---|
50 | 48 | #define ETP_RETRY_COUNT 3 |
---|
51 | | - |
---|
52 | | -#define ETP_MAX_FINGERS 5 |
---|
53 | | -#define ETP_FINGER_DATA_LEN 5 |
---|
54 | | -#define ETP_REPORT_ID 0x5D |
---|
55 | | -#define ETP_TP_REPORT_ID 0x5E |
---|
56 | | -#define ETP_REPORT_ID_OFFSET 2 |
---|
57 | | -#define ETP_TOUCH_INFO_OFFSET 3 |
---|
58 | | -#define ETP_FINGER_DATA_OFFSET 4 |
---|
59 | | -#define ETP_HOVER_INFO_OFFSET 30 |
---|
60 | | -#define ETP_MAX_REPORT_LEN 34 |
---|
61 | 49 | |
---|
62 | 50 | /* The main device structure */ |
---|
63 | 51 | struct elan_tp_data { |
---|
.. | .. |
---|
87 | 75 | u8 sm_version; |
---|
88 | 76 | u8 iap_version; |
---|
89 | 77 | u16 fw_checksum; |
---|
| 78 | + unsigned int report_features; |
---|
| 79 | + unsigned int report_len; |
---|
90 | 80 | int pressure_adjustment; |
---|
91 | 81 | u8 mode; |
---|
92 | 82 | u16 ic_type; |
---|
93 | 83 | u16 fw_validpage_count; |
---|
94 | | - u16 fw_signature_address; |
---|
| 84 | + u16 fw_page_size; |
---|
| 85 | + u32 fw_signature_address; |
---|
95 | 86 | |
---|
96 | 87 | bool irq_wake; |
---|
97 | 88 | |
---|
.. | .. |
---|
99 | 90 | u8 max_baseline; |
---|
100 | 91 | bool baseline_ready; |
---|
101 | 92 | u8 clickpad; |
---|
| 93 | + bool middle_button; |
---|
102 | 94 | }; |
---|
103 | 95 | |
---|
104 | | -static int elan_get_fwinfo(u16 ic_type, u16 *validpage_count, |
---|
105 | | - u16 *signature_address) |
---|
| 96 | +static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count, |
---|
| 97 | + u32 *signature_address, u16 *page_size) |
---|
106 | 98 | { |
---|
107 | 99 | switch (ic_type) { |
---|
108 | 100 | case 0x00: |
---|
.. | .. |
---|
127 | 119 | case 0x10: |
---|
128 | 120 | *validpage_count = 1024; |
---|
129 | 121 | break; |
---|
| 122 | + case 0x11: |
---|
| 123 | + *validpage_count = 1280; |
---|
| 124 | + break; |
---|
| 125 | + case 0x13: |
---|
| 126 | + *validpage_count = 2048; |
---|
| 127 | + break; |
---|
| 128 | + case 0x14: |
---|
| 129 | + case 0x15: |
---|
| 130 | + *validpage_count = 1024; |
---|
| 131 | + break; |
---|
130 | 132 | default: |
---|
131 | 133 | /* unknown ic type clear value */ |
---|
132 | 134 | *validpage_count = 0; |
---|
133 | 135 | *signature_address = 0; |
---|
| 136 | + *page_size = 0; |
---|
134 | 137 | return -ENXIO; |
---|
135 | 138 | } |
---|
136 | 139 | |
---|
137 | 140 | *signature_address = |
---|
138 | 141 | (*validpage_count * ETP_FW_PAGE_SIZE) - ETP_FW_SIGNATURE_SIZE; |
---|
139 | 142 | |
---|
| 143 | + if ((ic_type == 0x14 || ic_type == 0x15) && iap_version >= 2) { |
---|
| 144 | + *validpage_count /= 8; |
---|
| 145 | + *page_size = ETP_FW_PAGE_SIZE_512; |
---|
| 146 | + } else if (ic_type >= 0x0D && iap_version >= 1) { |
---|
| 147 | + *validpage_count /= 2; |
---|
| 148 | + *page_size = ETP_FW_PAGE_SIZE_128; |
---|
| 149 | + } else { |
---|
| 150 | + *page_size = ETP_FW_PAGE_SIZE; |
---|
| 151 | + } |
---|
| 152 | + |
---|
140 | 153 | return 0; |
---|
141 | 154 | } |
---|
142 | 155 | |
---|
143 | | -static int elan_enable_power(struct elan_tp_data *data) |
---|
| 156 | +static int elan_set_power(struct elan_tp_data *data, bool on) |
---|
144 | 157 | { |
---|
145 | 158 | int repeat = ETP_RETRY_COUNT; |
---|
146 | 159 | int error; |
---|
147 | 160 | |
---|
148 | | - error = regulator_enable(data->vcc); |
---|
149 | | - if (error) { |
---|
150 | | - dev_err(&data->client->dev, |
---|
151 | | - "failed to enable regulator: %d\n", error); |
---|
152 | | - return error; |
---|
153 | | - } |
---|
154 | | - |
---|
155 | 161 | do { |
---|
156 | | - error = data->ops->power_control(data->client, true); |
---|
| 162 | + error = data->ops->power_control(data->client, on); |
---|
157 | 163 | if (error >= 0) |
---|
158 | 164 | return 0; |
---|
159 | 165 | |
---|
160 | 166 | msleep(30); |
---|
161 | 167 | } while (--repeat > 0); |
---|
162 | 168 | |
---|
163 | | - dev_err(&data->client->dev, "failed to enable power: %d\n", error); |
---|
164 | | - return error; |
---|
165 | | -} |
---|
166 | | - |
---|
167 | | -static int elan_disable_power(struct elan_tp_data *data) |
---|
168 | | -{ |
---|
169 | | - int repeat = ETP_RETRY_COUNT; |
---|
170 | | - int error; |
---|
171 | | - |
---|
172 | | - do { |
---|
173 | | - error = data->ops->power_control(data->client, false); |
---|
174 | | - if (!error) { |
---|
175 | | - error = regulator_disable(data->vcc); |
---|
176 | | - if (error) { |
---|
177 | | - dev_err(&data->client->dev, |
---|
178 | | - "failed to disable regulator: %d\n", |
---|
179 | | - error); |
---|
180 | | - /* Attempt to power the chip back up */ |
---|
181 | | - data->ops->power_control(data->client, true); |
---|
182 | | - break; |
---|
183 | | - } |
---|
184 | | - |
---|
185 | | - return 0; |
---|
186 | | - } |
---|
187 | | - |
---|
188 | | - msleep(30); |
---|
189 | | - } while (--repeat > 0); |
---|
190 | | - |
---|
191 | | - dev_err(&data->client->dev, "failed to disable power: %d\n", error); |
---|
| 169 | + dev_err(&data->client->dev, "failed to set power %s: %d\n", |
---|
| 170 | + on ? "on" : "off", error); |
---|
192 | 171 | return error; |
---|
193 | 172 | } |
---|
194 | 173 | |
---|
.. | .. |
---|
216 | 195 | if (error) |
---|
217 | 196 | return error; |
---|
218 | 197 | |
---|
219 | | - error = data->ops->get_sm_version(data->client, &data->ic_type, |
---|
220 | | - &data->sm_version, &data->clickpad); |
---|
| 198 | + error = data->ops->get_pattern(data->client, &data->pattern); |
---|
| 199 | + if (error) |
---|
| 200 | + return error; |
---|
| 201 | + |
---|
| 202 | + error = data->ops->get_sm_version(data->client, data->pattern, |
---|
| 203 | + &data->ic_type, &data->sm_version, |
---|
| 204 | + &data->clickpad); |
---|
221 | 205 | if (error) |
---|
222 | 206 | return error; |
---|
223 | 207 | |
---|
.. | .. |
---|
313 | 297 | static int elan_query_device_info(struct elan_tp_data *data) |
---|
314 | 298 | { |
---|
315 | 299 | int error; |
---|
316 | | - u16 ic_type; |
---|
317 | 300 | |
---|
318 | | - error = data->ops->get_version(data->client, false, &data->fw_version); |
---|
| 301 | + error = data->ops->get_version(data->client, data->pattern, false, |
---|
| 302 | + &data->fw_version); |
---|
319 | 303 | if (error) |
---|
320 | 304 | return error; |
---|
321 | 305 | |
---|
.. | .. |
---|
324 | 308 | if (error) |
---|
325 | 309 | return error; |
---|
326 | 310 | |
---|
327 | | - error = data->ops->get_version(data->client, true, &data->iap_version); |
---|
| 311 | + error = data->ops->get_version(data->client, data->pattern, |
---|
| 312 | + true, &data->iap_version); |
---|
328 | 313 | if (error) |
---|
329 | 314 | return error; |
---|
330 | 315 | |
---|
.. | .. |
---|
333 | 318 | if (error) |
---|
334 | 319 | return error; |
---|
335 | 320 | |
---|
336 | | - error = data->ops->get_pattern(data->client, &data->pattern); |
---|
| 321 | + error = data->ops->get_report_features(data->client, data->pattern, |
---|
| 322 | + &data->report_features, |
---|
| 323 | + &data->report_len); |
---|
337 | 324 | if (error) |
---|
338 | 325 | return error; |
---|
339 | 326 | |
---|
340 | | - if (data->pattern == 0x01) |
---|
341 | | - ic_type = data->ic_type; |
---|
342 | | - else |
---|
343 | | - ic_type = data->iap_version; |
---|
344 | | - |
---|
345 | | - error = elan_get_fwinfo(ic_type, &data->fw_validpage_count, |
---|
346 | | - &data->fw_signature_address); |
---|
| 327 | + error = elan_get_fwinfo(data->ic_type, data->iap_version, |
---|
| 328 | + &data->fw_validpage_count, |
---|
| 329 | + &data->fw_signature_address, |
---|
| 330 | + &data->fw_page_size); |
---|
347 | 331 | if (error) |
---|
348 | 332 | dev_warn(&data->client->dev, |
---|
349 | 333 | "unexpected iap version %#04x (ic type: %#04x), firmware update will not work\n", |
---|
.. | .. |
---|
352 | 336 | return 0; |
---|
353 | 337 | } |
---|
354 | 338 | |
---|
355 | | -static unsigned int elan_convert_resolution(u8 val) |
---|
| 339 | +static unsigned int elan_convert_resolution(u8 val, u8 pattern) |
---|
356 | 340 | { |
---|
357 | 341 | /* |
---|
358 | | - * (value from firmware) * 10 + 790 = dpi |
---|
359 | | - * |
---|
| 342 | + * pattern <= 0x01: |
---|
| 343 | + * (value from firmware) * 10 + 790 = dpi |
---|
| 344 | + * else |
---|
| 345 | + * ((value from firmware) + 3) * 100 = dpi |
---|
| 346 | + */ |
---|
| 347 | + int res = pattern <= 0x01 ? |
---|
| 348 | + (int)(char)val * 10 + 790 : ((int)(char)val + 3) * 100; |
---|
| 349 | + /* |
---|
360 | 350 | * We also have to convert dpi to dots/mm (*10/254 to avoid floating |
---|
361 | 351 | * point). |
---|
362 | 352 | */ |
---|
363 | | - |
---|
364 | | - return ((int)(char)val * 10 + 790) * 10 / 254; |
---|
| 353 | + return res * 10 / 254; |
---|
365 | 354 | } |
---|
366 | 355 | |
---|
367 | 356 | static int elan_query_device_parameters(struct elan_tp_data *data) |
---|
368 | 357 | { |
---|
| 358 | + struct i2c_client *client = data->client; |
---|
369 | 359 | unsigned int x_traces, y_traces; |
---|
| 360 | + u32 x_mm, y_mm; |
---|
370 | 361 | u8 hw_x_res, hw_y_res; |
---|
371 | 362 | int error; |
---|
372 | 363 | |
---|
373 | | - error = data->ops->get_max(data->client, &data->max_x, &data->max_y); |
---|
374 | | - if (error) |
---|
375 | | - return error; |
---|
| 364 | + if (device_property_read_u32(&client->dev, |
---|
| 365 | + "touchscreen-size-x", &data->max_x) || |
---|
| 366 | + device_property_read_u32(&client->dev, |
---|
| 367 | + "touchscreen-size-y", &data->max_y)) { |
---|
| 368 | + error = data->ops->get_max(data->client, |
---|
| 369 | + &data->max_x, |
---|
| 370 | + &data->max_y); |
---|
| 371 | + if (error) |
---|
| 372 | + return error; |
---|
| 373 | + } else { |
---|
| 374 | + /* size is the maximum + 1 */ |
---|
| 375 | + --data->max_x; |
---|
| 376 | + --data->max_y; |
---|
| 377 | + } |
---|
376 | 378 | |
---|
377 | | - error = data->ops->get_num_traces(data->client, &x_traces, &y_traces); |
---|
378 | | - if (error) |
---|
379 | | - return error; |
---|
380 | | - |
---|
| 379 | + if (device_property_read_u32(&client->dev, |
---|
| 380 | + "elan,x_traces", |
---|
| 381 | + &x_traces) || |
---|
| 382 | + device_property_read_u32(&client->dev, |
---|
| 383 | + "elan,y_traces", |
---|
| 384 | + &y_traces)) { |
---|
| 385 | + error = data->ops->get_num_traces(data->client, |
---|
| 386 | + &x_traces, &y_traces); |
---|
| 387 | + if (error) |
---|
| 388 | + return error; |
---|
| 389 | + } |
---|
381 | 390 | data->width_x = data->max_x / x_traces; |
---|
382 | 391 | data->width_y = data->max_y / y_traces; |
---|
383 | 392 | |
---|
384 | | - error = data->ops->get_resolution(data->client, &hw_x_res, &hw_y_res); |
---|
385 | | - if (error) |
---|
386 | | - return error; |
---|
| 393 | + if (device_property_read_u32(&client->dev, |
---|
| 394 | + "touchscreen-x-mm", &x_mm) || |
---|
| 395 | + device_property_read_u32(&client->dev, |
---|
| 396 | + "touchscreen-y-mm", &y_mm)) { |
---|
| 397 | + error = data->ops->get_resolution(data->client, |
---|
| 398 | + &hw_x_res, &hw_y_res); |
---|
| 399 | + if (error) |
---|
| 400 | + return error; |
---|
387 | 401 | |
---|
388 | | - data->x_res = elan_convert_resolution(hw_x_res); |
---|
389 | | - data->y_res = elan_convert_resolution(hw_y_res); |
---|
| 402 | + data->x_res = elan_convert_resolution(hw_x_res, data->pattern); |
---|
| 403 | + data->y_res = elan_convert_resolution(hw_y_res, data->pattern); |
---|
| 404 | + } else { |
---|
| 405 | + data->x_res = (data->max_x + 1) / x_mm; |
---|
| 406 | + data->y_res = (data->max_y + 1) / y_mm; |
---|
| 407 | + } |
---|
| 408 | + |
---|
| 409 | + if (device_property_read_bool(&client->dev, "elan,clickpad")) |
---|
| 410 | + data->clickpad = 1; |
---|
| 411 | + |
---|
| 412 | + if (device_property_read_bool(&client->dev, "elan,middle-button")) |
---|
| 413 | + data->middle_button = true; |
---|
390 | 414 | |
---|
391 | 415 | return 0; |
---|
392 | 416 | } |
---|
.. | .. |
---|
396 | 420 | * IAP firmware updater related routines |
---|
397 | 421 | ********************************************************** |
---|
398 | 422 | */ |
---|
399 | | -static int elan_write_fw_block(struct elan_tp_data *data, |
---|
| 423 | +static int elan_write_fw_block(struct elan_tp_data *data, u16 page_size, |
---|
400 | 424 | const u8 *page, u16 checksum, int idx) |
---|
401 | 425 | { |
---|
402 | 426 | int retry = ETP_RETRY_COUNT; |
---|
403 | 427 | int error; |
---|
404 | 428 | |
---|
405 | 429 | do { |
---|
406 | | - error = data->ops->write_fw_block(data->client, |
---|
| 430 | + error = data->ops->write_fw_block(data->client, page_size, |
---|
407 | 431 | page, checksum, idx); |
---|
408 | 432 | if (!error) |
---|
409 | 433 | return 0; |
---|
.. | .. |
---|
426 | 450 | u16 boot_page_count; |
---|
427 | 451 | u16 sw_checksum = 0, fw_checksum = 0; |
---|
428 | 452 | |
---|
429 | | - error = data->ops->prepare_fw_update(client); |
---|
| 453 | + error = data->ops->prepare_fw_update(client, data->ic_type, |
---|
| 454 | + data->iap_version, |
---|
| 455 | + data->fw_page_size); |
---|
430 | 456 | if (error) |
---|
431 | 457 | return error; |
---|
432 | 458 | |
---|
433 | 459 | iap_start_addr = get_unaligned_le16(&fw->data[ETP_IAP_START_ADDR * 2]); |
---|
434 | 460 | |
---|
435 | | - boot_page_count = (iap_start_addr * 2) / ETP_FW_PAGE_SIZE; |
---|
| 461 | + boot_page_count = (iap_start_addr * 2) / data->fw_page_size; |
---|
436 | 462 | for (i = boot_page_count; i < data->fw_validpage_count; i++) { |
---|
437 | 463 | u16 checksum = 0; |
---|
438 | | - const u8 *page = &fw->data[i * ETP_FW_PAGE_SIZE]; |
---|
| 464 | + const u8 *page = &fw->data[i * data->fw_page_size]; |
---|
439 | 465 | |
---|
440 | | - for (j = 0; j < ETP_FW_PAGE_SIZE; j += 2) |
---|
| 466 | + for (j = 0; j < data->fw_page_size; j += 2) |
---|
441 | 467 | checksum += ((page[j + 1] << 8) | page[j]); |
---|
442 | 468 | |
---|
443 | | - error = elan_write_fw_block(data, page, checksum, i); |
---|
| 469 | + error = elan_write_fw_block(data, data->fw_page_size, |
---|
| 470 | + page, checksum, i); |
---|
444 | 471 | if (error) { |
---|
445 | 472 | dev_err(dev, "write page %d fail: %d\n", i, error); |
---|
446 | 473 | return error; |
---|
.. | .. |
---|
852 | 879 | * Elan isr functions |
---|
853 | 880 | ****************************************************************** |
---|
854 | 881 | */ |
---|
855 | | -static void elan_report_contact(struct elan_tp_data *data, |
---|
856 | | - int contact_num, bool contact_valid, |
---|
857 | | - u8 *finger_data) |
---|
| 882 | +static void elan_report_contact(struct elan_tp_data *data, int contact_num, |
---|
| 883 | + bool contact_valid, bool high_precision, |
---|
| 884 | + u8 *packet, u8 *finger_data) |
---|
858 | 885 | { |
---|
859 | 886 | struct input_dev *input = data->input; |
---|
860 | 887 | unsigned int pos_x, pos_y; |
---|
861 | | - unsigned int pressure, mk_x, mk_y; |
---|
862 | | - unsigned int area_x, area_y, major, minor; |
---|
863 | | - unsigned int scaled_pressure; |
---|
| 888 | + unsigned int pressure, scaled_pressure; |
---|
864 | 889 | |
---|
865 | 890 | if (contact_valid) { |
---|
866 | | - pos_x = ((finger_data[0] & 0xf0) << 4) | |
---|
867 | | - finger_data[1]; |
---|
868 | | - pos_y = ((finger_data[0] & 0x0f) << 8) | |
---|
869 | | - finger_data[2]; |
---|
870 | | - mk_x = (finger_data[3] & 0x0f); |
---|
871 | | - mk_y = (finger_data[3] >> 4); |
---|
872 | | - pressure = finger_data[4]; |
---|
| 891 | + if (high_precision) { |
---|
| 892 | + pos_x = get_unaligned_be16(&finger_data[0]); |
---|
| 893 | + pos_y = get_unaligned_be16(&finger_data[2]); |
---|
| 894 | + } else { |
---|
| 895 | + pos_x = ((finger_data[0] & 0xf0) << 4) | finger_data[1]; |
---|
| 896 | + pos_y = ((finger_data[0] & 0x0f) << 8) | finger_data[2]; |
---|
| 897 | + } |
---|
873 | 898 | |
---|
874 | 899 | if (pos_x > data->max_x || pos_y > data->max_y) { |
---|
875 | 900 | dev_dbg(input->dev.parent, |
---|
.. | .. |
---|
879 | 904 | return; |
---|
880 | 905 | } |
---|
881 | 906 | |
---|
882 | | - /* |
---|
883 | | - * To avoid treating large finger as palm, let's reduce the |
---|
884 | | - * width x and y per trace. |
---|
885 | | - */ |
---|
886 | | - area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE); |
---|
887 | | - area_y = mk_y * (data->width_y - ETP_FWIDTH_REDUCE); |
---|
888 | | - |
---|
889 | | - major = max(area_x, area_y); |
---|
890 | | - minor = min(area_x, area_y); |
---|
891 | | - |
---|
| 907 | + pressure = finger_data[4]; |
---|
892 | 908 | scaled_pressure = pressure + data->pressure_adjustment; |
---|
893 | | - |
---|
894 | 909 | if (scaled_pressure > ETP_MAX_PRESSURE) |
---|
895 | 910 | scaled_pressure = ETP_MAX_PRESSURE; |
---|
896 | 911 | |
---|
.. | .. |
---|
899 | 914 | input_report_abs(input, ABS_MT_POSITION_X, pos_x); |
---|
900 | 915 | input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y); |
---|
901 | 916 | input_report_abs(input, ABS_MT_PRESSURE, scaled_pressure); |
---|
902 | | - input_report_abs(input, ABS_TOOL_WIDTH, mk_x); |
---|
903 | | - input_report_abs(input, ABS_MT_TOUCH_MAJOR, major); |
---|
904 | | - input_report_abs(input, ABS_MT_TOUCH_MINOR, minor); |
---|
| 917 | + |
---|
| 918 | + if (data->report_features & ETP_FEATURE_REPORT_MK) { |
---|
| 919 | + unsigned int mk_x, mk_y, area_x, area_y; |
---|
| 920 | + u8 mk_data = high_precision ? |
---|
| 921 | + packet[ETP_MK_DATA_OFFSET + contact_num] : |
---|
| 922 | + finger_data[3]; |
---|
| 923 | + |
---|
| 924 | + mk_x = mk_data & 0x0f; |
---|
| 925 | + mk_y = mk_data >> 4; |
---|
| 926 | + |
---|
| 927 | + /* |
---|
| 928 | + * To avoid treating large finger as palm, let's reduce |
---|
| 929 | + * the width x and y per trace. |
---|
| 930 | + */ |
---|
| 931 | + area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE); |
---|
| 932 | + area_y = mk_y * (data->width_y - ETP_FWIDTH_REDUCE); |
---|
| 933 | + |
---|
| 934 | + input_report_abs(input, ABS_TOOL_WIDTH, mk_x); |
---|
| 935 | + input_report_abs(input, ABS_MT_TOUCH_MAJOR, |
---|
| 936 | + max(area_x, area_y)); |
---|
| 937 | + input_report_abs(input, ABS_MT_TOUCH_MINOR, |
---|
| 938 | + min(area_x, area_y)); |
---|
| 939 | + } |
---|
905 | 940 | } else { |
---|
906 | 941 | input_mt_slot(input, contact_num); |
---|
907 | | - input_mt_report_slot_state(input, MT_TOOL_FINGER, false); |
---|
| 942 | + input_mt_report_slot_inactive(input); |
---|
908 | 943 | } |
---|
909 | 944 | } |
---|
910 | 945 | |
---|
911 | | -static void elan_report_absolute(struct elan_tp_data *data, u8 *packet) |
---|
| 946 | +static void elan_report_absolute(struct elan_tp_data *data, u8 *packet, |
---|
| 947 | + bool high_precision) |
---|
912 | 948 | { |
---|
913 | 949 | struct input_dev *input = data->input; |
---|
914 | 950 | u8 *finger_data = &packet[ETP_FINGER_DATA_OFFSET]; |
---|
.. | .. |
---|
917 | 953 | u8 hover_info = packet[ETP_HOVER_INFO_OFFSET]; |
---|
918 | 954 | bool contact_valid, hover_event; |
---|
919 | 955 | |
---|
920 | | - hover_event = hover_info & 0x40; |
---|
921 | | - for (i = 0; i < ETP_MAX_FINGERS; i++) { |
---|
922 | | - contact_valid = tp_info & (1U << (3 + i)); |
---|
923 | | - elan_report_contact(data, i, contact_valid, finger_data); |
---|
| 956 | + pm_wakeup_event(&data->client->dev, 0); |
---|
924 | 957 | |
---|
| 958 | + hover_event = hover_info & BIT(6); |
---|
| 959 | + |
---|
| 960 | + for (i = 0; i < ETP_MAX_FINGERS; i++) { |
---|
| 961 | + contact_valid = tp_info & BIT(3 + i); |
---|
| 962 | + elan_report_contact(data, i, contact_valid, high_precision, |
---|
| 963 | + packet, finger_data); |
---|
925 | 964 | if (contact_valid) |
---|
926 | 965 | finger_data += ETP_FINGER_DATA_LEN; |
---|
927 | 966 | } |
---|
928 | 967 | |
---|
929 | | - input_report_key(input, BTN_LEFT, tp_info & 0x01); |
---|
930 | | - input_report_key(input, BTN_RIGHT, tp_info & 0x02); |
---|
| 968 | + input_report_key(input, BTN_LEFT, tp_info & BIT(0)); |
---|
| 969 | + input_report_key(input, BTN_MIDDLE, tp_info & BIT(2)); |
---|
| 970 | + input_report_key(input, BTN_RIGHT, tp_info & BIT(1)); |
---|
931 | 971 | input_report_abs(input, ABS_DISTANCE, hover_event != 0); |
---|
932 | 972 | input_mt_report_pointer_emulation(input, true); |
---|
933 | 973 | input_sync(input); |
---|
.. | .. |
---|
938 | 978 | struct input_dev *input = data->tp_input; |
---|
939 | 979 | u8 *packet = &report[ETP_REPORT_ID_OFFSET + 1]; |
---|
940 | 980 | int x, y; |
---|
| 981 | + |
---|
| 982 | + pm_wakeup_event(&data->client->dev, 0); |
---|
941 | 983 | |
---|
942 | 984 | if (!data->tp_input) { |
---|
943 | 985 | dev_warn_once(&data->client->dev, |
---|
.. | .. |
---|
963 | 1005 | static irqreturn_t elan_isr(int irq, void *dev_id) |
---|
964 | 1006 | { |
---|
965 | 1007 | struct elan_tp_data *data = dev_id; |
---|
966 | | - struct device *dev = &data->client->dev; |
---|
967 | 1008 | int error; |
---|
968 | 1009 | u8 report[ETP_MAX_REPORT_LEN]; |
---|
969 | 1010 | |
---|
.. | .. |
---|
977 | 1018 | goto out; |
---|
978 | 1019 | } |
---|
979 | 1020 | |
---|
980 | | - error = data->ops->get_report(data->client, report); |
---|
| 1021 | + error = data->ops->get_report(data->client, report, data->report_len); |
---|
981 | 1022 | if (error) |
---|
982 | 1023 | goto out; |
---|
983 | 1024 | |
---|
984 | 1025 | switch (report[ETP_REPORT_ID_OFFSET]) { |
---|
985 | 1026 | case ETP_REPORT_ID: |
---|
986 | | - elan_report_absolute(data, report); |
---|
| 1027 | + elan_report_absolute(data, report, false); |
---|
| 1028 | + break; |
---|
| 1029 | + case ETP_REPORT_ID2: |
---|
| 1030 | + elan_report_absolute(data, report, true); |
---|
987 | 1031 | break; |
---|
988 | 1032 | case ETP_TP_REPORT_ID: |
---|
| 1033 | + case ETP_TP_REPORT_ID2: |
---|
989 | 1034 | elan_report_trackpoint(data, report); |
---|
990 | 1035 | break; |
---|
991 | 1036 | default: |
---|
992 | | - dev_err(dev, "invalid report id data (%x)\n", |
---|
| 1037 | + dev_err(&data->client->dev, "invalid report id data (%x)\n", |
---|
993 | 1038 | report[ETP_REPORT_ID_OFFSET]); |
---|
994 | 1039 | } |
---|
995 | 1040 | |
---|
.. | .. |
---|
1059 | 1104 | |
---|
1060 | 1105 | __set_bit(EV_ABS, input->evbit); |
---|
1061 | 1106 | __set_bit(INPUT_PROP_POINTER, input->propbit); |
---|
1062 | | - if (data->clickpad) |
---|
| 1107 | + if (data->clickpad) { |
---|
1063 | 1108 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); |
---|
1064 | | - else |
---|
| 1109 | + } else { |
---|
1065 | 1110 | __set_bit(BTN_RIGHT, input->keybit); |
---|
| 1111 | + if (data->middle_button) |
---|
| 1112 | + __set_bit(BTN_MIDDLE, input->keybit); |
---|
| 1113 | + } |
---|
1066 | 1114 | __set_bit(BTN_LEFT, input->keybit); |
---|
1067 | 1115 | |
---|
1068 | 1116 | /* Set up ST parameters */ |
---|
.. | .. |
---|
1071 | 1119 | input_abs_set_res(input, ABS_X, data->x_res); |
---|
1072 | 1120 | input_abs_set_res(input, ABS_Y, data->y_res); |
---|
1073 | 1121 | input_set_abs_params(input, ABS_PRESSURE, 0, ETP_MAX_PRESSURE, 0, 0); |
---|
1074 | | - input_set_abs_params(input, ABS_TOOL_WIDTH, 0, ETP_FINGER_WIDTH, 0, 0); |
---|
| 1122 | + if (data->report_features & ETP_FEATURE_REPORT_MK) |
---|
| 1123 | + input_set_abs_params(input, ABS_TOOL_WIDTH, |
---|
| 1124 | + 0, ETP_FINGER_WIDTH, 0, 0); |
---|
1075 | 1125 | input_set_abs_params(input, ABS_DISTANCE, 0, 1, 0, 0); |
---|
1076 | 1126 | |
---|
1077 | 1127 | /* And MT parameters */ |
---|
.. | .. |
---|
1081 | 1131 | input_abs_set_res(input, ABS_MT_POSITION_Y, data->y_res); |
---|
1082 | 1132 | input_set_abs_params(input, ABS_MT_PRESSURE, 0, |
---|
1083 | 1133 | ETP_MAX_PRESSURE, 0, 0); |
---|
1084 | | - input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, |
---|
1085 | | - ETP_FINGER_WIDTH * max_width, 0, 0); |
---|
1086 | | - input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, |
---|
1087 | | - ETP_FINGER_WIDTH * min_width, 0, 0); |
---|
| 1134 | + if (data->report_features & ETP_FEATURE_REPORT_MK) { |
---|
| 1135 | + input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, |
---|
| 1136 | + 0, ETP_FINGER_WIDTH * max_width, 0, 0); |
---|
| 1137 | + input_set_abs_params(input, ABS_MT_TOUCH_MINOR, |
---|
| 1138 | + 0, ETP_FINGER_WIDTH * min_width, 0, 0); |
---|
| 1139 | + } |
---|
1088 | 1140 | |
---|
1089 | 1141 | data->input = input; |
---|
1090 | 1142 | |
---|
.. | .. |
---|
1096 | 1148 | struct elan_tp_data *data = _data; |
---|
1097 | 1149 | |
---|
1098 | 1150 | regulator_disable(data->vcc); |
---|
1099 | | -} |
---|
1100 | | - |
---|
1101 | | -static void elan_remove_sysfs_groups(void *_data) |
---|
1102 | | -{ |
---|
1103 | | - struct elan_tp_data *data = _data; |
---|
1104 | | - |
---|
1105 | | - sysfs_remove_groups(&data->client->dev.kobj, elan_sysfs_groups); |
---|
1106 | 1151 | } |
---|
1107 | 1152 | |
---|
1108 | 1153 | static int elan_probe(struct i2c_client *client, |
---|
.. | .. |
---|
1154 | 1199 | return error; |
---|
1155 | 1200 | } |
---|
1156 | 1201 | |
---|
1157 | | - error = devm_add_action(dev, elan_disable_regulator, data); |
---|
| 1202 | + error = devm_add_action_or_reset(dev, elan_disable_regulator, data); |
---|
1158 | 1203 | if (error) { |
---|
1159 | | - regulator_disable(data->vcc); |
---|
1160 | 1204 | dev_err(dev, "Failed to add disable regulator action: %d\n", |
---|
1161 | 1205 | error); |
---|
1162 | 1206 | return error; |
---|
.. | .. |
---|
1229 | 1273 | return error; |
---|
1230 | 1274 | } |
---|
1231 | 1275 | |
---|
1232 | | - error = sysfs_create_groups(&dev->kobj, elan_sysfs_groups); |
---|
| 1276 | + error = devm_device_add_groups(dev, elan_sysfs_groups); |
---|
1233 | 1277 | if (error) { |
---|
1234 | 1278 | dev_err(dev, "failed to create sysfs attributes: %d\n", error); |
---|
1235 | | - return error; |
---|
1236 | | - } |
---|
1237 | | - |
---|
1238 | | - error = devm_add_action(dev, elan_remove_sysfs_groups, data); |
---|
1239 | | - if (error) { |
---|
1240 | | - elan_remove_sysfs_groups(data); |
---|
1241 | | - dev_err(dev, "Failed to add sysfs cleanup action: %d\n", |
---|
1242 | | - error); |
---|
1243 | 1279 | return error; |
---|
1244 | 1280 | } |
---|
1245 | 1281 | |
---|
.. | .. |
---|
1291 | 1327 | /* Enable wake from IRQ */ |
---|
1292 | 1328 | data->irq_wake = (enable_irq_wake(client->irq) == 0); |
---|
1293 | 1329 | } else { |
---|
1294 | | - ret = elan_disable_power(data); |
---|
| 1330 | + ret = elan_set_power(data, false); |
---|
| 1331 | + if (ret) |
---|
| 1332 | + goto err; |
---|
| 1333 | + |
---|
| 1334 | + ret = regulator_disable(data->vcc); |
---|
| 1335 | + if (ret) { |
---|
| 1336 | + dev_err(dev, "error %d disabling regulator\n", ret); |
---|
| 1337 | + /* Attempt to power the chip back up */ |
---|
| 1338 | + elan_set_power(data, true); |
---|
| 1339 | + } |
---|
1295 | 1340 | } |
---|
1296 | 1341 | |
---|
| 1342 | +err: |
---|
1297 | 1343 | mutex_unlock(&data->sysfs_mutex); |
---|
1298 | 1344 | return ret; |
---|
1299 | 1345 | } |
---|
.. | .. |
---|
1304 | 1350 | struct elan_tp_data *data = i2c_get_clientdata(client); |
---|
1305 | 1351 | int error; |
---|
1306 | 1352 | |
---|
1307 | | - if (device_may_wakeup(dev) && data->irq_wake) { |
---|
| 1353 | + if (!device_may_wakeup(dev)) { |
---|
| 1354 | + error = regulator_enable(data->vcc); |
---|
| 1355 | + if (error) { |
---|
| 1356 | + dev_err(dev, "error %d enabling regulator\n", error); |
---|
| 1357 | + goto err; |
---|
| 1358 | + } |
---|
| 1359 | + } else if (data->irq_wake) { |
---|
1308 | 1360 | disable_irq_wake(client->irq); |
---|
1309 | 1361 | data->irq_wake = false; |
---|
1310 | 1362 | } |
---|
1311 | 1363 | |
---|
1312 | | - error = elan_enable_power(data); |
---|
| 1364 | + error = elan_set_power(data, true); |
---|
1313 | 1365 | if (error) { |
---|
1314 | 1366 | dev_err(dev, "power up when resuming failed: %d\n", error); |
---|
1315 | 1367 | goto err; |
---|
.. | .. |
---|
1333 | 1385 | MODULE_DEVICE_TABLE(i2c, elan_id); |
---|
1334 | 1386 | |
---|
1335 | 1387 | #ifdef CONFIG_ACPI |
---|
1336 | | -static const struct acpi_device_id elan_acpi_id[] = { |
---|
1337 | | - { "ELAN0000", 0 }, |
---|
1338 | | - { "ELAN0100", 0 }, |
---|
1339 | | - { "ELAN0600", 0 }, |
---|
1340 | | - { "ELAN0601", 0 }, |
---|
1341 | | - { "ELAN0602", 0 }, |
---|
1342 | | - { "ELAN0603", 0 }, |
---|
1343 | | - { "ELAN0604", 0 }, |
---|
1344 | | - { "ELAN0605", 0 }, |
---|
1345 | | - { "ELAN0606", 0 }, |
---|
1346 | | - { "ELAN0607", 0 }, |
---|
1347 | | - { "ELAN0608", 0 }, |
---|
1348 | | - { "ELAN0609", 0 }, |
---|
1349 | | - { "ELAN060B", 0 }, |
---|
1350 | | - { "ELAN060C", 0 }, |
---|
1351 | | - { "ELAN060F", 0 }, |
---|
1352 | | - { "ELAN0610", 0 }, |
---|
1353 | | - { "ELAN0611", 0 }, |
---|
1354 | | - { "ELAN0612", 0 }, |
---|
1355 | | - { "ELAN0615", 0 }, |
---|
1356 | | - { "ELAN0616", 0 }, |
---|
1357 | | - { "ELAN0617", 0 }, |
---|
1358 | | - { "ELAN0618", 0 }, |
---|
1359 | | - { "ELAN0619", 0 }, |
---|
1360 | | - { "ELAN061A", 0 }, |
---|
1361 | | -/* { "ELAN061B", 0 }, not working on the Lenovo Legion Y7000 */ |
---|
1362 | | - { "ELAN061C", 0 }, |
---|
1363 | | - { "ELAN061D", 0 }, |
---|
1364 | | - { "ELAN061E", 0 }, |
---|
1365 | | - { "ELAN061F", 0 }, |
---|
1366 | | - { "ELAN0620", 0 }, |
---|
1367 | | - { "ELAN0621", 0 }, |
---|
1368 | | - { "ELAN0622", 0 }, |
---|
1369 | | - { "ELAN0623", 0 }, |
---|
1370 | | - { "ELAN0624", 0 }, |
---|
1371 | | - { "ELAN0625", 0 }, |
---|
1372 | | - { "ELAN0626", 0 }, |
---|
1373 | | - { "ELAN0627", 0 }, |
---|
1374 | | - { "ELAN0628", 0 }, |
---|
1375 | | - { "ELAN0629", 0 }, |
---|
1376 | | - { "ELAN062A", 0 }, |
---|
1377 | | - { "ELAN062B", 0 }, |
---|
1378 | | - { "ELAN062C", 0 }, |
---|
1379 | | - { "ELAN062D", 0 }, |
---|
1380 | | - { "ELAN0631", 0 }, |
---|
1381 | | - { "ELAN0632", 0 }, |
---|
1382 | | - { "ELAN1000", 0 }, |
---|
1383 | | - { } |
---|
1384 | | -}; |
---|
1385 | 1388 | MODULE_DEVICE_TABLE(acpi, elan_acpi_id); |
---|
1386 | 1389 | #endif |
---|
1387 | 1390 | |
---|