aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse
diff options
context:
space:
mode:
authorSoeren Sonnenburg <kernel@nn7.de>2007-07-20 00:29:32 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-07-20 00:29:32 -0400
commit5a6eb676d3bc4d7a6feab200a92437b62ad298da (patch)
treef4199c4161c046c43eb8ec96cd7fc09886dc044a /drivers/input/mouse
parente6b20d8d62d87451f41365945b27202d7dadaee6 (diff)
Input: appletouch - improve powersaving for Geyser3 devices
The appletouch geyser3 devices found in the Intel Macs (and possibly some later PPC ones?) send a constant stream of packets after the first touch. This results in the kernel waking up around once every couple of milliseconds to process them, making it almost impossible to spend any significant amount of time in C3 state on a dynamic HZ kernel. Sending the mode initialization code makes the device shut up until it's touched again. This patch does so after receiving 10 packets with no interesting content. Signed-off-by: Soeren Sonnenburg <kernel@nn7.de> Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r--drivers/input/mouse/appletouch.c111
1 files changed, 74 insertions, 37 deletions
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index e3215267db11..2bea1b2c631c 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -155,6 +155,8 @@ struct atp {
155 int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; 155 int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
156 int overflowwarn; /* overflow warning printed? */ 156 int overflowwarn; /* overflow warning printed? */
157 int datalen; /* size of an USB urb transfer */ 157 int datalen; /* size of an USB urb transfer */
158 int idlecount; /* number of empty packets */
159 struct work_struct work;
158}; 160};
159 161
160#define dbg_dump(msg, tab) \ 162#define dbg_dump(msg, tab) \
@@ -208,6 +210,55 @@ static inline int atp_is_geyser_3(struct atp *dev)
208 (productId == GEYSER4_JIS_PRODUCT_ID); 210 (productId == GEYSER4_JIS_PRODUCT_ID);
209} 211}
210 212
213/*
214 * By default Geyser 3 device sends standard USB HID mouse
215 * packets (Report ID 2). This code changes device mode, so it
216 * sends raw sensor reports (Report ID 5).
217 */
218static int atp_geyser3_init(struct usb_device *udev)
219{
220 char data[8];
221 int size;
222
223 size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
224 ATP_GEYSER3_MODE_READ_REQUEST_ID,
225 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
226 ATP_GEYSER3_MODE_REQUEST_VALUE,
227 ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
228
229 if (size != 8) {
230 err("Could not do mode read request from device"
231 " (Geyser 3 mode)");
232 return -EIO;
233 }
234
235 /* Apply the mode switch */
236 data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE;
237
238 size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
239 ATP_GEYSER3_MODE_WRITE_REQUEST_ID,
240 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
241 ATP_GEYSER3_MODE_REQUEST_VALUE,
242 ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
243
244 if (size != 8) {
245 err("Could not do mode write request to device"
246 " (Geyser 3 mode)");
247 return -EIO;
248 }
249 return 0;
250}
251
252/* Reinitialise the device if it's a geyser 3 */
253static void atp_reinit(struct work_struct *work)
254{
255 struct atp *dev = container_of(work, struct atp, work);
256 struct usb_device *udev = dev->udev;
257
258 dev->idlecount = 0;
259 atp_geyser3_init(udev);
260}
261
211static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, 262static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
212 int *z, int *fingers) 263 int *z, int *fingers)
213{ 264{
@@ -439,8 +490,8 @@ static void atp_complete(struct urb* urb)
439 } 490 }
440 dev->x_old = x; 491 dev->x_old = x;
441 dev->y_old = y; 492 dev->y_old = y;
442 } 493
443 else if (!x && !y) { 494 } else if (!x && !y) {
444 495
445 dev->x_old = dev->y_old = -1; 496 dev->x_old = dev->y_old = -1;
446 input_report_key(dev->input, BTN_TOUCH, 0); 497 input_report_key(dev->input, BTN_TOUCH, 0);
@@ -449,11 +500,21 @@ static void atp_complete(struct urb* urb)
449 500
450 /* reset the accumulator on release */ 501 /* reset the accumulator on release */
451 memset(dev->xy_acc, 0, sizeof(dev->xy_acc)); 502 memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
452 }
453 503
454 input_report_key(dev->input, BTN_LEFT, 504 /* Geyser 3 will continue to send packets continually after
455 !!dev->data[dev->datalen - 1]); 505 the first touch unless reinitialised. Do so if it's been
506 idle for a while in order to avoid waking the kernel up
507 several hundred times a second */
508 if (atp_is_geyser_3(dev)) {
509 dev->idlecount++;
510 if (dev->idlecount == 10) {
511 dev->valid = 0;
512 schedule_work(&dev->work);
513 }
514 }
515 }
456 516
517 input_report_key(dev->input, BTN_LEFT, dev->data[dev->datalen - 1] & 1);
457 input_sync(dev->input); 518 input_sync(dev->input);
458 519
459exit: 520exit:
@@ -480,6 +541,7 @@ static void atp_close(struct input_dev *input)
480 struct atp *dev = input_get_drvdata(input); 541 struct atp *dev = input_get_drvdata(input);
481 542
482 usb_kill_urb(dev->urb); 543 usb_kill_urb(dev->urb);
544 cancel_work_sync(&dev->work);
483 dev->open = 0; 545 dev->open = 0;
484} 546}
485 547
@@ -528,40 +590,10 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
528 dev->datalen = 81; 590 dev->datalen = 81;
529 591
530 if (atp_is_geyser_3(dev)) { 592 if (atp_is_geyser_3(dev)) {
531 /* 593 /* switch to raw sensor mode */
532 * By default Geyser 3 device sends standard USB HID mouse 594 if (atp_geyser3_init(udev))
533 * packets (Report ID 2). This code changes device mode, so it
534 * sends raw sensor reports (Report ID 5).
535 */
536 char data[8];
537 int size;
538
539 size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
540 ATP_GEYSER3_MODE_READ_REQUEST_ID,
541 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
542 ATP_GEYSER3_MODE_REQUEST_VALUE,
543 ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
544
545 if (size != 8) {
546 err("Could not do mode read request from device"
547 " (Geyser 3 mode)");
548 goto err_free_devs; 595 goto err_free_devs;
549 }
550
551 /* Apply the mode switch */
552 data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE;
553
554 size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
555 ATP_GEYSER3_MODE_WRITE_REQUEST_ID,
556 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
557 ATP_GEYSER3_MODE_REQUEST_VALUE,
558 ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
559 596
560 if (size != 8) {
561 err("Could not do mode write request to device"
562 " (Geyser 3 mode)");
563 goto err_free_devs;
564 }
565 printk("appletouch Geyser 3 inited.\n"); 597 printk("appletouch Geyser 3 inited.\n");
566 } 598 }
567 599
@@ -636,6 +668,8 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
636 /* save our data pointer in this interface device */ 668 /* save our data pointer in this interface device */
637 usb_set_intfdata(iface, dev); 669 usb_set_intfdata(iface, dev);
638 670
671 INIT_WORK(&dev->work, atp_reinit);
672
639 return 0; 673 return 0;
640 674
641 err_free_buffer: 675 err_free_buffer:
@@ -669,14 +703,17 @@ static void atp_disconnect(struct usb_interface *iface)
669static int atp_suspend(struct usb_interface *iface, pm_message_t message) 703static int atp_suspend(struct usb_interface *iface, pm_message_t message)
670{ 704{
671 struct atp *dev = usb_get_intfdata(iface); 705 struct atp *dev = usb_get_intfdata(iface);
706
672 usb_kill_urb(dev->urb); 707 usb_kill_urb(dev->urb);
673 dev->valid = 0; 708 dev->valid = 0;
709
674 return 0; 710 return 0;
675} 711}
676 712
677static int atp_resume(struct usb_interface *iface) 713static int atp_resume(struct usb_interface *iface)
678{ 714{
679 struct atp *dev = usb_get_intfdata(iface); 715 struct atp *dev = usb_get_intfdata(iface);
716
680 if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC)) 717 if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
681 return -EIO; 718 return -EIO;
682 719