mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
Input: elan_i2c - adjust for newer firmware pressure reporting
Get pressure format flag from firmware to check if we need to normalize pressure data before reporting it. Signed-off-by: Duson Lin <dusonlin@emc.com.tw> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
8b8a518ef1
commit
b9bced0eec
4 changed files with 49 additions and 10 deletions
|
@ -25,6 +25,7 @@
|
|||
#define ETP_ENABLE_CALIBRATE 0x0002
|
||||
#define ETP_DISABLE_CALIBRATE 0x0000
|
||||
#define ETP_DISABLE_POWER 0x0001
|
||||
#define ETP_PRESSURE_OFFSET 25
|
||||
|
||||
/* IAP Firmware handling */
|
||||
#define ETP_FW_NAME "elan_i2c.bin"
|
||||
|
@ -79,6 +80,8 @@ struct elan_transport_ops {
|
|||
struct completion *reset_done);
|
||||
|
||||
int (*get_report)(struct i2c_client *client, u8 *report);
|
||||
int (*get_pressure_adjustment)(struct i2c_client *client,
|
||||
int *adjustment);
|
||||
};
|
||||
|
||||
extern const struct elan_transport_ops elan_smbus_ops, elan_i2c_ops;
|
||||
|
|
|
@ -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
|
||||
|
@ -81,7 +80,7 @@ struct elan_tp_data {
|
|||
u8 sm_version;
|
||||
u8 iap_version;
|
||||
u16 fw_checksum;
|
||||
|
||||
int pressure_adjustment;
|
||||
u8 mode;
|
||||
|
||||
bool irq_wake;
|
||||
|
@ -229,6 +228,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;
|
||||
}
|
||||
|
||||
|
@ -726,8 +730,8 @@ static void elan_report_contact(struct elan_tp_data *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) |
|
||||
|
@ -756,15 +760,16 @@ 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_PRESSURE, 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);
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#define ETP_I2C_MAX_X_AXIS_CMD 0x0106
|
||||
#define ETP_I2C_MAX_Y_AXIS_CMD 0x0107
|
||||
#define ETP_I2C_RESOLUTION_CMD 0x0108
|
||||
#define ETP_I2C_PRESSURE_CMD 0x010A
|
||||
#define ETP_I2C_IAP_VERSION_CMD 0x0110
|
||||
#define ETP_I2C_SET_CMD 0x0300
|
||||
#define ETP_I2C_POWER_CMD 0x0307
|
||||
|
@ -370,6 +371,27 @@ static int elan_i2c_get_num_traces(struct i2c_client *client,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int elan_i2c_get_pressure_adjustment(struct i2c_client *client,
|
||||
int *adjustment)
|
||||
{
|
||||
int error;
|
||||
u8 val[3];
|
||||
|
||||
error = elan_i2c_read_cmd(client, ETP_I2C_PRESSURE_CMD, val);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "failed to get pressure format: %d\n",
|
||||
error);
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((val[0] >> 4) & 0x1)
|
||||
*adjustment = 0;
|
||||
else
|
||||
*adjustment = ETP_PRESSURE_OFFSET;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elan_i2c_iap_get_mode(struct i2c_client *client, enum tp_mode *mode)
|
||||
{
|
||||
int error;
|
||||
|
@ -602,6 +624,7 @@ const struct elan_transport_ops elan_i2c_ops = {
|
|||
.get_sm_version = elan_i2c_get_sm_version,
|
||||
.get_product_id = elan_i2c_get_product_id,
|
||||
.get_checksum = elan_i2c_get_checksum,
|
||||
.get_pressure_adjustment = elan_i2c_get_pressure_adjustment,
|
||||
|
||||
.get_max = elan_i2c_get_max,
|
||||
.get_resolution = elan_i2c_get_resolution,
|
||||
|
|
|
@ -274,6 +274,13 @@ static int elan_smbus_get_num_traces(struct i2c_client *client,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int elan_smbus_get_pressure_adjustment(struct i2c_client *client,
|
||||
int *adjustment)
|
||||
{
|
||||
*adjustment = ETP_PRESSURE_OFFSET;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elan_smbus_iap_get_mode(struct i2c_client *client,
|
||||
enum tp_mode *mode)
|
||||
{
|
||||
|
@ -497,6 +504,7 @@ const struct elan_transport_ops elan_smbus_ops = {
|
|||
.get_sm_version = elan_smbus_get_sm_version,
|
||||
.get_product_id = elan_smbus_get_product_id,
|
||||
.get_checksum = elan_smbus_get_checksum,
|
||||
.get_pressure_adjustment = elan_smbus_get_pressure_adjustment,
|
||||
|
||||
.get_max = elan_smbus_get_max,
|
||||
.get_resolution = elan_smbus_get_resolution,
|
||||
|
|
Loading…
Reference in a new issue