aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorMasaki Ota <masaki.ota@jp.alps.com>2017-03-17 17:10:57 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-30 03:41:22 -0400
commit81643d000315229e5ff13cff943a69da9ab92a80 (patch)
treeeb5f77e5ab5c5a4ff933a38ffb28d59ebbbe7278 /drivers/input
parent9e13bcef24691b44c4de1257ba1ab6d2b8a43440 (diff)
Input: ALPS - fix V8+ protocol handling (73 03 28)
commit e7348396c6d51b57c95c6646c390cd078e038e19 upstream. Devices identified as E7="73 03 28" use slightly modified version of V8 protocol, with lower count per electrode, different offsets, and different feature bits in OTP data. Fixes: aeaa881f9b17 ("Input: ALPS - set DualPoint flag for 74 03 28 devices") Signed-off-by: Masaki Ota <masaki.ota@jp.alps.com> Acked-by: Pali Rohar <pali.rohar@gmail.com> Tested-by: Paul Donohue <linux-kernel@PaulSD.com> Tested-by: Nick Fletcher <nick.m.fletcher@gmail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/mouse/alps.c66
-rw-r--r--drivers/input/mouse/alps.h11
2 files changed, 61 insertions, 16 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index b93fe83a0b63..3101a84ec8b5 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -2461,14 +2461,34 @@ static int alps_update_device_area_ss4_v2(unsigned char otp[][4],
2461 int num_y_electrode; 2461 int num_y_electrode;
2462 int x_pitch, y_pitch, x_phys, y_phys; 2462 int x_pitch, y_pitch, x_phys, y_phys;
2463 2463
2464 num_x_electrode = SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F); 2464 if (IS_SS4PLUS_DEV(priv->dev_id)) {
2465 num_y_electrode = SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F); 2465 num_x_electrode =
2466 SS4PLUS_NUMSENSOR_XOFFSET + (otp[0][2] & 0x0F);
2467 num_y_electrode =
2468 SS4PLUS_NUMSENSOR_YOFFSET + ((otp[0][2] >> 4) & 0x0F);
2466 2469
2467 priv->x_max = (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE; 2470 priv->x_max =
2468 priv->y_max = (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE; 2471 (num_x_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
2472 priv->y_max =
2473 (num_y_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
2469 2474
2470 x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM; 2475 x_pitch = (otp[0][1] & 0x0F) + SS4PLUS_MIN_PITCH_MM;
2471 y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM; 2476 y_pitch = ((otp[0][1] >> 4) & 0x0F) + SS4PLUS_MIN_PITCH_MM;
2477
2478 } else {
2479 num_x_electrode =
2480 SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F);
2481 num_y_electrode =
2482 SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F);
2483
2484 priv->x_max =
2485 (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
2486 priv->y_max =
2487 (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
2488
2489 x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM;
2490 y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM;
2491 }
2472 2492
2473 x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */ 2493 x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */
2474 y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */ 2494 y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */
@@ -2484,7 +2504,10 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
2484{ 2504{
2485 unsigned char is_btnless; 2505 unsigned char is_btnless;
2486 2506
2487 is_btnless = (otp[1][1] >> 3) & 0x01; 2507 if (IS_SS4PLUS_DEV(priv->dev_id))
2508 is_btnless = (otp[1][0] >> 1) & 0x01;
2509 else
2510 is_btnless = (otp[1][1] >> 3) & 0x01;
2488 2511
2489 if (is_btnless) 2512 if (is_btnless)
2490 priv->flags |= ALPS_BUTTONPAD; 2513 priv->flags |= ALPS_BUTTONPAD;
@@ -2492,6 +2515,21 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
2492 return 0; 2515 return 0;
2493} 2516}
2494 2517
2518static int alps_update_dual_info_ss4_v2(unsigned char otp[][4],
2519 struct alps_data *priv)
2520{
2521 bool is_dual = false;
2522
2523 if (IS_SS4PLUS_DEV(priv->dev_id))
2524 is_dual = (otp[0][0] >> 4) & 0x01;
2525
2526 if (is_dual)
2527 priv->flags |= ALPS_DUALPOINT |
2528 ALPS_DUALPOINT_WITH_PRESSURE;
2529
2530 return 0;
2531}
2532
2495static int alps_set_defaults_ss4_v2(struct psmouse *psmouse, 2533static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
2496 struct alps_data *priv) 2534 struct alps_data *priv)
2497{ 2535{
@@ -2507,6 +2545,8 @@ static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
2507 2545
2508 alps_update_btn_info_ss4_v2(otp, priv); 2546 alps_update_btn_info_ss4_v2(otp, priv);
2509 2547
2548 alps_update_dual_info_ss4_v2(otp, priv);
2549
2510 return 0; 2550 return 0;
2511} 2551}
2512 2552
@@ -2752,10 +2792,6 @@ static int alps_set_protocol(struct psmouse *psmouse,
2752 if (alps_set_defaults_ss4_v2(psmouse, priv)) 2792 if (alps_set_defaults_ss4_v2(psmouse, priv))
2753 return -EIO; 2793 return -EIO;
2754 2794
2755 if (priv->fw_ver[1] == 0x1)
2756 priv->flags |= ALPS_DUALPOINT |
2757 ALPS_DUALPOINT_WITH_PRESSURE;
2758
2759 break; 2795 break;
2760 } 2796 }
2761 2797
@@ -2826,10 +2862,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
2826 ec[2] >= 0x90 && ec[2] <= 0x9d) { 2862 ec[2] >= 0x90 && ec[2] <= 0x9d) {
2827 protocol = &alps_v3_protocol_data; 2863 protocol = &alps_v3_protocol_data;
2828 } else if (e7[0] == 0x73 && e7[1] == 0x03 && 2864 } else if (e7[0] == 0x73 && e7[1] == 0x03 &&
2829 e7[2] == 0x14 && ec[1] == 0x02) { 2865 (e7[2] == 0x14 || e7[2] == 0x28)) {
2830 protocol = &alps_v8_protocol_data;
2831 } else if (e7[0] == 0x73 && e7[1] == 0x03 &&
2832 e7[2] == 0x28 && ec[1] == 0x01) {
2833 protocol = &alps_v8_protocol_data; 2866 protocol = &alps_v8_protocol_data;
2834 } else { 2867 } else {
2835 psmouse_dbg(psmouse, 2868 psmouse_dbg(psmouse,
@@ -2839,7 +2872,8 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
2839 } 2872 }
2840 2873
2841 if (priv) { 2874 if (priv) {
2842 /* Save the Firmware version */ 2875 /* Save Device ID and Firmware version */
2876 memcpy(priv->dev_id, e7, 3);
2843 memcpy(priv->fw_ver, ec, 3); 2877 memcpy(priv->fw_ver, ec, 3);
2844 error = alps_set_protocol(psmouse, priv, protocol); 2878 error = alps_set_protocol(psmouse, priv, protocol);
2845 if (error) 2879 if (error)
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index b9417e2d7ad3..dbfd26073e1a 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -54,6 +54,16 @@ enum SS4_PACKET_ID {
54 54
55#define SS4_MASK_NORMAL_BUTTONS 0x07 55#define SS4_MASK_NORMAL_BUTTONS 0x07
56 56
57#define SS4PLUS_COUNT_PER_ELECTRODE 128
58#define SS4PLUS_NUMSENSOR_XOFFSET 16
59#define SS4PLUS_NUMSENSOR_YOFFSET 5
60#define SS4PLUS_MIN_PITCH_MM 37
61
62#define IS_SS4PLUS_DEV(_b) (((_b[0]) == 0x73) && \
63 ((_b[1]) == 0x03) && \
64 ((_b[2]) == 0x28) \
65 )
66
57#define SS4_1F_X_V2(_b) ((_b[0] & 0x0007) | \ 67#define SS4_1F_X_V2(_b) ((_b[0] & 0x0007) | \
58 ((_b[1] << 3) & 0x0078) | \ 68 ((_b[1] << 3) & 0x0078) | \
59 ((_b[1] << 2) & 0x0380) | \ 69 ((_b[1] << 2) & 0x0380) | \
@@ -263,6 +273,7 @@ struct alps_data {
263 int addr_command; 273 int addr_command;
264 u16 proto_version; 274 u16 proto_version;
265 u8 byte0, mask0; 275 u8 byte0, mask0;
276 u8 dev_id[3];
266 u8 fw_ver[3]; 277 u8 fw_ver[3];
267 int flags; 278 int flags;
268 int x_max; 279 int x_max;