提交 e7348396 编写于 作者: M Masaki Ota 提交者: Dmitry Torokhov

Input: ALPS - fix V8+ protocol handling (73 03 28)

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: aeaa881f ("Input: ALPS - set DualPoint flag for 74 03 28 devices")
Signed-off-by: NMasaki Ota <masaki.ota@jp.alps.com>
Acked-by: NPali Rohar <pali.rohar@gmail.com>
Tested-by: NPaul Donohue <linux-kernel@PaulSD.com>
Tested-by: NNick Fletcher <nick.m.fletcher@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: NDmitry Torokhov <dmitry.torokhov@gmail.com>
上级 92461f5d
...@@ -2462,14 +2462,34 @@ static int alps_update_device_area_ss4_v2(unsigned char otp[][4], ...@@ -2462,14 +2462,34 @@ static int alps_update_device_area_ss4_v2(unsigned char otp[][4],
int num_y_electrode; int num_y_electrode;
int x_pitch, y_pitch, x_phys, y_phys; int x_pitch, y_pitch, x_phys, y_phys;
num_x_electrode = SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F); if (IS_SS4PLUS_DEV(priv->dev_id)) {
num_y_electrode = SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F); 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->x_max =
priv->y_max = (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE; (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; x_pitch = (otp[0][1] & 0x0F) + SS4PLUS_MIN_PITCH_MM;
y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_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 */ 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 */ 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], ...@@ -2485,7 +2505,10 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
{ {
unsigned char is_btnless; 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) if (is_btnless)
priv->flags |= ALPS_BUTTONPAD; priv->flags |= ALPS_BUTTONPAD;
...@@ -2493,6 +2516,21 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4], ...@@ -2493,6 +2516,21 @@ static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
return 0; 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, static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
struct alps_data *priv) struct alps_data *priv)
{ {
...@@ -2508,6 +2546,8 @@ static int alps_set_defaults_ss4_v2(struct psmouse *psmouse, ...@@ -2508,6 +2546,8 @@ static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
alps_update_btn_info_ss4_v2(otp, priv); alps_update_btn_info_ss4_v2(otp, priv);
alps_update_dual_info_ss4_v2(otp, priv);
return 0; return 0;
} }
...@@ -2753,10 +2793,6 @@ static int alps_set_protocol(struct psmouse *psmouse, ...@@ -2753,10 +2793,6 @@ static int alps_set_protocol(struct psmouse *psmouse,
if (alps_set_defaults_ss4_v2(psmouse, priv)) if (alps_set_defaults_ss4_v2(psmouse, priv))
return -EIO; return -EIO;
if (priv->fw_ver[1] == 0x1)
priv->flags |= ALPS_DUALPOINT |
ALPS_DUALPOINT_WITH_PRESSURE;
break; break;
} }
...@@ -2827,10 +2863,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) ...@@ -2827,10 +2863,7 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
ec[2] >= 0x90 && ec[2] <= 0x9d) { ec[2] >= 0x90 && ec[2] <= 0x9d) {
protocol = &alps_v3_protocol_data; protocol = &alps_v3_protocol_data;
} else if (e7[0] == 0x73 && e7[1] == 0x03 && } else if (e7[0] == 0x73 && e7[1] == 0x03 &&
e7[2] == 0x14 && ec[1] == 0x02) { (e7[2] == 0x14 || e7[2] == 0x28)) {
protocol = &alps_v8_protocol_data;
} else if (e7[0] == 0x73 && e7[1] == 0x03 &&
e7[2] == 0x28 && ec[1] == 0x01) {
protocol = &alps_v8_protocol_data; protocol = &alps_v8_protocol_data;
} else { } else {
psmouse_dbg(psmouse, psmouse_dbg(psmouse,
...@@ -2840,7 +2873,8 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) ...@@ -2840,7 +2873,8 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
} }
if (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); memcpy(priv->fw_ver, ec, 3);
error = alps_set_protocol(psmouse, priv, protocol); error = alps_set_protocol(psmouse, priv, protocol);
if (error) if (error)
......
...@@ -54,6 +54,16 @@ enum SS4_PACKET_ID { ...@@ -54,6 +54,16 @@ enum SS4_PACKET_ID {
#define SS4_MASK_NORMAL_BUTTONS 0x07 #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) && \ #define SS4_IS_IDLE_V2(_b) (((_b[0]) == 0x18) && \
((_b[1]) == 0x10) && \ ((_b[1]) == 0x10) && \
((_b[2]) == 0x00) && \ ((_b[2]) == 0x00) && \
...@@ -283,6 +293,7 @@ struct alps_data { ...@@ -283,6 +293,7 @@ struct alps_data {
int addr_command; int addr_command;
u16 proto_version; u16 proto_version;
u8 byte0, mask0; u8 byte0, mask0;
u8 dev_id[3];
u8 fw_ver[3]; u8 fw_ver[3];
int flags; int flags;
int x_max; int x_max;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册