| From e7348396c6d51b57c95c6646c390cd078e038e19 Mon Sep 17 00:00:00 2001 |
| From: Masaki Ota <masaki.ota@jp.alps.com> |
| Date: Fri, 17 Mar 2017 14:10:57 -0700 |
| Subject: [PATCH] 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> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> |
| |
| diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c |
| index 72b28ebfe360..262d9b620fcf 100644 |
| --- a/drivers/input/mouse/alps.c |
| +++ b/drivers/input/mouse/alps.c |
| @@ -2462,14 +2462,34 @@ static int alps_update_device_area_ss4_v2(unsigned char otp[][4], |
| int num_y_electrode; |
| int x_pitch, y_pitch, x_phys, y_phys; |
| |
| - num_x_electrode = SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F); |
| - num_y_electrode = SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F); |
| + if (IS_SS4PLUS_DEV(priv->dev_id)) { |
| + num_x_electrode = |
| + SS4PLUS_NUMSENSOR_XOFFSET + (otp[0][2] & 0x0F); |
| + num_y_electrode = |
| + SS4PLUS_NUMSENSOR_YOFFSET + ((otp[0][2] >> 4) & 0x0F); |
| |
| - priv->x_max = (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE; |
| - priv->y_max = (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE; |
| + priv->x_max = |
| + (num_x_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE; |
| + priv->y_max = |
| + (num_y_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE; |
| |
| - x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM; |
| - y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM; |
| + x_pitch = (otp[0][1] & 0x0F) + SS4PLUS_MIN_PITCH_MM; |
| + y_pitch = ((otp[0][1] >> 4) & 0x0F) + SS4PLUS_MIN_PITCH_MM; |
| + |
| + } else { |
| + num_x_electrode = |
| + SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F); |
| + num_y_electrode = |
| + SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F); |
| + |
| + priv->x_max = |
| + (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE; |
| + priv->y_max = |
| + (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE; |
| + |
| + x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM; |
| + y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM; |
| + } |
| |
| x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */ |
| y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */ |
| @@ -2485,7 +2505,10 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4], |
| { |
| unsigned char is_btnless; |
| |
| - is_btnless = (otp[1][1] >> 3) & 0x01; |
| + if (IS_SS4PLUS_DEV(priv->dev_id)) |
| + is_btnless = (otp[1][0] >> 1) & 0x01; |
| + else |
| + is_btnless = (otp[1][1] >> 3) & 0x01; |
| |
| if (is_btnless) |
| priv->flags |= ALPS_BUTTONPAD; |
| @@ -2493,6 +2516,21 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4], |
| return 0; |
| } |
| |
| +static int alps_update_dual_info_ss4_v2(unsigned char otp[][4], |
| + struct alps_data *priv) |
| +{ |
| + bool is_dual = false; |
| + |
| + if (IS_SS4PLUS_DEV(priv->dev_id)) |
| + is_dual = (otp[0][0] >> 4) & 0x01; |
| + |
| + if (is_dual) |
| + priv->flags |= ALPS_DUALPOINT | |
| + ALPS_DUALPOINT_WITH_PRESSURE; |
| + |
| + return 0; |
| +} |
| + |
| static int alps_set_defaults_ss4_v2(struct psmouse *psmouse, |
| struct alps_data *priv) |
| { |
| @@ -2508,6 +2546,8 @@ static int alps_set_defaults_ss4_v2(struct psmouse *psmouse, |
| |
| alps_update_btn_info_ss4_v2(otp, priv); |
| |
| + alps_update_dual_info_ss4_v2(otp, priv); |
| + |
| return 0; |
| } |
| |
| @@ -2753,10 +2793,6 @@ static int alps_set_protocol(struct psmouse *psmouse, |
| if (alps_set_defaults_ss4_v2(psmouse, priv)) |
| return -EIO; |
| |
| - if (priv->fw_ver[1] == 0x1) |
| - priv->flags |= ALPS_DUALPOINT | |
| - ALPS_DUALPOINT_WITH_PRESSURE; |
| - |
| break; |
| } |
| |
| @@ -2827,10 +2863,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) |
| ec[2] >= 0x90 && ec[2] <= 0x9d) { |
| protocol = &alps_v3_protocol_data; |
| } else if (e7[0] == 0x73 && e7[1] == 0x03 && |
| - e7[2] == 0x14 && ec[1] == 0x02) { |
| - protocol = &alps_v8_protocol_data; |
| - } else if (e7[0] == 0x73 && e7[1] == 0x03 && |
| - e7[2] == 0x28 && ec[1] == 0x01) { |
| + (e7[2] == 0x14 || e7[2] == 0x28)) { |
| protocol = &alps_v8_protocol_data; |
| } else { |
| psmouse_dbg(psmouse, |
| @@ -2840,7 +2873,8 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) |
| } |
| |
| if (priv) { |
| - /* Save the Firmware version */ |
| + /* Save Device ID and Firmware version */ |
| + memcpy(priv->dev_id, e7, 3); |
| memcpy(priv->fw_ver, ec, 3); |
| error = alps_set_protocol(psmouse, priv, protocol); |
| if (error) |
| diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h |
| index 6d279aa27cb9..4334f2805d93 100644 |
| --- a/drivers/input/mouse/alps.h |
| +++ b/drivers/input/mouse/alps.h |
| @@ -54,6 +54,16 @@ enum SS4_PACKET_ID { |
| |
| #define SS4_MASK_NORMAL_BUTTONS 0x07 |
| |
| +#define SS4PLUS_COUNT_PER_ELECTRODE 128 |
| +#define SS4PLUS_NUMSENSOR_XOFFSET 16 |
| +#define SS4PLUS_NUMSENSOR_YOFFSET 5 |
| +#define SS4PLUS_MIN_PITCH_MM 37 |
| + |
| +#define IS_SS4PLUS_DEV(_b) (((_b[0]) == 0x73) && \ |
| + ((_b[1]) == 0x03) && \ |
| + ((_b[2]) == 0x28) \ |
| + ) |
| + |
| #define SS4_IS_IDLE_V2(_b) (((_b[0]) == 0x18) && \ |
| ((_b[1]) == 0x10) && \ |
| ((_b[2]) == 0x00) && \ |
| @@ -283,6 +293,7 @@ struct alps_data { |
| int addr_command; |
| u16 proto_version; |
| u8 byte0, mask0; |
| + u8 dev_id[3]; |
| u8 fw_ver[3]; |
| int flags; |
| int x_max; |
| -- |
| 2.12.0 |
| |