diff options
Diffstat (limited to 'drivers/input')
28 files changed, 383 insertions, 115 deletions
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index ebf4be5b7c4e..2d175b5928ff 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -50,9 +50,8 @@ static LIST_HEAD(gameport_list); | |||
50 | 50 | ||
51 | static struct bus_type gameport_bus; | 51 | static struct bus_type gameport_bus; |
52 | 52 | ||
53 | static void gameport_add_driver(struct gameport_driver *drv); | ||
54 | static void gameport_add_port(struct gameport *gameport); | 53 | static void gameport_add_port(struct gameport *gameport); |
55 | static void gameport_destroy_port(struct gameport *gameport); | 54 | static void gameport_attach_driver(struct gameport_driver *drv); |
56 | static void gameport_reconnect_port(struct gameport *gameport); | 55 | static void gameport_reconnect_port(struct gameport *gameport); |
57 | static void gameport_disconnect_port(struct gameport *gameport); | 56 | static void gameport_disconnect_port(struct gameport *gameport); |
58 | 57 | ||
@@ -230,7 +229,6 @@ static void gameport_find_driver(struct gameport *gameport) | |||
230 | 229 | ||
231 | enum gameport_event_type { | 230 | enum gameport_event_type { |
232 | GAMEPORT_REGISTER_PORT, | 231 | GAMEPORT_REGISTER_PORT, |
233 | GAMEPORT_REGISTER_DRIVER, | ||
234 | GAMEPORT_ATTACH_DRIVER, | 232 | GAMEPORT_ATTACH_DRIVER, |
235 | }; | 233 | }; |
236 | 234 | ||
@@ -374,8 +372,8 @@ static void gameport_handle_event(void) | |||
374 | gameport_add_port(event->object); | 372 | gameport_add_port(event->object); |
375 | break; | 373 | break; |
376 | 374 | ||
377 | case GAMEPORT_REGISTER_DRIVER: | 375 | case GAMEPORT_ATTACH_DRIVER: |
378 | gameport_add_driver(event->object); | 376 | gameport_attach_driver(event->object); |
379 | break; | 377 | break; |
380 | 378 | ||
381 | default: | 379 | default: |
@@ -706,14 +704,14 @@ static int gameport_driver_remove(struct device *dev) | |||
706 | return 0; | 704 | return 0; |
707 | } | 705 | } |
708 | 706 | ||
709 | static void gameport_add_driver(struct gameport_driver *drv) | 707 | static void gameport_attach_driver(struct gameport_driver *drv) |
710 | { | 708 | { |
711 | int error; | 709 | int error; |
712 | 710 | ||
713 | error = driver_register(&drv->driver); | 711 | error = driver_attach(&drv->driver); |
714 | if (error) | 712 | if (error) |
715 | printk(KERN_ERR | 713 | printk(KERN_ERR |
716 | "gameport: driver_register() failed for %s, error: %d\n", | 714 | "gameport: driver_attach() failed for %s, error: %d\n", |
717 | drv->driver.name, error); | 715 | drv->driver.name, error); |
718 | } | 716 | } |
719 | 717 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index d44065d2e662..e54e002665b0 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -29,6 +29,23 @@ MODULE_LICENSE("GPL"); | |||
29 | 29 | ||
30 | #define INPUT_DEVICES 256 | 30 | #define INPUT_DEVICES 256 |
31 | 31 | ||
32 | /* | ||
33 | * EV_ABS events which should not be cached are listed here. | ||
34 | */ | ||
35 | static unsigned int input_abs_bypass_init_data[] __initdata = { | ||
36 | ABS_MT_TOUCH_MAJOR, | ||
37 | ABS_MT_TOUCH_MINOR, | ||
38 | ABS_MT_WIDTH_MAJOR, | ||
39 | ABS_MT_WIDTH_MINOR, | ||
40 | ABS_MT_ORIENTATION, | ||
41 | ABS_MT_POSITION_X, | ||
42 | ABS_MT_POSITION_Y, | ||
43 | ABS_MT_TOOL_TYPE, | ||
44 | ABS_MT_BLOB_ID, | ||
45 | 0 | ||
46 | }; | ||
47 | static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)]; | ||
48 | |||
32 | static LIST_HEAD(input_dev_list); | 49 | static LIST_HEAD(input_dev_list); |
33 | static LIST_HEAD(input_handler_list); | 50 | static LIST_HEAD(input_handler_list); |
34 | 51 | ||
@@ -161,6 +178,10 @@ static void input_handle_event(struct input_dev *dev, | |||
161 | disposition = INPUT_PASS_TO_HANDLERS; | 178 | disposition = INPUT_PASS_TO_HANDLERS; |
162 | } | 179 | } |
163 | break; | 180 | break; |
181 | case SYN_MT_REPORT: | ||
182 | dev->sync = 0; | ||
183 | disposition = INPUT_PASS_TO_HANDLERS; | ||
184 | break; | ||
164 | } | 185 | } |
165 | break; | 186 | break; |
166 | 187 | ||
@@ -192,6 +213,11 @@ static void input_handle_event(struct input_dev *dev, | |||
192 | case EV_ABS: | 213 | case EV_ABS: |
193 | if (is_event_supported(code, dev->absbit, ABS_MAX)) { | 214 | if (is_event_supported(code, dev->absbit, ABS_MAX)) { |
194 | 215 | ||
216 | if (test_bit(code, input_abs_bypass)) { | ||
217 | disposition = INPUT_PASS_TO_HANDLERS; | ||
218 | break; | ||
219 | } | ||
220 | |||
195 | value = input_defuzz_abs_event(value, | 221 | value = input_defuzz_abs_event(value, |
196 | dev->abs[code], dev->absfuzz[code]); | 222 | dev->abs[code], dev->absfuzz[code]); |
197 | 223 | ||
@@ -1549,7 +1575,6 @@ int input_register_handle(struct input_handle *handle) | |||
1549 | return error; | 1575 | return error; |
1550 | list_add_tail_rcu(&handle->d_node, &dev->h_list); | 1576 | list_add_tail_rcu(&handle->d_node, &dev->h_list); |
1551 | mutex_unlock(&dev->mutex); | 1577 | mutex_unlock(&dev->mutex); |
1552 | synchronize_rcu(); | ||
1553 | 1578 | ||
1554 | /* | 1579 | /* |
1555 | * Since we are supposed to be called from ->connect() | 1580 | * Since we are supposed to be called from ->connect() |
@@ -1635,10 +1660,20 @@ static const struct file_operations input_fops = { | |||
1635 | .open = input_open_file, | 1660 | .open = input_open_file, |
1636 | }; | 1661 | }; |
1637 | 1662 | ||
1663 | static void __init input_init_abs_bypass(void) | ||
1664 | { | ||
1665 | const unsigned int *p; | ||
1666 | |||
1667 | for (p = input_abs_bypass_init_data; *p; p++) | ||
1668 | input_abs_bypass[BIT_WORD(*p)] |= BIT_MASK(*p); | ||
1669 | } | ||
1670 | |||
1638 | static int __init input_init(void) | 1671 | static int __init input_init(void) |
1639 | { | 1672 | { |
1640 | int err; | 1673 | int err; |
1641 | 1674 | ||
1675 | input_init_abs_bypass(); | ||
1676 | |||
1642 | err = class_register(&input_class); | 1677 | err = class_register(&input_class); |
1643 | if (err) { | 1678 | if (err) { |
1644 | printk(KERN_ERR "input: unable to register input_dev class\n"); | 1679 | printk(KERN_ERR "input: unable to register input_dev class\n"); |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index f999dc60c3b8..444dec07e5d8 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -880,7 +880,7 @@ static unsigned int atkbd_hp_zv6100_forced_release_keys[] = { | |||
880 | }; | 880 | }; |
881 | 881 | ||
882 | /* | 882 | /* |
883 | * Samsung NC10 with Fn+F? key release not working | 883 | * Samsung NC10,NC20 with Fn+F? key release not working |
884 | */ | 884 | */ |
885 | static unsigned int atkbd_samsung_forced_release_keys[] = { | 885 | static unsigned int atkbd_samsung_forced_release_keys[] = { |
886 | 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U | 886 | 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U |
@@ -1534,6 +1534,24 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1534 | .driver_data = atkbd_samsung_forced_release_keys, | 1534 | .driver_data = atkbd_samsung_forced_release_keys, |
1535 | }, | 1535 | }, |
1536 | { | 1536 | { |
1537 | .ident = "Samsung NC20", | ||
1538 | .matches = { | ||
1539 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | ||
1540 | DMI_MATCH(DMI_PRODUCT_NAME, "NC20"), | ||
1541 | }, | ||
1542 | .callback = atkbd_setup_forced_release, | ||
1543 | .driver_data = atkbd_samsung_forced_release_keys, | ||
1544 | }, | ||
1545 | { | ||
1546 | .ident = "Samsung SQ45S70S", | ||
1547 | .matches = { | ||
1548 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | ||
1549 | DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"), | ||
1550 | }, | ||
1551 | .callback = atkbd_setup_forced_release, | ||
1552 | .driver_data = atkbd_samsung_forced_release_keys, | ||
1553 | }, | ||
1554 | { | ||
1537 | .ident = "Fujitsu Amilo PA 1510", | 1555 | .ident = "Fujitsu Amilo PA 1510", |
1538 | .matches = { | 1556 | .matches = { |
1539 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 1557 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index e94b7d735aca..d427f322e207 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -252,7 +252,7 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
252 | } | 252 | } |
253 | 253 | ||
254 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, | 254 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, |
255 | IRQF_SAMPLE_RANDOM, DRV_NAME, pdev); | 255 | 0, DRV_NAME, pdev); |
256 | if (error) { | 256 | if (error) { |
257 | printk(KERN_ERR DRV_NAME | 257 | printk(KERN_ERR DRV_NAME |
258 | ": unable to claim irq %d; error %d\n", | 258 | ": unable to claim irq %d; error %d\n", |
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 058fa8b02c21..87ec7b18ac69 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
@@ -100,8 +100,20 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id) | |||
100 | /* disable keyboard interrupt and schedule for handling */ | 100 | /* disable keyboard interrupt and schedule for handling */ |
101 | if (cpu_is_omap24xx()) { | 101 | if (cpu_is_omap24xx()) { |
102 | int i; | 102 | int i; |
103 | for (i = 0; i < omap_kp->rows; i++) | 103 | |
104 | disable_irq(gpio_to_irq(row_gpios[i])); | 104 | for (i = 0; i < omap_kp->rows; i++) { |
105 | int gpio_irq = gpio_to_irq(row_gpios[i]); | ||
106 | /* | ||
107 | * The interrupt which we're currently handling should | ||
108 | * be disabled _nosync() to avoid deadlocks waiting | ||
109 | * for this handler to complete. All others should | ||
110 | * be disabled the regular way for SMP safety. | ||
111 | */ | ||
112 | if (gpio_irq == irq) | ||
113 | disable_irq_nosync(gpio_irq); | ||
114 | else | ||
115 | disable_irq(gpio_irq); | ||
116 | } | ||
105 | } else | 117 | } else |
106 | /* disable keyboard interrupt and schedule for handling */ | 118 | /* disable keyboard interrupt and schedule for handling */ |
107 | omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 119 | omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 203abac1e23e..5c0a631d1455 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -214,7 +214,7 @@ config INPUT_SGI_BTNS | |||
214 | 214 | ||
215 | config HP_SDC_RTC | 215 | config HP_SDC_RTC |
216 | tristate "HP SDC Real Time Clock" | 216 | tristate "HP SDC Real Time Clock" |
217 | depends on GSC || HP300 | 217 | depends on (GSC || HP300) && SERIO |
218 | select HP_SDC | 218 | select HP_SDC |
219 | help | 219 | help |
220 | Say Y here if you want to support the built-in real time clock | 220 | Say Y here if you want to support the built-in real time clock |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index cbedf957cc58..daecc75c72e6 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #define ALPS_FW_BK_2 0x40 | 37 | #define ALPS_FW_BK_2 0x40 |
38 | 38 | ||
39 | static const struct alps_model_info alps_model_data[] = { | 39 | static const struct alps_model_info alps_model_data[] = { |
40 | { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ | ||
40 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ | 41 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ |
41 | { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, | 42 | { { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, |
42 | { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, | 43 | { { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, |
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 454b96112f03..e0140fdc02a5 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
@@ -255,15 +255,22 @@ MODULE_PARM_DESC(debug, "Activate debugging output"); | |||
255 | */ | 255 | */ |
256 | static int atp_geyser_init(struct usb_device *udev) | 256 | static int atp_geyser_init(struct usb_device *udev) |
257 | { | 257 | { |
258 | char data[8]; | 258 | char *data; |
259 | int size; | 259 | int size; |
260 | int i; | 260 | int i; |
261 | int ret; | ||
262 | |||
263 | data = kmalloc(8, GFP_KERNEL); | ||
264 | if (!data) { | ||
265 | err("Out of memory"); | ||
266 | return -ENOMEM; | ||
267 | } | ||
261 | 268 | ||
262 | size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | 269 | size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
263 | ATP_GEYSER_MODE_READ_REQUEST_ID, | 270 | ATP_GEYSER_MODE_READ_REQUEST_ID, |
264 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 271 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
265 | ATP_GEYSER_MODE_REQUEST_VALUE, | 272 | ATP_GEYSER_MODE_REQUEST_VALUE, |
266 | ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000); | 273 | ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000); |
267 | 274 | ||
268 | if (size != 8) { | 275 | if (size != 8) { |
269 | dprintk("atp_geyser_init: read error\n"); | 276 | dprintk("atp_geyser_init: read error\n"); |
@@ -271,7 +278,8 @@ static int atp_geyser_init(struct usb_device *udev) | |||
271 | dprintk("appletouch[%d]: %d\n", i, data[i]); | 278 | dprintk("appletouch[%d]: %d\n", i, data[i]); |
272 | 279 | ||
273 | err("Failed to read mode from device."); | 280 | err("Failed to read mode from device."); |
274 | return -EIO; | 281 | ret = -EIO; |
282 | goto out_free; | ||
275 | } | 283 | } |
276 | 284 | ||
277 | /* Apply the mode switch */ | 285 | /* Apply the mode switch */ |
@@ -281,7 +289,7 @@ static int atp_geyser_init(struct usb_device *udev) | |||
281 | ATP_GEYSER_MODE_WRITE_REQUEST_ID, | 289 | ATP_GEYSER_MODE_WRITE_REQUEST_ID, |
282 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 290 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
283 | ATP_GEYSER_MODE_REQUEST_VALUE, | 291 | ATP_GEYSER_MODE_REQUEST_VALUE, |
284 | ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000); | 292 | ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000); |
285 | 293 | ||
286 | if (size != 8) { | 294 | if (size != 8) { |
287 | dprintk("atp_geyser_init: write error\n"); | 295 | dprintk("atp_geyser_init: write error\n"); |
@@ -289,9 +297,13 @@ static int atp_geyser_init(struct usb_device *udev) | |||
289 | dprintk("appletouch[%d]: %d\n", i, data[i]); | 297 | dprintk("appletouch[%d]: %d\n", i, data[i]); |
290 | 298 | ||
291 | err("Failed to request geyser raw mode"); | 299 | err("Failed to request geyser raw mode"); |
292 | return -EIO; | 300 | ret = -EIO; |
301 | goto out_free; | ||
293 | } | 302 | } |
294 | return 0; | 303 | ret = 0; |
304 | out_free: | ||
305 | kfree(data); | ||
306 | return ret; | ||
295 | } | 307 | } |
296 | 308 | ||
297 | /* | 309 | /* |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2998a6ac9ae4..2d8fc0bf6923 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -51,6 +51,10 @@ | |||
51 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 | 51 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 |
52 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 | 52 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 |
53 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 | 53 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 |
54 | /* Macbook5,1 (unibody), aka wellspring3 */ | ||
55 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 | ||
56 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 | ||
57 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 | ||
54 | 58 | ||
55 | #define BCM5974_DEVICE(prod) { \ | 59 | #define BCM5974_DEVICE(prod) { \ |
56 | .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ | 60 | .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ |
@@ -72,6 +76,10 @@ static const struct usb_device_id bcm5974_table[] = { | |||
72 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI), | 76 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI), |
73 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO), | 77 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO), |
74 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), | 78 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), |
79 | /* Macbook5,1 */ | ||
80 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), | ||
81 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), | ||
82 | BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), | ||
75 | /* Terminating entry */ | 83 | /* Terminating entry */ |
76 | {} | 84 | {} |
77 | }; | 85 | }; |
@@ -96,14 +104,23 @@ struct bt_data { | |||
96 | u8 rel_y; /* relative y coordinate */ | 104 | u8 rel_y; /* relative y coordinate */ |
97 | }; | 105 | }; |
98 | 106 | ||
99 | /* trackpad header structure */ | 107 | /* trackpad header types */ |
100 | struct tp_header { | 108 | enum tp_type { |
101 | u8 unknown1[16]; /* constants, timers, etc */ | 109 | TYPE1, /* plain trackpad */ |
102 | u8 fingers; /* number of fingers on trackpad */ | 110 | TYPE2 /* button integrated in trackpad */ |
103 | u8 unknown2[9]; /* constants, timers, etc */ | ||
104 | }; | 111 | }; |
105 | 112 | ||
106 | /* trackpad finger structure */ | 113 | /* trackpad finger data offsets, le16-aligned */ |
114 | #define FINGER_TYPE1 (13 * sizeof(__le16)) | ||
115 | #define FINGER_TYPE2 (15 * sizeof(__le16)) | ||
116 | |||
117 | /* trackpad button data offsets */ | ||
118 | #define BUTTON_TYPE2 15 | ||
119 | |||
120 | /* list of device capability bits */ | ||
121 | #define HAS_INTEGRATED_BUTTON 1 | ||
122 | |||
123 | /* trackpad finger structure, le16-aligned */ | ||
107 | struct tp_finger { | 124 | struct tp_finger { |
108 | __le16 origin; /* zero when switching track finger */ | 125 | __le16 origin; /* zero when switching track finger */ |
109 | __le16 abs_x; /* absolute x coodinate */ | 126 | __le16 abs_x; /* absolute x coodinate */ |
@@ -117,13 +134,11 @@ struct tp_finger { | |||
117 | __le16 force_minor; /* trackpad force, minor axis? */ | 134 | __le16 force_minor; /* trackpad force, minor axis? */ |
118 | __le16 unused[3]; /* zeros */ | 135 | __le16 unused[3]; /* zeros */ |
119 | __le16 multi; /* one finger: varies, more fingers: constant */ | 136 | __le16 multi; /* one finger: varies, more fingers: constant */ |
120 | }; | 137 | } __attribute__((packed,aligned(2))); |
121 | 138 | ||
122 | /* trackpad data structure, empirically at least ten fingers */ | 139 | /* trackpad finger data size, empirically at least ten fingers */ |
123 | struct tp_data { | 140 | #define SIZEOF_FINGER sizeof(struct tp_finger) |
124 | struct tp_header header; | 141 | #define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) |
125 | struct tp_finger finger[16]; | ||
126 | }; | ||
127 | 142 | ||
128 | /* device-specific parameters */ | 143 | /* device-specific parameters */ |
129 | struct bcm5974_param { | 144 | struct bcm5974_param { |
@@ -136,9 +151,12 @@ struct bcm5974_param { | |||
136 | /* device-specific configuration */ | 151 | /* device-specific configuration */ |
137 | struct bcm5974_config { | 152 | struct bcm5974_config { |
138 | int ansi, iso, jis; /* the product id of this device */ | 153 | int ansi, iso, jis; /* the product id of this device */ |
154 | int caps; /* device capability bitmask */ | ||
139 | int bt_ep; /* the endpoint of the button interface */ | 155 | int bt_ep; /* the endpoint of the button interface */ |
140 | int bt_datalen; /* data length of the button interface */ | 156 | int bt_datalen; /* data length of the button interface */ |
141 | int tp_ep; /* the endpoint of the trackpad interface */ | 157 | int tp_ep; /* the endpoint of the trackpad interface */ |
158 | enum tp_type tp_type; /* type of trackpad interface */ | ||
159 | int tp_offset; /* offset to trackpad finger data */ | ||
142 | int tp_datalen; /* data length of the trackpad interface */ | 160 | int tp_datalen; /* data length of the trackpad interface */ |
143 | struct bcm5974_param p; /* finger pressure limits */ | 161 | struct bcm5974_param p; /* finger pressure limits */ |
144 | struct bcm5974_param w; /* finger width limits */ | 162 | struct bcm5974_param w; /* finger width limits */ |
@@ -158,7 +176,7 @@ struct bcm5974 { | |||
158 | struct urb *bt_urb; /* button usb request block */ | 176 | struct urb *bt_urb; /* button usb request block */ |
159 | struct bt_data *bt_data; /* button transferred data */ | 177 | struct bt_data *bt_data; /* button transferred data */ |
160 | struct urb *tp_urb; /* trackpad usb request block */ | 178 | struct urb *tp_urb; /* trackpad usb request block */ |
161 | struct tp_data *tp_data; /* trackpad transferred data */ | 179 | u8 *tp_data; /* trackpad transferred data */ |
162 | int fingers; /* number of fingers on trackpad */ | 180 | int fingers; /* number of fingers on trackpad */ |
163 | }; | 181 | }; |
164 | 182 | ||
@@ -183,8 +201,9 @@ static const struct bcm5974_config bcm5974_config_table[] = { | |||
183 | USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, | 201 | USB_DEVICE_ID_APPLE_WELLSPRING_ANSI, |
184 | USB_DEVICE_ID_APPLE_WELLSPRING_ISO, | 202 | USB_DEVICE_ID_APPLE_WELLSPRING_ISO, |
185 | USB_DEVICE_ID_APPLE_WELLSPRING_JIS, | 203 | USB_DEVICE_ID_APPLE_WELLSPRING_JIS, |
204 | 0, | ||
186 | 0x84, sizeof(struct bt_data), | 205 | 0x84, sizeof(struct bt_data), |
187 | 0x81, sizeof(struct tp_data), | 206 | 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, |
188 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, | 207 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, |
189 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | 208 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, |
190 | { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, | 209 | { DIM_X, DIM_X / SN_COORD, -4824, 5342 }, |
@@ -194,13 +213,26 @@ static const struct bcm5974_config bcm5974_config_table[] = { | |||
194 | USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, | 213 | USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI, |
195 | USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, | 214 | USB_DEVICE_ID_APPLE_WELLSPRING2_ISO, |
196 | USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, | 215 | USB_DEVICE_ID_APPLE_WELLSPRING2_JIS, |
216 | 0, | ||
197 | 0x84, sizeof(struct bt_data), | 217 | 0x84, sizeof(struct bt_data), |
198 | 0x81, sizeof(struct tp_data), | 218 | 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS, |
199 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, | 219 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 }, |
200 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | 220 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, |
201 | { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, | 221 | { DIM_X, DIM_X / SN_COORD, -4824, 4824 }, |
202 | { DIM_Y, DIM_Y / SN_COORD, -172, 4290 } | 222 | { DIM_Y, DIM_Y / SN_COORD, -172, 4290 } |
203 | }, | 223 | }, |
224 | { | ||
225 | USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI, | ||
226 | USB_DEVICE_ID_APPLE_WELLSPRING3_ISO, | ||
227 | USB_DEVICE_ID_APPLE_WELLSPRING3_JIS, | ||
228 | HAS_INTEGRATED_BUTTON, | ||
229 | 0x84, sizeof(struct bt_data), | ||
230 | 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, | ||
231 | { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, | ||
232 | { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, | ||
233 | { DIM_X, DIM_X / SN_COORD, -4460, 5166 }, | ||
234 | { DIM_Y, DIM_Y / SN_COORD, -75, 6700 } | ||
235 | }, | ||
204 | {} | 236 | {} |
205 | }; | 237 | }; |
206 | 238 | ||
@@ -257,6 +289,7 @@ static void setup_events_to_report(struct input_dev *input_dev, | |||
257 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | 289 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); |
258 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | 290 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); |
259 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | 291 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); |
292 | __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); | ||
260 | __set_bit(BTN_LEFT, input_dev->keybit); | 293 | __set_bit(BTN_LEFT, input_dev->keybit); |
261 | } | 294 | } |
262 | 295 | ||
@@ -266,6 +299,11 @@ static int report_bt_state(struct bcm5974 *dev, int size) | |||
266 | if (size != sizeof(struct bt_data)) | 299 | if (size != sizeof(struct bt_data)) |
267 | return -EIO; | 300 | return -EIO; |
268 | 301 | ||
302 | dprintk(7, | ||
303 | "bcm5974: button data: %x %x %x %x\n", | ||
304 | dev->bt_data->unknown1, dev->bt_data->button, | ||
305 | dev->bt_data->rel_x, dev->bt_data->rel_y); | ||
306 | |||
269 | input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); | 307 | input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); |
270 | input_sync(dev->input); | 308 | input_sync(dev->input); |
271 | 309 | ||
@@ -276,29 +314,37 @@ static int report_bt_state(struct bcm5974 *dev, int size) | |||
276 | static int report_tp_state(struct bcm5974 *dev, int size) | 314 | static int report_tp_state(struct bcm5974 *dev, int size) |
277 | { | 315 | { |
278 | const struct bcm5974_config *c = &dev->cfg; | 316 | const struct bcm5974_config *c = &dev->cfg; |
279 | const struct tp_finger *f = dev->tp_data->finger; | 317 | const struct tp_finger *f; |
280 | struct input_dev *input = dev->input; | 318 | struct input_dev *input = dev->input; |
281 | const int fingers = (size - 26) / 28; | 319 | int raw_p, raw_w, raw_x, raw_y, raw_n; |
282 | int raw_p, raw_w, raw_x, raw_y; | 320 | int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0; |
283 | int ptest = 0, origin = 0, nmin = 0, nmax = 0; | ||
284 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; | 321 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; |
285 | 322 | ||
286 | if (size < 26 || (size - 26) % 28 != 0) | 323 | if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) |
287 | return -EIO; | 324 | return -EIO; |
288 | 325 | ||
326 | /* finger data, le16-aligned */ | ||
327 | f = (const struct tp_finger *)(dev->tp_data + c->tp_offset); | ||
328 | raw_n = (size - c->tp_offset) / SIZEOF_FINGER; | ||
329 | |||
289 | /* always track the first finger; when detached, start over */ | 330 | /* always track the first finger; when detached, start over */ |
290 | if (fingers) { | 331 | if (raw_n) { |
291 | raw_p = raw2int(f->force_major); | 332 | raw_p = raw2int(f->force_major); |
292 | raw_w = raw2int(f->size_major); | 333 | raw_w = raw2int(f->size_major); |
293 | raw_x = raw2int(f->abs_x); | 334 | raw_x = raw2int(f->abs_x); |
294 | raw_y = raw2int(f->abs_y); | 335 | raw_y = raw2int(f->abs_y); |
295 | 336 | ||
296 | dprintk(9, | 337 | dprintk(9, |
297 | "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n", | 338 | "bcm5974: " |
298 | raw_p, raw_w, raw_x, raw_y); | 339 | "raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n", |
340 | raw_p, raw_w, raw_x, raw_y, raw_n); | ||
299 | 341 | ||
300 | ptest = int2bound(&c->p, raw_p); | 342 | ptest = int2bound(&c->p, raw_p); |
301 | origin = raw2int(f->origin); | 343 | origin = raw2int(f->origin); |
344 | |||
345 | /* set the integrated button if applicable */ | ||
346 | if (c->tp_type == TYPE2) | ||
347 | ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); | ||
302 | } | 348 | } |
303 | 349 | ||
304 | /* while tracking finger still valid, count all fingers */ | 350 | /* while tracking finger still valid, count all fingers */ |
@@ -307,12 +353,13 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
307 | abs_w = int2bound(&c->w, raw_w); | 353 | abs_w = int2bound(&c->w, raw_w); |
308 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); | 354 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); |
309 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); | 355 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); |
310 | for (; f != dev->tp_data->finger + fingers; f++) { | 356 | while (raw_n--) { |
311 | ptest = int2bound(&c->p, raw2int(f->force_major)); | 357 | ptest = int2bound(&c->p, raw2int(f->force_major)); |
312 | if (ptest > PRESSURE_LOW) | 358 | if (ptest > PRESSURE_LOW) |
313 | nmax++; | 359 | nmax++; |
314 | if (ptest > PRESSURE_HIGH) | 360 | if (ptest > PRESSURE_HIGH) |
315 | nmin++; | 361 | nmin++; |
362 | f++; | ||
316 | } | 363 | } |
317 | } | 364 | } |
318 | 365 | ||
@@ -324,7 +371,8 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
324 | input_report_key(input, BTN_TOUCH, dev->fingers > 0); | 371 | input_report_key(input, BTN_TOUCH, dev->fingers > 0); |
325 | input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); | 372 | input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1); |
326 | input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); | 373 | input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2); |
327 | input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2); | 374 | input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3); |
375 | input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3); | ||
328 | 376 | ||
329 | input_report_abs(input, ABS_PRESSURE, abs_p); | 377 | input_report_abs(input, ABS_PRESSURE, abs_p); |
330 | input_report_abs(input, ABS_TOOL_WIDTH, abs_w); | 378 | input_report_abs(input, ABS_TOOL_WIDTH, abs_w); |
@@ -335,11 +383,15 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
335 | 383 | ||
336 | dprintk(8, | 384 | dprintk(8, |
337 | "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " | 385 | "bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d " |
338 | "nmin: %d nmax: %d n: %d\n", | 386 | "nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w, |
339 | abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers); | 387 | abs_x, abs_y, nmin, nmax, dev->fingers, ibt); |
340 | 388 | ||
341 | } | 389 | } |
342 | 390 | ||
391 | /* type 2 reports button events via ibt only */ | ||
392 | if (c->tp_type == TYPE2) | ||
393 | input_report_key(input, BTN_LEFT, ibt); | ||
394 | |||
343 | input_sync(input); | 395 | input_sync(input); |
344 | 396 | ||
345 | return 0; | 397 | return 0; |
@@ -649,6 +701,8 @@ static int bcm5974_probe(struct usb_interface *iface, | |||
649 | input_dev->name = "bcm5974"; | 701 | input_dev->name = "bcm5974"; |
650 | input_dev->phys = dev->phys; | 702 | input_dev->phys = dev->phys; |
651 | usb_to_input_id(dev->udev, &input_dev->id); | 703 | usb_to_input_id(dev->udev, &input_dev->id); |
704 | /* report driver capabilities via the version field */ | ||
705 | input_dev->id.version = cfg->caps; | ||
652 | input_dev->dev.parent = &iface->dev; | 706 | input_dev->dev.parent = &iface->dev; |
653 | 707 | ||
654 | input_set_drvdata(input_dev, dev); | 708 | input_set_drvdata(input_dev, dev); |
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 6ab0eb1ada1c..4bc78892ba91 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Elantech Touchpad driver (v5) | 2 | * Elantech Touchpad driver (v6) |
3 | * | 3 | * |
4 | * Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net> | 4 | * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 as published | 7 | * under the terms of the GNU General Public License version 2 as published |
@@ -178,6 +178,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
178 | struct elantech_data *etd = psmouse->private; | 178 | struct elantech_data *etd = psmouse->private; |
179 | unsigned char *packet = psmouse->packet; | 179 | unsigned char *packet = psmouse->packet; |
180 | int fingers; | 180 | int fingers; |
181 | static int old_fingers; | ||
181 | 182 | ||
182 | if (etd->fw_version_maj == 0x01) { | 183 | if (etd->fw_version_maj == 0x01) { |
183 | /* byte 0: D U p1 p2 1 p3 R L | 184 | /* byte 0: D U p1 p2 1 p3 R L |
@@ -190,6 +191,14 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
190 | fingers = (packet[0] & 0xc0) >> 6; | 191 | fingers = (packet[0] & 0xc0) >> 6; |
191 | } | 192 | } |
192 | 193 | ||
194 | if (etd->jumpy_cursor) { | ||
195 | /* Discard packets that are likely to have bogus coordinates */ | ||
196 | if (fingers > old_fingers) { | ||
197 | elantech_debug("elantech.c: discarding packet\n"); | ||
198 | goto discard_packet_v1; | ||
199 | } | ||
200 | } | ||
201 | |||
193 | input_report_key(dev, BTN_TOUCH, fingers != 0); | 202 | input_report_key(dev, BTN_TOUCH, fingers != 0); |
194 | 203 | ||
195 | /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 | 204 | /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 |
@@ -216,6 +225,9 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
216 | } | 225 | } |
217 | 226 | ||
218 | input_sync(dev); | 227 | input_sync(dev); |
228 | |||
229 | discard_packet_v1: | ||
230 | old_fingers = fingers; | ||
219 | } | 231 | } |
220 | 232 | ||
221 | /* | 233 | /* |
@@ -363,9 +375,14 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) | |||
363 | rc = -1; | 375 | rc = -1; |
364 | break; | 376 | break; |
365 | } | 377 | } |
378 | } | ||
379 | |||
380 | if (rc == 0) { | ||
366 | /* | 381 | /* |
367 | * Read back reg 0x10. The touchpad is probably initalising | 382 | * Read back reg 0x10. For hardware version 1 we must make |
368 | * and not ready until we read back the value we just wrote. | 383 | * sure the absolute mode bit is set. For hardware version 2 |
384 | * the touchpad is probably initalising and not ready until | ||
385 | * we read back the value we just wrote. | ||
369 | */ | 386 | */ |
370 | do { | 387 | do { |
371 | rc = elantech_read_reg(psmouse, 0x10, &val); | 388 | rc = elantech_read_reg(psmouse, 0x10, &val); |
@@ -373,12 +390,18 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) | |||
373 | break; | 390 | break; |
374 | tries--; | 391 | tries--; |
375 | elantech_debug("elantech.c: retrying read (%d).\n", | 392 | elantech_debug("elantech.c: retrying read (%d).\n", |
376 | tries); | 393 | tries); |
377 | msleep(ETP_READ_BACK_DELAY); | 394 | msleep(ETP_READ_BACK_DELAY); |
378 | } while (tries > 0); | 395 | } while (tries > 0); |
379 | if (rc) | 396 | |
397 | if (rc) { | ||
380 | pr_err("elantech.c: failed to read back register 0x10.\n"); | 398 | pr_err("elantech.c: failed to read back register 0x10.\n"); |
381 | break; | 399 | } else if (etd->hw_version == 1 && |
400 | !(val & ETP_R10_ABSOLUTE_MODE)) { | ||
401 | pr_err("elantech.c: touchpad refuses " | ||
402 | "to switch to absolute mode.\n"); | ||
403 | rc = -1; | ||
404 | } | ||
382 | } | 405 | } |
383 | 406 | ||
384 | if (rc) | 407 | if (rc) |
@@ -662,6 +685,17 @@ int elantech_init(struct psmouse *psmouse) | |||
662 | param[0], param[1], param[2]); | 685 | param[0], param[1], param[2]); |
663 | etd->capabilities = param[0]; | 686 | etd->capabilities = param[0]; |
664 | 687 | ||
688 | /* | ||
689 | * This firmware seems to suffer from misreporting coordinates when | ||
690 | * a touch action starts causing the mouse cursor or scrolled page | ||
691 | * to jump. Enable a workaround. | ||
692 | */ | ||
693 | if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) { | ||
694 | pr_info("elantech.c: firmware version 2.34 detected, " | ||
695 | "enabling jumpy cursor workaround\n"); | ||
696 | etd->jumpy_cursor = 1; | ||
697 | } | ||
698 | |||
665 | if (elantech_set_absolute_mode(psmouse)) { | 699 | if (elantech_set_absolute_mode(psmouse)) { |
666 | pr_err("elantech.c: failed to put touchpad into absolute mode.\n"); | 700 | pr_err("elantech.c: failed to put touchpad into absolute mode.\n"); |
667 | goto init_fail; | 701 | goto init_fail; |
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index bee282b540bc..ed848cc80814 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Elantech Touchpad driver (v5) | 2 | * Elantech Touchpad driver (v6) |
3 | * | 3 | * |
4 | * Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net> | 4 | * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 as published | 7 | * under the terms of the GNU General Public License version 2 as published |
@@ -104,6 +104,7 @@ struct elantech_data { | |||
104 | unsigned char fw_version_min; | 104 | unsigned char fw_version_min; |
105 | unsigned char hw_version; | 105 | unsigned char hw_version; |
106 | unsigned char paritycheck; | 106 | unsigned char paritycheck; |
107 | unsigned char jumpy_cursor; | ||
107 | unsigned char parity[256]; | 108 | unsigned char parity[256]; |
108 | }; | 109 | }; |
109 | 110 | ||
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index df81b0aaa9f8..15ac3205ac05 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
@@ -61,6 +61,12 @@ static const struct dmi_system_id lifebook_dmi_table[] = { | |||
61 | }, | 61 | }, |
62 | }, | 62 | }, |
63 | { | 63 | { |
64 | .ident = "Lifebook B-2130", | ||
65 | .matches = { | ||
66 | DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"), | ||
67 | }, | ||
68 | }, | ||
69 | { | ||
64 | .ident = "Lifebook B213x/B2150", | 70 | .ident = "Lifebook B213x/B2150", |
65 | .matches = { | 71 | .matches = { |
66 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), | 72 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), |
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c index d196abfb68bc..5f278176eb9b 100644 --- a/drivers/input/mouse/maplemouse.c +++ b/drivers/input/mouse/maplemouse.c | |||
@@ -2,8 +2,8 @@ | |||
2 | * SEGA Dreamcast mouse driver | 2 | * SEGA Dreamcast mouse driver |
3 | * Based on drivers/usb/usbmouse.c | 3 | * Based on drivers/usb/usbmouse.c |
4 | * | 4 | * |
5 | * Copyright Yaegashi Takeshi, 2001 | 5 | * Copyright (c) Yaegashi Takeshi, 2001 |
6 | * Adrian McMenamin, 2008 | 6 | * Copyright (c) Adrian McMenamin, 2008 - 2009 |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
@@ -29,7 +29,7 @@ static void dc_mouse_callback(struct mapleq *mq) | |||
29 | struct maple_device *mapledev = mq->dev; | 29 | struct maple_device *mapledev = mq->dev; |
30 | struct dc_mouse *mse = maple_get_drvdata(mapledev); | 30 | struct dc_mouse *mse = maple_get_drvdata(mapledev); |
31 | struct input_dev *dev = mse->dev; | 31 | struct input_dev *dev = mse->dev; |
32 | unsigned char *res = mq->recvbuf; | 32 | unsigned char *res = mq->recvbuf->buf; |
33 | 33 | ||
34 | buttons = ~res[8]; | 34 | buttons = ~res[8]; |
35 | relx = *(unsigned short *)(res + 12) - 512; | 35 | relx = *(unsigned short *)(res + 12) - 512; |
@@ -47,7 +47,7 @@ static void dc_mouse_callback(struct mapleq *mq) | |||
47 | 47 | ||
48 | static int dc_mouse_open(struct input_dev *dev) | 48 | static int dc_mouse_open(struct input_dev *dev) |
49 | { | 49 | { |
50 | struct dc_mouse *mse = dev->dev.platform_data; | 50 | struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev)); |
51 | 51 | ||
52 | maple_getcond_callback(mse->mdev, dc_mouse_callback, HZ/50, | 52 | maple_getcond_callback(mse->mdev, dc_mouse_callback, HZ/50, |
53 | MAPLE_FUNC_MOUSE); | 53 | MAPLE_FUNC_MOUSE); |
@@ -57,29 +57,33 @@ static int dc_mouse_open(struct input_dev *dev) | |||
57 | 57 | ||
58 | static void dc_mouse_close(struct input_dev *dev) | 58 | static void dc_mouse_close(struct input_dev *dev) |
59 | { | 59 | { |
60 | struct dc_mouse *mse = dev->dev.platform_data; | 60 | struct dc_mouse *mse = maple_get_drvdata(to_maple_dev(&dev->dev)); |
61 | 61 | ||
62 | maple_getcond_callback(mse->mdev, dc_mouse_callback, 0, | 62 | maple_getcond_callback(mse->mdev, dc_mouse_callback, 0, |
63 | MAPLE_FUNC_MOUSE); | 63 | MAPLE_FUNC_MOUSE); |
64 | } | 64 | } |
65 | 65 | ||
66 | 66 | /* allow the mouse to be used */ | |
67 | static int __devinit probe_maple_mouse(struct device *dev) | 67 | static int __devinit probe_maple_mouse(struct device *dev) |
68 | { | 68 | { |
69 | struct maple_device *mdev = to_maple_dev(dev); | 69 | struct maple_device *mdev = to_maple_dev(dev); |
70 | struct maple_driver *mdrv = to_maple_driver(dev->driver); | 70 | struct maple_driver *mdrv = to_maple_driver(dev->driver); |
71 | int error; | ||
71 | struct input_dev *input_dev; | 72 | struct input_dev *input_dev; |
72 | struct dc_mouse *mse; | 73 | struct dc_mouse *mse; |
73 | int error; | ||
74 | 74 | ||
75 | mse = kzalloc(sizeof(struct dc_mouse), GFP_KERNEL); | 75 | mse = kzalloc(sizeof(struct dc_mouse), GFP_KERNEL); |
76 | input_dev = input_allocate_device(); | 76 | if (!mse) { |
77 | |||
78 | if (!mse || !input_dev) { | ||
79 | error = -ENOMEM; | 77 | error = -ENOMEM; |
80 | goto fail; | 78 | goto fail; |
81 | } | 79 | } |
82 | 80 | ||
81 | input_dev = input_allocate_device(); | ||
82 | if (!input_dev) { | ||
83 | error = -ENOMEM; | ||
84 | goto fail_nomem; | ||
85 | } | ||
86 | |||
83 | mse->dev = input_dev; | 87 | mse->dev = input_dev; |
84 | mse->mdev = mdev; | 88 | mse->mdev = mdev; |
85 | 89 | ||
@@ -89,25 +93,24 @@ static int __devinit probe_maple_mouse(struct device *dev) | |||
89 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); | 93 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); |
90 | input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | | 94 | input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | |
91 | BIT_MASK(REL_WHEEL); | 95 | BIT_MASK(REL_WHEEL); |
92 | input_dev->name = mdev->product_name; | ||
93 | input_dev->id.bustype = BUS_HOST; | ||
94 | input_dev->open = dc_mouse_open; | 96 | input_dev->open = dc_mouse_open; |
95 | input_dev->close = dc_mouse_close; | 97 | input_dev->close = dc_mouse_close; |
98 | input_dev->name = mdev->product_name; | ||
99 | input_dev->id.bustype = BUS_HOST; | ||
100 | error = input_register_device(input_dev); | ||
101 | if (error) | ||
102 | goto fail_register; | ||
96 | 103 | ||
97 | mdev->driver = mdrv; | 104 | mdev->driver = mdrv; |
98 | maple_set_drvdata(mdev, mse); | 105 | maple_set_drvdata(mdev, mse); |
99 | 106 | ||
100 | error = input_register_device(input_dev); | 107 | return error; |
101 | if (error) | ||
102 | goto fail; | ||
103 | |||
104 | return 0; | ||
105 | 108 | ||
106 | fail: | 109 | fail_register: |
107 | input_free_device(input_dev); | 110 | input_free_device(input_dev); |
108 | maple_set_drvdata(mdev, NULL); | 111 | fail_nomem: |
109 | kfree(mse); | 112 | kfree(mse); |
110 | mdev->driver = NULL; | 113 | fail: |
111 | return error; | 114 | return error; |
112 | } | 115 | } |
113 | 116 | ||
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index f63995f854ff..3941f97cfa60 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c | |||
@@ -108,7 +108,6 @@ static int pc110pad_open(struct input_dev *dev) | |||
108 | */ | 108 | */ |
109 | static int __init pc110pad_init(void) | 109 | static int __init pc110pad_init(void) |
110 | { | 110 | { |
111 | struct pci_dev *dev; | ||
112 | int err; | 111 | int err; |
113 | 112 | ||
114 | if (!no_pci_devices()) | 113 | if (!no_pci_devices()) |
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index bfe49243f38b..1c9410d1822c 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c | |||
@@ -819,6 +819,7 @@ static const struct parisc_device_id hp_sdc_tbl[] = { | |||
819 | MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl); | 819 | MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl); |
820 | 820 | ||
821 | static int __init hp_sdc_init_hppa(struct parisc_device *d); | 821 | static int __init hp_sdc_init_hppa(struct parisc_device *d); |
822 | static struct delayed_work moduleloader_work; | ||
822 | 823 | ||
823 | static struct parisc_driver hp_sdc_driver = { | 824 | static struct parisc_driver hp_sdc_driver = { |
824 | .name = "hp_sdc", | 825 | .name = "hp_sdc", |
@@ -930,8 +931,15 @@ static int __init hp_sdc_init(void) | |||
930 | 931 | ||
931 | #if defined(__hppa__) | 932 | #if defined(__hppa__) |
932 | 933 | ||
934 | static void request_module_delayed(struct work_struct *work) | ||
935 | { | ||
936 | request_module("hp_sdc_mlc"); | ||
937 | } | ||
938 | |||
933 | static int __init hp_sdc_init_hppa(struct parisc_device *d) | 939 | static int __init hp_sdc_init_hppa(struct parisc_device *d) |
934 | { | 940 | { |
941 | int ret; | ||
942 | |||
935 | if (!d) | 943 | if (!d) |
936 | return 1; | 944 | return 1; |
937 | if (hp_sdc.dev != NULL) | 945 | if (hp_sdc.dev != NULL) |
@@ -944,13 +952,26 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d) | |||
944 | hp_sdc.data_io = d->hpa.start + 0x800; | 952 | hp_sdc.data_io = d->hpa.start + 0x800; |
945 | hp_sdc.status_io = d->hpa.start + 0x801; | 953 | hp_sdc.status_io = d->hpa.start + 0x801; |
946 | 954 | ||
947 | return hp_sdc_init(); | 955 | INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed); |
956 | |||
957 | ret = hp_sdc_init(); | ||
958 | /* after sucessfull initialization give SDC some time to settle | ||
959 | * and then load the hp_sdc_mlc upper layer driver */ | ||
960 | if (!ret) | ||
961 | schedule_delayed_work(&moduleloader_work, | ||
962 | msecs_to_jiffies(2000)); | ||
963 | |||
964 | return ret; | ||
948 | } | 965 | } |
949 | 966 | ||
950 | #endif /* __hppa__ */ | 967 | #endif /* __hppa__ */ |
951 | 968 | ||
952 | static void hp_sdc_exit(void) | 969 | static void hp_sdc_exit(void) |
953 | { | 970 | { |
971 | /* do nothing if we don't have a SDC */ | ||
972 | if (!hp_sdc.dev) | ||
973 | return; | ||
974 | |||
954 | write_lock_irq(&hp_sdc.lock); | 975 | write_lock_irq(&hp_sdc.lock); |
955 | 976 | ||
956 | /* Turn off all maskable "sub-function" irq's. */ | 977 | /* Turn off all maskable "sub-function" irq's. */ |
@@ -969,6 +990,7 @@ static void hp_sdc_exit(void) | |||
969 | tasklet_kill(&hp_sdc.task); | 990 | tasklet_kill(&hp_sdc.task); |
970 | 991 | ||
971 | #if defined(__hppa__) | 992 | #if defined(__hppa__) |
993 | cancel_delayed_work_sync(&moduleloader_work); | ||
972 | if (unregister_parisc_driver(&hp_sdc_driver)) | 994 | if (unregister_parisc_driver(&hp_sdc_driver)) |
973 | printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); | 995 | printk(KERN_WARNING PREFIX "Error unregistering HP SDC"); |
974 | #endif | 996 | #endif |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 83ed2d56b924..fb8a3cd3ffd0 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -377,6 +377,24 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
377 | { } | 377 | { } |
378 | }; | 378 | }; |
379 | 379 | ||
380 | static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { | ||
381 | { | ||
382 | .ident = "MSI Wind U-100", | ||
383 | .matches = { | ||
384 | DMI_MATCH(DMI_BOARD_NAME, "U-100"), | ||
385 | DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), | ||
386 | }, | ||
387 | }, | ||
388 | { | ||
389 | .ident = "LG Electronics X110", | ||
390 | .matches = { | ||
391 | DMI_MATCH(DMI_BOARD_NAME, "X110"), | ||
392 | DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), | ||
393 | }, | ||
394 | }, | ||
395 | { } | ||
396 | }; | ||
397 | |||
380 | #ifdef CONFIG_PNP | 398 | #ifdef CONFIG_PNP |
381 | static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { | 399 | static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { |
382 | { | 400 | { |
@@ -386,6 +404,13 @@ static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { | |||
386 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), | 404 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), |
387 | }, | 405 | }, |
388 | }, | 406 | }, |
407 | { | ||
408 | .ident = "MSI Wind U-100", | ||
409 | .matches = { | ||
410 | DMI_MATCH(DMI_BOARD_NAME, "U-100"), | ||
411 | DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), | ||
412 | }, | ||
413 | }, | ||
389 | { } | 414 | { } |
390 | }; | 415 | }; |
391 | #endif | 416 | #endif |
@@ -698,6 +723,9 @@ static int __init i8042_platform_init(void) | |||
698 | #endif | 723 | #endif |
699 | 724 | ||
700 | #ifdef CONFIG_X86 | 725 | #ifdef CONFIG_X86 |
726 | if (dmi_check_system(i8042_dmi_reset_table)) | ||
727 | i8042_reset = 1; | ||
728 | |||
701 | if (dmi_check_system(i8042_dmi_noloop_table)) | 729 | if (dmi_check_system(i8042_dmi_noloop_table)) |
702 | i8042_noloop = 1; | 730 | i8042_noloop = 1; |
703 | 731 | ||
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 170f71ee5772..3cffb704e374 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -712,22 +712,43 @@ static int i8042_controller_check(void) | |||
712 | static int i8042_controller_selftest(void) | 712 | static int i8042_controller_selftest(void) |
713 | { | 713 | { |
714 | unsigned char param; | 714 | unsigned char param; |
715 | int i = 0; | ||
715 | 716 | ||
716 | if (!i8042_reset) | 717 | if (!i8042_reset) |
717 | return 0; | 718 | return 0; |
718 | 719 | ||
719 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { | 720 | /* |
720 | printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); | 721 | * We try this 5 times; on some really fragile systems this does not |
721 | return -ENODEV; | 722 | * take the first time... |
722 | } | 723 | */ |
724 | do { | ||
725 | |||
726 | if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { | ||
727 | printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n"); | ||
728 | return -ENODEV; | ||
729 | } | ||
730 | |||
731 | if (param == I8042_RET_CTL_TEST) | ||
732 | return 0; | ||
723 | 733 | ||
724 | if (param != I8042_RET_CTL_TEST) { | ||
725 | printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", | 734 | printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n", |
726 | param, I8042_RET_CTL_TEST); | 735 | param, I8042_RET_CTL_TEST); |
727 | return -EIO; | 736 | msleep(50); |
728 | } | 737 | } while (i++ < 5); |
729 | 738 | ||
739 | #ifdef CONFIG_X86 | ||
740 | /* | ||
741 | * On x86, we don't fail entire i8042 initialization if controller | ||
742 | * reset fails in hopes that keyboard port will still be functional | ||
743 | * and user will still get a working keyboard. This is especially | ||
744 | * important on netbooks. On other arches we trust hardware more. | ||
745 | */ | ||
746 | printk(KERN_INFO | ||
747 | "i8042: giving up on controller selftest, continuing anyway...\n"); | ||
730 | return 0; | 748 | return 0; |
749 | #else | ||
750 | return -EIO; | ||
751 | #endif | ||
731 | } | 752 | } |
732 | 753 | ||
733 | /* | 754 | /* |
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 57953c0eb82f..f412c69478a8 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c | |||
@@ -77,7 +77,7 @@ static irqreturn_t ps2_txint(int irq, void *dev_id) | |||
77 | spin_lock(&ps2if->lock); | 77 | spin_lock(&ps2if->lock); |
78 | status = sa1111_readl(ps2if->base + SA1111_PS2STAT); | 78 | status = sa1111_readl(ps2if->base + SA1111_PS2STAT); |
79 | if (ps2if->head == ps2if->tail) { | 79 | if (ps2if->head == ps2if->tail) { |
80 | disable_irq(irq); | 80 | disable_irq_nosync(irq); |
81 | /* done */ | 81 | /* done */ |
82 | } else if (status & PS2STAT_TXE) { | 82 | } else if (status & PS2STAT_TXE) { |
83 | sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA); | 83 | sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA); |
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 677680e9f54f..9710bfd49cf9 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
@@ -11,7 +11,7 @@ | |||
11 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> | 11 | * Copyright (c) 2000 Daniel Egger <egger@suse.de> |
12 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> | 12 | * Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com> |
13 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> | 13 | * Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be> |
14 | * Copyright (c) 2002-2008 Ping Cheng <pingc@wacom.com> | 14 | * Copyright (c) 2002-2009 Ping Cheng <pingc@wacom.com> |
15 | * | 15 | * |
16 | * ChangeLog: | 16 | * ChangeLog: |
17 | * v0.1 (vp) - Initial release | 17 | * v0.1 (vp) - Initial release |
@@ -67,6 +67,7 @@ | |||
67 | * v1.47 (pc) - Added support for Bamboo | 67 | * v1.47 (pc) - Added support for Bamboo |
68 | * v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX | 68 | * v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX |
69 | * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) | 69 | * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) |
70 | * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28 | ||
70 | */ | 71 | */ |
71 | 72 | ||
72 | /* | 73 | /* |
@@ -87,7 +88,7 @@ | |||
87 | /* | 88 | /* |
88 | * Version Information | 89 | * Version Information |
89 | */ | 90 | */ |
90 | #define DRIVER_VERSION "v1.49" | 91 | #define DRIVER_VERSION "v1.50" |
91 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | 92 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" |
92 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | 93 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" |
93 | #define DRIVER_LICENSE "GPL" | 94 | #define DRIVER_LICENSE "GPL" |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 484496daa0f3..b8624f27abf9 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -289,6 +289,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
289 | 5000); /* 5 secs */ | 289 | 5000); /* 5 secs */ |
290 | } while (result < 0 && limit++ < 5); | 290 | } while (result < 0 && limit++ < 5); |
291 | 291 | ||
292 | /* No need to parse the Descriptor. It isn't an error though */ | ||
292 | if (result < 0) | 293 | if (result < 0) |
293 | goto out; | 294 | goto out; |
294 | 295 | ||
@@ -368,9 +369,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
368 | } | 369 | } |
369 | } | 370 | } |
370 | 371 | ||
371 | result = 0; | ||
372 | |||
373 | out: | 372 | out: |
373 | result = 0; | ||
374 | kfree(report); | 374 | kfree(report); |
375 | return result; | 375 | return result; |
376 | } | 376 | } |
@@ -425,6 +425,15 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
425 | 425 | ||
426 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | 426 | endpoint = &intf->cur_altsetting->endpoint[0].desc; |
427 | 427 | ||
428 | /* Initialize touch_x_max and touch_y_max in case it is not defined */ | ||
429 | if (wacom_wac->features->type == TABLETPC) { | ||
430 | features->touch_x_max = 1023; | ||
431 | features->touch_y_max = 1023; | ||
432 | } else { | ||
433 | features->touch_x_max = 0; | ||
434 | features->touch_y_max = 0; | ||
435 | } | ||
436 | |||
428 | /* TabletPC need to retrieve the physical and logical maximum from report descriptor */ | 437 | /* TabletPC need to retrieve the physical and logical maximum from report descriptor */ |
429 | if (wacom_wac->features->type == TABLETPC) { | 438 | if (wacom_wac->features->type == TABLETPC) { |
430 | if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { | 439 | if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { |
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index e4728a28f492..ecaeb7e8e75e 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c | |||
@@ -736,8 +736,8 @@ static int __devinit ad7877_probe(struct spi_device *spi) | |||
736 | 736 | ||
737 | /* Request AD7877 /DAV GPIO interrupt */ | 737 | /* Request AD7877 /DAV GPIO interrupt */ |
738 | 738 | ||
739 | err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING | | 739 | err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING, |
740 | IRQF_SAMPLE_RANDOM, spi->dev.driver->name, ts); | 740 | spi->dev.driver->name, ts); |
741 | if (err) { | 741 | if (err) { |
742 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); | 742 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); |
743 | goto err_free_mem; | 743 | goto err_free_mem; |
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index ea4c61d68683..5d8a70398807 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c | |||
@@ -448,8 +448,7 @@ static int __devinit ad7879_construct(bus_device *bus, struct ad7879 *ts) | |||
448 | ad7879_setup(ts); | 448 | ad7879_setup(ts); |
449 | 449 | ||
450 | err = request_irq(bus->irq, ad7879_irq, | 450 | err = request_irq(bus->irq, ad7879_irq, |
451 | IRQF_TRIGGER_FALLING | IRQF_SAMPLE_RANDOM, | 451 | IRQF_TRIGGER_FALLING, bus->dev.driver->name, ts); |
452 | bus->dev.driver->name, ts); | ||
453 | 452 | ||
454 | if (err) { | 453 | if (err) { |
455 | dev_err(&bus->dev, "irq %d busy?\n", bus->irq); | 454 | dev_err(&bus->dev, "irq %d busy?\n", bus->irq); |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 056ac77e2cf0..2b01e56568f8 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -127,6 +127,8 @@ struct ads7846 { | |||
127 | void (*filter_cleanup)(void *data); | 127 | void (*filter_cleanup)(void *data); |
128 | int (*get_pendown_state)(void); | 128 | int (*get_pendown_state)(void); |
129 | int gpio_pendown; | 129 | int gpio_pendown; |
130 | |||
131 | void (*wait_for_sync)(void); | ||
130 | }; | 132 | }; |
131 | 133 | ||
132 | /* leave chip selected when we're done, for quicker re-select? */ | 134 | /* leave chip selected when we're done, for quicker re-select? */ |
@@ -511,6 +513,10 @@ static int get_pendown_state(struct ads7846 *ts) | |||
511 | return !gpio_get_value(ts->gpio_pendown); | 513 | return !gpio_get_value(ts->gpio_pendown); |
512 | } | 514 | } |
513 | 515 | ||
516 | static void null_wait_for_sync(void) | ||
517 | { | ||
518 | } | ||
519 | |||
514 | /* | 520 | /* |
515 | * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, | 521 | * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, |
516 | * to retrieve touchscreen status. | 522 | * to retrieve touchscreen status. |
@@ -686,6 +692,7 @@ static void ads7846_rx_val(void *ads) | |||
686 | default: | 692 | default: |
687 | BUG(); | 693 | BUG(); |
688 | } | 694 | } |
695 | ts->wait_for_sync(); | ||
689 | status = spi_async(ts->spi, m); | 696 | status = spi_async(ts->spi, m); |
690 | if (status) | 697 | if (status) |
691 | dev_err(&ts->spi->dev, "spi_async --> %d\n", | 698 | dev_err(&ts->spi->dev, "spi_async --> %d\n", |
@@ -723,6 +730,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) | |||
723 | } else { | 730 | } else { |
724 | /* pen is still down, continue with the measurement */ | 731 | /* pen is still down, continue with the measurement */ |
725 | ts->msg_idx = 0; | 732 | ts->msg_idx = 0; |
733 | ts->wait_for_sync(); | ||
726 | status = spi_async(ts->spi, &ts->msg[0]); | 734 | status = spi_async(ts->spi, &ts->msg[0]); |
727 | if (status) | 735 | if (status) |
728 | dev_err(&ts->spi->dev, "spi_async --> %d\n", status); | 736 | dev_err(&ts->spi->dev, "spi_async --> %d\n", status); |
@@ -746,7 +754,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle) | |||
746 | * that here. (The "generic irq" framework may help...) | 754 | * that here. (The "generic irq" framework may help...) |
747 | */ | 755 | */ |
748 | ts->irq_disabled = 1; | 756 | ts->irq_disabled = 1; |
749 | disable_irq(ts->spi->irq); | 757 | disable_irq_nosync(ts->spi->irq); |
750 | ts->pending = 1; | 758 | ts->pending = 1; |
751 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), | 759 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), |
752 | HRTIMER_MODE_REL); | 760 | HRTIMER_MODE_REL); |
@@ -947,6 +955,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
947 | ts->penirq_recheck_delay_usecs = | 955 | ts->penirq_recheck_delay_usecs = |
948 | pdata->penirq_recheck_delay_usecs; | 956 | pdata->penirq_recheck_delay_usecs; |
949 | 957 | ||
958 | ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; | ||
959 | |||
950 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); | 960 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); |
951 | 961 | ||
952 | input_dev->name = "ADS784x Touchscreen"; | 962 | input_dev->name = "ADS784x Touchscreen"; |
diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c index fa67d782c3c3..3ffd4c4b170c 100644 --- a/drivers/input/touchscreen/da9034-ts.c +++ b/drivers/input/touchscreen/da9034-ts.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2006-2008 Marvell International Ltd. | 4 | * Copyright (C) 2006-2008 Marvell International Ltd. |
5 | * Fengwei Yin <fengwei.yin@marvell.com> | 5 | * Fengwei Yin <fengwei.yin@marvell.com> |
6 | * Bin Yang <bin.yang@marvell.com> | ||
6 | * Eric Miao <eric.miao@marvell.com> | 7 | * Eric Miao <eric.miao@marvell.com> |
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
@@ -175,6 +176,16 @@ static void da9034_event_handler(struct da9034_touch *touch, int event) | |||
175 | goto err_reset; | 176 | goto err_reset; |
176 | 177 | ||
177 | touch->state = STATE_STOP; | 178 | touch->state = STATE_STOP; |
179 | |||
180 | /* FIXME: PEN_{UP/DOWN} events are expected to be | ||
181 | * available by stopping TSI, but this is found not | ||
182 | * always true, delay and simulate such an event | ||
183 | * here is more reliable | ||
184 | */ | ||
185 | mdelay(1); | ||
186 | da9034_event_handler(touch, | ||
187 | is_pen_down(touch) ? EVENT_PEN_DOWN : | ||
188 | EVENT_PEN_UP); | ||
178 | break; | 189 | break; |
179 | 190 | ||
180 | case STATE_STOP: | 191 | case STATE_STOP: |
@@ -189,8 +200,6 @@ static void da9034_event_handler(struct da9034_touch *touch, int event) | |||
189 | report_pen_up(touch); | 200 | report_pen_up(touch); |
190 | touch->state = STATE_IDLE; | 201 | touch->state = STATE_IDLE; |
191 | } | 202 | } |
192 | |||
193 | input_sync(touch->input_dev); | ||
194 | break; | 203 | break; |
195 | 204 | ||
196 | case STATE_WAIT: | 205 | case STATE_WAIT: |
@@ -200,8 +209,10 @@ static void da9034_event_handler(struct da9034_touch *touch, int event) | |||
200 | if (is_pen_down(touch)) { | 209 | if (is_pen_down(touch)) { |
201 | start_tsi(touch); | 210 | start_tsi(touch); |
202 | touch->state = STATE_BUSY; | 211 | touch->state = STATE_BUSY; |
203 | } else | 212 | } else { |
213 | report_pen_up(touch); | ||
204 | touch->state = STATE_IDLE; | 214 | touch->state = STATE_IDLE; |
215 | } | ||
205 | break; | 216 | break; |
206 | } | 217 | } |
207 | return; | 218 | return; |
@@ -226,16 +237,12 @@ static int da9034_touch_notifier(struct notifier_block *nb, | |||
226 | struct da9034_touch *touch = | 237 | struct da9034_touch *touch = |
227 | container_of(nb, struct da9034_touch, notifier); | 238 | container_of(nb, struct da9034_touch, notifier); |
228 | 239 | ||
229 | if (event & DA9034_EVENT_PEN_DOWN) { | ||
230 | if (is_pen_down(touch)) | ||
231 | da9034_event_handler(touch, EVENT_PEN_DOWN); | ||
232 | else | ||
233 | da9034_event_handler(touch, EVENT_PEN_UP); | ||
234 | } | ||
235 | |||
236 | if (event & DA9034_EVENT_TSI_READY) | 240 | if (event & DA9034_EVENT_TSI_READY) |
237 | da9034_event_handler(touch, EVENT_TSI_READY); | 241 | da9034_event_handler(touch, EVENT_TSI_READY); |
238 | 242 | ||
243 | if ((event & DA9034_EVENT_PEN_DOWN) && touch->state == STATE_IDLE) | ||
244 | da9034_event_handler(touch, EVENT_PEN_DOWN); | ||
245 | |||
239 | return 0; | 246 | return 0; |
240 | } | 247 | } |
241 | 248 | ||
@@ -385,6 +392,6 @@ static void __exit da9034_touch_exit(void) | |||
385 | module_exit(da9034_touch_exit); | 392 | module_exit(da9034_touch_exit); |
386 | 393 | ||
387 | MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9034"); | 394 | MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9034"); |
388 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); | 395 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>, Bin Yang <bin.yang@marvell.com>"); |
389 | MODULE_LICENSE("GPL"); | 396 | MODULE_LICENSE("GPL"); |
390 | MODULE_ALIAS("platform:da9034-touch"); | 397 | MODULE_ALIAS("platform:da9034-touch"); |
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index dfa6a84ab50a..4cc047a5116e 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c | |||
@@ -111,13 +111,12 @@ static void wm97xx_acc_pen_up(struct wm97xx *wm) | |||
111 | #else | 111 | #else |
112 | static void wm97xx_acc_pen_up(struct wm97xx *wm) | 112 | static void wm97xx_acc_pen_up(struct wm97xx *wm) |
113 | { | 113 | { |
114 | int count = 16; | 114 | unsigned int count; |
115 | |||
115 | schedule_timeout_uninterruptible(1); | 116 | schedule_timeout_uninterruptible(1); |
116 | 117 | ||
117 | while (count < 16) { | 118 | for (count = 0; count < 16; count++) |
118 | MODR; | 119 | MODR; |
119 | count--; | ||
120 | } | ||
121 | } | 120 | } |
122 | #endif | 121 | #endif |
123 | 122 | ||
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 4ab070246892..536668fbda22 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -235,7 +235,7 @@ static irqreturn_t tsc2007_irq(int irq, void *handle) | |||
235 | spin_lock_irqsave(&ts->lock, flags); | 235 | spin_lock_irqsave(&ts->lock, flags); |
236 | 236 | ||
237 | if (likely(ts->get_pendown_state())) { | 237 | if (likely(ts->get_pendown_state())) { |
238 | disable_irq(ts->irq); | 238 | disable_irq_nosync(ts->irq); |
239 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), | 239 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), |
240 | HRTIMER_MODE_REL); | 240 | HRTIMER_MODE_REL); |
241 | } | 241 | } |
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index e868264fe799..f100c7f4c1db 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
@@ -256,7 +256,7 @@ static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid) | |||
256 | struct ucb1400_ts *ucb = devid; | 256 | struct ucb1400_ts *ucb = devid; |
257 | 257 | ||
258 | if (irqnr == ucb->irq) { | 258 | if (irqnr == ucb->irq) { |
259 | disable_irq(ucb->irq); | 259 | disable_irq_nosync(ucb->irq); |
260 | ucb->irq_pending = 1; | 260 | ucb->irq_pending = 1; |
261 | wake_up(&ucb->ts_wait); | 261 | wake_up(&ucb->ts_wait); |
262 | return IRQ_HANDLED; | 262 | return IRQ_HANDLED; |
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index cec480bffe38..69af8385ab14 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
@@ -370,8 +370,7 @@ static int wm97xx_init_pen_irq(struct wm97xx *wm) | |||
370 | * provided. */ | 370 | * provided. */ |
371 | BUG_ON(!wm->mach_ops->irq_enable); | 371 | BUG_ON(!wm->mach_ops->irq_enable); |
372 | 372 | ||
373 | if (request_irq(wm->pen_irq, wm97xx_pen_interrupt, | 373 | if (request_irq(wm->pen_irq, wm97xx_pen_interrupt, IRQF_SHARED, |
374 | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | ||
375 | "wm97xx-pen", wm)) { | 374 | "wm97xx-pen", wm)) { |
376 | dev_err(wm->dev, | 375 | dev_err(wm->dev, |
377 | "Failed to register pen down interrupt, polling"); | 376 | "Failed to register pen down interrupt, polling"); |