diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-07-09 15:32:56 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-07-09 15:33:35 -0400 |
commit | a66413fbc37994710d638aec3314f735a7ac0df5 (patch) | |
tree | 2c3608e65ce9090cbf83a8d8deaeb375e25e3207 /drivers/input/mouse | |
parent | 28d5fd860f97f017573c4cd8f199bab867c50a11 (diff) |
Input: synaptics - set minimum coordinates as reported by firmware
Newer Synaptics firmware allows to query minimum coordinates reported by
the device, let's use this data.
Acked-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r-- | drivers/input/mouse/synaptics.c | 56 | ||||
-rw-r--r-- | drivers/input/mouse/synaptics.h | 8 |
2 files changed, 43 insertions, 21 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 86bd89a28710..5538fc657af1 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -207,27 +207,37 @@ static int synaptics_identify(struct psmouse *psmouse) | |||
207 | static int synaptics_resolution(struct psmouse *psmouse) | 207 | static int synaptics_resolution(struct psmouse *psmouse) |
208 | { | 208 | { |
209 | struct synaptics_data *priv = psmouse->private; | 209 | struct synaptics_data *priv = psmouse->private; |
210 | unsigned char res[3]; | 210 | unsigned char resp[3]; |
211 | unsigned char max[3]; | ||
212 | 211 | ||
213 | if (SYN_ID_MAJOR(priv->identity) < 4) | 212 | if (SYN_ID_MAJOR(priv->identity) < 4) |
214 | return 0; | 213 | return 0; |
215 | 214 | ||
216 | if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, res) == 0) { | 215 | if (synaptics_send_cmd(psmouse, SYN_QUE_RESOLUTION, resp) == 0) { |
217 | if (res[0] != 0 && (res[1] & 0x80) && res[2] != 0) { | 216 | if (resp[0] != 0 && (resp[1] & 0x80) && resp[2] != 0) { |
218 | priv->x_res = res[0]; /* x resolution in units/mm */ | 217 | priv->x_res = resp[0]; /* x resolution in units/mm */ |
219 | priv->y_res = res[2]; /* y resolution in units/mm */ | 218 | priv->y_res = resp[2]; /* y resolution in units/mm */ |
220 | } | 219 | } |
221 | } | 220 | } |
222 | 221 | ||
223 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && | 222 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && |
224 | SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { | 223 | SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { |
225 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_DIMENSIONS, max)) { | 224 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { |
226 | printk(KERN_ERR "Synaptics claims to have dimensions query," | 225 | printk(KERN_ERR "Synaptics claims to have max coordinates" |
227 | " but I'm not able to read it.\n"); | 226 | " query, but I'm not able to read it.\n"); |
227 | } else { | ||
228 | priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); | ||
229 | priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); | ||
230 | } | ||
231 | } | ||
232 | |||
233 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 && | ||
234 | SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) { | ||
235 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) { | ||
236 | printk(KERN_ERR "Synaptics claims to have min coordinates" | ||
237 | " query, but I'm not able to read it.\n"); | ||
228 | } else { | 238 | } else { |
229 | priv->x_max = (max[0] << 5) | ((max[1] & 0x0f) << 1); | 239 | priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); |
230 | priv->y_max = (max[2] << 5) | ((max[1] & 0xf0) >> 3); | 240 | priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); |
231 | } | 241 | } |
232 | } | 242 | } |
233 | 243 | ||
@@ -693,19 +703,27 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
693 | __set_bit(INPUT_PROP_POINTER, dev->propbit); | 703 | __set_bit(INPUT_PROP_POINTER, dev->propbit); |
694 | 704 | ||
695 | __set_bit(EV_ABS, dev->evbit); | 705 | __set_bit(EV_ABS, dev->evbit); |
696 | input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, | 706 | input_set_abs_params(dev, ABS_X, |
697 | priv->x_max ?: XMAX_NOMINAL, fuzz, 0); | 707 | priv->x_min ?: XMIN_NOMINAL, |
698 | input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, | 708 | priv->x_max ?: XMAX_NOMINAL, |
699 | priv->y_max ?: YMAX_NOMINAL, fuzz, 0); | 709 | fuzz, 0); |
710 | input_set_abs_params(dev, ABS_Y, | ||
711 | priv->y_min ?: YMIN_NOMINAL, | ||
712 | priv->y_max ?: YMAX_NOMINAL, | ||
713 | fuzz, 0); | ||
700 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 714 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
701 | 715 | ||
702 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { | 716 | if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) { |
703 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | 717 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); |
704 | input_mt_init_slots(dev, 2); | 718 | input_mt_init_slots(dev, 2); |
705 | input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL, | 719 | input_set_abs_params(dev, ABS_MT_POSITION_X, |
706 | priv->x_max ?: XMAX_NOMINAL, fuzz, 0); | 720 | priv->x_min ?: XMIN_NOMINAL, |
707 | input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL, | 721 | priv->x_max ?: XMAX_NOMINAL, |
708 | priv->y_max ?: YMAX_NOMINAL, fuzz, 0); | 722 | fuzz, 0); |
723 | input_set_abs_params(dev, ABS_MT_POSITION_Y, | ||
724 | priv->y_min ?: YMIN_NOMINAL, | ||
725 | priv->y_max ?: YMAX_NOMINAL, | ||
726 | fuzz, 0); | ||
709 | 727 | ||
710 | input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res); | 728 | input_abs_set_res(dev, ABS_MT_POSITION_X, priv->x_res); |
711 | input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res); | 729 | input_abs_set_res(dev, ABS_MT_POSITION_Y, priv->y_res); |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index b8025b0ee2bd..a4394e1f12a2 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -19,7 +19,8 @@ | |||
19 | #define SYN_QUE_RESOLUTION 0x08 | 19 | #define SYN_QUE_RESOLUTION 0x08 |
20 | #define SYN_QUE_EXT_CAPAB 0x09 | 20 | #define SYN_QUE_EXT_CAPAB 0x09 |
21 | #define SYN_QUE_EXT_CAPAB_0C 0x0c | 21 | #define SYN_QUE_EXT_CAPAB_0C 0x0c |
22 | #define SYN_QUE_EXT_DIMENSIONS 0x0d | 22 | #define SYN_QUE_EXT_MAX_COORDS 0x0d |
23 | #define SYN_QUE_EXT_MIN_COORDS 0x0f | ||
23 | 24 | ||
24 | /* synatics modes */ | 25 | /* synatics modes */ |
25 | #define SYN_BIT_ABSOLUTE_MODE (1 << 7) | 26 | #define SYN_BIT_ABSOLUTE_MODE (1 << 7) |
@@ -73,10 +74,12 @@ | |||
73 | * 2 0x04 reduced filtering firmware does less filtering on | 74 | * 2 0x04 reduced filtering firmware does less filtering on |
74 | * position data, driver should watch | 75 | * position data, driver should watch |
75 | * for noise. | 76 | * for noise. |
77 | * 2 0x20 report min query 0x0f gives min coord reported | ||
76 | */ | 78 | */ |
77 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ | 79 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100000) /* 1-button ClickPad */ |
78 | #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ | 80 | #define SYN_CAP_CLICKPAD2BTN(ex0c) ((ex0c) & 0x000100) /* 2-button ClickPad */ |
79 | #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) | 81 | #define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000) |
82 | #define SYN_CAP_MIN_DIMENSIONS(ex0c) ((ex0c) & 0x000200) | ||
80 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) | 83 | #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) |
81 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) | 84 | #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) |
82 | 85 | ||
@@ -134,7 +137,8 @@ struct synaptics_data { | |||
134 | unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ | 137 | unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ |
135 | unsigned long int identity; /* Identification */ | 138 | unsigned long int identity; /* Identification */ |
136 | unsigned int x_res, y_res; /* X/Y resolution in units/mm */ | 139 | unsigned int x_res, y_res; /* X/Y resolution in units/mm */ |
137 | unsigned int x_max, y_max; /* Max dimensions (from FW) */ | 140 | unsigned int x_max, y_max; /* Max coordinates (from FW) */ |
141 | unsigned int x_min, y_min; /* Min coordinates (from FW) */ | ||
138 | 142 | ||
139 | unsigned char pkt_type; /* packet type - old, new, etc */ | 143 | unsigned char pkt_type; /* packet type - old, new, etc */ |
140 | unsigned char mode; /* current mode byte */ | 144 | unsigned char mode; /* current mode byte */ |