diff mbox

[4/4] Input: elan_i2c - Add pressure normalization

Message ID 37C3176B-C1AD-4417-AF27-A9CBEAA468AC@emc.com.tw (mailing list archive)
State New, archived
Headers show

Commit Message

Duson Lin April 11, 2015, 11:01 a.m. UTC
Get pressure format flag form firmware to check need to send normalized
pressure data to upper OS or not. The normalized data will approximate
the measure of area of the ideal metal weight. For example, using the
8 mm metal weight touch the touchpad surface, the ideal value is 4*4=16
(ignore the constent pi) and the pressure get from firmware will near 16.

Signed-off-by: Duson Lin <dusonlin@emc.com.tw>
---
 drivers/input/mouse/elan_i2c.h       |    7 +++++--
 drivers/input/mouse/elan_i2c_core.c  |   25 +++++++++++++++----------
 drivers/input/mouse/elan_i2c_i2c.c   |   26 ++++++++++++++++++++++++--
 drivers/input/mouse/elan_i2c_smbus.c |   12 ++++++++++--
 4 files changed, 54 insertions(+), 16 deletions(-)

Comments

Dmitry Torokhov April 12, 2015, 11:15 p.m. UTC | #1
Hi Duson,

On Sat, Apr 11, 2015 at 07:01:00PM +0800, duson wrote:
> Get pressure format flag form firmware to check need to send normalized
> pressure data to upper OS or not. The normalized data will approximate
> the measure of area of the ideal metal weight. For example, using the
> 8 mm metal weight touch the touchpad surface, the ideal value is 4*4=16
> (ignore the constent pi) and the pressure get from firmware will near 16.
> 
> Signed-off-by: Duson Lin <dusonlin@emc.com.tw>
> ---
>  drivers/input/mouse/elan_i2c.h       |    7 +++++--
>  drivers/input/mouse/elan_i2c_core.c  |   25 +++++++++++++++----------
>  drivers/input/mouse/elan_i2c_i2c.c   |   26 ++++++++++++++++++++++++--
>  drivers/input/mouse/elan_i2c_smbus.c |   12 ++++++++++--
>  4 files changed, 54 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h
> index e100c1b..5ca846e 100644
> --- a/drivers/input/mouse/elan_i2c.h
> +++ b/drivers/input/mouse/elan_i2c.h
> @@ -1,4 +1,4 @@
> -/*
> +?/*
>   * Elan I2C/SMBus Touchpad driver
>   *
>   * Copyright (c) 2013 ELAN Microelectronics Corp.
> @@ -17,7 +17,7 @@
>   */
>  
>  #ifndef _ELAN_I2C_H
> -#define _ELAN_i2C_H
> +#define _ELAN_I2C_H
>  

This has already been fixed in my tree.

>  #include <linux/types.h>
>  
> @@ -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;
> diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
> index 4b970e2..6333ba6 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
> @@ -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);
> diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c
> index e29b28c..f5031b5 100644
> --- a/drivers/input/mouse/elan_i2c_i2c.c
> +++ b/drivers/input/mouse/elan_i2c_i2c.c
> @@ -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
> @@ -361,8 +362,28 @@ static int elan_i2c_get_num_traces(struct i2c_client *client,
>  		return error;
>  	}
>  
> -	*x_traces = val[0] - 1;
> -	*y_traces = val[1] - 1;
> +	*x_traces = val[0];
> +	*y_traces = val[1];

This change seems unrelated to the patch, please send separately if
needed.

> +
> +	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;
>  }
> @@ -599,6 +620,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,
> diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c
> index 5cd4a05..2b6516f 100644
> --- a/drivers/input/mouse/elan_i2c_smbus.c
> +++ b/drivers/input/mouse/elan_i2c_smbus.c
> @@ -268,12 +268,19 @@ static int elan_smbus_get_num_traces(struct i2c_client *client,
>  		return error;
>  	}
>  
> -	*x_traces = val[1] - 1;
> -	*y_traces = val[2] - 1;
> +	*x_traces = val[1];
> +	*y_traces = val[2];

This change seems unrelated to the patch, please send separately if
needed.

>  
>  	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,
> -- 

Applied (but dropped changes to the number of traces calculations).

Thank you.
Duson Lin April 12, 2015, 11:51 p.m. UTC | #2
Hi Dmitry,

OK! I will send another patch again. Thank you.

Duson

-----Original Message-----
From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com] 
Sent: Monday, April 13, 2015 7:15 AM
To: duson
Cc: linux-input@vger.kernel.org; linux-kernel@vger.kernel.org; ???
Subject: Re: [PATCH 4/4] Input: elan_i2c - Add pressure normalization

Hi Duson,

