diff options
Diffstat (limited to 'drivers/input/mouse/elan_i2c_core.c')
-rw-r--r-- | drivers/input/mouse/elan_i2c_core.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 7ce8bfe22d7e..fd5068b2542d 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -4,7 +4,7 @@ * Copyright (c) 2013 ELAN Microelectronics Corp. * * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw> - * Version: 1.5.6 + * Version: 1.5.7 * * Based on cyapa driver: * copyright (c) 2011-2012 Cypress Semiconductor, Inc. @@ -40,8 +40,7 @@ #include "elan_i2c.h" #define DRIVER_NAME "elan_i2c" -#define ELAN_DRIVER_VERSION "1.5.6" -#define ETP_PRESSURE_OFFSET 25 +#define ELAN_DRIVER_VERSION "1.5.7" #define ETP_MAX_PRESSURE 255 #define ETP_FWIDTH_REDUCE 90 #define ETP_FINGER_WIDTH 15 @@ -53,6 +52,7 @@ #define ETP_REPORT_ID_OFFSET 2 #define ETP_TOUCH_INFO_OFFSET 3 #define ETP_FINGER_DATA_OFFSET 4 +#define ETP_HOVER_INFO_OFFSET 30 #define ETP_MAX_REPORT_LEN 34 /* The main device structure */ @@ -81,7 +81,7 @@ struct elan_tp_data { u8 sm_version; u8 iap_version; u16 fw_checksum; - + int pressure_adjustment; u8 mode; bool irq_wake; @@ -99,7 +99,7 @@ static int elan_enable_power(struct elan_tp_data *data) error = regulator_enable(data->vcc); if (error) { dev_err(&data->client->dev, - "Failed to enable regulator: %d\n", error); + "failed to enable regulator: %d\n", error); return error; } @@ -111,6 +111,7 @@ static int elan_enable_power(struct elan_tp_data *data) msleep(30); } while (--repeat > 0); + dev_err(&data->client->dev, "failed to enable power: %d\n", error); return error; } @@ -125,7 +126,7 @@ static int elan_disable_power(struct elan_tp_data *data) error = regulator_disable(data->vcc); if (error) { dev_err(&data->client->dev, - "Failed to disable regulator: %d\n", + "failed to disable regulator: %d\n", error); /* Attempt to power the chip back up */ data->ops->power_control(data->client, true); @@ -138,6 +139,7 @@ static int elan_disable_power(struct elan_tp_data *data) msleep(30); } while (--repeat > 0); + dev_err(&data->client->dev, "failed to disable power: %d\n", error); return error; } @@ -196,7 +198,6 @@ static int elan_initialize(struct elan_tp_data *data) if (!error) return 0; - repeat--; msleep(30); } while (--repeat > 0); @@ -228,6 +229,11 @@ static int elan_query_device_info(struct elan_tp_data *data) if (error) return error; + error = data->ops->get_pressure_adjustment(data->client, + &data->pressure_adjustment); + if (error) + return error; + return 0; } @@ -720,13 +726,13 @@ static const struct attribute_group *elan_sysfs_groups[] = { */ static void elan_report_contact(struct elan_tp_data *data, int contact_num, bool contact_valid, - u8 *finger_data) + bool hover_event, u8 *finger_data) { struct input_dev *input = data->input; unsigned int pos_x, pos_y; unsigned int pressure, mk_x, mk_y; - unsigned int area_x, area_y, major, minor, new_pressure; - + unsigned int area_x, area_y, major, minor; + unsigned int scaled_pressure; if (contact_valid) { pos_x = ((finger_data[0] & 0xf0) << 4) | @@ -755,15 +761,18 @@ static void elan_report_contact(struct elan_tp_data *data, major = max(area_x, area_y); minor = min(area_x, area_y); - new_pressure = pressure + ETP_PRESSURE_OFFSET; - if (new_pressure > ETP_MAX_PRESSURE) - new_pressure = ETP_MAX_PRESSURE; + scaled_pressure = pressure + data->pressure_adjustment; + + if (scaled_pressure > ETP_MAX_PRESSURE) + scaled_pressure = ETP_MAX_PRESSURE; input_mt_slot(input, contact_num); input_mt_report_slot_state(input, MT_TOOL_FINGER, true); input_report_abs(input, ABS_MT_POSITION_X, pos_x); input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y); - input_report_abs(input, ABS_MT_PRESSURE, new_pressure); + input_report_abs(input, ABS_MT_DISTANCE, hover_event); + input_report_abs(input, ABS_MT_PRESSURE, + hover_event ? 0 : scaled_pressure); input_report_abs(input, ABS_TOOL_WIDTH, mk_x); input_report_abs(input, ABS_MT_TOUCH_MAJOR, major); input_report_abs(input, ABS_MT_TOUCH_MINOR, minor); @@ -779,11 +788,14 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet) u8 *finger_data = &packet[ETP_FINGER_DATA_OFFSET]; int i; u8 tp_info = packet[ETP_TOUCH_INFO_OFFSET]; - bool contact_valid; + u8 hover_info = packet[ETP_HOVER_INFO_OFFSET]; + bool contact_valid, hover_event; + hover_event = hover_info & 0x40; for (i = 0; i < ETP_MAX_FINGERS; i++) { contact_valid = tp_info & (1U << (3 + i)); - elan_report_contact(data, i, contact_valid, finger_data); + elan_report_contact(data, i, contact_valid, hover_event, + finger_data); if (contact_valid) finger_data += ETP_FINGER_DATA_LEN; @@ -877,6 +889,7 @@ static int elan_setup_input_device(struct elan_tp_data *data) ETP_FINGER_WIDTH * max_width, 0, 0); input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, ETP_FINGER_WIDTH * min_width, 0, 0); + input_set_abs_params(input, ABS_MT_DISTANCE, 0, 1, 0, 0); data->input = input; @@ -1084,16 +1097,18 @@ static int __maybe_unused elan_resume(struct device *dev) } error = elan_enable_power(data); - if (error) + if (error) { dev_err(dev, "power up when resuming failed: %d\n", error); + goto err; + } error = elan_initialize(data); if (error) dev_err(dev, "initialize when resuming failed: %d\n", error); +err: enable_irq(data->client->irq); - - return 0; + return error; } static SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume); |