.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Elan I2C/SMBus Touchpad driver - SMBus interface |
---|
3 | 4 | * |
---|
.. | .. |
---|
8 | 9 | * Based on cyapa driver: |
---|
9 | 10 | * copyright (c) 2011-2012 Cypress Semiconductor, Inc. |
---|
10 | 11 | * copyright (c) 2011-2012 Google, Inc. |
---|
11 | | - * |
---|
12 | | - * This program is free software; you can redistribute it and/or modify it |
---|
13 | | - * under the terms of the GNU General Public License version 2 as published |
---|
14 | | - * by the Free Software Foundation. |
---|
15 | 12 | * |
---|
16 | 13 | * Trademarks are the property of their respective owners. |
---|
17 | 14 | */ |
---|
.. | .. |
---|
48 | 45 | #define ETP_SMBUS_CALIBRATE_QUERY 0xC5 |
---|
49 | 46 | |
---|
50 | 47 | #define ETP_SMBUS_REPORT_LEN 32 |
---|
| 48 | +#define ETP_SMBUS_REPORT_LEN2 7 |
---|
51 | 49 | #define ETP_SMBUS_REPORT_OFFSET 2 |
---|
52 | 50 | #define ETP_SMBUS_HELLOPACKET_LEN 5 |
---|
53 | 51 | #define ETP_SMBUS_IAP_PASSWORD 0x1234 |
---|
.. | .. |
---|
150 | 148 | } |
---|
151 | 149 | |
---|
152 | 150 | static int elan_smbus_get_version(struct i2c_client *client, |
---|
153 | | - bool iap, u8 *version) |
---|
| 151 | + u8 pattern, bool iap, u8 *version) |
---|
154 | 152 | { |
---|
155 | 153 | int error; |
---|
156 | 154 | u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; |
---|
.. | .. |
---|
169 | 167 | return 0; |
---|
170 | 168 | } |
---|
171 | 169 | |
---|
172 | | -static int elan_smbus_get_sm_version(struct i2c_client *client, |
---|
173 | | - u16 *ic_type, u8 *version, |
---|
174 | | - u8 *clickpad) |
---|
| 170 | +static int elan_smbus_get_sm_version(struct i2c_client *client, u8 pattern, |
---|
| 171 | + u16 *ic_type, u8 *version, u8 *clickpad) |
---|
175 | 172 | { |
---|
176 | 173 | int error; |
---|
177 | 174 | u8 val[I2C_SMBUS_BLOCK_MAX] = {0}; |
---|
.. | .. |
---|
343 | 340 | return 0; |
---|
344 | 341 | } |
---|
345 | 342 | |
---|
346 | | -static int elan_smbus_prepare_fw_update(struct i2c_client *client) |
---|
| 343 | +static int elan_smbus_prepare_fw_update(struct i2c_client *client, u16 ic_type, |
---|
| 344 | + u8 iap_version, u16 fw_page_size) |
---|
347 | 345 | { |
---|
348 | 346 | struct device *dev = &client->dev; |
---|
349 | 347 | int len; |
---|
.. | .. |
---|
417 | 415 | } |
---|
418 | 416 | |
---|
419 | 417 | |
---|
420 | | -static int elan_smbus_write_fw_block(struct i2c_client *client, |
---|
| 418 | +static int elan_smbus_write_fw_block(struct i2c_client *client, u16 fw_page_size, |
---|
421 | 419 | const u8 *page, u16 checksum, int idx) |
---|
422 | 420 | { |
---|
423 | 421 | struct device *dev = &client->dev; |
---|
.. | .. |
---|
432 | 430 | */ |
---|
433 | 431 | error = i2c_smbus_write_block_data(client, |
---|
434 | 432 | ETP_SMBUS_WRITE_FW_BLOCK, |
---|
435 | | - ETP_FW_PAGE_SIZE / 2, |
---|
| 433 | + fw_page_size / 2, |
---|
436 | 434 | page); |
---|
437 | 435 | if (error) { |
---|
438 | 436 | dev_err(dev, "Failed to write page %d (part %d): %d\n", |
---|
.. | .. |
---|
442 | 440 | |
---|
443 | 441 | error = i2c_smbus_write_block_data(client, |
---|
444 | 442 | ETP_SMBUS_WRITE_FW_BLOCK, |
---|
445 | | - ETP_FW_PAGE_SIZE / 2, |
---|
446 | | - page + ETP_FW_PAGE_SIZE / 2); |
---|
| 443 | + fw_page_size / 2, |
---|
| 444 | + page + fw_page_size / 2); |
---|
447 | 445 | if (error) { |
---|
448 | 446 | dev_err(dev, "Failed to write page %d (part %d): %d\n", |
---|
449 | 447 | idx, 2, error); |
---|
.. | .. |
---|
472 | 470 | return 0; |
---|
473 | 471 | } |
---|
474 | 472 | |
---|
475 | | -static int elan_smbus_get_report(struct i2c_client *client, u8 *report) |
---|
| 473 | +static int elan_smbus_get_report_features(struct i2c_client *client, u8 pattern, |
---|
| 474 | + unsigned int *features, |
---|
| 475 | + unsigned int *report_len) |
---|
| 476 | +{ |
---|
| 477 | + /* |
---|
| 478 | + * SMBus controllers with pattern 2 lack area info, as newer |
---|
| 479 | + * high-precision packets use that space for coordinates. |
---|
| 480 | + */ |
---|
| 481 | + *features = pattern <= 0x01 ? ETP_FEATURE_REPORT_MK : 0; |
---|
| 482 | + *report_len = ETP_SMBUS_REPORT_LEN; |
---|
| 483 | + return 0; |
---|
| 484 | +} |
---|
| 485 | + |
---|
| 486 | +static int elan_smbus_get_report(struct i2c_client *client, |
---|
| 487 | + u8 *report, unsigned int report_len) |
---|
476 | 488 | { |
---|
477 | 489 | int len; |
---|
478 | 490 | |
---|
.. | .. |
---|
486 | 498 | return len; |
---|
487 | 499 | } |
---|
488 | 500 | |
---|
489 | | - if (len != ETP_SMBUS_REPORT_LEN) { |
---|
| 501 | + if (report[ETP_REPORT_ID_OFFSET] == ETP_TP_REPORT_ID2) |
---|
| 502 | + report_len = ETP_SMBUS_REPORT_LEN2; |
---|
| 503 | + |
---|
| 504 | + if (len != report_len) { |
---|
490 | 505 | dev_err(&client->dev, |
---|
491 | 506 | "wrong report length (%d vs %d expected)\n", |
---|
492 | | - len, ETP_SMBUS_REPORT_LEN); |
---|
| 507 | + len, report_len); |
---|
493 | 508 | return -EIO; |
---|
494 | 509 | } |
---|
495 | 510 | |
---|
.. | .. |
---|
537 | 552 | .write_fw_block = elan_smbus_write_fw_block, |
---|
538 | 553 | .finish_fw_update = elan_smbus_finish_fw_update, |
---|
539 | 554 | |
---|
| 555 | + .get_report_features = elan_smbus_get_report_features, |
---|
540 | 556 | .get_report = elan_smbus_get_report, |
---|
541 | 557 | .get_pattern = elan_smbus_get_pattern, |
---|
542 | 558 | }; |
---|