On Sat, Apr 11, 2015 at 07:01:00PM +0800, duson wrote:
> Get pressure format flag form firmware to check need to send 
> normalized pressure data to upper OS or not. The normalized data will 
> approximate the measure of area of the ideal metal weight. For 
> example, using the
> 8 mm metal weight touch the touchpad surface, the ideal value is 
> 4*4=16 (ignore the constent pi) and the pressure get from firmware will near 16.
> 
> Signed-off-by: Duson Lin <dusonlin@emc.com.tw>
> ---
>  drivers/input/mouse/elan_i2c.h       |    7 +++++--
>  drivers/input/mouse/elan_i2c_core.c  |   25 +++++++++++++++----------
>  drivers/input/mouse/elan_i2c_i2c.c   |   26 ++++++++++++++++++++++++--
>  drivers/input/mouse/elan_i2c_smbus.c |   12 ++++++++++--
>  4 files changed, 54 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/input/mouse/elan_i2c.h 
> b/drivers/input/mouse/elan_i2c.h index e100c1b..5ca846e 100644
> --- a/drivers/input/mouse/elan_i2c.h
> +++ b/drivers/input/mouse/elan_i2c.h
> @@ -1,4 +1,4 @@
> -/*
> +?/*
>   * Elan I2C/SMBus Touchpad driver
>   *
>   * Copyright (c) 2013 ELAN Microelectronics Corp.
> @@ -17,7 +17,7 @@
>   */
>  
>  #ifndef _ELAN_I2C_H
> -#define _ELAN_i2C_H
> +#define _ELAN_I2C_H
>  

This has already been fixed in my tree.

>  #include <linux/types.h>
>  
> @@ -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; 
> diff --git a/drivers/input/mouse/elan_i2c_core.c 
> b/drivers/input/mouse/elan_i2c_core.c
> index 4b970e2..6333ba6 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
> @@ -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); diff --git 
> a/drivers/input/mouse/elan_i2c_i2c.c 
> b/drivers/input/mouse/elan_i2c_i2c.c
> index e29b28c..f5031b5 100644
> --- a/drivers/input/mouse/elan_i2c_i2c.c
> +++ b/drivers/input/mouse/elan_i2c_i2c.c
> @@ -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
> @@ -361,8 +362,28 @@ static int elan_i2c_get_num_traces(struct i2c_client *client,
>  		return error;
>  	}
>  
> -	*x_traces = val[0] - 1;
> -	*y_traces = val[1] - 1;
> +	*x_traces = val[0];
> +	*y_traces = val[1];

This change seems unrelated to the patch, please send separately if needed.

> +
> +	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;
>  }
> @@ -599,6 +620,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,
> diff --git a/drivers/input/mouse/elan_i2c_smbus.c 
> b/drivers/input/mouse/elan_i2c_smbus.c
> index 5cd4a05..2b6516f 100644
> --- a/drivers/input/mouse/elan_i2c_smbus.c
> +++ b/drivers/input/mouse/elan_i2c_smbus.c
> @@ -268,12 +268,19 @@ static int elan_smbus_get_num_traces(struct i2c_client *client,
>  		return error;
>  	}
>  
> -	*x_traces = val[1] - 1;
> -	*y_traces = val[2] - 1;
> +	*x_traces = val[1];
> +	*y_traces = val[2];

This change seems unrelated to the patch, please send separately if needed.

>  
>  	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,
> --

Applied (but dropped changes to the number of traces calculations).

Thank you.

--
Dmitry

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h
index e100c1b..5ca846e 100644
--- a/drivers/input/mouse/elan_i2c.h
+++ b/drivers/input/mouse/elan_i2c.h
@@ -1,4 +1,4 @@ 
-/*
+?/*
  * Elan I2C/SMBus Touchpad driver
  *
  * Copyright (c) 2013 ELAN Microelectronics Corp.
@@ -17,7 +17,7 @@ 
  */
 
 #ifndef _ELAN_I2C_H
-#define _ELAN_i2C_H
+#define _ELAN_I2C_H
 
 #include <linux/types.h>
 
@@ -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;
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 4b970e2..6333ba6 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
@@ -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);
diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c
index e29b28c..f5031b5 100644
--- a/drivers/input/mouse/elan_i2c_i2c.c
+++ b/drivers/input/mouse/elan_i2c_i2c.c
@@ -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
@@ -361,8 +362,28 @@  static int elan_i2c_get_num_traces(struct i2c_client *client,
 		return error;
 	}
 
-	*x_traces = val[0] - 1;
-	*y_traces = val[1] - 1;
+	*x_traces = val[0];
+	*y_traces = val[1];
+
+	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;
 }
@@ -599,6 +620,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,
diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c
index 5cd4a05..2b6516f 100644
--- a/drivers/input/mouse/elan_i2c_smbus.c
+++ b/drivers/input/mouse/elan_i2c_smbus.c
@@ -268,12 +268,19 @@  static int elan_smbus_get_num_traces(struct i2c_client *client,
 		return error;
 	}
 
-	*x_traces = val[1] - 1;
-	*y_traces = val[2] - 1;
+	*x_traces = val[1];
+	*y_traces = val[2];
 
 	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,