aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKT Liao <ktalex.liao@gmail.com>2016-11-27 23:59:29 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2017-05-11 20:44:23 -0400
commita2eaf299d134cfe780c68c771f88d81516c1e70d (patch)
tree76c6b5e035fefb17e15d4cfc60bdda871e1be9c0
parentc5928551fd41b2eecdad78fa2be2a4a13ed5fde9 (diff)
Input: elan_i2c - add support for fetching chip type on newer hardware
Newer Elantech hardware requires different way of fetching chip type and version data. Signed-off-by: KT Liao <kt.liao@emc.com.tw> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/mouse/elan_i2c.h3
-rw-r--r--drivers/input/mouse/elan_i2c_core.c33
-rw-r--r--drivers/input/mouse/elan_i2c_i2c.c71
-rw-r--r--drivers/input/mouse/elan_i2c_smbus.c9
4 files changed, 99 insertions, 17 deletions
diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h
index c0ec26118732..61c202436250 100644
--- a/drivers/input/mouse/elan_i2c.h
+++ b/drivers/input/mouse/elan_i2c.h
@@ -58,7 +58,7 @@ struct elan_transport_ops {
58 58
59 int (*get_version)(struct i2c_client *client, bool iap, u8 *version); 59 int (*get_version)(struct i2c_client *client, bool iap, u8 *version);
60 int (*get_sm_version)(struct i2c_client *client, 60 int (*get_sm_version)(struct i2c_client *client,
61 u8* ic_type, u8 *version); 61 u16 *ic_type, u8 *version);
62 int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum); 62 int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum);
63 int (*get_product_id)(struct i2c_client *client, u16 *id); 63 int (*get_product_id)(struct i2c_client *client, u16 *id);
64 64
@@ -82,6 +82,7 @@ struct elan_transport_ops {
82 int (*get_report)(struct i2c_client *client, u8 *report); 82 int (*get_report)(struct i2c_client *client, u8 *report);
83 int (*get_pressure_adjustment)(struct i2c_client *client, 83 int (*get_pressure_adjustment)(struct i2c_client *client,
84 int *adjustment); 84 int *adjustment);
85 int (*get_pattern)(struct i2c_client *client, u8 *pattern);
85}; 86};
86 87
87extern const struct elan_transport_ops elan_smbus_ops, elan_i2c_ops; 88extern const struct elan_transport_ops elan_smbus_ops, elan_i2c_ops;
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 551ad2934fa7..3b616cb7c67f 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw> 6 * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
7 * Author: KT Liao <kt.liao@emc.com.tw> 7 * Author: KT Liao <kt.liao@emc.com.tw>
8 * Version: 1.6.2 8 * Version: 1.6.3
9 * 9 *
10 * Based on cyapa driver: 10 * Based on cyapa driver:
11 * copyright (c) 2011-2012 Cypress Semiconductor, Inc. 11 * copyright (c) 2011-2012 Cypress Semiconductor, Inc.
@@ -41,7 +41,7 @@
41#include "elan_i2c.h" 41#include "elan_i2c.h"
42 42
43#define DRIVER_NAME "elan_i2c" 43#define DRIVER_NAME "elan_i2c"
44#define ELAN_DRIVER_VERSION "1.6.2" 44#define ELAN_DRIVER_VERSION "1.6.3"
45#define ELAN_VENDOR_ID 0x04f3 45#define ELAN_VENDOR_ID 0x04f3
46#define ETP_MAX_PRESSURE 255 46#define ETP_MAX_PRESSURE 255
47#define ETP_FWIDTH_REDUCE 90 47#define ETP_FWIDTH_REDUCE 90
@@ -78,6 +78,7 @@ struct elan_tp_data {
78 unsigned int x_res; 78 unsigned int x_res;
79 unsigned int y_res; 79 unsigned int y_res;
80 80
81 u8 pattern;
81 u16 product_id; 82 u16 product_id;
82 u8 fw_version; 83 u8 fw_version;
83 u8 sm_version; 84 u8 sm_version;
@@ -85,7 +86,7 @@ struct elan_tp_data {
85 u16 fw_checksum; 86 u16 fw_checksum;
86 int pressure_adjustment; 87 int pressure_adjustment;
87 u8 mode; 88 u8 mode;
88 u8 ic_type; 89 u16 ic_type;
89 u16 fw_validpage_count; 90 u16 fw_validpage_count;
90 u16 fw_signature_address; 91 u16 fw_signature_address;
91 92
@@ -96,10 +97,10 @@ struct elan_tp_data {
96 bool baseline_ready; 97 bool baseline_ready;
97}; 98};
98 99
99static int elan_get_fwinfo(u8 iap_version, u16 *validpage_count, 100static int elan_get_fwinfo(u16 ic_type, u16 *validpage_count,
100 u16 *signature_address) 101 u16 *signature_address)
101{ 102{
102 switch (iap_version) { 103 switch (ic_type) {
103 case 0x00: 104 case 0x00:
104 case 0x06: 105 case 0x06:
105 case 0x08: 106 case 0x08:
@@ -119,6 +120,9 @@ static int elan_get_fwinfo(u8 iap_version, u16 *validpage_count,
119 case 0x0E: 120 case 0x0E:
120 *validpage_count = 640; 121 *validpage_count = 640;
121 break; 122 break;
123 case 0x10:
124 *validpage_count = 1024;
125 break;
122 default: 126 default:
123 /* unknown ic type clear value */ 127 /* unknown ic type clear value */
124 *validpage_count = 0; 128 *validpage_count = 0;
@@ -305,6 +309,7 @@ static int elan_initialize(struct elan_tp_data *data)
305static int elan_query_device_info(struct elan_tp_data *data) 309static int elan_query_device_info(struct elan_tp_data *data)
306{ 310{
307 int error; 311 int error;
312 u16 ic_type;
308 313
309 error = data->ops->get_version(data->client, false, &data->fw_version); 314 error = data->ops->get_version(data->client, false, &data->fw_version);
310 if (error) 315 if (error)
@@ -324,7 +329,16 @@ static int elan_query_device_info(struct elan_tp_data *data)
324 if (error) 329 if (error)
325 return error; 330 return error;
326 331
327 error = elan_get_fwinfo(data->iap_version, &data->fw_validpage_count, 332 error = data->ops->get_pattern(data->client, &data->pattern);
333 if (error)
334 return error;
335
336 if (data->pattern == 0x01)
337 ic_type = data->ic_type;
338 else
339 ic_type = data->iap_version;
340
341 error = elan_get_fwinfo(ic_type, &data->fw_validpage_count,
328 &data->fw_signature_address); 342 &data->fw_signature_address);
329 if (error) 343 if (error)
330 dev_warn(&data->client->dev, 344 dev_warn(&data->client->dev,
@@ -1108,10 +1122,13 @@ static int elan_probe(struct i2c_client *client,
1108 "Elan Touchpad Extra Information:\n" 1122 "Elan Touchpad Extra Information:\n"
1109 " Max ABS X,Y: %d,%d\n" 1123 " Max ABS X,Y: %d,%d\n"
1110 " Width X,Y: %d,%d\n" 1124 " Width X,Y: %d,%d\n"
1111 " Resolution X,Y: %d,%d (dots/mm)\n", 1125 " Resolution X,Y: %d,%d (dots/mm)\n"
1126 " ic type: 0x%x\n"
1127 " info pattern: 0x%x\n",
1112 data->max_x, data->max_y, 1128 data->max_x, data->max_y,
1113 data->width_x, data->width_y, 1129 data->width_x, data->width_y,
1114 data->x_res, data->y_res); 1130 data->x_res, data->y_res,
1131 data->ic_type, data->pattern);
1115 1132
1116 /* Set up input device properties based on queried parameters. */ 1133 /* Set up input device properties based on queried parameters. */
1117 error = elan_setup_input_device(data); 1134 error = elan_setup_input_device(data);
diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c
index a679e56c44cd..3be75c6e8090 100644
--- a/drivers/input/mouse/elan_i2c_i2c.c
+++ b/drivers/input/mouse/elan_i2c_i2c.c
@@ -34,9 +34,12 @@
34#define ETP_I2C_DESC_CMD 0x0001 34#define ETP_I2C_DESC_CMD 0x0001
35#define ETP_I2C_REPORT_DESC_CMD 0x0002 35#define ETP_I2C_REPORT_DESC_CMD 0x0002
36#define ETP_I2C_STAND_CMD 0x0005 36#define ETP_I2C_STAND_CMD 0x0005
37#define ETP_I2C_PATTERN_CMD 0x0100
37#define ETP_I2C_UNIQUEID_CMD 0x0101 38#define ETP_I2C_UNIQUEID_CMD 0x0101
38#define ETP_I2C_FW_VERSION_CMD 0x0102 39#define ETP_I2C_FW_VERSION_CMD 0x0102
39#define ETP_I2C_SM_VERSION_CMD 0x0103 40#define ETP_I2C_IC_TYPE_CMD 0x0103
41#define ETP_I2C_OSM_VERSION_CMD 0x0103
42#define ETP_I2C_NSM_VERSION_CMD 0x0104
40#define ETP_I2C_XY_TRACENUM_CMD 0x0105 43#define ETP_I2C_XY_TRACENUM_CMD 0x0105
41#define ETP_I2C_MAX_X_AXIS_CMD 0x0106 44#define ETP_I2C_MAX_X_AXIS_CMD 0x0106
42#define ETP_I2C_MAX_Y_AXIS_CMD 0x0107 45#define ETP_I2C_MAX_Y_AXIS_CMD 0x0107
@@ -239,12 +242,34 @@ static int elan_i2c_get_baseline_data(struct i2c_client *client,
239 return 0; 242 return 0;
240} 243}
241 244
245static int elan_i2c_get_pattern(struct i2c_client *client, u8 *pattern)
246{
247 int error;
248 u8 val[3];
249
250 error = elan_i2c_read_cmd(client, ETP_I2C_PATTERN_CMD, val);
251 if (error) {
252 dev_err(&client->dev, "failed to get pattern: %d\n", error);
253 return error;
254 }
255 *pattern = val[1];
256
257 return 0;
258}
259
242static int elan_i2c_get_version(struct i2c_client *client, 260static int elan_i2c_get_version(struct i2c_client *client,
243 bool iap, u8 *version) 261 bool iap, u8 *version)
244{ 262{
245 int error; 263 int error;
264 u8 pattern_ver;
246 u8 val[3]; 265 u8 val[3];
247 266
267 error = elan_i2c_get_pattern(client, &pattern_ver);
268 if (error) {
269 dev_err(&client->dev, "failed to get pattern version\n");
270 return error;
271 }
272
248 error = elan_i2c_read_cmd(client, 273 error = elan_i2c_read_cmd(client,
249 iap ? ETP_I2C_IAP_VERSION_CMD : 274 iap ? ETP_I2C_IAP_VERSION_CMD :
250 ETP_I2C_FW_VERSION_CMD, 275 ETP_I2C_FW_VERSION_CMD,
@@ -255,24 +280,54 @@ static int elan_i2c_get_version(struct i2c_client *client,
255 return error; 280 return error;
256 } 281 }
257 282
258 *version = val[0]; 283 if (pattern_ver == 0x01)
284 *version = iap ? val[1] : val[0];
285 else
286 *version = val[0];
259 return 0; 287 return 0;
260} 288}
261 289
262static int elan_i2c_get_sm_version(struct i2c_client *client, 290static int elan_i2c_get_sm_version(struct i2c_client *client,
263 u8 *ic_type, u8 *version) 291 u16 *ic_type, u8 *version)
264{ 292{
265 int error; 293 int error;
294 u8 pattern_ver;
266 u8 val[3]; 295 u8 val[3];
267 296
268 error = elan_i2c_read_cmd(client, ETP_I2C_SM_VERSION_CMD, val); 297 error = elan_i2c_get_pattern(client, &pattern_ver);
269 if (error) { 298 if (error) {
270 dev_err(&client->dev, "failed to get SM version: %d\n", error); 299 dev_err(&client->dev, "failed to get pattern version\n");
271 return error; 300 return error;
272 } 301 }
273 302
274 *version = val[0]; 303 if (pattern_ver == 0x01) {
275 *ic_type = val[1]; 304 error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_CMD, val);
305 if (error) {
306 dev_err(&client->dev, "failed to get ic type: %d\n",
307 error);
308 return error;
309 }
310 *ic_type = be16_to_cpup((__be16 *)val);
311
312 error = elan_i2c_read_cmd(client, ETP_I2C_NSM_VERSION_CMD,
313 val);
314 if (error) {
315 dev_err(&client->dev, "failed to get SM version: %d\n",
316 error);
317 return error;
318 }
319 *version = val[1];
320 } else {
321 error = elan_i2c_read_cmd(client, ETP_I2C_OSM_VERSION_CMD, val);
322 if (error) {
323 dev_err(&client->dev, "failed to get SM version: %d\n",
324 error);
325 return error;
326 }
327 *version = val[0];
328 *ic_type = val[1];
329 }
330
276 return 0; 331 return 0;
277} 332}
278 333
@@ -639,5 +694,7 @@ const struct elan_transport_ops elan_i2c_ops = {
639 .write_fw_block = elan_i2c_write_fw_block, 694 .write_fw_block = elan_i2c_write_fw_block,
640 .finish_fw_update = elan_i2c_finish_fw_update, 695 .finish_fw_update = elan_i2c_finish_fw_update,
641 696
697 .get_pattern = elan_i2c_get_pattern,
698
642 .get_report = elan_i2c_get_report, 699 .get_report = elan_i2c_get_report,
643}; 700};
diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c
index e23b2495d52e..df7a57ca7331 100644
--- a/drivers/input/mouse/elan_i2c_smbus.c
+++ b/drivers/input/mouse/elan_i2c_smbus.c
@@ -166,7 +166,7 @@ static int elan_smbus_get_version(struct i2c_client *client,
166} 166}
167 167
168static int elan_smbus_get_sm_version(struct i2c_client *client, 168static int elan_smbus_get_sm_version(struct i2c_client *client,
169 u8 *ic_type, u8 *version) 169 u16 *ic_type, u8 *version)
170{ 170{
171 int error; 171 int error;
172 u8 val[3]; 172 u8 val[3];
@@ -495,6 +495,12 @@ static int elan_smbus_finish_fw_update(struct i2c_client *client,
495 return 0; 495 return 0;
496} 496}
497 497
498static int elan_smbus_get_pattern(struct i2c_client *client, u8 *pattern)
499{
500 *pattern = 0;
501 return 0;
502}
503
498const struct elan_transport_ops elan_smbus_ops = { 504const struct elan_transport_ops elan_smbus_ops = {
499 .initialize = elan_smbus_initialize, 505 .initialize = elan_smbus_initialize,
500 .sleep_control = elan_smbus_sleep_control, 506 .sleep_control = elan_smbus_sleep_control,
@@ -524,4 +530,5 @@ const struct elan_transport_ops elan_smbus_ops = {
524 .finish_fw_update = elan_smbus_finish_fw_update, 530 .finish_fw_update = elan_smbus_finish_fw_update,
525 531
526 .get_report = elan_smbus_get_report, 532 .get_report = elan_smbus_get_report,
533 .get_pattern = elan_smbus_get_pattern,
527}; 534};