diff options
Diffstat (limited to 'drivers/input/mouse/elantech.c')
-rw-r--r-- | drivers/input/mouse/elantech.c | 80 |
1 files changed, 67 insertions, 13 deletions
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index e2a9867c19d5..d2c0db159b18 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -43,6 +43,24 @@ static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, | |||
43 | } | 43 | } |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * V3 and later support this fast command | ||
47 | */ | ||
48 | static int elantech_send_cmd(struct psmouse *psmouse, unsigned char c, | ||
49 | unsigned char *param) | ||
50 | { | ||
51 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
52 | |||
53 | if (ps2_command(ps2dev, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
54 | ps2_command(ps2dev, NULL, c) || | ||
55 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { | ||
56 | psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c); | ||
57 | return -1; | ||
58 | } | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | /* | ||
46 | * A retrying version of ps2_command | 64 | * A retrying version of ps2_command |
47 | */ | 65 | */ |
48 | static int elantech_ps2_command(struct psmouse *psmouse, | 66 | static int elantech_ps2_command(struct psmouse *psmouse, |
@@ -863,13 +881,13 @@ static int elantech_set_range(struct psmouse *psmouse, | |||
863 | i = (etd->fw_version > 0x020800 && | 881 | i = (etd->fw_version > 0x020800 && |
864 | etd->fw_version < 0x020900) ? 1 : 2; | 882 | etd->fw_version < 0x020900) ? 1 : 2; |
865 | 883 | ||
866 | if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) | 884 | if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) |
867 | return -1; | 885 | return -1; |
868 | 886 | ||
869 | fixed_dpi = param[1] & 0x10; | 887 | fixed_dpi = param[1] & 0x10; |
870 | 888 | ||
871 | if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) { | 889 | if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) { |
872 | if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param)) | 890 | if (etd->send_cmd(psmouse, ETP_SAMPLE_QUERY, param)) |
873 | return -1; | 891 | return -1; |
874 | 892 | ||
875 | *x_max = (etd->capabilities[1] - i) * param[1] / 2; | 893 | *x_max = (etd->capabilities[1] - i) * param[1] / 2; |
@@ -888,7 +906,7 @@ static int elantech_set_range(struct psmouse *psmouse, | |||
888 | break; | 906 | break; |
889 | 907 | ||
890 | case 3: | 908 | case 3: |
891 | if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) | 909 | if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) |
892 | return -1; | 910 | return -1; |
893 | 911 | ||
894 | *x_max = (0x0f & param[0]) << 8 | param[1]; | 912 | *x_max = (0x0f & param[0]) << 8 | param[1]; |
@@ -896,7 +914,7 @@ static int elantech_set_range(struct psmouse *psmouse, | |||
896 | break; | 914 | break; |
897 | 915 | ||
898 | case 4: | 916 | case 4: |
899 | if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) | 917 | if (etd->send_cmd(psmouse, ETP_FW_ID_QUERY, param)) |
900 | return -1; | 918 | return -1; |
901 | 919 | ||
902 | *x_max = (0x0f & param[0]) << 8 | param[1]; | 920 | *x_max = (0x0f & param[0]) << 8 | param[1]; |
@@ -913,6 +931,30 @@ static int elantech_set_range(struct psmouse *psmouse, | |||
913 | } | 931 | } |
914 | 932 | ||
915 | /* | 933 | /* |
934 | * (value from firmware) * 10 + 790 = dpi | ||
935 | * we also have to convert dpi to dots/mm (*10/254 to avoid floating point) | ||
936 | */ | ||
937 | static unsigned int elantech_convert_res(unsigned int val) | ||
938 | { | ||
939 | return (val * 10 + 790) * 10 / 254; | ||
940 | } | ||
941 | |||
942 | static int elantech_get_resolution_v4(struct psmouse *psmouse, | ||
943 | unsigned int *x_res, | ||
944 | unsigned int *y_res) | ||
945 | { | ||
946 | unsigned char param[3]; | ||
947 | |||
948 | if (elantech_send_cmd(psmouse, ETP_RESOLUTION_QUERY, param)) | ||
949 | return -1; | ||
950 | |||
951 | *x_res = elantech_convert_res(param[1] & 0x0f); | ||
952 | *y_res = elantech_convert_res((param[1] & 0xf0) >> 4); | ||
953 | |||
954 | return 0; | ||
955 | } | ||
956 | |||
957 | /* | ||
916 | * Set the appropriate event bits for the input subsystem | 958 | * Set the appropriate event bits for the input subsystem |
917 | */ | 959 | */ |
918 | static int elantech_set_input_params(struct psmouse *psmouse) | 960 | static int elantech_set_input_params(struct psmouse *psmouse) |
@@ -920,6 +962,7 @@ static int elantech_set_input_params(struct psmouse *psmouse) | |||
920 | struct input_dev *dev = psmouse->dev; | 962 | struct input_dev *dev = psmouse->dev; |
921 | struct elantech_data *etd = psmouse->private; | 963 | struct elantech_data *etd = psmouse->private; |
922 | unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; | 964 | unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; |
965 | unsigned int x_res = 0, y_res = 0; | ||
923 | 966 | ||
924 | if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) | 967 | if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) |
925 | return -1; | 968 | return -1; |
@@ -967,10 +1010,20 @@ static int elantech_set_input_params(struct psmouse *psmouse) | |||
967 | break; | 1010 | break; |
968 | 1011 | ||
969 | case 4: | 1012 | case 4: |
1013 | if (elantech_get_resolution_v4(psmouse, &x_res, &y_res)) { | ||
1014 | /* | ||
1015 | * if query failed, print a warning and leave the values | ||
1016 | * zero to resemble synaptics.c behavior. | ||
1017 | */ | ||
1018 | psmouse_warn(psmouse, "couldn't query resolution data.\n"); | ||
1019 | } | ||
1020 | |||
970 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 1021 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
971 | /* For X to recognize me as touchpad. */ | 1022 | /* For X to recognize me as touchpad. */ |
972 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); | 1023 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); |
973 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); | 1024 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); |
1025 | input_abs_set_res(dev, ABS_X, x_res); | ||
1026 | input_abs_set_res(dev, ABS_Y, y_res); | ||
974 | /* | 1027 | /* |
975 | * range of pressure and width is the same as v2, | 1028 | * range of pressure and width is the same as v2, |
976 | * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. | 1029 | * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. |
@@ -983,6 +1036,8 @@ static int elantech_set_input_params(struct psmouse *psmouse) | |||
983 | input_mt_init_slots(dev, ETP_MAX_FINGERS); | 1036 | input_mt_init_slots(dev, ETP_MAX_FINGERS); |
984 | input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); | 1037 | input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); |
985 | input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); | 1038 | input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); |
1039 | input_abs_set_res(dev, ABS_MT_POSITION_X, x_res); | ||
1040 | input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res); | ||
986 | input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, | 1041 | input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, |
987 | ETP_PMAX_V2, 0, 0); | 1042 | ETP_PMAX_V2, 0, 0); |
988 | /* | 1043 | /* |
@@ -1031,16 +1086,13 @@ static ssize_t elantech_set_int_attr(struct psmouse *psmouse, | |||
1031 | struct elantech_data *etd = psmouse->private; | 1086 | struct elantech_data *etd = psmouse->private; |
1032 | struct elantech_attr_data *attr = data; | 1087 | struct elantech_attr_data *attr = data; |
1033 | unsigned char *reg = (unsigned char *) etd + attr->field_offset; | 1088 | unsigned char *reg = (unsigned char *) etd + attr->field_offset; |
1034 | unsigned long value; | 1089 | unsigned char value; |
1035 | int err; | 1090 | int err; |
1036 | 1091 | ||
1037 | err = strict_strtoul(buf, 16, &value); | 1092 | err = kstrtou8(buf, 16, &value); |
1038 | if (err) | 1093 | if (err) |
1039 | return err; | 1094 | return err; |
1040 | 1095 | ||
1041 | if (value > 0xff) | ||
1042 | return -EINVAL; | ||
1043 | |||
1044 | /* Do we need to preserve some bits for version 2 hardware too? */ | 1096 | /* Do we need to preserve some bits for version 2 hardware too? */ |
1045 | if (etd->hw_version == 1) { | 1097 | if (etd->hw_version == 1) { |
1046 | if (attr->reg == 0x10) | 1098 | if (attr->reg == 0x10) |
@@ -1233,9 +1285,11 @@ static int elantech_set_properties(struct elantech_data *etd) | |||
1233 | } | 1285 | } |
1234 | } | 1286 | } |
1235 | 1287 | ||
1236 | /* | 1288 | /* decide which send_cmd we're gonna use early */ |
1237 | * Turn on packet checking by default. | 1289 | etd->send_cmd = etd->hw_version >= 3 ? elantech_send_cmd : |
1238 | */ | 1290 | synaptics_send_cmd; |
1291 | |||
1292 | /* Turn on packet checking by default */ | ||
1239 | etd->paritycheck = 1; | 1293 | etd->paritycheck = 1; |
1240 | 1294 | ||
1241 | /* | 1295 | /* |
@@ -1291,7 +1345,7 @@ int elantech_init(struct psmouse *psmouse) | |||
1291 | "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n", | 1345 | "assuming hardware version %d (with firmware version 0x%02x%02x%02x)\n", |
1292 | etd->hw_version, param[0], param[1], param[2]); | 1346 | etd->hw_version, param[0], param[1], param[2]); |
1293 | 1347 | ||
1294 | if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, | 1348 | if (etd->send_cmd(psmouse, ETP_CAPABILITIES_QUERY, |
1295 | etd->capabilities)) { | 1349 | etd->capabilities)) { |
1296 | psmouse_err(psmouse, "failed to query capabilities.\n"); | 1350 | psmouse_err(psmouse, "failed to query capabilities.\n"); |
1297 | goto init_fail; | 1351 | goto init_fail; |