[4/6] Input: elantech - High resolution report for new pattern 2
diff mbox series

Message ID 20191209034159.30394-1-dave.wang@emc.com.tw
State New
Headers show
Series
  • Untitled series #213357
Related show

Commit Message

Dave Wang Dec. 9, 2019, 3:41 a.m. UTC
From: "Dave.Wang" <dave.wang@emc.com.tw>

Due to the higher resolution touchpad is produced, the former
resolution bits were not enough. Extend the resolution bits
from 12 to 14 bits and also remove the mk value for new pattern 2.

Signed-off-by: Dave Wang <dave.wang@emc.com.tw>
---
 drivers/input/mouse/elantech.c | 66 +++++++++++++++++++++++++---------
 1 file changed, 49 insertions(+), 17 deletions(-)

Patch
diff mbox series

diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 322b181d00e9..53d7ff719d76 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -639,15 +639,21 @@  static void process_packet_head_v4(struct psmouse *psmouse)
 	struct elantech_data *etd = psmouse->private;
 	unsigned char *packet = psmouse->packet;
 	int id = ((packet[3] & 0xe0) >> 5) - 1;
-	int pres, traces;
+	int pres, traces = 0;
 
 	if (id < 0)
 		return;
 
-	etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2];
-	etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
-	pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
-	traces = (packet[0] & 0xf0) >> 4;
+	if (etd->info.pattern <= 0x01) {
+		etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2];
+		etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]);
+		pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4);
+		traces = (packet[0] & 0xf0) >> 4;
+	} else {
+		etd->mt[id].x = ((packet[1] & 0x3f) << 8) | packet[2];
+		etd->mt[id].y = etd->y_max - (((packet[4] & 0x3f) << 8) | packet[5]);
+		pres = (packet[4] & 0xc0) | ((packet[1] & 0xc0) >> 2) | ((packet[0] & 0xf0) >> 4);
+	}
 
 	input_mt_slot(dev, id);
 	input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
@@ -655,9 +661,11 @@  static void process_packet_head_v4(struct psmouse *psmouse)
 	input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
 	input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
 	input_report_abs(dev, ABS_MT_PRESSURE, pres);
-	input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width);
-	/* report this for backwards compatibility */
-	input_report_abs(dev, ABS_TOOL_WIDTH, traces);
+	if (etd->info.pattern <= 0x01) {
+		input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width);
+		/* report this for backwards compatibility */
+		input_report_abs(dev, ABS_TOOL_WIDTH, traces);
+	}
 
 	elantech_input_sync_v4(psmouse);
 }
@@ -1057,15 +1065,24 @@  static int elantech_set_absolute_mode(struct psmouse *psmouse)
 }
 
 /*
- * (value from firmware) * 10 + 790 = dpi
+ * pattern <= 0x01:
+ *	(value from firmware) * 10 + 790 = dpi
+ * else
+ *	((value from firmware) + 3) * 100 = dpi
+ *
  * we also have to convert dpi to dots/mm (*10/254 to avoid floating point)
  */
-static unsigned int elantech_convert_res(unsigned int val)
+static unsigned int elantech_convert_res(unsigned int val,
+					unsigned char pattern)
 {
-	return (val * 10 + 790) * 10 / 254;
+	if (pattern <= 0x01)
+		return (val * 10 + 790) * 10 / 254;
+	else
+		return ((val + 3) * 100) * 10 / 254;
 }
 
 static int elantech_get_resolution_v4(struct psmouse *psmouse,
+					  unsigned char pattern,
 				      unsigned int *x_res,
 				      unsigned int *y_res,
 				      unsigned int *bus)
@@ -1075,8 +1092,8 @@  static int elantech_get_resolution_v4(struct psmouse *psmouse,
 	if (elantech_send_cmd(psmouse, ETP_RESOLUTION_QUERY, param))
 		return -1;
 
-	*x_res = elantech_convert_res(param[1] & 0x0f);
-	*y_res = elantech_convert_res((param[1] & 0xf0) >> 4);
+	*x_res = elantech_convert_res(param[1] & 0x0f, pattern);
+	*y_res = elantech_convert_res((param[1] & 0xf0) >> 4, pattern);
 	*bus = param[2];
 
 	return 0;
@@ -1194,7 +1211,8 @@  static int elantech_set_input_params(struct psmouse *psmouse)
 		 */
 		input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2,
 				     ETP_PMAX_V2, 0, 0);
-		input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
+		if (etd->info.pattern <= 0x01)
+			input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
 				     ETP_WMAX_V2, 0, 0);
 		/* Multitouch capable pad, up to 5 fingers. */
 		input_mt_init_slots(dev, ETP_MAX_FINGERS, 0);
@@ -1206,7 +1224,8 @@  static int elantech_set_input_params(struct psmouse *psmouse)
 		 * The firmware reports how many trace lines the finger spans,
 		 * convert to surface unit as Protocol-B requires.
 		 */
-		input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0,
+		if (etd->info.pattern <= 0x01)
+			input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0,
 				     ETP_WMAX_V2 * width, 0, 0);
 		break;
 	}
@@ -1628,6 +1647,7 @@  static int elantech_query_info(struct psmouse *psmouse,
 {
 	unsigned char param[3];
 	unsigned char traces;
+	unsigned char y_max_l;
 
 	memset(info, 0, sizeof(*info));
 
@@ -1732,6 +1752,7 @@  static int elantech_query_info(struct psmouse *psmouse,
 	info->y_res = 31;
 	if (info->hw_version == 4) {
 		if (elantech_get_resolution_v4(psmouse,
+							info->pattern,
 					       &info->x_res,
 					       &info->y_res,
 					       &info->bus)) {
@@ -1800,8 +1821,19 @@  static int elantech_query_info(struct psmouse *psmouse,
 		if (info->send_cmd(psmouse, ETP_FW_ID_QUERY, param))
 			return -EINVAL;
 
-		info->x_max = (0x0f & param[0]) << 8 | param[1];
-		info->y_max = (0xf0 & param[0]) << 4 | param[2];
+		if (info->pattern <= 0x01) {
+			info->x_max = (0x0f & param[0]) << 8 | param[1];
+			info->y_max = (0xf0 & param[0]) << 4 | param[2];
+		} else {
+			info->x_max = (param[0] << 8) | param[1];
+			y_max_l = param[2];
+
+			if (info->send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
+				return -1;
+
+			info->y_max = param[2] << 8 | y_max_l;
+		}
+
 		traces = info->capabilities[1];
 		if ((traces < 2) || (traces > info->x_max))
 			return -EINVAL;