diff options
author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2009-09-22 19:49:27 -0400 |
---|---|---|
committer | Anton Vorontsov <avorontsov@ru.mvista.com> | 2009-09-22 19:49:27 -0400 |
commit | f056878332a91ed984a116bad4e7d49aefff9e6e (patch) | |
tree | 572f4757c8e7811d45e0be0c2ae529c78fb63441 /drivers/input | |
parent | 3961f7c3cf247eee5df7fabadc7a40f2deeb98f3 (diff) | |
parent | 7fa07729e439a6184bd824746d06a49cca553f15 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
drivers/power/wm97xx_battery.c
Diffstat (limited to 'drivers/input')
78 files changed, 6864 insertions, 1770 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 114efd8dc8f5..1148140d08a1 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -608,8 +608,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
608 | p, compat_mode); | 608 | p, compat_mode); |
609 | 609 | ||
610 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) | 610 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) |
611 | return str_to_user(dev_name(&evdev->dev), | 611 | return str_to_user(dev->name, _IOC_SIZE(cmd), p); |
612 | _IOC_SIZE(cmd), p); | ||
613 | 612 | ||
614 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) | 613 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) |
615 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); | 614 | return str_to_user(dev->phys, _IOC_SIZE(cmd), p); |
diff --git a/drivers/input/input.c b/drivers/input/input.c index 7c237e6ac711..556539d617a4 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -1144,7 +1144,7 @@ static struct attribute_group input_dev_caps_attr_group = { | |||
1144 | .attrs = input_dev_caps_attrs, | 1144 | .attrs = input_dev_caps_attrs, |
1145 | }; | 1145 | }; |
1146 | 1146 | ||
1147 | static struct attribute_group *input_dev_attr_groups[] = { | 1147 | static const struct attribute_group *input_dev_attr_groups[] = { |
1148 | &input_dev_attr_group, | 1148 | &input_dev_attr_group, |
1149 | &input_dev_id_attr_group, | 1149 | &input_dev_id_attr_group, |
1150 | &input_dev_caps_attr_group, | 1150 | &input_dev_caps_attr_group, |
@@ -1265,14 +1265,14 @@ static struct device_type input_dev_type = { | |||
1265 | .uevent = input_dev_uevent, | 1265 | .uevent = input_dev_uevent, |
1266 | }; | 1266 | }; |
1267 | 1267 | ||
1268 | static char *input_nodename(struct device *dev) | 1268 | static char *input_devnode(struct device *dev, mode_t *mode) |
1269 | { | 1269 | { |
1270 | return kasprintf(GFP_KERNEL, "input/%s", dev_name(dev)); | 1270 | return kasprintf(GFP_KERNEL, "input/%s", dev_name(dev)); |
1271 | } | 1271 | } |
1272 | 1272 | ||
1273 | struct class input_class = { | 1273 | struct class input_class = { |
1274 | .name = "input", | 1274 | .name = "input", |
1275 | .nodename = input_nodename, | 1275 | .devnode = input_devnode, |
1276 | }; | 1276 | }; |
1277 | EXPORT_SYMBOL_GPL(input_class); | 1277 | EXPORT_SYMBOL_GPL(input_class); |
1278 | 1278 | ||
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 0e12f89276a3..901b2525993e 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -452,12 +452,85 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) | |||
452 | (joydev->exist ? 0 : (POLLHUP | POLLERR)); | 452 | (joydev->exist ? 0 : (POLLHUP | POLLERR)); |
453 | } | 453 | } |
454 | 454 | ||
455 | static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev, | ||
456 | void __user *argp, size_t len) | ||
457 | { | ||
458 | __u8 *abspam; | ||
459 | int i; | ||
460 | int retval = 0; | ||
461 | |||
462 | len = min(len, sizeof(joydev->abspam)); | ||
463 | |||
464 | /* Validate the map. */ | ||
465 | abspam = kmalloc(len, GFP_KERNEL); | ||
466 | if (!abspam) | ||
467 | return -ENOMEM; | ||
468 | |||
469 | if (copy_from_user(abspam, argp, len)) { | ||
470 | retval = -EFAULT; | ||
471 | goto out; | ||
472 | } | ||
473 | |||
474 | for (i = 0; i < joydev->nabs; i++) { | ||
475 | if (abspam[i] > ABS_MAX) { | ||
476 | retval = -EINVAL; | ||
477 | goto out; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | memcpy(joydev->abspam, abspam, len); | ||
482 | |||
483 | out: | ||
484 | kfree(abspam); | ||
485 | return retval; | ||
486 | } | ||
487 | |||
488 | static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, | ||
489 | void __user *argp, size_t len) | ||
490 | { | ||
491 | __u16 *keypam; | ||
492 | int i; | ||
493 | int retval = 0; | ||
494 | |||
495 | len = min(len, sizeof(joydev->keypam)); | ||
496 | |||
497 | /* Validate the map. */ | ||
498 | keypam = kmalloc(len, GFP_KERNEL); | ||
499 | if (!keypam) | ||
500 | return -ENOMEM; | ||
501 | |||
502 | if (copy_from_user(keypam, argp, len)) { | ||
503 | retval = -EFAULT; | ||
504 | goto out; | ||
505 | } | ||
506 | |||
507 | for (i = 0; i < joydev->nkey; i++) { | ||
508 | if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) { | ||
509 | retval = -EINVAL; | ||
510 | goto out; | ||
511 | } | ||
512 | } | ||
513 | |||
514 | memcpy(joydev->keypam, keypam, len); | ||
515 | |||
516 | for (i = 0; i < joydev->nkey; i++) | ||
517 | joydev->keymap[keypam[i] - BTN_MISC] = i; | ||
518 | |||
519 | out: | ||
520 | kfree(keypam); | ||
521 | return retval; | ||
522 | } | ||
523 | |||
524 | |||
455 | static int joydev_ioctl_common(struct joydev *joydev, | 525 | static int joydev_ioctl_common(struct joydev *joydev, |
456 | unsigned int cmd, void __user *argp) | 526 | unsigned int cmd, void __user *argp) |
457 | { | 527 | { |
458 | struct input_dev *dev = joydev->handle.dev; | 528 | struct input_dev *dev = joydev->handle.dev; |
529 | size_t len; | ||
459 | int i, j; | 530 | int i, j; |
531 | const char *name; | ||
460 | 532 | ||
533 | /* Process fixed-sized commands. */ | ||
461 | switch (cmd) { | 534 | switch (cmd) { |
462 | 535 | ||
463 | case JS_SET_CAL: | 536 | case JS_SET_CAL: |
@@ -499,55 +572,38 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
499 | return copy_to_user(argp, joydev->corr, | 572 | return copy_to_user(argp, joydev->corr, |
500 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; | 573 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; |
501 | 574 | ||
502 | case JSIOCSAXMAP: | 575 | } |
503 | if (copy_from_user(joydev->abspam, argp, | ||
504 | sizeof(__u8) * (ABS_MAX + 1))) | ||
505 | return -EFAULT; | ||
506 | 576 | ||
507 | for (i = 0; i < joydev->nabs; i++) { | 577 | /* |
508 | if (joydev->abspam[i] > ABS_MAX) | 578 | * Process variable-sized commands (the axis and button map commands |
509 | return -EINVAL; | 579 | * are considered variable-sized to decouple them from the values of |
510 | joydev->absmap[joydev->abspam[i]] = i; | 580 | * ABS_MAX and KEY_MAX). |
511 | } | 581 | */ |
512 | return 0; | 582 | switch (cmd & ~IOCSIZE_MASK) { |
513 | 583 | ||
514 | case JSIOCGAXMAP: | 584 | case (JSIOCSAXMAP & ~IOCSIZE_MASK): |
515 | return copy_to_user(argp, joydev->abspam, | 585 | return joydev_handle_JSIOCSAXMAP(joydev, argp, _IOC_SIZE(cmd)); |
516 | sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; | ||
517 | 586 | ||
518 | case JSIOCSBTNMAP: | 587 | case (JSIOCGAXMAP & ~IOCSIZE_MASK): |
519 | if (copy_from_user(joydev->keypam, argp, | 588 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); |
520 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) | 589 | return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : len; |
521 | return -EFAULT; | ||
522 | 590 | ||
523 | for (i = 0; i < joydev->nkey; i++) { | 591 | case (JSIOCSBTNMAP & ~IOCSIZE_MASK): |
524 | if (joydev->keypam[i] > KEY_MAX || | 592 | return joydev_handle_JSIOCSBTNMAP(joydev, argp, _IOC_SIZE(cmd)); |
525 | joydev->keypam[i] < BTN_MISC) | ||
526 | return -EINVAL; | ||
527 | joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; | ||
528 | } | ||
529 | 593 | ||
530 | return 0; | 594 | case (JSIOCGBTNMAP & ~IOCSIZE_MASK): |
595 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); | ||
596 | return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : len; | ||
531 | 597 | ||
532 | case JSIOCGBTNMAP: | 598 | case JSIOCGNAME(0): |
533 | return copy_to_user(argp, joydev->keypam, | 599 | name = dev->name; |
534 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; | 600 | if (!name) |
601 | return 0; | ||
535 | 602 | ||
536 | default: | 603 | len = min_t(size_t, _IOC_SIZE(cmd), strlen(name) + 1); |
537 | if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { | 604 | return copy_to_user(argp, name, len) ? -EFAULT : len; |
538 | int len; | ||
539 | const char *name = dev_name(&dev->dev); | ||
540 | |||
541 | if (!name) | ||
542 | return 0; | ||
543 | len = strlen(name) + 1; | ||
544 | if (len > _IOC_SIZE(cmd)) | ||
545 | len = _IOC_SIZE(cmd); | ||
546 | if (copy_to_user(argp, name, len)) | ||
547 | return -EFAULT; | ||
548 | return len; | ||
549 | } | ||
550 | } | 605 | } |
606 | |||
551 | return -EINVAL; | 607 | return -EINVAL; |
552 | } | 608 | } |
553 | 609 | ||
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index baabf8302645..f6c688cae334 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c | |||
@@ -74,6 +74,7 @@ static struct iforce_device iforce_device[] = { | |||
74 | { 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_avb_wheel, abs_wheel, ff_iforce }, | 74 | { 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_avb_wheel, abs_wheel, ff_iforce }, |
75 | { 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_avb_tw, abs_wheel, ff_iforce }, //? | 75 | { 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_avb_tw, abs_wheel, ff_iforce }, //? |
76 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? | 76 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? |
77 | { 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, | ||
77 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? | 78 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? |
78 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? | 79 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? |
79 | { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? | 80 | { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? |
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index f83185aeb511..9f289d8f52c6 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c | |||
@@ -223,6 +223,7 @@ static struct usb_device_id iforce_usb_ids [] = { | |||
223 | { USB_DEVICE(0x05ef, 0x8884) }, /* AVB Mag Turbo Force */ | 223 | { USB_DEVICE(0x05ef, 0x8884) }, /* AVB Mag Turbo Force */ |
224 | { USB_DEVICE(0x05ef, 0x8888) }, /* AVB Top Shot FFB Racing Wheel */ | 224 | { USB_DEVICE(0x05ef, 0x8888) }, /* AVB Top Shot FFB Racing Wheel */ |
225 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ | 225 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ |
226 | { USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */ | ||
226 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ | 227 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ |
227 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ | 228 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ |
228 | { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ | 229 | { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index b868b8d5fbb3..2388cf578a62 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
@@ -144,6 +144,7 @@ static const struct xpad_device { | |||
144 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 144 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, |
145 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 145 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
146 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 146 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, |
147 | { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, | ||
147 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 148 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, |
148 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN } | 149 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN } |
149 | }; | 150 | }; |
@@ -208,6 +209,7 @@ static struct usb_device_id xpad_table [] = { | |||
208 | XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ | 209 | XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ |
209 | XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ | 210 | XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ |
210 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ | 211 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ |
212 | XPAD_XBOX360_VENDOR(0x1bad), /* Rock Band Drums */ | ||
211 | { } | 213 | { } |
212 | }; | 214 | }; |
213 | 215 | ||
@@ -470,20 +472,20 @@ static void xpad_irq_out(struct urb *urb) | |||
470 | status = urb->status; | 472 | status = urb->status; |
471 | 473 | ||
472 | switch (status) { | 474 | switch (status) { |
473 | case 0: | 475 | case 0: |
474 | /* success */ | 476 | /* success */ |
475 | break; | 477 | return; |
476 | case -ECONNRESET: | 478 | |
477 | case -ENOENT: | 479 | case -ECONNRESET: |
478 | case -ESHUTDOWN: | 480 | case -ENOENT: |
479 | /* this urb is terminated, clean up */ | 481 | case -ESHUTDOWN: |
480 | dbg("%s - urb shutting down with status: %d", | 482 | /* this urb is terminated, clean up */ |
481 | __func__, status); | 483 | dbg("%s - urb shutting down with status: %d", __func__, status); |
482 | return; | 484 | return; |
483 | default: | 485 | |
484 | dbg("%s - nonzero urb status received: %d", | 486 | default: |
485 | __func__, status); | 487 | dbg("%s - nonzero urb status received: %d", __func__, status); |
486 | goto exit; | 488 | goto exit; |
487 | } | 489 | } |
488 | 490 | ||
489 | exit: | 491 | exit: |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 9d8f796c6745..3525c19be428 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -12,6 +12,42 @@ menuconfig INPUT_KEYBOARD | |||
12 | 12 | ||
13 | if INPUT_KEYBOARD | 13 | if INPUT_KEYBOARD |
14 | 14 | ||
15 | config KEYBOARD_AAED2000 | ||
16 | tristate "AAED-2000 keyboard" | ||
17 | depends on MACH_AAED2000 | ||
18 | select INPUT_POLLDEV | ||
19 | default y | ||
20 | help | ||
21 | Say Y here to enable the keyboard on the Agilent AAED-2000 | ||
22 | development board. | ||
23 | |||
24 | To compile this driver as a module, choose M here: the | ||
25 | module will be called aaed2000_kbd. | ||
26 | |||
27 | config KEYBOARD_AMIGA | ||
28 | tristate "Amiga keyboard" | ||
29 | depends on AMIGA | ||
30 | help | ||
31 | Say Y here if you are running Linux on any AMIGA and have a keyboard | ||
32 | attached. | ||
33 | |||
34 | To compile this driver as a module, choose M here: the | ||
35 | module will be called amikbd. | ||
36 | |||
37 | config ATARI_KBD_CORE | ||
38 | bool | ||
39 | |||
40 | config KEYBOARD_ATARI | ||
41 | tristate "Atari keyboard" | ||
42 | depends on ATARI | ||
43 | select ATARI_KBD_CORE | ||
44 | help | ||
45 | Say Y here if you are running Linux on any Atari and have a keyboard | ||
46 | attached. | ||
47 | |||
48 | To compile this driver as a module, choose M here: the | ||
49 | module will be called atakbd. | ||
50 | |||
15 | config KEYBOARD_ATKBD | 51 | config KEYBOARD_ATKBD |
16 | tristate "AT keyboard" if EMBEDDED || !X86 | 52 | tristate "AT keyboard" if EMBEDDED || !X86 |
17 | default y | 53 | default y |
@@ -68,69 +104,14 @@ config KEYBOARD_ATKBD_RDI_KEYCODES | |||
68 | right-hand column will be interpreted as the key shown in the | 104 | right-hand column will be interpreted as the key shown in the |
69 | left-hand column. | 105 | left-hand column. |
70 | 106 | ||
71 | config KEYBOARD_SUNKBD | 107 | config KEYBOARD_BFIN |
72 | tristate "Sun Type 4 and Type 5 keyboard" | 108 | tristate "Blackfin BF54x keypad support" |
73 | select SERIO | 109 | depends on (BF54x && !BF544) |
74 | help | ||
75 | Say Y here if you want to use a Sun Type 4 or Type 5 keyboard, | ||
76 | connected either to the Sun keyboard connector or to an serial | ||
77 | (RS-232) port via a simple adapter. | ||
78 | |||
79 | To compile this driver as a module, choose M here: the | ||
80 | module will be called sunkbd. | ||
81 | |||
82 | config KEYBOARD_LKKBD | ||
83 | tristate "DECstation/VAXstation LK201/LK401 keyboard" | ||
84 | select SERIO | ||
85 | help | ||
86 | Say Y here if you want to use a LK201 or LK401 style serial | ||
87 | keyboard. This keyboard is also useable on PCs if you attach | ||
88 | it with the inputattach program. The connector pinout is | ||
89 | described within lkkbd.c. | ||
90 | |||
91 | To compile this driver as a module, choose M here: the | ||
92 | module will be called lkkbd. | ||
93 | |||
94 | config KEYBOARD_LOCOMO | ||
95 | tristate "LoCoMo Keyboard Support" | ||
96 | depends on SHARP_LOCOMO && INPUT_KEYBOARD | ||
97 | help | ||
98 | Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA | ||
99 | |||
100 | To compile this driver as a module, choose M here: the | ||
101 | module will be called locomokbd. | ||
102 | |||
103 | config KEYBOARD_XTKBD | ||
104 | tristate "XT keyboard" | ||
105 | select SERIO | ||
106 | help | ||
107 | Say Y here if you want to use the old IBM PC/XT keyboard (or | ||
108 | compatible) on your system. This is only possible with a | ||
109 | parallel port keyboard adapter, you cannot connect it to the | ||
110 | keyboard port on a PC that runs Linux. | ||
111 | |||
112 | To compile this driver as a module, choose M here: the | ||
113 | module will be called xtkbd. | ||
114 | |||
115 | config KEYBOARD_NEWTON | ||
116 | tristate "Newton keyboard" | ||
117 | select SERIO | ||
118 | help | ||
119 | Say Y here if you have a Newton keyboard on a serial port. | ||
120 | |||
121 | To compile this driver as a module, choose M here: the | ||
122 | module will be called newtonkbd. | ||
123 | |||
124 | config KEYBOARD_STOWAWAY | ||
125 | tristate "Stowaway keyboard" | ||
126 | select SERIO | ||
127 | help | 110 | help |
128 | Say Y here if you have a Stowaway keyboard on a serial port. | 111 | Say Y here if you want to use the BF54x keypad. |
129 | Stowaway compatible keyboards like Dicota Input-PDA keyboard | ||
130 | are also supported by this driver. | ||
131 | 112 | ||
132 | To compile this driver as a module, choose M here: the | 113 | To compile this driver as a module, choose M here: the |
133 | module will be called stowaway. | 114 | module will be called bf54x-keys. |
134 | 115 | ||
135 | config KEYBOARD_CORGI | 116 | config KEYBOARD_CORGI |
136 | tristate "Corgi keyboard" | 117 | tristate "Corgi keyboard" |
@@ -143,61 +124,50 @@ config KEYBOARD_CORGI | |||
143 | To compile this driver as a module, choose M here: the | 124 | To compile this driver as a module, choose M here: the |
144 | module will be called corgikbd. | 125 | module will be called corgikbd. |
145 | 126 | ||
146 | config KEYBOARD_SPITZ | 127 | config KEYBOARD_LKKBD |
147 | tristate "Spitz keyboard" | 128 | tristate "DECstation/VAXstation LK201/LK401 keyboard" |
148 | depends on PXA_SHARPSL | 129 | select SERIO |
149 | default y | ||
150 | help | 130 | help |
151 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, | 131 | Say Y here if you want to use a LK201 or LK401 style serial |
152 | SL-C3000 and Sl-C3100 series of PDAs. | 132 | keyboard. This keyboard is also useable on PCs if you attach |
133 | it with the inputattach program. The connector pinout is | ||
134 | described within lkkbd.c. | ||
153 | 135 | ||
154 | To compile this driver as a module, choose M here: the | 136 | To compile this driver as a module, choose M here: the |
155 | module will be called spitzkbd. | 137 | module will be called lkkbd. |
156 | 138 | ||
157 | config KEYBOARD_TOSA | 139 | config KEYBOARD_EP93XX |
158 | tristate "Tosa keyboard" | 140 | tristate "EP93xx Matrix Keypad support" |
159 | depends on MACH_TOSA | 141 | depends on ARCH_EP93XX |
160 | default y | ||
161 | help | 142 | help |
162 | Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) | 143 | Say Y here to enable the matrix keypad on the Cirrus EP93XX. |
163 | 144 | ||
164 | To compile this driver as a module, choose M here: the | 145 | To compile this driver as a module, choose M here: the |
165 | module will be called tosakbd. | 146 | module will be called ep93xx_keypad. |
166 | 147 | ||
167 | config KEYBOARD_TOSA_USE_EXT_KEYCODES | 148 | config KEYBOARD_GPIO |
168 | bool "Tosa keyboard: use extended keycodes" | 149 | tristate "GPIO Buttons" |
169 | depends on KEYBOARD_TOSA | 150 | depends on GENERIC_GPIO |
170 | default n | ||
171 | help | 151 | help |
172 | Say Y here to enable the tosa keyboard driver to generate extended | 152 | This driver implements support for buttons connected |
173 | (>= 127) keycodes. Be aware, that they can't be correctly interpreted | 153 | to GPIO pins of various CPUs (and some other chips). |
174 | by either console keyboard driver or by Kdrive keybd driver. | ||
175 | |||
176 | Say Y only if you know, what you are doing! | ||
177 | 154 | ||
178 | config KEYBOARD_AMIGA | 155 | Say Y here if your device has buttons connected |
179 | tristate "Amiga keyboard" | 156 | directly to such GPIO pins. Your board-specific |
180 | depends on AMIGA | 157 | setup logic must also provide a platform device, |
181 | help | 158 | with configuration data saying which GPIOs are used. |
182 | Say Y here if you are running Linux on any AMIGA and have a keyboard | ||
183 | attached. | ||
184 | 159 | ||
185 | To compile this driver as a module, choose M here: the | 160 | To compile this driver as a module, choose M here: the |
186 | module will be called amikbd. | 161 | module will be called gpio_keys. |
187 | 162 | ||
188 | config ATARI_KBD_CORE | 163 | config KEYBOARD_MATRIX |
189 | bool | 164 | tristate "GPIO driven matrix keypad support" |
190 | 165 | depends on GENERIC_GPIO | |
191 | config KEYBOARD_ATARI | ||
192 | tristate "Atari keyboard" | ||
193 | depends on ATARI | ||
194 | select ATARI_KBD_CORE | ||
195 | help | 166 | help |
196 | Say Y here if you are running Linux on any Atari and have a keyboard | 167 | Enable support for GPIO driven matrix keypad. |
197 | attached. | ||
198 | 168 | ||
199 | To compile this driver as a module, choose M here: the | 169 | To compile this driver as a module, choose M here: the |
200 | module will be called atakbd. | 170 | module will be called matrix_keypad. |
201 | 171 | ||
202 | config KEYBOARD_HIL_OLD | 172 | config KEYBOARD_HIL_OLD |
203 | tristate "HP HIL keyboard support (simple driver)" | 173 | tristate "HP HIL keyboard support (simple driver)" |
@@ -217,7 +187,7 @@ config KEYBOARD_HIL_OLD | |||
217 | submenu. | 187 | submenu. |
218 | 188 | ||
219 | config KEYBOARD_HIL | 189 | config KEYBOARD_HIL |
220 | tristate "HP HIL keyboard support" | 190 | tristate "HP HIL keyboard/pointer support" |
221 | depends on GSC || HP300 | 191 | depends on GSC || HP300 |
222 | default y | 192 | default y |
223 | select HP_SDC | 193 | select HP_SDC |
@@ -226,7 +196,8 @@ config KEYBOARD_HIL | |||
226 | help | 196 | help |
227 | The "Human Interface Loop" is a older, 8-channel USB-like | 197 | The "Human Interface Loop" is a older, 8-channel USB-like |
228 | controller used in several Hewlett Packard models. | 198 | controller used in several Hewlett Packard models. |
229 | This driver implements support for HIL-keyboards attached | 199 | This driver implements support for HIL-keyboards and pointing |
200 | devices (mice, tablets, touchscreens) attached | ||
230 | to your machine, so normally you should say Y here. | 201 | to your machine, so normally you should say Y here. |
231 | 202 | ||
232 | config KEYBOARD_HP6XX | 203 | config KEYBOARD_HP6XX |
@@ -261,20 +232,39 @@ config KEYBOARD_LM8323 | |||
261 | To compile this driver as a module, choose M here: the | 232 | To compile this driver as a module, choose M here: the |
262 | module will be called lm8323. | 233 | module will be called lm8323. |
263 | 234 | ||
264 | config KEYBOARD_OMAP | 235 | config KEYBOARD_LOCOMO |
265 | tristate "TI OMAP keypad support" | 236 | tristate "LoCoMo Keyboard Support" |
266 | depends on (ARCH_OMAP1 || ARCH_OMAP2) | 237 | depends on SHARP_LOCOMO |
267 | help | 238 | help |
268 | Say Y here if you want to use the OMAP keypad. | 239 | Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA |
269 | 240 | ||
270 | To compile this driver as a module, choose M here: the | 241 | To compile this driver as a module, choose M here: the |
271 | module will be called omap-keypad. | 242 | module will be called locomokbd. |
243 | |||
244 | config KEYBOARD_MAPLE | ||
245 | tristate "Maple bus keyboard" | ||
246 | depends on SH_DREAMCAST && MAPLE | ||
247 | help | ||
248 | Say Y here if you have a Dreamcast console running Linux and have | ||
249 | a keyboard attached to its Maple bus. | ||
250 | |||
251 | To compile this driver as a module, choose M here: the | ||
252 | module will be called maple_keyb. | ||
253 | |||
254 | config KEYBOARD_NEWTON | ||
255 | tristate "Newton keyboard" | ||
256 | select SERIO | ||
257 | help | ||
258 | Say Y here if you have a Newton keyboard on a serial port. | ||
259 | |||
260 | To compile this driver as a module, choose M here: the | ||
261 | module will be called newtonkbd. | ||
272 | 262 | ||
273 | config KEYBOARD_PXA27x | 263 | config KEYBOARD_PXA27x |
274 | tristate "PXA27x/PXA3xx keypad support" | 264 | tristate "PXA27x/PXA3xx keypad support" |
275 | depends on PXA27x || PXA3xx | 265 | depends on PXA27x || PXA3xx |
276 | help | 266 | help |
277 | Enable support for PXA27x/PXA3xx keypad controller | 267 | Enable support for PXA27x/PXA3xx keypad controller. |
278 | 268 | ||
279 | To compile this driver as a module, choose M here: the | 269 | To compile this driver as a module, choose M here: the |
280 | module will be called pxa27x_keypad. | 270 | module will be called pxa27x_keypad. |
@@ -288,51 +278,38 @@ config KEYBOARD_PXA930_ROTARY | |||
288 | To compile this driver as a module, choose M here: the | 278 | To compile this driver as a module, choose M here: the |
289 | module will be called pxa930_rotary. | 279 | module will be called pxa930_rotary. |
290 | 280 | ||
291 | config KEYBOARD_AAED2000 | 281 | config KEYBOARD_SPITZ |
292 | tristate "AAED-2000 keyboard" | 282 | tristate "Spitz keyboard" |
293 | depends on MACH_AAED2000 | 283 | depends on PXA_SHARPSL |
294 | select INPUT_POLLDEV | ||
295 | default y | 284 | default y |
296 | help | 285 | help |
297 | Say Y here to enable the keyboard on the Agilent AAED-2000 | 286 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, |
298 | development board. | 287 | SL-C3000 and Sl-C3100 series of PDAs. |
299 | |||
300 | To compile this driver as a module, choose M here: the | ||
301 | module will be called aaed2000_kbd. | ||
302 | |||
303 | config KEYBOARD_GPIO | ||
304 | tristate "GPIO Buttons" | ||
305 | depends on GENERIC_GPIO | ||
306 | help | ||
307 | This driver implements support for buttons connected | ||
308 | to GPIO pins of various CPUs (and some other chips). | ||
309 | |||
310 | Say Y here if your device has buttons connected | ||
311 | directly to such GPIO pins. Your board-specific | ||
312 | setup logic must also provide a platform device, | ||
313 | with configuration data saying which GPIOs are used. | ||
314 | 288 | ||
315 | To compile this driver as a module, choose M here: the | 289 | To compile this driver as a module, choose M here: the |
316 | module will be called gpio-keys. | 290 | module will be called spitzkbd. |
317 | 291 | ||
318 | config KEYBOARD_MAPLE | 292 | config KEYBOARD_STOWAWAY |
319 | tristate "Maple bus keyboard" | 293 | tristate "Stowaway keyboard" |
320 | depends on SH_DREAMCAST && MAPLE | 294 | select SERIO |
321 | help | 295 | help |
322 | Say Y here if you have a Dreamcast console running Linux and have | 296 | Say Y here if you have a Stowaway keyboard on a serial port. |
323 | a keyboard attached to its Maple bus. | 297 | Stowaway compatible keyboards like Dicota Input-PDA keyboard |
298 | are also supported by this driver. | ||
324 | 299 | ||
325 | To compile this driver as a module, choose M here: the | 300 | To compile this driver as a module, choose M here: the |
326 | module will be called maple_keyb. | 301 | module will be called stowaway. |
327 | 302 | ||
328 | config KEYBOARD_BFIN | 303 | config KEYBOARD_SUNKBD |
329 | tristate "Blackfin BF54x keypad support" | 304 | tristate "Sun Type 4 and Type 5 keyboard" |
330 | depends on (BF54x && !BF544) | 305 | select SERIO |
331 | help | 306 | help |
332 | Say Y here if you want to use the BF54x keypad. | 307 | Say Y here if you want to use a Sun Type 4 or Type 5 keyboard, |
308 | connected either to the Sun keyboard connector or to an serial | ||
309 | (RS-232) port via a simple adapter. | ||
333 | 310 | ||
334 | To compile this driver as a module, choose M here: the | 311 | To compile this driver as a module, choose M here: the |
335 | module will be called bf54x-keys. | 312 | module will be called sunkbd. |
336 | 313 | ||
337 | config KEYBOARD_SH_KEYSC | 314 | config KEYBOARD_SH_KEYSC |
338 | tristate "SuperH KEYSC keypad support" | 315 | tristate "SuperH KEYSC keypad support" |
@@ -344,13 +321,66 @@ config KEYBOARD_SH_KEYSC | |||
344 | To compile this driver as a module, choose M here: the | 321 | To compile this driver as a module, choose M here: the |
345 | module will be called sh_keysc. | 322 | module will be called sh_keysc. |
346 | 323 | ||
347 | config KEYBOARD_EP93XX | 324 | config KEYBOARD_OMAP |
348 | tristate "EP93xx Matrix Keypad support" | 325 | tristate "TI OMAP keypad support" |
349 | depends on ARCH_EP93XX | 326 | depends on (ARCH_OMAP1 || ARCH_OMAP2) |
350 | help | 327 | help |
351 | Say Y here to enable the matrix keypad on the Cirrus EP93XX. | 328 | Say Y here if you want to use the OMAP keypad. |
352 | 329 | ||
353 | To compile this driver as a module, choose M here: the | 330 | To compile this driver as a module, choose M here: the |
354 | module will be called ep93xx_keypad. | 331 | module will be called omap-keypad. |
332 | |||
333 | config KEYBOARD_TWL4030 | ||
334 | tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" | ||
335 | depends on TWL4030_CORE | ||
336 | help | ||
337 | Say Y here if your board use the keypad controller on | ||
338 | TWL4030 family chips. It's safe to say enable this | ||
339 | even on boards that don't use the keypad controller. | ||
340 | |||
341 | To compile this driver as a module, choose M here: the | ||
342 | module will be called twl4030_keypad. | ||
343 | |||
344 | config KEYBOARD_TOSA | ||
345 | tristate "Tosa keyboard" | ||
346 | depends on MACH_TOSA | ||
347 | default y | ||
348 | help | ||
349 | Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) | ||
350 | |||
351 | To compile this driver as a module, choose M here: the | ||
352 | module will be called tosakbd. | ||
353 | |||
354 | config KEYBOARD_TOSA_USE_EXT_KEYCODES | ||
355 | bool "Tosa keyboard: use extended keycodes" | ||
356 | depends on KEYBOARD_TOSA | ||
357 | help | ||
358 | Say Y here to enable the tosa keyboard driver to generate extended | ||
359 | (>= 127) keycodes. Be aware, that they can't be correctly interpreted | ||
360 | by either console keyboard driver or by Kdrive keybd driver. | ||
361 | |||
362 | Say Y only if you know, what you are doing! | ||
363 | |||
364 | config KEYBOARD_XTKBD | ||
365 | tristate "XT keyboard" | ||
366 | select SERIO | ||
367 | help | ||
368 | Say Y here if you want to use the old IBM PC/XT keyboard (or | ||
369 | compatible) on your system. This is only possible with a | ||
370 | parallel port keyboard adapter, you cannot connect it to the | ||
371 | keyboard port on a PC that runs Linux. | ||
372 | |||
373 | To compile this driver as a module, choose M here: the | ||
374 | module will be called xtkbd. | ||
375 | |||
376 | config KEYBOARD_W90P910 | ||
377 | tristate "W90P910 Matrix Keypad support" | ||
378 | depends on ARCH_W90X900 | ||
379 | help | ||
380 | Say Y here to enable the matrix keypad on evaluation board | ||
381 | based on W90P910. | ||
382 | |||
383 | To compile this driver as a module, choose M here: the | ||
384 | module will be called w90p910_keypad. | ||
355 | 385 | ||
356 | endif | 386 | endif |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 156b647a259b..8a7a22b30266 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -4,29 +4,32 @@ | |||
4 | 4 | ||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
8 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | ||
9 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o | ||
10 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | ||
11 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 8 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
12 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 9 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
13 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o | 10 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
14 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | 11 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o |
15 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | ||
16 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o | 12 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o |
17 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | 13 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o |
18 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | 14 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o |
19 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 15 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
20 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o | 16 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o |
17 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | ||
18 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | ||
19 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o | ||
21 | obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o | 20 | obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o |
21 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o | ||
22 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | ||
23 | obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o | ||
24 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | ||
22 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o | 25 | obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o |
23 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o | 26 | obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o |
24 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | 27 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o |
25 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | ||
26 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | ||
27 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | ||
28 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | ||
29 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | ||
30 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | ||
31 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 28 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
32 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o | 29 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o |
30 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | ||
31 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | ||
32 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | ||
33 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | ||
34 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | ||
35 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index df3f8aa68115..adb09e2ba394 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -68,7 +68,9 @@ MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and | |||
68 | * are loadable via a userland utility. | 68 | * are loadable via a userland utility. |
69 | */ | 69 | */ |
70 | 70 | ||
71 | static const unsigned short atkbd_set2_keycode[512] = { | 71 | #define ATKBD_KEYMAP_SIZE 512 |
72 | |||
73 | static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] = { | ||
72 | 74 | ||
73 | #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES | 75 | #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES |
74 | 76 | ||
@@ -99,7 +101,7 @@ static const unsigned short atkbd_set2_keycode[512] = { | |||
99 | #endif | 101 | #endif |
100 | }; | 102 | }; |
101 | 103 | ||
102 | static const unsigned short atkbd_set3_keycode[512] = { | 104 | static const unsigned short atkbd_set3_keycode[ATKBD_KEYMAP_SIZE] = { |
103 | 105 | ||
104 | 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60, | 106 | 0, 0, 0, 0, 0, 0, 0, 59, 1,138,128,129,130, 15, 41, 60, |
105 | 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62, | 107 | 131, 29, 42, 86, 58, 16, 2, 61,133, 56, 44, 31, 30, 17, 3, 62, |
@@ -200,8 +202,8 @@ struct atkbd { | |||
200 | char phys[32]; | 202 | char phys[32]; |
201 | 203 | ||
202 | unsigned short id; | 204 | unsigned short id; |
203 | unsigned short keycode[512]; | 205 | unsigned short keycode[ATKBD_KEYMAP_SIZE]; |
204 | DECLARE_BITMAP(force_release_mask, 512); | 206 | DECLARE_BITMAP(force_release_mask, ATKBD_KEYMAP_SIZE); |
205 | unsigned char set; | 207 | unsigned char set; |
206 | unsigned char translated; | 208 | unsigned char translated; |
207 | unsigned char extra; | 209 | unsigned char extra; |
@@ -227,7 +229,7 @@ struct atkbd { | |||
227 | }; | 229 | }; |
228 | 230 | ||
229 | /* | 231 | /* |
230 | * System-specific ketymap fixup routine | 232 | * System-specific keymap fixup routine |
231 | */ | 233 | */ |
232 | static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); | 234 | static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); |
233 | static void *atkbd_platform_fixup_data; | 235 | static void *atkbd_platform_fixup_data; |
@@ -253,6 +255,7 @@ static struct device_attribute atkbd_attr_##_name = \ | |||
253 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); | 255 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); |
254 | 256 | ||
255 | ATKBD_DEFINE_ATTR(extra); | 257 | ATKBD_DEFINE_ATTR(extra); |
258 | ATKBD_DEFINE_ATTR(force_release); | ||
256 | ATKBD_DEFINE_ATTR(scroll); | 259 | ATKBD_DEFINE_ATTR(scroll); |
257 | ATKBD_DEFINE_ATTR(set); | 260 | ATKBD_DEFINE_ATTR(set); |
258 | ATKBD_DEFINE_ATTR(softrepeat); | 261 | ATKBD_DEFINE_ATTR(softrepeat); |
@@ -272,6 +275,7 @@ ATKBD_DEFINE_RO_ATTR(err_count); | |||
272 | 275 | ||
273 | static struct attribute *atkbd_attributes[] = { | 276 | static struct attribute *atkbd_attributes[] = { |
274 | &atkbd_attr_extra.attr, | 277 | &atkbd_attr_extra.attr, |
278 | &atkbd_attr_force_release.attr, | ||
275 | &atkbd_attr_scroll.attr, | 279 | &atkbd_attr_scroll.attr, |
276 | &atkbd_attr_set.attr, | 280 | &atkbd_attr_set.attr, |
277 | &atkbd_attr_softrepeat.attr, | 281 | &atkbd_attr_softrepeat.attr, |
@@ -880,6 +884,14 @@ static unsigned int atkbd_hp_zv6100_forced_release_keys[] = { | |||
880 | }; | 884 | }; |
881 | 885 | ||
882 | /* | 886 | /* |
887 | * Perform fixup for HP (Compaq) Presario R4000 R4100 R4200 that don't generate | ||
888 | * release for their volume buttons | ||
889 | */ | ||
890 | static unsigned int atkbd_hp_r4000_forced_release_keys[] = { | ||
891 | 0xae, 0xb0, -1U | ||
892 | }; | ||
893 | |||
894 | /* | ||
883 | * Samsung NC10,NC20 with Fn+F? key release not working | 895 | * Samsung NC10,NC20 with Fn+F? key release not working |
884 | */ | 896 | */ |
885 | static unsigned int atkbd_samsung_forced_release_keys[] = { | 897 | static unsigned int atkbd_samsung_forced_release_keys[] = { |
@@ -895,6 +907,13 @@ static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = { | |||
895 | }; | 907 | }; |
896 | 908 | ||
897 | /* | 909 | /* |
910 | * Amilo Pi 3525 key release for Fn+Volume keys not working | ||
911 | */ | ||
912 | static unsigned int atkbd_amilo_pi3525_forced_release_keys[] = { | ||
913 | 0x20, 0xa0, 0x2e, 0xae, 0x30, 0xb0, -1U | ||
914 | }; | ||
915 | |||
916 | /* | ||
898 | * Amilo Xi 3650 key release for light touch bar not working | 917 | * Amilo Xi 3650 key release for light touch bar not working |
899 | */ | 918 | */ |
900 | static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = { | 919 | static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = { |
@@ -902,6 +921,13 @@ static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = { | |||
902 | }; | 921 | }; |
903 | 922 | ||
904 | /* | 923 | /* |
924 | * Soltech TA12 system with broken key release on volume keys and mute key | ||
925 | */ | ||
926 | static unsigned int atkdb_soltech_ta12_forced_release_keys[] = { | ||
927 | 0xa0, 0xae, 0xb0, -1U | ||
928 | }; | ||
929 | |||
930 | /* | ||
905 | * atkbd_set_keycode_table() initializes keyboard's keycode table | 931 | * atkbd_set_keycode_table() initializes keyboard's keycode table |
906 | * according to the selected scancode set | 932 | * according to the selected scancode set |
907 | */ | 933 | */ |
@@ -912,7 +938,7 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd) | |||
912 | int i, j; | 938 | int i, j; |
913 | 939 | ||
914 | memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); | 940 | memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); |
915 | bitmap_zero(atkbd->force_release_mask, 512); | 941 | bitmap_zero(atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); |
916 | 942 | ||
917 | if (atkbd->translated) { | 943 | if (atkbd->translated) { |
918 | for (i = 0; i < 128; i++) { | 944 | for (i = 0; i < 128; i++) { |
@@ -1019,7 +1045,7 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd) | |||
1019 | input_dev->keycodesize = sizeof(unsigned short); | 1045 | input_dev->keycodesize = sizeof(unsigned short); |
1020 | input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); | 1046 | input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); |
1021 | 1047 | ||
1022 | for (i = 0; i < 512; i++) | 1048 | for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) |
1023 | if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) | 1049 | if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) |
1024 | __set_bit(atkbd->keycode[i], input_dev->keybit); | 1050 | __set_bit(atkbd->keycode[i], input_dev->keybit); |
1025 | } | 1051 | } |
@@ -1287,6 +1313,33 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun | |||
1287 | return count; | 1313 | return count; |
1288 | } | 1314 | } |
1289 | 1315 | ||
1316 | static ssize_t atkbd_show_force_release(struct atkbd *atkbd, char *buf) | ||
1317 | { | ||
1318 | size_t len = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, | ||
1319 | atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); | ||
1320 | |||
1321 | buf[len++] = '\n'; | ||
1322 | buf[len] = '\0'; | ||
1323 | |||
1324 | return len; | ||
1325 | } | ||
1326 | |||
1327 | static ssize_t atkbd_set_force_release(struct atkbd *atkbd, | ||
1328 | const char *buf, size_t count) | ||
1329 | { | ||
1330 | /* 64 bytes on stack should be acceptable */ | ||
1331 | DECLARE_BITMAP(new_mask, ATKBD_KEYMAP_SIZE); | ||
1332 | int err; | ||
1333 | |||
1334 | err = bitmap_parselist(buf, new_mask, ATKBD_KEYMAP_SIZE); | ||
1335 | if (err) | ||
1336 | return err; | ||
1337 | |||
1338 | memcpy(atkbd->force_release_mask, new_mask, sizeof(atkbd->force_release_mask)); | ||
1339 | return count; | ||
1340 | } | ||
1341 | |||
1342 | |||
1290 | static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) | 1343 | static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf) |
1291 | { | 1344 | { |
1292 | return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0); | 1345 | return sprintf(buf, "%d\n", atkbd->scroll ? 1 : 0); |
@@ -1523,6 +1576,33 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1523 | .driver_data = atkbd_hp_zv6100_forced_release_keys, | 1576 | .driver_data = atkbd_hp_zv6100_forced_release_keys, |
1524 | }, | 1577 | }, |
1525 | { | 1578 | { |
1579 | .ident = "HP Presario R4000", | ||
1580 | .matches = { | ||
1581 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
1582 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"), | ||
1583 | }, | ||
1584 | .callback = atkbd_setup_forced_release, | ||
1585 | .driver_data = atkbd_hp_r4000_forced_release_keys, | ||
1586 | }, | ||
1587 | { | ||
1588 | .ident = "HP Presario R4100", | ||
1589 | .matches = { | ||
1590 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
1591 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"), | ||
1592 | }, | ||
1593 | .callback = atkbd_setup_forced_release, | ||
1594 | .driver_data = atkbd_hp_r4000_forced_release_keys, | ||
1595 | }, | ||
1596 | { | ||
1597 | .ident = "HP Presario R4200", | ||
1598 | .matches = { | ||
1599 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
1600 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"), | ||
1601 | }, | ||
1602 | .callback = atkbd_setup_forced_release, | ||
1603 | .driver_data = atkbd_hp_r4000_forced_release_keys, | ||
1604 | }, | ||
1605 | { | ||
1526 | .ident = "Inventec Symphony", | 1606 | .ident = "Inventec Symphony", |
1527 | .matches = { | 1607 | .matches = { |
1528 | DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"), | 1608 | DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"), |
@@ -1568,6 +1648,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1568 | .driver_data = atkbd_amilo_pa1510_forced_release_keys, | 1648 | .driver_data = atkbd_amilo_pa1510_forced_release_keys, |
1569 | }, | 1649 | }, |
1570 | { | 1650 | { |
1651 | .ident = "Fujitsu Amilo Pi 3525", | ||
1652 | .matches = { | ||
1653 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | ||
1654 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 3525"), | ||
1655 | }, | ||
1656 | .callback = atkbd_setup_forced_release, | ||
1657 | .driver_data = atkbd_amilo_pi3525_forced_release_keys, | ||
1658 | }, | ||
1659 | { | ||
1571 | .ident = "Fujitsu Amilo Xi 3650", | 1660 | .ident = "Fujitsu Amilo Xi 3650", |
1572 | .matches = { | 1661 | .matches = { |
1573 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 1662 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
@@ -1576,6 +1665,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1576 | .callback = atkbd_setup_forced_release, | 1665 | .callback = atkbd_setup_forced_release, |
1577 | .driver_data = atkbd_amilo_xi3650_forced_release_keys, | 1666 | .driver_data = atkbd_amilo_xi3650_forced_release_keys, |
1578 | }, | 1667 | }, |
1668 | { | ||
1669 | .ident = "Soltech Corporation TA12", | ||
1670 | .matches = { | ||
1671 | DMI_MATCH(DMI_SYS_VENDOR, "Soltech Corporation"), | ||
1672 | DMI_MATCH(DMI_PRODUCT_NAME, "TA12"), | ||
1673 | }, | ||
1674 | .callback = atkbd_setup_forced_release, | ||
1675 | .driver_data = atkdb_soltech_ta12_forced_release_keys, | ||
1676 | }, | ||
1579 | { } | 1677 | { } |
1580 | }; | 1678 | }; |
1581 | 1679 | ||
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index d427f322e207..fe376a27fe57 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
@@ -184,14 +184,13 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
184 | int i, error; | 184 | int i, error; |
185 | 185 | ||
186 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { | 186 | if (!pdata->rows || !pdata->cols || !pdata->keymap) { |
187 | printk(KERN_ERR DRV_NAME | 187 | dev_err(&pdev->dev, "no rows, cols or keymap from pdata\n"); |
188 | ": No rows, cols or keymap from pdata\n"); | ||
189 | return -EINVAL; | 188 | return -EINVAL; |
190 | } | 189 | } |
191 | 190 | ||
192 | if (!pdata->keymapsize || | 191 | if (!pdata->keymapsize || |
193 | pdata->keymapsize > (pdata->rows * pdata->cols)) { | 192 | pdata->keymapsize > (pdata->rows * pdata->cols)) { |
194 | printk(KERN_ERR DRV_NAME ": Invalid keymapsize\n"); | 193 | dev_err(&pdev->dev, "invalid keymapsize\n"); |
195 | return -EINVAL; | 194 | return -EINVAL; |
196 | } | 195 | } |
197 | 196 | ||
@@ -211,8 +210,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
211 | 210 | ||
212 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || | 211 | if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || |
213 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { | 212 | !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { |
214 | printk(KERN_WARNING DRV_NAME | 213 | dev_warn(&pdev->dev, |
215 | ": Invalid Debounce/Columndrive Time in platform data\n"); | 214 | "invalid platform debounce/columndrive time\n"); |
216 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ | 215 | bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ |
217 | } else { | 216 | } else { |
218 | bfin_write_KPAD_MSEL( | 217 | bfin_write_KPAD_MSEL( |
@@ -231,16 +230,14 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
231 | 230 | ||
232 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], | 231 | if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows], |
233 | DRV_NAME)) { | 232 | DRV_NAME)) { |
234 | printk(KERN_ERR DRV_NAME | 233 | dev_err(&pdev->dev, "requesting peripherals failed\n"); |
235 | ": Requesting Peripherals failed\n"); | ||
236 | error = -EFAULT; | 234 | error = -EFAULT; |
237 | goto out0; | 235 | goto out0; |
238 | } | 236 | } |
239 | 237 | ||
240 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], | 238 | if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols], |
241 | DRV_NAME)) { | 239 | DRV_NAME)) { |
242 | printk(KERN_ERR DRV_NAME | 240 | dev_err(&pdev->dev, "requesting peripherals failed\n"); |
243 | ": Requesting Peripherals failed\n"); | ||
244 | error = -EFAULT; | 241 | error = -EFAULT; |
245 | goto out1; | 242 | goto out1; |
246 | } | 243 | } |
@@ -254,9 +251,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
254 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, | 251 | error = request_irq(bf54x_kpad->irq, bfin_kpad_isr, |
255 | 0, DRV_NAME, pdev); | 252 | 0, DRV_NAME, pdev); |
256 | if (error) { | 253 | if (error) { |
257 | printk(KERN_ERR DRV_NAME | 254 | dev_err(&pdev->dev, "unable to claim irq %d\n", |
258 | ": unable to claim irq %d; error %d\n", | 255 | bf54x_kpad->irq); |
259 | bf54x_kpad->irq, error); | ||
260 | goto out2; | 256 | goto out2; |
261 | } | 257 | } |
262 | 258 | ||
@@ -297,8 +293,7 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
297 | 293 | ||
298 | error = input_register_device(input); | 294 | error = input_register_device(input); |
299 | if (error) { | 295 | if (error) { |
300 | printk(KERN_ERR DRV_NAME | 296 | dev_err(&pdev->dev, "unable to register input device\n"); |
301 | ": Unable to register input device (%d)\n", error); | ||
302 | goto out4; | 297 | goto out4; |
303 | } | 298 | } |
304 | 299 | ||
@@ -316,9 +311,6 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) | |||
316 | 311 | ||
317 | device_init_wakeup(&pdev->dev, 1); | 312 | device_init_wakeup(&pdev->dev, 1); |
318 | 313 | ||
319 | printk(KERN_ERR DRV_NAME | ||
320 | ": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq); | ||
321 | |||
322 | return 0; | 314 | return 0; |
323 | 315 | ||
324 | out4: | 316 | out4: |
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 2157cd7de00c..a88aff3816a0 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -29,7 +29,8 @@ | |||
29 | struct gpio_button_data { | 29 | struct gpio_button_data { |
30 | struct gpio_keys_button *button; | 30 | struct gpio_keys_button *button; |
31 | struct input_dev *input; | 31 | struct input_dev *input; |
32 | struct delayed_work work; | 32 | struct timer_list timer; |
33 | struct work_struct work; | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | struct gpio_keys_drvdata { | 36 | struct gpio_keys_drvdata { |
@@ -40,7 +41,7 @@ struct gpio_keys_drvdata { | |||
40 | static void gpio_keys_report_event(struct work_struct *work) | 41 | static void gpio_keys_report_event(struct work_struct *work) |
41 | { | 42 | { |
42 | struct gpio_button_data *bdata = | 43 | struct gpio_button_data *bdata = |
43 | container_of(work, struct gpio_button_data, work.work); | 44 | container_of(work, struct gpio_button_data, work); |
44 | struct gpio_keys_button *button = bdata->button; | 45 | struct gpio_keys_button *button = bdata->button; |
45 | struct input_dev *input = bdata->input; | 46 | struct input_dev *input = bdata->input; |
46 | unsigned int type = button->type ?: EV_KEY; | 47 | unsigned int type = button->type ?: EV_KEY; |
@@ -50,17 +51,25 @@ static void gpio_keys_report_event(struct work_struct *work) | |||
50 | input_sync(input); | 51 | input_sync(input); |
51 | } | 52 | } |
52 | 53 | ||
54 | static void gpio_keys_timer(unsigned long _data) | ||
55 | { | ||
56 | struct gpio_button_data *data = (struct gpio_button_data *)_data; | ||
57 | |||
58 | schedule_work(&data->work); | ||
59 | } | ||
60 | |||
53 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) | 61 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) |
54 | { | 62 | { |
55 | struct gpio_button_data *bdata = dev_id; | 63 | struct gpio_button_data *bdata = dev_id; |
56 | struct gpio_keys_button *button = bdata->button; | 64 | struct gpio_keys_button *button = bdata->button; |
57 | unsigned long delay; | ||
58 | 65 | ||
59 | BUG_ON(irq != gpio_to_irq(button->gpio)); | 66 | BUG_ON(irq != gpio_to_irq(button->gpio)); |
60 | 67 | ||
61 | delay = button->debounce_interval ? | 68 | if (button->debounce_interval) |
62 | msecs_to_jiffies(button->debounce_interval) : 0; | 69 | mod_timer(&bdata->timer, |
63 | schedule_delayed_work(&bdata->work, delay); | 70 | jiffies + msecs_to_jiffies(button->debounce_interval)); |
71 | else | ||
72 | schedule_work(&bdata->work); | ||
64 | 73 | ||
65 | return IRQ_HANDLED; | 74 | return IRQ_HANDLED; |
66 | } | 75 | } |
@@ -107,7 +116,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
107 | 116 | ||
108 | bdata->input = input; | 117 | bdata->input = input; |
109 | bdata->button = button; | 118 | bdata->button = button; |
110 | INIT_DELAYED_WORK(&bdata->work, gpio_keys_report_event); | 119 | setup_timer(&bdata->timer, |
120 | gpio_keys_timer, (unsigned long)bdata); | ||
121 | INIT_WORK(&bdata->work, gpio_keys_report_event); | ||
111 | 122 | ||
112 | error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); | 123 | error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); |
113 | if (error < 0) { | 124 | if (error < 0) { |
@@ -166,7 +177,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
166 | fail2: | 177 | fail2: |
167 | while (--i >= 0) { | 178 | while (--i >= 0) { |
168 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); | 179 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); |
169 | cancel_delayed_work_sync(&ddata->data[i].work); | 180 | if (pdata->buttons[i].debounce_interval) |
181 | del_timer_sync(&ddata->data[i].timer); | ||
182 | cancel_work_sync(&ddata->data[i].work); | ||
170 | gpio_free(pdata->buttons[i].gpio); | 183 | gpio_free(pdata->buttons[i].gpio); |
171 | } | 184 | } |
172 | 185 | ||
@@ -190,7 +203,9 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
190 | for (i = 0; i < pdata->nbuttons; i++) { | 203 | for (i = 0; i < pdata->nbuttons; i++) { |
191 | int irq = gpio_to_irq(pdata->buttons[i].gpio); | 204 | int irq = gpio_to_irq(pdata->buttons[i].gpio); |
192 | free_irq(irq, &ddata->data[i]); | 205 | free_irq(irq, &ddata->data[i]); |
193 | cancel_delayed_work_sync(&ddata->data[i].work); | 206 | if (pdata->buttons[i].debounce_interval) |
207 | del_timer_sync(&ddata->data[i].timer); | ||
208 | cancel_work_sync(&ddata->data[i].work); | ||
194 | gpio_free(pdata->buttons[i].gpio); | 209 | gpio_free(pdata->buttons[i].gpio); |
195 | } | 210 | } |
196 | 211 | ||
@@ -201,8 +216,9 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
201 | 216 | ||
202 | 217 | ||
203 | #ifdef CONFIG_PM | 218 | #ifdef CONFIG_PM |
204 | static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) | 219 | static int gpio_keys_suspend(struct device *dev) |
205 | { | 220 | { |
221 | struct platform_device *pdev = to_platform_device(dev); | ||
206 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 222 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
207 | int i; | 223 | int i; |
208 | 224 | ||
@@ -219,8 +235,9 @@ static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state) | |||
219 | return 0; | 235 | return 0; |
220 | } | 236 | } |
221 | 237 | ||
222 | static int gpio_keys_resume(struct platform_device *pdev) | 238 | static int gpio_keys_resume(struct device *dev) |
223 | { | 239 | { |
240 | struct platform_device *pdev = to_platform_device(dev); | ||
224 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 241 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
225 | int i; | 242 | int i; |
226 | 243 | ||
@@ -236,19 +253,22 @@ static int gpio_keys_resume(struct platform_device *pdev) | |||
236 | 253 | ||
237 | return 0; | 254 | return 0; |
238 | } | 255 | } |
239 | #else | 256 | |
240 | #define gpio_keys_suspend NULL | 257 | static const struct dev_pm_ops gpio_keys_pm_ops = { |
241 | #define gpio_keys_resume NULL | 258 | .suspend = gpio_keys_suspend, |
259 | .resume = gpio_keys_resume, | ||
260 | }; | ||
242 | #endif | 261 | #endif |
243 | 262 | ||
244 | static struct platform_driver gpio_keys_device_driver = { | 263 | static struct platform_driver gpio_keys_device_driver = { |
245 | .probe = gpio_keys_probe, | 264 | .probe = gpio_keys_probe, |
246 | .remove = __devexit_p(gpio_keys_remove), | 265 | .remove = __devexit_p(gpio_keys_remove), |
247 | .suspend = gpio_keys_suspend, | ||
248 | .resume = gpio_keys_resume, | ||
249 | .driver = { | 266 | .driver = { |
250 | .name = "gpio-keys", | 267 | .name = "gpio-keys", |
251 | .owner = THIS_MODULE, | 268 | .owner = THIS_MODULE, |
269 | #ifdef CONFIG_PM | ||
270 | .pm = &gpio_keys_pm_ops, | ||
271 | #endif | ||
252 | } | 272 | } |
253 | }; | 273 | }; |
254 | 274 | ||
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 6f356705ee3b..c83f4b2ec7d3 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c | |||
@@ -37,19 +37,19 @@ | |||
37 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/semaphore.h> | 40 | #include <linux/completion.h> |
41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | #include <linux/pci_ids.h> | 42 | #include <linux/pci_ids.h> |
43 | 43 | ||
44 | #define PREFIX "HIL KEYB: " | 44 | #define PREFIX "HIL: " |
45 | #define HIL_GENERIC_NAME "HIL keyboard" | ||
46 | 45 | ||
47 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); | 46 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); |
48 | MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); | 47 | MODULE_DESCRIPTION("HIL keyboard/mouse driver"); |
49 | MODULE_LICENSE("Dual BSD/GPL"); | 48 | MODULE_LICENSE("Dual BSD/GPL"); |
50 | MODULE_ALIAS("serio:ty03pr25id00ex*"); | 49 | MODULE_ALIAS("serio:ty03pr25id00ex*"); /* HIL keyboard */ |
50 | MODULE_ALIAS("serio:ty03pr25id0Fex*"); /* HIL mouse */ | ||
51 | 51 | ||
52 | #define HIL_KBD_MAX_LENGTH 16 | 52 | #define HIL_PACKET_MAX_LENGTH 16 |
53 | 53 | ||
54 | #define HIL_KBD_SET1_UPBIT 0x01 | 54 | #define HIL_KBD_SET1_UPBIT 0x01 |
55 | #define HIL_KBD_SET1_SHIFT 1 | 55 | #define HIL_KBD_SET1_SHIFT 1 |
@@ -67,308 +67,497 @@ static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] __read_mostly = | |||
67 | 67 | ||
68 | static const char hil_language[][16] = { HIL_LOCALE_MAP }; | 68 | static const char hil_language[][16] = { HIL_LOCALE_MAP }; |
69 | 69 | ||
70 | struct hil_kbd { | 70 | struct hil_dev { |
71 | struct input_dev *dev; | 71 | struct input_dev *dev; |
72 | struct serio *serio; | 72 | struct serio *serio; |
73 | 73 | ||
74 | /* Input buffer and index for packets from HIL bus. */ | 74 | /* Input buffer and index for packets from HIL bus. */ |
75 | hil_packet data[HIL_KBD_MAX_LENGTH]; | 75 | hil_packet data[HIL_PACKET_MAX_LENGTH]; |
76 | int idx4; /* four counts per packet */ | 76 | int idx4; /* four counts per packet */ |
77 | 77 | ||
78 | /* Raw device info records from HIL bus, see hil.h for fields. */ | 78 | /* Raw device info records from HIL bus, see hil.h for fields. */ |
79 | char idd[HIL_KBD_MAX_LENGTH]; /* DID byte and IDD record */ | 79 | char idd[HIL_PACKET_MAX_LENGTH]; /* DID byte and IDD record */ |
80 | char rsc[HIL_KBD_MAX_LENGTH]; /* RSC record */ | 80 | char rsc[HIL_PACKET_MAX_LENGTH]; /* RSC record */ |
81 | char exd[HIL_KBD_MAX_LENGTH]; /* EXD record */ | 81 | char exd[HIL_PACKET_MAX_LENGTH]; /* EXD record */ |
82 | char rnm[HIL_KBD_MAX_LENGTH + 1]; /* RNM record + NULL term. */ | 82 | char rnm[HIL_PACKET_MAX_LENGTH + 1]; /* RNM record + NULL term. */ |
83 | 83 | ||
84 | /* Something to sleep around with. */ | 84 | struct completion cmd_done; |
85 | struct semaphore sem; | 85 | |
86 | bool is_pointer; | ||
87 | /* Extra device details needed for pointing devices. */ | ||
88 | unsigned int nbtn, naxes; | ||
89 | unsigned int btnmap[7]; | ||
86 | }; | 90 | }; |
87 | 91 | ||
88 | /* Process a complete packet after transfer from the HIL */ | 92 | static bool hil_dev_is_command_response(hil_packet p) |
89 | static void hil_kbd_process_record(struct hil_kbd *kbd) | ||
90 | { | 93 | { |
91 | struct input_dev *dev = kbd->dev; | 94 | if ((p & ~HIL_CMDCT_POL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) |
92 | hil_packet *data = kbd->data; | 95 | return false; |
93 | hil_packet p; | ||
94 | int idx, i, cnt; | ||
95 | 96 | ||
96 | idx = kbd->idx4/4; | 97 | if ((p & ~HIL_CMDCT_RPL) == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) |
97 | p = data[idx - 1]; | 98 | return false; |
98 | 99 | ||
99 | if ((p & ~HIL_CMDCT_POL) == | 100 | return true; |
100 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) | 101 | } |
101 | goto report; | 102 | |
102 | if ((p & ~HIL_CMDCT_RPL) == | 103 | static void hil_dev_handle_command_response(struct hil_dev *dev) |
103 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) | 104 | { |
104 | goto report; | 105 | hil_packet p; |
106 | char *buf; | ||
107 | int i, idx; | ||
108 | |||
109 | idx = dev->idx4 / 4; | ||
110 | p = dev->data[idx - 1]; | ||
105 | 111 | ||
106 | /* Not a poll response. See if we are loading config records. */ | ||
107 | switch (p & HIL_PKT_DATA_MASK) { | 112 | switch (p & HIL_PKT_DATA_MASK) { |
108 | case HIL_CMD_IDD: | 113 | case HIL_CMD_IDD: |
109 | for (i = 0; i < idx; i++) | 114 | buf = dev->idd; |
110 | kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
111 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
112 | kbd->idd[i] = 0; | ||
113 | break; | 115 | break; |
114 | 116 | ||
115 | case HIL_CMD_RSC: | 117 | case HIL_CMD_RSC: |
116 | for (i = 0; i < idx; i++) | 118 | buf = dev->rsc; |
117 | kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
118 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
119 | kbd->rsc[i] = 0; | ||
120 | break; | 119 | break; |
121 | 120 | ||
122 | case HIL_CMD_EXD: | 121 | case HIL_CMD_EXD: |
123 | for (i = 0; i < idx; i++) | 122 | buf = dev->exd; |
124 | kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | ||
125 | for (; i < HIL_KBD_MAX_LENGTH; i++) | ||
126 | kbd->exd[i] = 0; | ||
127 | break; | 123 | break; |
128 | 124 | ||
129 | case HIL_CMD_RNM: | 125 | case HIL_CMD_RNM: |
130 | for (i = 0; i < idx; i++) | 126 | dev->rnm[HIL_PACKET_MAX_LENGTH] = 0; |
131 | kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK; | 127 | buf = dev->rnm; |
132 | for (; i < HIL_KBD_MAX_LENGTH + 1; i++) | ||
133 | kbd->rnm[i] = '\0'; | ||
134 | break; | 128 | break; |
135 | 129 | ||
136 | default: | 130 | default: |
137 | /* These occur when device isn't present */ | 131 | /* These occur when device isn't present */ |
138 | if (p == (HIL_ERR_INT | HIL_PKT_CMD)) | 132 | if (p != (HIL_ERR_INT | HIL_PKT_CMD)) { |
139 | break; | 133 | /* Anything else we'd like to know about. */ |
140 | /* Anything else we'd like to know about. */ | 134 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); |
141 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); | 135 | } |
142 | break; | 136 | goto out; |
143 | } | 137 | } |
144 | goto out; | ||
145 | 138 | ||
146 | report: | 139 | for (i = 0; i < idx; i++) |
147 | cnt = 1; | 140 | buf[i] = dev->data[i] & HIL_PKT_DATA_MASK; |
141 | for (; i < HIL_PACKET_MAX_LENGTH; i++) | ||
142 | buf[i] = 0; | ||
143 | out: | ||
144 | complete(&dev->cmd_done); | ||
145 | } | ||
146 | |||
147 | static void hil_dev_handle_kbd_events(struct hil_dev *kbd) | ||
148 | { | ||
149 | struct input_dev *dev = kbd->dev; | ||
150 | int idx = kbd->idx4 / 4; | ||
151 | int i; | ||
152 | |||
148 | switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { | 153 | switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) { |
149 | case HIL_POL_CHARTYPE_NONE: | 154 | case HIL_POL_CHARTYPE_NONE: |
150 | break; | 155 | return; |
151 | 156 | ||
152 | case HIL_POL_CHARTYPE_ASCII: | 157 | case HIL_POL_CHARTYPE_ASCII: |
153 | while (cnt < idx - 1) | 158 | for (i = 1; i < idx - 1; i++) |
154 | input_report_key(dev, kbd->data[cnt++] & 0x7f, 1); | 159 | input_report_key(dev, kbd->data[i] & 0x7f, 1); |
155 | break; | 160 | break; |
156 | 161 | ||
157 | case HIL_POL_CHARTYPE_RSVD1: | 162 | case HIL_POL_CHARTYPE_RSVD1: |
158 | case HIL_POL_CHARTYPE_RSVD2: | 163 | case HIL_POL_CHARTYPE_RSVD2: |
159 | case HIL_POL_CHARTYPE_BINARY: | 164 | case HIL_POL_CHARTYPE_BINARY: |
160 | while (cnt < idx - 1) | 165 | for (i = 1; i < idx - 1; i++) |
161 | input_report_key(dev, kbd->data[cnt++], 1); | 166 | input_report_key(dev, kbd->data[i], 1); |
162 | break; | 167 | break; |
163 | 168 | ||
164 | case HIL_POL_CHARTYPE_SET1: | 169 | case HIL_POL_CHARTYPE_SET1: |
165 | while (cnt < idx - 1) { | 170 | for (i = 1; i < idx - 1; i++) { |
166 | unsigned int key; | 171 | unsigned int key = kbd->data[i]; |
167 | int up; | 172 | int up = key & HIL_KBD_SET1_UPBIT; |
168 | key = kbd->data[cnt++]; | 173 | |
169 | up = key & HIL_KBD_SET1_UPBIT; | ||
170 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 174 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
171 | key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT]; | 175 | key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT]; |
172 | if (key != KEY_RESERVED) | 176 | input_report_key(dev, key, !up); |
173 | input_report_key(dev, key, !up); | ||
174 | } | 177 | } |
175 | break; | 178 | break; |
176 | 179 | ||
177 | case HIL_POL_CHARTYPE_SET2: | 180 | case HIL_POL_CHARTYPE_SET2: |
178 | while (cnt < idx - 1) { | 181 | for (i = 1; i < idx - 1; i++) { |
179 | unsigned int key; | 182 | unsigned int key = kbd->data[i]; |
180 | int up; | 183 | int up = key & HIL_KBD_SET2_UPBIT; |
181 | key = kbd->data[cnt++]; | 184 | |
182 | up = key & HIL_KBD_SET2_UPBIT; | ||
183 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 185 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
184 | key = key >> HIL_KBD_SET2_SHIFT; | 186 | key = key >> HIL_KBD_SET2_SHIFT; |
185 | if (key != KEY_RESERVED) | 187 | input_report_key(dev, key, !up); |
186 | input_report_key(dev, key, !up); | ||
187 | } | 188 | } |
188 | break; | 189 | break; |
189 | 190 | ||
190 | case HIL_POL_CHARTYPE_SET3: | 191 | case HIL_POL_CHARTYPE_SET3: |
191 | while (cnt < idx - 1) { | 192 | for (i = 1; i < idx - 1; i++) { |
192 | unsigned int key; | 193 | unsigned int key = kbd->data[i]; |
193 | int up; | 194 | int up = key & HIL_KBD_SET3_UPBIT; |
194 | key = kbd->data[cnt++]; | 195 | |
195 | up = key & HIL_KBD_SET3_UPBIT; | ||
196 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); | 196 | key &= (~HIL_KBD_SET1_UPBIT & 0xff); |
197 | key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT]; | 197 | key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT]; |
198 | if (key != KEY_RESERVED) | 198 | input_report_key(dev, key, !up); |
199 | input_report_key(dev, key, !up); | ||
200 | } | 199 | } |
201 | break; | 200 | break; |
202 | } | 201 | } |
203 | out: | 202 | |
204 | kbd->idx4 = 0; | 203 | input_sync(dev); |
205 | up(&kbd->sem); | ||
206 | } | 204 | } |
207 | 205 | ||
208 | static void hil_kbd_process_err(struct hil_kbd *kbd) | 206 | static void hil_dev_handle_ptr_events(struct hil_dev *ptr) |
207 | { | ||
208 | struct input_dev *dev = ptr->dev; | ||
209 | int idx = ptr->idx4 / 4; | ||
210 | hil_packet p = ptr->data[idx - 1]; | ||
211 | int i, cnt, laxis; | ||
212 | bool absdev, ax16; | ||
213 | |||
214 | if ((p & HIL_CMDCT_POL) != idx - 1) { | ||
215 | printk(KERN_WARNING PREFIX | ||
216 | "Malformed poll packet %x (idx = %i)\n", p, idx); | ||
217 | return; | ||
218 | } | ||
219 | |||
220 | i = (p & HIL_POL_AXIS_ALT) ? 3 : 0; | ||
221 | laxis = (p & HIL_POL_NUM_AXES_MASK) + i; | ||
222 | |||
223 | ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ | ||
224 | absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; | ||
225 | |||
226 | for (cnt = 1; i < laxis; i++) { | ||
227 | unsigned int lo, hi, val; | ||
228 | |||
229 | lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK; | ||
230 | hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0; | ||
231 | |||
232 | if (absdev) { | ||
233 | val = lo + (hi << 8); | ||
234 | #ifdef TABLET_AUTOADJUST | ||
235 | if (val < dev->absmin[ABS_X + i]) | ||
236 | dev->absmin[ABS_X + i] = val; | ||
237 | if (val > dev->absmax[ABS_X + i]) | ||
238 | dev->absmax[ABS_X + i] = val; | ||
239 | #endif | ||
240 | if (i%3) val = dev->absmax[ABS_X + i] - val; | ||
241 | input_report_abs(dev, ABS_X + i, val); | ||
242 | } else { | ||
243 | val = (int) (((int8_t)lo) | ((int8_t)hi << 8)); | ||
244 | if (i % 3) | ||
245 | val *= -1; | ||
246 | input_report_rel(dev, REL_X + i, val); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | while (cnt < idx - 1) { | ||
251 | unsigned int btn = ptr->data[cnt++]; | ||
252 | int up = btn & 1; | ||
253 | |||
254 | btn &= 0xfe; | ||
255 | if (btn == 0x8e) | ||
256 | continue; /* TODO: proximity == touch? */ | ||
257 | if (btn > 0x8c || btn < 0x80) | ||
258 | continue; | ||
259 | btn = (btn - 0x80) >> 1; | ||
260 | btn = ptr->btnmap[btn]; | ||
261 | input_report_key(dev, btn, !up); | ||
262 | } | ||
263 | |||
264 | input_sync(dev); | ||
265 | } | ||
266 | |||
267 | static void hil_dev_process_err(struct hil_dev *dev) | ||
209 | { | 268 | { |
210 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); | 269 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); |
211 | kbd->idx4 = 0; | 270 | dev->idx4 = 0; |
212 | up(&kbd->sem); | 271 | complete(&dev->cmd_done); /* just in case somebody is waiting */ |
213 | } | 272 | } |
214 | 273 | ||
215 | static irqreturn_t hil_kbd_interrupt(struct serio *serio, | 274 | static irqreturn_t hil_dev_interrupt(struct serio *serio, |
216 | unsigned char data, unsigned int flags) | 275 | unsigned char data, unsigned int flags) |
217 | { | 276 | { |
218 | struct hil_kbd *kbd; | 277 | struct hil_dev *dev; |
219 | hil_packet packet; | 278 | hil_packet packet; |
220 | int idx; | 279 | int idx; |
221 | 280 | ||
222 | kbd = serio_get_drvdata(serio); | 281 | dev = serio_get_drvdata(serio); |
223 | BUG_ON(kbd == NULL); | 282 | BUG_ON(dev == NULL); |
224 | 283 | ||
225 | if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) { | 284 | if (dev->idx4 >= HIL_PACKET_MAX_LENGTH * sizeof(hil_packet)) { |
226 | hil_kbd_process_err(kbd); | 285 | hil_dev_process_err(dev); |
227 | return IRQ_HANDLED; | 286 | goto out; |
228 | } | 287 | } |
229 | idx = kbd->idx4/4; | 288 | |
230 | if (!(kbd->idx4 % 4)) | 289 | idx = dev->idx4 / 4; |
231 | kbd->data[idx] = 0; | 290 | if (!(dev->idx4 % 4)) |
232 | packet = kbd->data[idx]; | 291 | dev->data[idx] = 0; |
233 | packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8); | 292 | packet = dev->data[idx]; |
234 | kbd->data[idx] = packet; | 293 | packet |= ((hil_packet)data) << ((3 - (dev->idx4 % 4)) * 8); |
294 | dev->data[idx] = packet; | ||
235 | 295 | ||
236 | /* Records of N 4-byte hil_packets must terminate with a command. */ | 296 | /* Records of N 4-byte hil_packets must terminate with a command. */ |
237 | if ((++(kbd->idx4)) % 4) | 297 | if ((++dev->idx4 % 4) == 0) { |
238 | return IRQ_HANDLED; | 298 | if ((packet & 0xffff0000) != HIL_ERR_INT) { |
239 | if ((packet & 0xffff0000) != HIL_ERR_INT) { | 299 | hil_dev_process_err(dev); |
240 | hil_kbd_process_err(kbd); | 300 | } else if (packet & HIL_PKT_CMD) { |
241 | return IRQ_HANDLED; | 301 | if (hil_dev_is_command_response(packet)) |
302 | hil_dev_handle_command_response(dev); | ||
303 | else if (dev->is_pointer) | ||
304 | hil_dev_handle_ptr_events(dev); | ||
305 | else | ||
306 | hil_dev_handle_kbd_events(dev); | ||
307 | dev->idx4 = 0; | ||
308 | } | ||
242 | } | 309 | } |
243 | if (packet & HIL_PKT_CMD) | 310 | out: |
244 | hil_kbd_process_record(kbd); | ||
245 | return IRQ_HANDLED; | 311 | return IRQ_HANDLED; |
246 | } | 312 | } |
247 | 313 | ||
248 | static void hil_kbd_disconnect(struct serio *serio) | 314 | static void hil_dev_disconnect(struct serio *serio) |
249 | { | 315 | { |
250 | struct hil_kbd *kbd; | 316 | struct hil_dev *dev = serio_get_drvdata(serio); |
251 | 317 | ||
252 | kbd = serio_get_drvdata(serio); | 318 | BUG_ON(dev == NULL); |
253 | BUG_ON(kbd == NULL); | ||
254 | 319 | ||
255 | serio_close(serio); | 320 | serio_close(serio); |
256 | input_unregister_device(kbd->dev); | 321 | input_unregister_device(dev->dev); |
257 | kfree(kbd); | 322 | serio_set_drvdata(serio, NULL); |
323 | kfree(dev); | ||
324 | } | ||
325 | |||
326 | static void hil_dev_keyboard_setup(struct hil_dev *kbd) | ||
327 | { | ||
328 | struct input_dev *input_dev = kbd->dev; | ||
329 | uint8_t did = kbd->idd[0]; | ||
330 | int i; | ||
331 | |||
332 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
333 | input_dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | | ||
334 | BIT_MASK(LED_SCROLLL); | ||
335 | |||
336 | for (i = 0; i < 128; i++) { | ||
337 | __set_bit(hil_kbd_set1[i], input_dev->keybit); | ||
338 | __set_bit(hil_kbd_set3[i], input_dev->keybit); | ||
339 | } | ||
340 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
341 | |||
342 | input_dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; | ||
343 | input_dev->keycodesize = sizeof(hil_kbd_set1[0]); | ||
344 | input_dev->keycode = hil_kbd_set1; | ||
345 | |||
346 | input_dev->name = strlen(kbd->rnm) ? kbd->rnm : "HIL keyboard"; | ||
347 | input_dev->phys = "hpkbd/input0"; | ||
348 | |||
349 | printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n", | ||
350 | did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); | ||
258 | } | 351 | } |
259 | 352 | ||
260 | static int hil_kbd_connect(struct serio *serio, struct serio_driver *drv) | 353 | static void hil_dev_pointer_setup(struct hil_dev *ptr) |
261 | { | 354 | { |
262 | struct hil_kbd *kbd; | 355 | struct input_dev *input_dev = ptr->dev; |
263 | uint8_t did, *idd; | 356 | uint8_t did = ptr->idd[0]; |
264 | int i; | 357 | uint8_t *idd = ptr->idd + 1; |
358 | unsigned int naxsets = HIL_IDD_NUM_AXSETS(*idd); | ||
359 | unsigned int i, btntype; | ||
360 | const char *txt; | ||
361 | |||
362 | ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); | ||
363 | |||
364 | switch (did & HIL_IDD_DID_TYPE_MASK) { | ||
365 | case HIL_IDD_DID_TYPE_REL: | ||
366 | input_dev->evbit[0] = BIT_MASK(EV_REL); | ||
265 | 367 | ||
266 | kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); | 368 | for (i = 0; i < ptr->naxes; i++) |
267 | if (!kbd) | 369 | __set_bit(REL_X + i, input_dev->relbit); |
268 | return -ENOMEM; | ||
269 | 370 | ||
270 | kbd->dev = input_allocate_device(); | 371 | for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++) |
271 | if (!kbd->dev) | 372 | __set_bit(REL_X + i, input_dev->relbit); |
373 | |||
374 | txt = "relative"; | ||
375 | break; | ||
376 | |||
377 | case HIL_IDD_DID_TYPE_ABS: | ||
378 | input_dev->evbit[0] = BIT_MASK(EV_ABS); | ||
379 | |||
380 | for (i = 0; i < ptr->naxes; i++) | ||
381 | input_set_abs_params(input_dev, ABS_X + i, | ||
382 | 0, HIL_IDD_AXIS_MAX(idd, i), 0, 0); | ||
383 | |||
384 | for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++) | ||
385 | input_set_abs_params(input_dev, ABS_X + i, | ||
386 | 0, HIL_IDD_AXIS_MAX(idd, i - 3), 0, 0); | ||
387 | |||
388 | #ifdef TABLET_AUTOADJUST | ||
389 | for (i = 0; i < ABS_MAX; i++) { | ||
390 | int diff = input_dev->absmax[ABS_X + i] / 10; | ||
391 | input_dev->absmin[ABS_X + i] += diff; | ||
392 | input_dev->absmax[ABS_X + i] -= diff; | ||
393 | } | ||
394 | #endif | ||
395 | |||
396 | txt = "absolute"; | ||
397 | break; | ||
398 | |||
399 | default: | ||
400 | BUG(); | ||
401 | } | ||
402 | |||
403 | ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); | ||
404 | if (ptr->nbtn) | ||
405 | input_dev->evbit[0] |= BIT_MASK(EV_KEY); | ||
406 | |||
407 | btntype = BTN_MISC; | ||
408 | if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) | ||
409 | #ifdef TABLET_SIMULATES_MOUSE | ||
410 | btntype = BTN_TOUCH; | ||
411 | #else | ||
412 | btntype = BTN_DIGI; | ||
413 | #endif | ||
414 | if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) | ||
415 | btntype = BTN_TOUCH; | ||
416 | |||
417 | if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) | ||
418 | btntype = BTN_MOUSE; | ||
419 | |||
420 | for (i = 0; i < ptr->nbtn; i++) { | ||
421 | __set_bit(btntype | i, input_dev->keybit); | ||
422 | ptr->btnmap[i] = btntype | i; | ||
423 | } | ||
424 | |||
425 | if (btntype == BTN_MOUSE) { | ||
426 | /* Swap buttons 2 and 3 */ | ||
427 | ptr->btnmap[1] = BTN_MIDDLE; | ||
428 | ptr->btnmap[2] = BTN_RIGHT; | ||
429 | } | ||
430 | |||
431 | input_dev->name = strlen(ptr->rnm) ? ptr->rnm : "HIL pointer device"; | ||
432 | |||
433 | printk(KERN_INFO PREFIX | ||
434 | "HIL pointer device found (did: 0x%02x, axis: %s)\n", | ||
435 | did, txt); | ||
436 | printk(KERN_INFO PREFIX | ||
437 | "HIL pointer has %i buttons and %i sets of %i axes\n", | ||
438 | ptr->nbtn, naxsets, ptr->naxes); | ||
439 | } | ||
440 | |||
441 | static int hil_dev_connect(struct serio *serio, struct serio_driver *drv) | ||
442 | { | ||
443 | struct hil_dev *dev; | ||
444 | struct input_dev *input_dev; | ||
445 | uint8_t did, *idd; | ||
446 | int error; | ||
447 | |||
448 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
449 | input_dev = input_allocate_device(); | ||
450 | if (!dev || !input_dev) { | ||
451 | error = -ENOMEM; | ||
272 | goto bail0; | 452 | goto bail0; |
453 | } | ||
273 | 454 | ||
274 | if (serio_open(serio, drv)) | 455 | dev->serio = serio; |
275 | goto bail1; | 456 | dev->dev = input_dev; |
276 | 457 | ||
277 | serio_set_drvdata(serio, kbd); | 458 | error = serio_open(serio, drv); |
278 | kbd->serio = serio; | 459 | if (error) |
460 | goto bail0; | ||
279 | 461 | ||
280 | init_MUTEX_LOCKED(&kbd->sem); | 462 | serio_set_drvdata(serio, dev); |
281 | 463 | ||
282 | /* Get device info. MLC driver supplies devid/status/etc. */ | 464 | /* Get device info. MLC driver supplies devid/status/etc. */ |
283 | serio->write(serio, 0); | 465 | init_completion(&dev->cmd_done); |
284 | serio->write(serio, 0); | 466 | serio_write(serio, 0); |
285 | serio->write(serio, HIL_PKT_CMD >> 8); | 467 | serio_write(serio, 0); |
286 | serio->write(serio, HIL_CMD_IDD); | 468 | serio_write(serio, HIL_PKT_CMD >> 8); |
287 | down(&kbd->sem); | 469 | serio_write(serio, HIL_CMD_IDD); |
288 | 470 | error = wait_for_completion_killable(&dev->cmd_done); | |
289 | serio->write(serio, 0); | 471 | if (error) |
290 | serio->write(serio, 0); | 472 | goto bail1; |
291 | serio->write(serio, HIL_PKT_CMD >> 8); | 473 | |
292 | serio->write(serio, HIL_CMD_RSC); | 474 | init_completion(&dev->cmd_done); |
293 | down(&kbd->sem); | 475 | serio_write(serio, 0); |
294 | 476 | serio_write(serio, 0); | |
295 | serio->write(serio, 0); | 477 | serio_write(serio, HIL_PKT_CMD >> 8); |
296 | serio->write(serio, 0); | 478 | serio_write(serio, HIL_CMD_RSC); |
297 | serio->write(serio, HIL_PKT_CMD >> 8); | 479 | error = wait_for_completion_killable(&dev->cmd_done); |
298 | serio->write(serio, HIL_CMD_RNM); | 480 | if (error) |
299 | down(&kbd->sem); | 481 | goto bail1; |
300 | 482 | ||
301 | serio->write(serio, 0); | 483 | init_completion(&dev->cmd_done); |
302 | serio->write(serio, 0); | 484 | serio_write(serio, 0); |
303 | serio->write(serio, HIL_PKT_CMD >> 8); | 485 | serio_write(serio, 0); |
304 | serio->write(serio, HIL_CMD_EXD); | 486 | serio_write(serio, HIL_PKT_CMD >> 8); |
305 | down(&kbd->sem); | 487 | serio_write(serio, HIL_CMD_RNM); |
306 | 488 | error = wait_for_completion_killable(&dev->cmd_done); | |
307 | up(&kbd->sem); | 489 | if (error) |
308 | 490 | goto bail1; | |
309 | did = kbd->idd[0]; | 491 | |
310 | idd = kbd->idd + 1; | 492 | init_completion(&dev->cmd_done); |
493 | serio_write(serio, 0); | ||
494 | serio_write(serio, 0); | ||
495 | serio_write(serio, HIL_PKT_CMD >> 8); | ||
496 | serio_write(serio, HIL_CMD_EXD); | ||
497 | error = wait_for_completion_killable(&dev->cmd_done); | ||
498 | if (error) | ||
499 | goto bail1; | ||
500 | |||
501 | did = dev->idd[0]; | ||
502 | idd = dev->idd + 1; | ||
503 | |||
311 | switch (did & HIL_IDD_DID_TYPE_MASK) { | 504 | switch (did & HIL_IDD_DID_TYPE_MASK) { |
312 | case HIL_IDD_DID_TYPE_KB_INTEGRAL: | 505 | case HIL_IDD_DID_TYPE_KB_INTEGRAL: |
313 | case HIL_IDD_DID_TYPE_KB_ITF: | 506 | case HIL_IDD_DID_TYPE_KB_ITF: |
314 | case HIL_IDD_DID_TYPE_KB_RSVD: | 507 | case HIL_IDD_DID_TYPE_KB_RSVD: |
315 | case HIL_IDD_DID_TYPE_CHAR: | 508 | case HIL_IDD_DID_TYPE_CHAR: |
316 | printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n", | 509 | if (HIL_IDD_NUM_BUTTONS(idd) || |
317 | did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]); | 510 | HIL_IDD_NUM_AXES_PER_SET(*idd)) { |
318 | break; | 511 | printk(KERN_INFO PREFIX |
319 | default: | 512 | "combo devices are not supported.\n"); |
320 | goto bail2; | 513 | goto bail1; |
321 | } | 514 | } |
322 | 515 | ||
323 | if (HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) { | 516 | dev->is_pointer = false; |
324 | printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n"); | 517 | hil_dev_keyboard_setup(dev); |
325 | goto bail2; | 518 | break; |
326 | } | ||
327 | 519 | ||
328 | kbd->dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 520 | case HIL_IDD_DID_TYPE_REL: |
329 | kbd->dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | | 521 | case HIL_IDD_DID_TYPE_ABS: |
330 | BIT_MASK(LED_SCROLLL); | 522 | dev->is_pointer = true; |
331 | kbd->dev->keycodemax = HIL_KEYCODES_SET1_TBLSIZE; | 523 | hil_dev_pointer_setup(dev); |
332 | kbd->dev->keycodesize = sizeof(hil_kbd_set1[0]); | 524 | break; |
333 | kbd->dev->keycode = hil_kbd_set1; | ||
334 | kbd->dev->name = strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME; | ||
335 | kbd->dev->phys = "hpkbd/input0"; /* XXX */ | ||
336 | |||
337 | kbd->dev->id.bustype = BUS_HIL; | ||
338 | kbd->dev->id.vendor = PCI_VENDOR_ID_HP; | ||
339 | kbd->dev->id.product = 0x0001; /* TODO: get from kbd->rsc */ | ||
340 | kbd->dev->id.version = 0x0100; /* TODO: get from kbd->rsc */ | ||
341 | kbd->dev->dev.parent = &serio->dev; | ||
342 | 525 | ||
343 | for (i = 0; i < 128; i++) { | 526 | default: |
344 | set_bit(hil_kbd_set1[i], kbd->dev->keybit); | 527 | goto bail1; |
345 | set_bit(hil_kbd_set3[i], kbd->dev->keybit); | ||
346 | } | 528 | } |
347 | clear_bit(0, kbd->dev->keybit); | ||
348 | 529 | ||
349 | input_register_device(kbd->dev); | 530 | input_dev->id.bustype = BUS_HIL; |
350 | printk(KERN_INFO "input: %s, ID: %d\n", | 531 | input_dev->id.vendor = PCI_VENDOR_ID_HP; |
351 | kbd->dev->name, did); | 532 | input_dev->id.product = 0x0001; /* TODO: get from kbd->rsc */ |
533 | input_dev->id.version = 0x0100; /* TODO: get from kbd->rsc */ | ||
534 | input_dev->dev.parent = &serio->dev; | ||
535 | |||
536 | if (!dev->is_pointer) { | ||
537 | serio_write(serio, 0); | ||
538 | serio_write(serio, 0); | ||
539 | serio_write(serio, HIL_PKT_CMD >> 8); | ||
540 | /* Enable Keyswitch Autorepeat 1 */ | ||
541 | serio_write(serio, HIL_CMD_EK1); | ||
542 | /* No need to wait for completion */ | ||
543 | } | ||
352 | 544 | ||
353 | serio->write(serio, 0); | 545 | error = input_register_device(input_dev); |
354 | serio->write(serio, 0); | 546 | if (error) |
355 | serio->write(serio, HIL_PKT_CMD >> 8); | 547 | goto bail1; |
356 | serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */ | ||
357 | down(&kbd->sem); | ||
358 | up(&kbd->sem); | ||
359 | 548 | ||
360 | return 0; | 549 | return 0; |
361 | bail2: | 550 | |
551 | bail1: | ||
362 | serio_close(serio); | 552 | serio_close(serio); |
363 | serio_set_drvdata(serio, NULL); | 553 | serio_set_drvdata(serio, NULL); |
364 | bail1: | ||
365 | input_free_device(kbd->dev); | ||
366 | bail0: | 554 | bail0: |
367 | kfree(kbd); | 555 | input_free_device(input_dev); |
368 | return -EIO; | 556 | kfree(dev); |
557 | return error; | ||
369 | } | 558 | } |
370 | 559 | ||
371 | static struct serio_device_id hil_kbd_ids[] = { | 560 | static struct serio_device_id hil_dev_ids[] = { |
372 | { | 561 | { |
373 | .type = SERIO_HIL_MLC, | 562 | .type = SERIO_HIL_MLC, |
374 | .proto = SERIO_HIL, | 563 | .proto = SERIO_HIL, |
@@ -378,26 +567,26 @@ static struct serio_device_id hil_kbd_ids[] = { | |||
378 | { 0 } | 567 | { 0 } |
379 | }; | 568 | }; |
380 | 569 | ||
381 | static struct serio_driver hil_kbd_serio_drv = { | 570 | static struct serio_driver hil_serio_drv = { |
382 | .driver = { | 571 | .driver = { |
383 | .name = "hil_kbd", | 572 | .name = "hil_dev", |
384 | }, | 573 | }, |
385 | .description = "HP HIL keyboard driver", | 574 | .description = "HP HIL keyboard/mouse/tablet driver", |
386 | .id_table = hil_kbd_ids, | 575 | .id_table = hil_dev_ids, |
387 | .connect = hil_kbd_connect, | 576 | .connect = hil_dev_connect, |
388 | .disconnect = hil_kbd_disconnect, | 577 | .disconnect = hil_dev_disconnect, |
389 | .interrupt = hil_kbd_interrupt | 578 | .interrupt = hil_dev_interrupt |
390 | }; | 579 | }; |
391 | 580 | ||
392 | static int __init hil_kbd_init(void) | 581 | static int __init hil_dev_init(void) |
393 | { | 582 | { |
394 | return serio_register_driver(&hil_kbd_serio_drv); | 583 | return serio_register_driver(&hil_serio_drv); |
395 | } | 584 | } |
396 | 585 | ||
397 | static void __exit hil_kbd_exit(void) | 586 | static void __exit hil_dev_exit(void) |
398 | { | 587 | { |
399 | serio_unregister_driver(&hil_kbd_serio_drv); | 588 | serio_unregister_driver(&hil_serio_drv); |
400 | } | 589 | } |
401 | 590 | ||
402 | module_init(hil_kbd_init); | 591 | module_init(hil_dev_init); |
403 | module_exit(hil_kbd_exit); | 592 | module_exit(hil_dev_exit); |
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 4730ef35c732..f9847e0fb553 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c | |||
@@ -525,12 +525,12 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, | |||
525 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); | 525 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); |
526 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); | 526 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); |
527 | if (leds_on != 0) { | 527 | if (leds_on != 0) { |
528 | lk->serio->write (lk->serio, LK_CMD_LED_ON); | 528 | serio_write (lk->serio, LK_CMD_LED_ON); |
529 | lk->serio->write (lk->serio, leds_on); | 529 | serio_write (lk->serio, leds_on); |
530 | } | 530 | } |
531 | if (leds_off != 0) { | 531 | if (leds_off != 0) { |
532 | lk->serio->write (lk->serio, LK_CMD_LED_OFF); | 532 | serio_write (lk->serio, LK_CMD_LED_OFF); |
533 | lk->serio->write (lk->serio, leds_off); | 533 | serio_write (lk->serio, leds_off); |
534 | } | 534 | } |
535 | return 0; | 535 | return 0; |
536 | 536 | ||
@@ -539,20 +539,20 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, | |||
539 | case SND_CLICK: | 539 | case SND_CLICK: |
540 | if (value == 0) { | 540 | if (value == 0) { |
541 | DBG ("%s: Deactivating key clicks\n", __func__); | 541 | DBG ("%s: Deactivating key clicks\n", __func__); |
542 | lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK); | 542 | serio_write (lk->serio, LK_CMD_DISABLE_KEYCLICK); |
543 | lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK); | 543 | serio_write (lk->serio, LK_CMD_DISABLE_CTRCLICK); |
544 | } else { | 544 | } else { |
545 | DBG ("%s: Activating key clicks\n", __func__); | 545 | DBG ("%s: Activating key clicks\n", __func__); |
546 | lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK); | 546 | serio_write (lk->serio, LK_CMD_ENABLE_KEYCLICK); |
547 | lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume)); | 547 | serio_write (lk->serio, volume_to_hw (lk->keyclick_volume)); |
548 | lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK); | 548 | serio_write (lk->serio, LK_CMD_ENABLE_CTRCLICK); |
549 | lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); | 549 | serio_write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); |
550 | } | 550 | } |
551 | return 0; | 551 | return 0; |
552 | 552 | ||
553 | case SND_BELL: | 553 | case SND_BELL: |
554 | if (value != 0) | 554 | if (value != 0) |
555 | lk->serio->write (lk->serio, LK_CMD_SOUND_BELL); | 555 | serio_write (lk->serio, LK_CMD_SOUND_BELL); |
556 | 556 | ||
557 | return 0; | 557 | return 0; |
558 | } | 558 | } |
@@ -579,10 +579,10 @@ lkkbd_reinit (struct work_struct *work) | |||
579 | unsigned char leds_off = 0; | 579 | unsigned char leds_off = 0; |
580 | 580 | ||
581 | /* Ask for ID */ | 581 | /* Ask for ID */ |
582 | lk->serio->write (lk->serio, LK_CMD_REQUEST_ID); | 582 | serio_write (lk->serio, LK_CMD_REQUEST_ID); |
583 | 583 | ||
584 | /* Reset parameters */ | 584 | /* Reset parameters */ |
585 | lk->serio->write (lk->serio, LK_CMD_SET_DEFAULTS); | 585 | serio_write (lk->serio, LK_CMD_SET_DEFAULTS); |
586 | 586 | ||
587 | /* Set LEDs */ | 587 | /* Set LEDs */ |
588 | CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); | 588 | CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); |
@@ -590,12 +590,12 @@ lkkbd_reinit (struct work_struct *work) | |||
590 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); | 590 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); |
591 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); | 591 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); |
592 | if (leds_on != 0) { | 592 | if (leds_on != 0) { |
593 | lk->serio->write (lk->serio, LK_CMD_LED_ON); | 593 | serio_write (lk->serio, LK_CMD_LED_ON); |
594 | lk->serio->write (lk->serio, leds_on); | 594 | serio_write (lk->serio, leds_on); |
595 | } | 595 | } |
596 | if (leds_off != 0) { | 596 | if (leds_off != 0) { |
597 | lk->serio->write (lk->serio, LK_CMD_LED_OFF); | 597 | serio_write (lk->serio, LK_CMD_LED_OFF); |
598 | lk->serio->write (lk->serio, leds_off); | 598 | serio_write (lk->serio, leds_off); |
599 | } | 599 | } |
600 | 600 | ||
601 | /* | 601 | /* |
@@ -603,31 +603,31 @@ lkkbd_reinit (struct work_struct *work) | |||
603 | * only work with a LK401 keyboard and grants access to | 603 | * only work with a LK401 keyboard and grants access to |
604 | * LAlt, RAlt, RCompose and RShift. | 604 | * LAlt, RAlt, RCompose and RShift. |
605 | */ | 605 | */ |
606 | lk->serio->write (lk->serio, LK_CMD_ENABLE_LK401); | 606 | serio_write (lk->serio, LK_CMD_ENABLE_LK401); |
607 | 607 | ||
608 | /* Set all keys to UPDOWN mode */ | 608 | /* Set all keys to UPDOWN mode */ |
609 | for (division = 1; division <= 14; division++) | 609 | for (division = 1; division <= 14; division++) |
610 | lk->serio->write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN, | 610 | serio_write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN, |
611 | division)); | 611 | division)); |
612 | 612 | ||
613 | /* Enable bell and set volume */ | 613 | /* Enable bell and set volume */ |
614 | lk->serio->write (lk->serio, LK_CMD_ENABLE_BELL); | 614 | serio_write (lk->serio, LK_CMD_ENABLE_BELL); |
615 | lk->serio->write (lk->serio, volume_to_hw (lk->bell_volume)); | 615 | serio_write (lk->serio, volume_to_hw (lk->bell_volume)); |
616 | 616 | ||
617 | /* Enable/disable keyclick (and possibly set volume) */ | 617 | /* Enable/disable keyclick (and possibly set volume) */ |
618 | if (test_bit (SND_CLICK, lk->dev->snd)) { | 618 | if (test_bit (SND_CLICK, lk->dev->snd)) { |
619 | lk->serio->write (lk->serio, LK_CMD_ENABLE_KEYCLICK); | 619 | serio_write (lk->serio, LK_CMD_ENABLE_KEYCLICK); |
620 | lk->serio->write (lk->serio, volume_to_hw (lk->keyclick_volume)); | 620 | serio_write (lk->serio, volume_to_hw (lk->keyclick_volume)); |
621 | lk->serio->write (lk->serio, LK_CMD_ENABLE_CTRCLICK); | 621 | serio_write (lk->serio, LK_CMD_ENABLE_CTRCLICK); |
622 | lk->serio->write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); | 622 | serio_write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); |
623 | } else { | 623 | } else { |
624 | lk->serio->write (lk->serio, LK_CMD_DISABLE_KEYCLICK); | 624 | serio_write (lk->serio, LK_CMD_DISABLE_KEYCLICK); |
625 | lk->serio->write (lk->serio, LK_CMD_DISABLE_CTRCLICK); | 625 | serio_write (lk->serio, LK_CMD_DISABLE_CTRCLICK); |
626 | } | 626 | } |
627 | 627 | ||
628 | /* Sound the bell if needed */ | 628 | /* Sound the bell if needed */ |
629 | if (test_bit (SND_BELL, lk->dev->snd)) | 629 | if (test_bit (SND_BELL, lk->dev->snd)) |
630 | lk->serio->write (lk->serio, LK_CMD_SOUND_BELL); | 630 | serio_write (lk->serio, LK_CMD_SOUND_BELL); |
631 | } | 631 | } |
632 | 632 | ||
633 | /* | 633 | /* |
@@ -684,8 +684,10 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) | |||
684 | input_dev->keycode = lk->keycode; | 684 | input_dev->keycode = lk->keycode; |
685 | input_dev->keycodesize = sizeof (lk_keycode_t); | 685 | input_dev->keycodesize = sizeof (lk_keycode_t); |
686 | input_dev->keycodemax = LK_NUM_KEYCODES; | 686 | input_dev->keycodemax = LK_NUM_KEYCODES; |
687 | |||
687 | for (i = 0; i < LK_NUM_KEYCODES; i++) | 688 | for (i = 0; i < LK_NUM_KEYCODES; i++) |
688 | set_bit (lk->keycode[i], input_dev->keybit); | 689 | __set_bit (lk->keycode[i], input_dev->keybit); |
690 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
689 | 691 | ||
690 | serio_set_drvdata (serio, lk); | 692 | serio_set_drvdata (serio, lk); |
691 | 693 | ||
@@ -697,7 +699,7 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) | |||
697 | if (err) | 699 | if (err) |
698 | goto fail3; | 700 | goto fail3; |
699 | 701 | ||
700 | lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET); | 702 | serio_write (lk->serio, LK_CMD_POWERCYCLE_RESET); |
701 | 703 | ||
702 | return 0; | 704 | return 0; |
703 | 705 | ||
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c new file mode 100644 index 000000000000..91cfe5170265 --- /dev/null +++ b/drivers/input/keyboard/matrix_keypad.c | |||
@@ -0,0 +1,444 @@ | |||
1 | /* | ||
2 | * GPIO driven matrix keyboard driver | ||
3 | * | ||
4 | * Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com> | ||
5 | * | ||
6 | * Based on corgikbd.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/types.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/jiffies.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/gpio.h> | ||
24 | #include <linux/input/matrix_keypad.h> | ||
25 | |||
26 | struct matrix_keypad { | ||
27 | const struct matrix_keypad_platform_data *pdata; | ||
28 | struct input_dev *input_dev; | ||
29 | unsigned short *keycodes; | ||
30 | unsigned int row_shift; | ||
31 | |||
32 | uint32_t last_key_state[MATRIX_MAX_COLS]; | ||
33 | struct delayed_work work; | ||
34 | bool scan_pending; | ||
35 | bool stopped; | ||
36 | spinlock_t lock; | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause | ||
41 | * minmal side effect when scanning other columns, here it is configured to | ||
42 | * be input, and it should work on most platforms. | ||
43 | */ | ||
44 | static void __activate_col(const struct matrix_keypad_platform_data *pdata, | ||
45 | int col, bool on) | ||
46 | { | ||
47 | bool level_on = !pdata->active_low; | ||
48 | |||
49 | if (on) { | ||
50 | gpio_direction_output(pdata->col_gpios[col], level_on); | ||
51 | } else { | ||
52 | gpio_set_value_cansleep(pdata->col_gpios[col], !level_on); | ||
53 | gpio_direction_input(pdata->col_gpios[col]); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | static void activate_col(const struct matrix_keypad_platform_data *pdata, | ||
58 | int col, bool on) | ||
59 | { | ||
60 | __activate_col(pdata, col, on); | ||
61 | |||
62 | if (on && pdata->col_scan_delay_us) | ||
63 | udelay(pdata->col_scan_delay_us); | ||
64 | } | ||
65 | |||
66 | static void activate_all_cols(const struct matrix_keypad_platform_data *pdata, | ||
67 | bool on) | ||
68 | { | ||
69 | int col; | ||
70 | |||
71 | for (col = 0; col < pdata->num_col_gpios; col++) | ||
72 | __activate_col(pdata, col, on); | ||
73 | } | ||
74 | |||
75 | static bool row_asserted(const struct matrix_keypad_platform_data *pdata, | ||
76 | int row) | ||
77 | { | ||
78 | return gpio_get_value_cansleep(pdata->row_gpios[row]) ? | ||
79 | !pdata->active_low : pdata->active_low; | ||
80 | } | ||
81 | |||
82 | static void enable_row_irqs(struct matrix_keypad *keypad) | ||
83 | { | ||
84 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
85 | int i; | ||
86 | |||
87 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
88 | enable_irq(gpio_to_irq(pdata->row_gpios[i])); | ||
89 | } | ||
90 | |||
91 | static void disable_row_irqs(struct matrix_keypad *keypad) | ||
92 | { | ||
93 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
94 | int i; | ||
95 | |||
96 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
97 | disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i])); | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * This gets the keys from keyboard and reports it to input subsystem | ||
102 | */ | ||
103 | static void matrix_keypad_scan(struct work_struct *work) | ||
104 | { | ||
105 | struct matrix_keypad *keypad = | ||
106 | container_of(work, struct matrix_keypad, work.work); | ||
107 | struct input_dev *input_dev = keypad->input_dev; | ||
108 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
109 | uint32_t new_state[MATRIX_MAX_COLS]; | ||
110 | int row, col, code; | ||
111 | |||
112 | /* de-activate all columns for scanning */ | ||
113 | activate_all_cols(pdata, false); | ||
114 | |||
115 | memset(new_state, 0, sizeof(new_state)); | ||
116 | |||
117 | /* assert each column and read the row status out */ | ||
118 | for (col = 0; col < pdata->num_col_gpios; col++) { | ||
119 | |||
120 | activate_col(pdata, col, true); | ||
121 | |||
122 | for (row = 0; row < pdata->num_row_gpios; row++) | ||
123 | new_state[col] |= | ||
124 | row_asserted(pdata, row) ? (1 << row) : 0; | ||
125 | |||
126 | activate_col(pdata, col, false); | ||
127 | } | ||
128 | |||
129 | for (col = 0; col < pdata->num_col_gpios; col++) { | ||
130 | uint32_t bits_changed; | ||
131 | |||
132 | bits_changed = keypad->last_key_state[col] ^ new_state[col]; | ||
133 | if (bits_changed == 0) | ||
134 | continue; | ||
135 | |||
136 | for (row = 0; row < pdata->num_row_gpios; row++) { | ||
137 | if ((bits_changed & (1 << row)) == 0) | ||
138 | continue; | ||
139 | |||
140 | code = MATRIX_SCAN_CODE(row, col, keypad->row_shift); | ||
141 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
142 | input_report_key(input_dev, | ||
143 | keypad->keycodes[code], | ||
144 | new_state[col] & (1 << row)); | ||
145 | } | ||
146 | } | ||
147 | input_sync(input_dev); | ||
148 | |||
149 | memcpy(keypad->last_key_state, new_state, sizeof(new_state)); | ||
150 | |||
151 | activate_all_cols(pdata, true); | ||
152 | |||
153 | /* Enable IRQs again */ | ||
154 | spin_lock_irq(&keypad->lock); | ||
155 | keypad->scan_pending = false; | ||
156 | enable_row_irqs(keypad); | ||
157 | spin_unlock_irq(&keypad->lock); | ||
158 | } | ||
159 | |||
160 | static irqreturn_t matrix_keypad_interrupt(int irq, void *id) | ||
161 | { | ||
162 | struct matrix_keypad *keypad = id; | ||
163 | unsigned long flags; | ||
164 | |||
165 | spin_lock_irqsave(&keypad->lock, flags); | ||
166 | |||
167 | /* | ||
168 | * See if another IRQ beaten us to it and scheduled the | ||
169 | * scan already. In that case we should not try to | ||
170 | * disable IRQs again. | ||
171 | */ | ||
172 | if (unlikely(keypad->scan_pending || keypad->stopped)) | ||
173 | goto out; | ||
174 | |||
175 | disable_row_irqs(keypad); | ||
176 | keypad->scan_pending = true; | ||
177 | schedule_delayed_work(&keypad->work, | ||
178 | msecs_to_jiffies(keypad->pdata->debounce_ms)); | ||
179 | |||
180 | out: | ||
181 | spin_unlock_irqrestore(&keypad->lock, flags); | ||
182 | return IRQ_HANDLED; | ||
183 | } | ||
184 | |||
185 | static int matrix_keypad_start(struct input_dev *dev) | ||
186 | { | ||
187 | struct matrix_keypad *keypad = input_get_drvdata(dev); | ||
188 | |||
189 | keypad->stopped = false; | ||
190 | mb(); | ||
191 | |||
192 | /* | ||
193 | * Schedule an immediate key scan to capture current key state; | ||
194 | * columns will be activated and IRQs be enabled after the scan. | ||
195 | */ | ||
196 | schedule_delayed_work(&keypad->work, 0); | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static void matrix_keypad_stop(struct input_dev *dev) | ||
202 | { | ||
203 | struct matrix_keypad *keypad = input_get_drvdata(dev); | ||
204 | |||
205 | keypad->stopped = true; | ||
206 | mb(); | ||
207 | flush_work(&keypad->work.work); | ||
208 | /* | ||
209 | * matrix_keypad_scan() will leave IRQs enabled; | ||
210 | * we should disable them now. | ||
211 | */ | ||
212 | disable_row_irqs(keypad); | ||
213 | } | ||
214 | |||
215 | #ifdef CONFIG_PM | ||
216 | static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state) | ||
217 | { | ||
218 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | ||
219 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
220 | int i; | ||
221 | |||
222 | matrix_keypad_stop(keypad->input_dev); | ||
223 | |||
224 | if (device_may_wakeup(&pdev->dev)) | ||
225 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
226 | enable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int matrix_keypad_resume(struct platform_device *pdev) | ||
232 | { | ||
233 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | ||
234 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
235 | int i; | ||
236 | |||
237 | if (device_may_wakeup(&pdev->dev)) | ||
238 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
239 | disable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); | ||
240 | |||
241 | matrix_keypad_start(keypad->input_dev); | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | #else | ||
246 | #define matrix_keypad_suspend NULL | ||
247 | #define matrix_keypad_resume NULL | ||
248 | #endif | ||
249 | |||
250 | static int __devinit init_matrix_gpio(struct platform_device *pdev, | ||
251 | struct matrix_keypad *keypad) | ||
252 | { | ||
253 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
254 | int i, err = -EINVAL; | ||
255 | |||
256 | /* initialized strobe lines as outputs, activated */ | ||
257 | for (i = 0; i < pdata->num_col_gpios; i++) { | ||
258 | err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col"); | ||
259 | if (err) { | ||
260 | dev_err(&pdev->dev, | ||
261 | "failed to request GPIO%d for COL%d\n", | ||
262 | pdata->col_gpios[i], i); | ||
263 | goto err_free_cols; | ||
264 | } | ||
265 | |||
266 | gpio_direction_output(pdata->col_gpios[i], !pdata->active_low); | ||
267 | } | ||
268 | |||
269 | for (i = 0; i < pdata->num_row_gpios; i++) { | ||
270 | err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row"); | ||
271 | if (err) { | ||
272 | dev_err(&pdev->dev, | ||
273 | "failed to request GPIO%d for ROW%d\n", | ||
274 | pdata->row_gpios[i], i); | ||
275 | goto err_free_rows; | ||
276 | } | ||
277 | |||
278 | gpio_direction_input(pdata->row_gpios[i]); | ||
279 | } | ||
280 | |||
281 | for (i = 0; i < pdata->num_row_gpios; i++) { | ||
282 | err = request_irq(gpio_to_irq(pdata->row_gpios[i]), | ||
283 | matrix_keypad_interrupt, | ||
284 | IRQF_DISABLED | | ||
285 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
286 | "matrix-keypad", keypad); | ||
287 | if (err) { | ||
288 | dev_err(&pdev->dev, | ||
289 | "Unable to acquire interrupt for GPIO line %i\n", | ||
290 | pdata->row_gpios[i]); | ||
291 | goto err_free_irqs; | ||
292 | } | ||
293 | } | ||
294 | |||
295 | /* initialized as disabled - enabled by input->open */ | ||
296 | disable_row_irqs(keypad); | ||
297 | return 0; | ||
298 | |||
299 | err_free_irqs: | ||
300 | while (--i >= 0) | ||
301 | free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); | ||
302 | i = pdata->num_row_gpios; | ||
303 | err_free_rows: | ||
304 | while (--i >= 0) | ||
305 | gpio_free(pdata->row_gpios[i]); | ||
306 | i = pdata->num_col_gpios; | ||
307 | err_free_cols: | ||
308 | while (--i >= 0) | ||
309 | gpio_free(pdata->col_gpios[i]); | ||
310 | |||
311 | return err; | ||
312 | } | ||
313 | |||
314 | static int __devinit matrix_keypad_probe(struct platform_device *pdev) | ||
315 | { | ||
316 | const struct matrix_keypad_platform_data *pdata; | ||
317 | const struct matrix_keymap_data *keymap_data; | ||
318 | struct matrix_keypad *keypad; | ||
319 | struct input_dev *input_dev; | ||
320 | unsigned short *keycodes; | ||
321 | unsigned int row_shift; | ||
322 | int err; | ||
323 | |||
324 | pdata = pdev->dev.platform_data; | ||
325 | if (!pdata) { | ||
326 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
327 | return -EINVAL; | ||
328 | } | ||
329 | |||
330 | keymap_data = pdata->keymap_data; | ||
331 | if (!keymap_data) { | ||
332 | dev_err(&pdev->dev, "no keymap data defined\n"); | ||
333 | return -EINVAL; | ||
334 | } | ||
335 | |||
336 | row_shift = get_count_order(pdata->num_col_gpios); | ||
337 | |||
338 | keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL); | ||
339 | keycodes = kzalloc((pdata->num_row_gpios << row_shift) * | ||
340 | sizeof(*keycodes), | ||
341 | GFP_KERNEL); | ||
342 | input_dev = input_allocate_device(); | ||
343 | if (!keypad || !keycodes || !input_dev) { | ||
344 | err = -ENOMEM; | ||
345 | goto err_free_mem; | ||
346 | } | ||
347 | |||
348 | keypad->input_dev = input_dev; | ||
349 | keypad->pdata = pdata; | ||
350 | keypad->keycodes = keycodes; | ||
351 | keypad->row_shift = row_shift; | ||
352 | keypad->stopped = true; | ||
353 | INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); | ||
354 | spin_lock_init(&keypad->lock); | ||
355 | |||
356 | input_dev->name = pdev->name; | ||
357 | input_dev->id.bustype = BUS_HOST; | ||
358 | input_dev->dev.parent = &pdev->dev; | ||
359 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
360 | input_dev->open = matrix_keypad_start; | ||
361 | input_dev->close = matrix_keypad_stop; | ||
362 | |||
363 | input_dev->keycode = keycodes; | ||
364 | input_dev->keycodesize = sizeof(*keycodes); | ||
365 | input_dev->keycodemax = pdata->num_row_gpios << row_shift; | ||
366 | |||
367 | matrix_keypad_build_keymap(keymap_data, row_shift, | ||
368 | input_dev->keycode, input_dev->keybit); | ||
369 | |||
370 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
371 | input_set_drvdata(input_dev, keypad); | ||
372 | |||
373 | err = init_matrix_gpio(pdev, keypad); | ||
374 | if (err) | ||
375 | goto err_free_mem; | ||
376 | |||
377 | err = input_register_device(keypad->input_dev); | ||
378 | if (err) | ||
379 | goto err_free_mem; | ||
380 | |||
381 | device_init_wakeup(&pdev->dev, pdata->wakeup); | ||
382 | platform_set_drvdata(pdev, keypad); | ||
383 | |||
384 | return 0; | ||
385 | |||
386 | err_free_mem: | ||
387 | input_free_device(input_dev); | ||
388 | kfree(keycodes); | ||
389 | kfree(keypad); | ||
390 | return err; | ||
391 | } | ||
392 | |||
393 | static int __devexit matrix_keypad_remove(struct platform_device *pdev) | ||
394 | { | ||
395 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | ||
396 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
397 | int i; | ||
398 | |||
399 | device_init_wakeup(&pdev->dev, 0); | ||
400 | |||
401 | for (i = 0; i < pdata->num_row_gpios; i++) { | ||
402 | free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); | ||
403 | gpio_free(pdata->row_gpios[i]); | ||
404 | } | ||
405 | |||
406 | for (i = 0; i < pdata->num_col_gpios; i++) | ||
407 | gpio_free(pdata->col_gpios[i]); | ||
408 | |||
409 | input_unregister_device(keypad->input_dev); | ||
410 | platform_set_drvdata(pdev, NULL); | ||
411 | kfree(keypad->keycodes); | ||
412 | kfree(keypad); | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static struct platform_driver matrix_keypad_driver = { | ||
418 | .probe = matrix_keypad_probe, | ||
419 | .remove = __devexit_p(matrix_keypad_remove), | ||
420 | .suspend = matrix_keypad_suspend, | ||
421 | .resume = matrix_keypad_resume, | ||
422 | .driver = { | ||
423 | .name = "matrix-keypad", | ||
424 | .owner = THIS_MODULE, | ||
425 | }, | ||
426 | }; | ||
427 | |||
428 | static int __init matrix_keypad_init(void) | ||
429 | { | ||
430 | return platform_driver_register(&matrix_keypad_driver); | ||
431 | } | ||
432 | |||
433 | static void __exit matrix_keypad_exit(void) | ||
434 | { | ||
435 | platform_driver_unregister(&matrix_keypad_driver); | ||
436 | } | ||
437 | |||
438 | module_init(matrix_keypad_init); | ||
439 | module_exit(matrix_keypad_exit); | ||
440 | |||
441 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
442 | MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver"); | ||
443 | MODULE_LICENSE("GPL v2"); | ||
444 | MODULE_ALIAS("platform:matrix-keypad"); | ||
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 87ec7b18ac69..bba85add35a3 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
@@ -116,7 +116,7 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id) | |||
116 | } | 116 | } |
117 | } else | 117 | } else |
118 | /* disable keyboard interrupt and schedule for handling */ | 118 | /* disable keyboard interrupt and schedule for handling */ |
119 | omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 119 | omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
120 | 120 | ||
121 | tasklet_schedule(&kp_tasklet); | 121 | tasklet_schedule(&kp_tasklet); |
122 | 122 | ||
@@ -143,20 +143,20 @@ static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state) | |||
143 | 143 | ||
144 | } else { | 144 | } else { |
145 | /* disable keyboard interrupt and schedule for handling */ | 145 | /* disable keyboard interrupt and schedule for handling */ |
146 | omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 146 | omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
147 | 147 | ||
148 | /* read the keypad status */ | 148 | /* read the keypad status */ |
149 | omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC); | 149 | omap_writew(0xff, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC); |
150 | for (col = 0; col < omap_kp->cols; col++) { | 150 | for (col = 0; col < omap_kp->cols; col++) { |
151 | omap_writew(~(1 << col) & 0xff, | 151 | omap_writew(~(1 << col) & 0xff, |
152 | OMAP_MPUIO_BASE + OMAP_MPUIO_KBC); | 152 | OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC); |
153 | 153 | ||
154 | udelay(omap_kp->delay); | 154 | udelay(omap_kp->delay); |
155 | 155 | ||
156 | state[col] = ~omap_readw(OMAP_MPUIO_BASE + | 156 | state[col] = ~omap_readw(OMAP1_MPUIO_BASE + |
157 | OMAP_MPUIO_KBR_LATCH) & 0xff; | 157 | OMAP_MPUIO_KBR_LATCH) & 0xff; |
158 | } | 158 | } |
159 | omap_writew(0x00, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC); | 159 | omap_writew(0x00, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC); |
160 | udelay(2); | 160 | udelay(2); |
161 | } | 161 | } |
162 | } | 162 | } |
@@ -234,7 +234,7 @@ static void omap_kp_tasklet(unsigned long data) | |||
234 | for (i = 0; i < omap_kp_data->rows; i++) | 234 | for (i = 0; i < omap_kp_data->rows; i++) |
235 | enable_irq(gpio_to_irq(row_gpios[i])); | 235 | enable_irq(gpio_to_irq(row_gpios[i])); |
236 | } else { | 236 | } else { |
237 | omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 237 | omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
238 | kp_cur_group = -1; | 238 | kp_cur_group = -1; |
239 | } | 239 | } |
240 | } | 240 | } |
@@ -317,7 +317,7 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) | |||
317 | 317 | ||
318 | /* Disable the interrupt for the MPUIO keyboard */ | 318 | /* Disable the interrupt for the MPUIO keyboard */ |
319 | if (!cpu_is_omap24xx()) | 319 | if (!cpu_is_omap24xx()) |
320 | omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 320 | omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
321 | 321 | ||
322 | keymap = pdata->keymap; | 322 | keymap = pdata->keymap; |
323 | 323 | ||
@@ -391,7 +391,7 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) | |||
391 | } | 391 | } |
392 | 392 | ||
393 | if (pdata->dbounce) | 393 | if (pdata->dbounce) |
394 | omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING); | 394 | omap_writew(0xff, OMAP1_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING); |
395 | 395 | ||
396 | /* scan current status and enable interrupt */ | 396 | /* scan current status and enable interrupt */ |
397 | omap_kp_scan_keypad(omap_kp, keypad_state); | 397 | omap_kp_scan_keypad(omap_kp, keypad_state); |
@@ -402,7 +402,7 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) | |||
402 | "omap-keypad", omap_kp) < 0) | 402 | "omap-keypad", omap_kp) < 0) |
403 | goto err4; | 403 | goto err4; |
404 | } | 404 | } |
405 | omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 405 | omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
406 | } else { | 406 | } else { |
407 | for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { | 407 | for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { |
408 | if (request_irq(gpio_to_irq(row_gpios[irq_idx]), | 408 | if (request_irq(gpio_to_irq(row_gpios[irq_idx]), |
@@ -449,7 +449,7 @@ static int __devexit omap_kp_remove(struct platform_device *pdev) | |||
449 | free_irq(gpio_to_irq(row_gpios[i]), 0); | 449 | free_irq(gpio_to_irq(row_gpios[i]), 0); |
450 | } | 450 | } |
451 | } else { | 451 | } else { |
452 | omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 452 | omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
453 | free_irq(omap_kp->irq, 0); | 453 | free_irq(omap_kp->irq, 0); |
454 | } | 454 | } |
455 | 455 | ||
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 0d2fc64a5e1c..79cd3e9fdf2e 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * | 8 | * |
9 | * Based on a previous implementations by Kevin O'Connor | 9 | * Based on a previous implementations by Kevin O'Connor |
10 | * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and | 10 | * <kevin_at_koconnor.net> and Alex Osborne <bobofdoom@gmail.com> and |
11 | * on some suggestions by Nicolas Pitre <nico@cam.org>. | 11 | * on some suggestions by Nicolas Pitre <nico@fluxnic.net>. |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License version 2 as | 14 | * it under the terms of the GNU General Public License version 2 as |
@@ -25,13 +25,13 @@ | |||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
28 | #include <linux/input/matrix_keypad.h> | ||
28 | 29 | ||
29 | #include <asm/mach/arch.h> | 30 | #include <asm/mach/arch.h> |
30 | #include <asm/mach/map.h> | 31 | #include <asm/mach/map.h> |
31 | 32 | ||
32 | #include <mach/hardware.h> | 33 | #include <mach/hardware.h> |
33 | #include <mach/pxa27x_keypad.h> | 34 | #include <mach/pxa27x_keypad.h> |
34 | |||
35 | /* | 35 | /* |
36 | * Keypad Controller registers | 36 | * Keypad Controller registers |
37 | */ | 37 | */ |
@@ -95,7 +95,8 @@ | |||
95 | #define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) | 95 | #define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) |
96 | #define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off)) | 96 | #define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off)) |
97 | 97 | ||
98 | #define MAX_MATRIX_KEY_NUM (8 * 8) | 98 | #define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS) |
99 | #define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM) | ||
99 | 100 | ||
100 | struct pxa27x_keypad { | 101 | struct pxa27x_keypad { |
101 | struct pxa27x_keypad_platform_data *pdata; | 102 | struct pxa27x_keypad_platform_data *pdata; |
@@ -106,73 +107,82 @@ struct pxa27x_keypad { | |||
106 | 107 | ||
107 | int irq; | 108 | int irq; |
108 | 109 | ||
109 | /* matrix key code map */ | 110 | unsigned short keycodes[MAX_KEYPAD_KEYS]; |
110 | unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; | 111 | int rotary_rel_code[2]; |
111 | 112 | ||
112 | /* state row bits of each column scan */ | 113 | /* state row bits of each column scan */ |
113 | uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS]; | 114 | uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS]; |
114 | uint32_t direct_key_state; | 115 | uint32_t direct_key_state; |
115 | 116 | ||
116 | unsigned int direct_key_mask; | 117 | unsigned int direct_key_mask; |
117 | |||
118 | int rotary_rel_code[2]; | ||
119 | int rotary_up_key[2]; | ||
120 | int rotary_down_key[2]; | ||
121 | }; | 118 | }; |
122 | 119 | ||
123 | static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) | 120 | static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad) |
124 | { | 121 | { |
125 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 122 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
126 | struct input_dev *input_dev = keypad->input_dev; | 123 | struct input_dev *input_dev = keypad->input_dev; |
127 | unsigned int *key; | 124 | unsigned short keycode; |
128 | int i; | 125 | int i; |
129 | 126 | ||
130 | key = &pdata->matrix_key_map[0]; | 127 | for (i = 0; i < pdata->matrix_key_map_size; i++) { |
131 | for (i = 0; i < pdata->matrix_key_map_size; i++, key++) { | 128 | unsigned int key = pdata->matrix_key_map[i]; |
132 | int row = ((*key) >> 28) & 0xf; | 129 | unsigned int row = KEY_ROW(key); |
133 | int col = ((*key) >> 24) & 0xf; | 130 | unsigned int col = KEY_COL(key); |
134 | int code = (*key) & 0xffffff; | 131 | unsigned int scancode = MATRIX_SCAN_CODE(row, col, |
132 | MATRIX_ROW_SHIFT); | ||
135 | 133 | ||
136 | keypad->matrix_keycodes[(row << 3) + col] = code; | 134 | keycode = KEY_VAL(key); |
137 | set_bit(code, input_dev->keybit); | 135 | keypad->keycodes[scancode] = keycode; |
136 | __set_bit(keycode, input_dev->keybit); | ||
138 | } | 137 | } |
139 | 138 | ||
140 | for (i = 0; i < pdata->direct_key_num; i++) | 139 | for (i = 0; i < pdata->direct_key_num; i++) { |
141 | set_bit(pdata->direct_key_map[i], input_dev->keybit); | 140 | keycode = pdata->direct_key_map[i]; |
142 | 141 | keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode; | |
143 | keypad->rotary_up_key[0] = pdata->rotary0_up_key; | 142 | __set_bit(keycode, input_dev->keybit); |
144 | keypad->rotary_up_key[1] = pdata->rotary1_up_key; | 143 | } |
145 | keypad->rotary_down_key[0] = pdata->rotary0_down_key; | ||
146 | keypad->rotary_down_key[1] = pdata->rotary1_down_key; | ||
147 | keypad->rotary_rel_code[0] = pdata->rotary0_rel_code; | ||
148 | keypad->rotary_rel_code[1] = pdata->rotary1_rel_code; | ||
149 | 144 | ||
150 | if (pdata->enable_rotary0) { | 145 | if (pdata->enable_rotary0) { |
151 | if (pdata->rotary0_up_key && pdata->rotary0_down_key) { | 146 | if (pdata->rotary0_up_key && pdata->rotary0_down_key) { |
152 | set_bit(pdata->rotary0_up_key, input_dev->keybit); | 147 | keycode = pdata->rotary0_up_key; |
153 | set_bit(pdata->rotary0_down_key, input_dev->keybit); | 148 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 0] = keycode; |
154 | } else | 149 | __set_bit(keycode, input_dev->keybit); |
155 | set_bit(pdata->rotary0_rel_code, input_dev->relbit); | 150 | |
151 | keycode = pdata->rotary0_down_key; | ||
152 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 1] = keycode; | ||
153 | __set_bit(keycode, input_dev->keybit); | ||
154 | |||
155 | keypad->rotary_rel_code[0] = -1; | ||
156 | } else { | ||
157 | keypad->rotary_rel_code[0] = pdata->rotary0_rel_code; | ||
158 | __set_bit(pdata->rotary0_rel_code, input_dev->relbit); | ||
159 | } | ||
156 | } | 160 | } |
157 | 161 | ||
158 | if (pdata->enable_rotary1) { | 162 | if (pdata->enable_rotary1) { |
159 | if (pdata->rotary1_up_key && pdata->rotary1_down_key) { | 163 | if (pdata->rotary1_up_key && pdata->rotary1_down_key) { |
160 | set_bit(pdata->rotary1_up_key, input_dev->keybit); | 164 | keycode = pdata->rotary1_up_key; |
161 | set_bit(pdata->rotary1_down_key, input_dev->keybit); | 165 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 2] = keycode; |
162 | } else | 166 | __set_bit(keycode, input_dev->keybit); |
163 | set_bit(pdata->rotary1_rel_code, input_dev->relbit); | 167 | |
168 | keycode = pdata->rotary1_down_key; | ||
169 | keypad->keycodes[MAX_MATRIX_KEY_NUM + 3] = keycode; | ||
170 | __set_bit(keycode, input_dev->keybit); | ||
171 | |||
172 | keypad->rotary_rel_code[1] = -1; | ||
173 | } else { | ||
174 | keypad->rotary_rel_code[1] = pdata->rotary1_rel_code; | ||
175 | __set_bit(pdata->rotary1_rel_code, input_dev->relbit); | ||
176 | } | ||
164 | } | 177 | } |
165 | } | ||
166 | 178 | ||
167 | static inline unsigned int lookup_matrix_keycode( | 179 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
168 | struct pxa27x_keypad *keypad, int row, int col) | ||
169 | { | ||
170 | return keypad->matrix_keycodes[(row << 3) + col]; | ||
171 | } | 180 | } |
172 | 181 | ||
173 | static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) | 182 | static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) |
174 | { | 183 | { |
175 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 184 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
185 | struct input_dev *input_dev = keypad->input_dev; | ||
176 | int row, col, num_keys_pressed = 0; | 186 | int row, col, num_keys_pressed = 0; |
177 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; | 187 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; |
178 | uint32_t kpas = keypad_readl(KPAS); | 188 | uint32_t kpas = keypad_readl(KPAS); |
@@ -215,6 +225,7 @@ static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) | |||
215 | scan: | 225 | scan: |
216 | for (col = 0; col < pdata->matrix_key_cols; col++) { | 226 | for (col = 0; col < pdata->matrix_key_cols; col++) { |
217 | uint32_t bits_changed; | 227 | uint32_t bits_changed; |
228 | int code; | ||
218 | 229 | ||
219 | bits_changed = keypad->matrix_key_state[col] ^ new_state[col]; | 230 | bits_changed = keypad->matrix_key_state[col] ^ new_state[col]; |
220 | if (bits_changed == 0) | 231 | if (bits_changed == 0) |
@@ -224,12 +235,13 @@ scan: | |||
224 | if ((bits_changed & (1 << row)) == 0) | 235 | if ((bits_changed & (1 << row)) == 0) |
225 | continue; | 236 | continue; |
226 | 237 | ||
227 | input_report_key(keypad->input_dev, | 238 | code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT); |
228 | lookup_matrix_keycode(keypad, row, col), | 239 | input_event(input_dev, EV_MSC, MSC_SCAN, code); |
229 | new_state[col] & (1 << row)); | 240 | input_report_key(input_dev, keypad->keycodes[code], |
241 | new_state[col] & (1 << row)); | ||
230 | } | 242 | } |
231 | } | 243 | } |
232 | input_sync(keypad->input_dev); | 244 | input_sync(input_dev); |
233 | memcpy(keypad->matrix_key_state, new_state, sizeof(new_state)); | 245 | memcpy(keypad->matrix_key_state, new_state, sizeof(new_state)); |
234 | } | 246 | } |
235 | 247 | ||
@@ -252,13 +264,15 @@ static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta) | |||
252 | if (delta == 0) | 264 | if (delta == 0) |
253 | return; | 265 | return; |
254 | 266 | ||
255 | if (keypad->rotary_up_key[r] && keypad->rotary_down_key[r]) { | 267 | if (keypad->rotary_rel_code[r] == -1) { |
256 | int keycode = (delta > 0) ? keypad->rotary_up_key[r] : | 268 | int code = MAX_MATRIX_KEY_NUM + 2 * r + (delta > 0 ? 0 : 1); |
257 | keypad->rotary_down_key[r]; | 269 | unsigned char keycode = keypad->keycodes[code]; |
258 | 270 | ||
259 | /* simulate a press-n-release */ | 271 | /* simulate a press-n-release */ |
272 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
260 | input_report_key(dev, keycode, 1); | 273 | input_report_key(dev, keycode, 1); |
261 | input_sync(dev); | 274 | input_sync(dev); |
275 | input_event(dev, EV_MSC, MSC_SCAN, code); | ||
262 | input_report_key(dev, keycode, 0); | 276 | input_report_key(dev, keycode, 0); |
263 | input_sync(dev); | 277 | input_sync(dev); |
264 | } else { | 278 | } else { |
@@ -286,6 +300,7 @@ static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) | |||
286 | static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | 300 | static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) |
287 | { | 301 | { |
288 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 302 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
303 | struct input_dev *input_dev = keypad->input_dev; | ||
289 | unsigned int new_state; | 304 | unsigned int new_state; |
290 | uint32_t kpdk, bits_changed; | 305 | uint32_t kpdk, bits_changed; |
291 | int i; | 306 | int i; |
@@ -295,9 +310,6 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
295 | if (pdata->enable_rotary0 || pdata->enable_rotary1) | 310 | if (pdata->enable_rotary0 || pdata->enable_rotary1) |
296 | pxa27x_keypad_scan_rotary(keypad); | 311 | pxa27x_keypad_scan_rotary(keypad); |
297 | 312 | ||
298 | if (pdata->direct_key_map == NULL) | ||
299 | return; | ||
300 | |||
301 | new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; | 313 | new_state = KPDK_DK(kpdk) & keypad->direct_key_mask; |
302 | bits_changed = keypad->direct_key_state ^ new_state; | 314 | bits_changed = keypad->direct_key_state ^ new_state; |
303 | 315 | ||
@@ -305,12 +317,15 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
305 | return; | 317 | return; |
306 | 318 | ||
307 | for (i = 0; i < pdata->direct_key_num; i++) { | 319 | for (i = 0; i < pdata->direct_key_num; i++) { |
308 | if (bits_changed & (1 << i)) | 320 | if (bits_changed & (1 << i)) { |
309 | input_report_key(keypad->input_dev, | 321 | int code = MAX_MATRIX_KEY_NUM + i; |
310 | pdata->direct_key_map[i], | 322 | |
311 | (new_state & (1 << i))); | 323 | input_event(input_dev, EV_MSC, MSC_SCAN, code); |
324 | input_report_key(input_dev, keypad->keycodes[code], | ||
325 | new_state & (1 << i)); | ||
326 | } | ||
312 | } | 327 | } |
313 | input_sync(keypad->input_dev); | 328 | input_sync(input_dev); |
314 | keypad->direct_key_state = new_state; | 329 | keypad->direct_key_state = new_state; |
315 | } | 330 | } |
316 | 331 | ||
@@ -388,8 +403,9 @@ static void pxa27x_keypad_close(struct input_dev *dev) | |||
388 | } | 403 | } |
389 | 404 | ||
390 | #ifdef CONFIG_PM | 405 | #ifdef CONFIG_PM |
391 | static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t state) | 406 | static int pxa27x_keypad_suspend(struct device *dev) |
392 | { | 407 | { |
408 | struct platform_device *pdev = to_platform_device(dev); | ||
393 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 409 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
394 | 410 | ||
395 | clk_disable(keypad->clk); | 411 | clk_disable(keypad->clk); |
@@ -400,8 +416,9 @@ static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t stat | |||
400 | return 0; | 416 | return 0; |
401 | } | 417 | } |
402 | 418 | ||
403 | static int pxa27x_keypad_resume(struct platform_device *pdev) | 419 | static int pxa27x_keypad_resume(struct device *dev) |
404 | { | 420 | { |
421 | struct platform_device *pdev = to_platform_device(dev); | ||
405 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 422 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
406 | struct input_dev *input_dev = keypad->input_dev; | 423 | struct input_dev *input_dev = keypad->input_dev; |
407 | 424 | ||
@@ -420,55 +437,58 @@ static int pxa27x_keypad_resume(struct platform_device *pdev) | |||
420 | 437 | ||
421 | return 0; | 438 | return 0; |
422 | } | 439 | } |
423 | #else | ||
424 | #define pxa27x_keypad_suspend NULL | ||
425 | #define pxa27x_keypad_resume NULL | ||
426 | #endif | ||
427 | 440 | ||
428 | #define res_size(res) ((res)->end - (res)->start + 1) | 441 | static const struct dev_pm_ops pxa27x_keypad_pm_ops = { |
442 | .suspend = pxa27x_keypad_suspend, | ||
443 | .resume = pxa27x_keypad_resume, | ||
444 | }; | ||
445 | #endif | ||
429 | 446 | ||
430 | static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | 447 | static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) |
431 | { | 448 | { |
449 | struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data; | ||
432 | struct pxa27x_keypad *keypad; | 450 | struct pxa27x_keypad *keypad; |
433 | struct input_dev *input_dev; | 451 | struct input_dev *input_dev; |
434 | struct resource *res; | 452 | struct resource *res; |
435 | int irq, error; | 453 | int irq, error; |
436 | 454 | ||
437 | keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL); | 455 | if (pdata == NULL) { |
438 | if (keypad == NULL) { | ||
439 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
440 | return -ENOMEM; | ||
441 | } | ||
442 | |||
443 | keypad->pdata = pdev->dev.platform_data; | ||
444 | if (keypad->pdata == NULL) { | ||
445 | dev_err(&pdev->dev, "no platform data defined\n"); | 456 | dev_err(&pdev->dev, "no platform data defined\n"); |
446 | error = -EINVAL; | 457 | return -EINVAL; |
447 | goto failed_free; | ||
448 | } | 458 | } |
449 | 459 | ||
450 | irq = platform_get_irq(pdev, 0); | 460 | irq = platform_get_irq(pdev, 0); |
451 | if (irq < 0) { | 461 | if (irq < 0) { |
452 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | 462 | dev_err(&pdev->dev, "failed to get keypad irq\n"); |
453 | error = -ENXIO; | 463 | return -ENXIO; |
454 | goto failed_free; | ||
455 | } | 464 | } |
456 | 465 | ||
457 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 466 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
458 | if (res == NULL) { | 467 | if (res == NULL) { |
459 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | 468 | dev_err(&pdev->dev, "failed to get I/O memory\n"); |
460 | error = -ENXIO; | 469 | return -ENXIO; |
470 | } | ||
471 | |||
472 | keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL); | ||
473 | input_dev = input_allocate_device(); | ||
474 | if (!keypad || !input_dev) { | ||
475 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
476 | error = -ENOMEM; | ||
461 | goto failed_free; | 477 | goto failed_free; |
462 | } | 478 | } |
463 | 479 | ||
464 | res = request_mem_region(res->start, res_size(res), pdev->name); | 480 | keypad->pdata = pdata; |
481 | keypad->input_dev = input_dev; | ||
482 | keypad->irq = irq; | ||
483 | |||
484 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
465 | if (res == NULL) { | 485 | if (res == NULL) { |
466 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | 486 | dev_err(&pdev->dev, "failed to request I/O memory\n"); |
467 | error = -EBUSY; | 487 | error = -EBUSY; |
468 | goto failed_free; | 488 | goto failed_free; |
469 | } | 489 | } |
470 | 490 | ||
471 | keypad->mmio_base = ioremap(res->start, res_size(res)); | 491 | keypad->mmio_base = ioremap(res->start, resource_size(res)); |
472 | if (keypad->mmio_base == NULL) { | 492 | if (keypad->mmio_base == NULL) { |
473 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | 493 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); |
474 | error = -ENXIO; | 494 | error = -ENXIO; |
@@ -482,43 +502,35 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | |||
482 | goto failed_free_io; | 502 | goto failed_free_io; |
483 | } | 503 | } |
484 | 504 | ||
485 | /* Create and register the input driver. */ | ||
486 | input_dev = input_allocate_device(); | ||
487 | if (!input_dev) { | ||
488 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
489 | error = -ENOMEM; | ||
490 | goto failed_put_clk; | ||
491 | } | ||
492 | |||
493 | input_dev->name = pdev->name; | 505 | input_dev->name = pdev->name; |
494 | input_dev->id.bustype = BUS_HOST; | 506 | input_dev->id.bustype = BUS_HOST; |
495 | input_dev->open = pxa27x_keypad_open; | 507 | input_dev->open = pxa27x_keypad_open; |
496 | input_dev->close = pxa27x_keypad_close; | 508 | input_dev->close = pxa27x_keypad_close; |
497 | input_dev->dev.parent = &pdev->dev; | 509 | input_dev->dev.parent = &pdev->dev; |
498 | 510 | ||
499 | keypad->input_dev = input_dev; | 511 | input_dev->keycode = keypad->keycodes; |
512 | input_dev->keycodesize = sizeof(keypad->keycodes[0]); | ||
513 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
514 | |||
500 | input_set_drvdata(input_dev, keypad); | 515 | input_set_drvdata(input_dev, keypad); |
501 | 516 | ||
502 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 517 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); |
503 | if ((keypad->pdata->enable_rotary0 && | 518 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
504 | keypad->pdata->rotary0_rel_code) || | ||
505 | (keypad->pdata->enable_rotary1 && | ||
506 | keypad->pdata->rotary1_rel_code)) { | ||
507 | input_dev->evbit[0] |= BIT_MASK(EV_REL); | ||
508 | } | ||
509 | 519 | ||
510 | pxa27x_keypad_build_keycode(keypad); | 520 | pxa27x_keypad_build_keycode(keypad); |
511 | platform_set_drvdata(pdev, keypad); | 521 | |
522 | if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) || | ||
523 | (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) { | ||
524 | input_dev->evbit[0] |= BIT_MASK(EV_REL); | ||
525 | } | ||
512 | 526 | ||
513 | error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED, | 527 | error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED, |
514 | pdev->name, keypad); | 528 | pdev->name, keypad); |
515 | if (error) { | 529 | if (error) { |
516 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 530 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
517 | goto failed_free_dev; | 531 | goto failed_put_clk; |
518 | } | 532 | } |
519 | 533 | ||
520 | keypad->irq = irq; | ||
521 | |||
522 | /* Register the input device */ | 534 | /* Register the input device */ |
523 | error = input_register_device(input_dev); | 535 | error = input_register_device(input_dev); |
524 | if (error) { | 536 | if (error) { |
@@ -526,22 +538,21 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | |||
526 | goto failed_free_irq; | 538 | goto failed_free_irq; |
527 | } | 539 | } |
528 | 540 | ||
541 | platform_set_drvdata(pdev, keypad); | ||
529 | device_init_wakeup(&pdev->dev, 1); | 542 | device_init_wakeup(&pdev->dev, 1); |
530 | 543 | ||
531 | return 0; | 544 | return 0; |
532 | 545 | ||
533 | failed_free_irq: | 546 | failed_free_irq: |
534 | free_irq(irq, pdev); | 547 | free_irq(irq, pdev); |
535 | platform_set_drvdata(pdev, NULL); | ||
536 | failed_free_dev: | ||
537 | input_free_device(input_dev); | ||
538 | failed_put_clk: | 548 | failed_put_clk: |
539 | clk_put(keypad->clk); | 549 | clk_put(keypad->clk); |
540 | failed_free_io: | 550 | failed_free_io: |
541 | iounmap(keypad->mmio_base); | 551 | iounmap(keypad->mmio_base); |
542 | failed_free_mem: | 552 | failed_free_mem: |
543 | release_mem_region(res->start, res_size(res)); | 553 | release_mem_region(res->start, resource_size(res)); |
544 | failed_free: | 554 | failed_free: |
555 | input_free_device(input_dev); | ||
545 | kfree(keypad); | 556 | kfree(keypad); |
546 | return error; | 557 | return error; |
547 | } | 558 | } |
@@ -552,8 +563,6 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) | |||
552 | struct resource *res; | 563 | struct resource *res; |
553 | 564 | ||
554 | free_irq(keypad->irq, pdev); | 565 | free_irq(keypad->irq, pdev); |
555 | |||
556 | clk_disable(keypad->clk); | ||
557 | clk_put(keypad->clk); | 566 | clk_put(keypad->clk); |
558 | 567 | ||
559 | input_unregister_device(keypad->input_dev); | 568 | input_unregister_device(keypad->input_dev); |
@@ -562,10 +571,11 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) | |||
562 | iounmap(keypad->mmio_base); | 571 | iounmap(keypad->mmio_base); |
563 | 572 | ||
564 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 573 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
565 | release_mem_region(res->start, res_size(res)); | 574 | release_mem_region(res->start, resource_size(res)); |
566 | 575 | ||
567 | platform_set_drvdata(pdev, NULL); | 576 | platform_set_drvdata(pdev, NULL); |
568 | kfree(keypad); | 577 | kfree(keypad); |
578 | |||
569 | return 0; | 579 | return 0; |
570 | } | 580 | } |
571 | 581 | ||
@@ -575,11 +585,12 @@ MODULE_ALIAS("platform:pxa27x-keypad"); | |||
575 | static struct platform_driver pxa27x_keypad_driver = { | 585 | static struct platform_driver pxa27x_keypad_driver = { |
576 | .probe = pxa27x_keypad_probe, | 586 | .probe = pxa27x_keypad_probe, |
577 | .remove = __devexit_p(pxa27x_keypad_remove), | 587 | .remove = __devexit_p(pxa27x_keypad_remove), |
578 | .suspend = pxa27x_keypad_suspend, | ||
579 | .resume = pxa27x_keypad_resume, | ||
580 | .driver = { | 588 | .driver = { |
581 | .name = "pxa27x-keypad", | 589 | .name = "pxa27x-keypad", |
582 | .owner = THIS_MODULE, | 590 | .owner = THIS_MODULE, |
591 | #ifdef CONFIG_PM | ||
592 | .pm = &pxa27x_keypad_pm_ops, | ||
593 | #endif | ||
583 | }, | 594 | }, |
584 | }; | 595 | }; |
585 | 596 | ||
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index cea70e6a1031..887af79b7bff 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c | |||
@@ -80,6 +80,9 @@ static irqreturn_t sh_keysc_isr(int irq, void *dev_id) | |||
80 | iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8), | 80 | iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8), |
81 | priv->iomem_base + KYCR2_OFFS); | 81 | priv->iomem_base + KYCR2_OFFS); |
82 | 82 | ||
83 | if (pdata->kycr2_delay) | ||
84 | udelay(pdata->kycr2_delay); | ||
85 | |||
83 | keys ^= ~0; | 86 | keys ^= ~0; |
84 | keys &= (1 << (sh_keysc_mode[pdata->mode].keyin * | 87 | keys &= (1 << (sh_keysc_mode[pdata->mode].keyin * |
85 | sh_keysc_mode[pdata->mode].keyout)) - 1; | 88 | sh_keysc_mode[pdata->mode].keyout)) - 1; |
@@ -128,7 +131,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
128 | struct resource *res; | 131 | struct resource *res; |
129 | struct input_dev *input; | 132 | struct input_dev *input; |
130 | char clk_name[8]; | 133 | char clk_name[8]; |
131 | int i, k; | 134 | int i; |
132 | int irq, error; | 135 | int irq, error; |
133 | 136 | ||
134 | if (!pdev->dev.platform_data) { | 137 | if (!pdev->dev.platform_data) { |
@@ -195,17 +198,19 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
195 | input->id.product = 0x0001; | 198 | input->id.product = 0x0001; |
196 | input->id.version = 0x0100; | 199 | input->id.version = 0x0100; |
197 | 200 | ||
201 | input->keycode = pdata->keycodes; | ||
202 | input->keycodesize = sizeof(pdata->keycodes[0]); | ||
203 | input->keycodemax = ARRAY_SIZE(pdata->keycodes); | ||
204 | |||
198 | error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); | 205 | error = request_irq(irq, sh_keysc_isr, 0, pdev->name, pdev); |
199 | if (error) { | 206 | if (error) { |
200 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 207 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
201 | goto err4; | 208 | goto err4; |
202 | } | 209 | } |
203 | 210 | ||
204 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { | 211 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) |
205 | k = pdata->keycodes[i]; | 212 | __set_bit(pdata->keycodes[i], input->keybit); |
206 | if (k) | 213 | __clear_bit(KEY_RESERVED, input->keybit); |
207 | input_set_capability(input, EV_KEY, k); | ||
208 | } | ||
209 | 214 | ||
210 | error = input_register_device(input); | 215 | error = input_register_device(input); |
211 | if (error) { | 216 | if (error) { |
@@ -221,7 +226,9 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
221 | iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); | 226 | iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); |
222 | 227 | ||
223 | device_init_wakeup(&pdev->dev, 1); | 228 | device_init_wakeup(&pdev->dev, 1); |
229 | |||
224 | return 0; | 230 | return 0; |
231 | |||
225 | err5: | 232 | err5: |
226 | free_irq(irq, pdev); | 233 | free_irq(irq, pdev); |
227 | err4: | 234 | err4: |
@@ -252,6 +259,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) | |||
252 | 259 | ||
253 | platform_set_drvdata(pdev, NULL); | 260 | platform_set_drvdata(pdev, NULL); |
254 | kfree(priv); | 261 | kfree(priv); |
262 | |||
255 | return 0; | 263 | return 0; |
256 | } | 264 | } |
257 | 265 | ||
@@ -267,11 +275,12 @@ static int sh_keysc_suspend(struct device *dev) | |||
267 | if (device_may_wakeup(dev)) { | 275 | if (device_may_wakeup(dev)) { |
268 | value |= 0x80; | 276 | value |= 0x80; |
269 | enable_irq_wake(irq); | 277 | enable_irq_wake(irq); |
270 | } | 278 | } else { |
271 | else | ||
272 | value &= ~0x80; | 279 | value &= ~0x80; |
280 | } | ||
273 | 281 | ||
274 | iowrite16(value, priv->iomem_base + KYCR1_OFFS); | 282 | iowrite16(value, priv->iomem_base + KYCR1_OFFS); |
283 | |||
275 | return 0; | 284 | return 0; |
276 | } | 285 | } |
277 | 286 | ||
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index 9fce6d1e29b2..472b56639cdb 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c | |||
@@ -73,7 +73,7 @@ static unsigned char sunkbd_keycode[128] = { | |||
73 | */ | 73 | */ |
74 | 74 | ||
75 | struct sunkbd { | 75 | struct sunkbd { |
76 | unsigned char keycode[128]; | 76 | unsigned char keycode[ARRAY_SIZE(sunkbd_keycode)]; |
77 | struct input_dev *dev; | 77 | struct input_dev *dev; |
78 | struct serio *serio; | 78 | struct serio *serio; |
79 | struct work_struct tq; | 79 | struct work_struct tq; |
@@ -81,7 +81,7 @@ struct sunkbd { | |||
81 | char name[64]; | 81 | char name[64]; |
82 | char phys[32]; | 82 | char phys[32]; |
83 | char type; | 83 | char type; |
84 | unsigned char enabled; | 84 | bool enabled; |
85 | volatile s8 reset; | 85 | volatile s8 reset; |
86 | volatile s8 layout; | 86 | volatile s8 layout; |
87 | }; | 87 | }; |
@@ -94,10 +94,14 @@ struct sunkbd { | |||
94 | static irqreturn_t sunkbd_interrupt(struct serio *serio, | 94 | static irqreturn_t sunkbd_interrupt(struct serio *serio, |
95 | unsigned char data, unsigned int flags) | 95 | unsigned char data, unsigned int flags) |
96 | { | 96 | { |
97 | struct sunkbd* sunkbd = serio_get_drvdata(serio); | 97 | struct sunkbd *sunkbd = serio_get_drvdata(serio); |
98 | 98 | ||
99 | if (sunkbd->reset <= -1) { /* If cp[i] is 0xff, sunkbd->reset will stay -1. */ | 99 | if (sunkbd->reset <= -1) { |
100 | sunkbd->reset = data; /* The keyboard sends 0xff 0xff 0xID on powerup */ | 100 | /* |
101 | * If cp[i] is 0xff, sunkbd->reset will stay -1. | ||
102 | * The keyboard sends 0xff 0xff 0xID on powerup. | ||
103 | */ | ||
104 | sunkbd->reset = data; | ||
101 | wake_up_interruptible(&sunkbd->wait); | 105 | wake_up_interruptible(&sunkbd->wait); |
102 | goto out; | 106 | goto out; |
103 | } | 107 | } |
@@ -110,29 +114,33 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio, | |||
110 | 114 | ||
111 | switch (data) { | 115 | switch (data) { |
112 | 116 | ||
113 | case SUNKBD_RET_RESET: | 117 | case SUNKBD_RET_RESET: |
114 | schedule_work(&sunkbd->tq); | 118 | schedule_work(&sunkbd->tq); |
115 | sunkbd->reset = -1; | 119 | sunkbd->reset = -1; |
116 | break; | 120 | break; |
117 | 121 | ||
118 | case SUNKBD_RET_LAYOUT: | 122 | case SUNKBD_RET_LAYOUT: |
119 | sunkbd->layout = -1; | 123 | sunkbd->layout = -1; |
120 | break; | 124 | break; |
125 | |||
126 | case SUNKBD_RET_ALLUP: /* All keys released */ | ||
127 | break; | ||
121 | 128 | ||
122 | case SUNKBD_RET_ALLUP: /* All keys released */ | 129 | default: |
130 | if (!sunkbd->enabled) | ||
123 | break; | 131 | break; |
124 | 132 | ||
125 | default: | 133 | if (sunkbd->keycode[data & SUNKBD_KEY]) { |
126 | if (!sunkbd->enabled) | 134 | input_report_key(sunkbd->dev, |
127 | break; | 135 | sunkbd->keycode[data & SUNKBD_KEY], |
128 | 136 | !(data & SUNKBD_RELEASE)); | |
129 | if (sunkbd->keycode[data & SUNKBD_KEY]) { | 137 | input_sync(sunkbd->dev); |
130 | input_report_key(sunkbd->dev, sunkbd->keycode[data & SUNKBD_KEY], !(data & SUNKBD_RELEASE)); | 138 | } else { |
131 | input_sync(sunkbd->dev); | 139 | printk(KERN_WARNING |
132 | } else { | 140 | "sunkbd.c: Unknown key (scancode %#x) %s.\n", |
133 | printk(KERN_WARNING "sunkbd.c: Unknown key (scancode %#x) %s.\n", | 141 | data & SUNKBD_KEY, |
134 | data & SUNKBD_KEY, data & SUNKBD_RELEASE ? "released" : "pressed"); | 142 | data & SUNKBD_RELEASE ? "released" : "pressed"); |
135 | } | 143 | } |
136 | } | 144 | } |
137 | out: | 145 | out: |
138 | return IRQ_HANDLED; | 146 | return IRQ_HANDLED; |
@@ -142,34 +150,37 @@ out: | |||
142 | * sunkbd_event() handles events from the input module. | 150 | * sunkbd_event() handles events from the input module. |
143 | */ | 151 | */ |
144 | 152 | ||
145 | static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 153 | static int sunkbd_event(struct input_dev *dev, |
154 | unsigned int type, unsigned int code, int value) | ||
146 | { | 155 | { |
147 | struct sunkbd *sunkbd = input_get_drvdata(dev); | 156 | struct sunkbd *sunkbd = input_get_drvdata(dev); |
148 | 157 | ||
149 | switch (type) { | 158 | switch (type) { |
150 | 159 | ||
151 | case EV_LED: | 160 | case EV_LED: |
152 | 161 | ||
153 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); | 162 | serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); |
154 | sunkbd->serio->write(sunkbd->serio, | 163 | serio_write(sunkbd->serio, |
155 | (!!test_bit(LED_CAPSL, dev->led) << 3) | (!!test_bit(LED_SCROLLL, dev->led) << 2) | | 164 | (!!test_bit(LED_CAPSL, dev->led) << 3) | |
156 | (!!test_bit(LED_COMPOSE, dev->led) << 1) | !!test_bit(LED_NUML, dev->led)); | 165 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | |
157 | return 0; | 166 | (!!test_bit(LED_COMPOSE, dev->led) << 1) | |
167 | !!test_bit(LED_NUML, dev->led)); | ||
168 | return 0; | ||
158 | 169 | ||
159 | case EV_SND: | 170 | case EV_SND: |
160 | 171 | ||
161 | switch (code) { | 172 | switch (code) { |
162 | 173 | ||
163 | case SND_CLICK: | 174 | case SND_CLICK: |
164 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value); | 175 | serio_write(sunkbd->serio, SUNKBD_CMD_NOCLICK - value); |
165 | return 0; | 176 | return 0; |
166 | 177 | ||
167 | case SND_BELL: | 178 | case SND_BELL: |
168 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value); | 179 | serio_write(sunkbd->serio, SUNKBD_CMD_BELLOFF - value); |
169 | return 0; | 180 | return 0; |
170 | } | 181 | } |
171 | 182 | ||
172 | break; | 183 | break; |
173 | } | 184 | } |
174 | 185 | ||
175 | return -1; | 186 | return -1; |
@@ -183,7 +194,7 @@ static int sunkbd_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
183 | static int sunkbd_initialize(struct sunkbd *sunkbd) | 194 | static int sunkbd_initialize(struct sunkbd *sunkbd) |
184 | { | 195 | { |
185 | sunkbd->reset = -2; | 196 | sunkbd->reset = -2; |
186 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_RESET); | 197 | serio_write(sunkbd->serio, SUNKBD_CMD_RESET); |
187 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); | 198 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); |
188 | if (sunkbd->reset < 0) | 199 | if (sunkbd->reset < 0) |
189 | return -1; | 200 | return -1; |
@@ -192,10 +203,13 @@ static int sunkbd_initialize(struct sunkbd *sunkbd) | |||
192 | 203 | ||
193 | if (sunkbd->type == 4) { /* Type 4 keyboard */ | 204 | if (sunkbd->type == 4) { /* Type 4 keyboard */ |
194 | sunkbd->layout = -2; | 205 | sunkbd->layout = -2; |
195 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_LAYOUT); | 206 | serio_write(sunkbd->serio, SUNKBD_CMD_LAYOUT); |
196 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->layout >= 0, HZ/4); | 207 | wait_event_interruptible_timeout(sunkbd->wait, |
197 | if (sunkbd->layout < 0) return -1; | 208 | sunkbd->layout >= 0, HZ / 4); |
198 | if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) sunkbd->type = 5; | 209 | if (sunkbd->layout < 0) |
210 | return -1; | ||
211 | if (sunkbd->layout & SUNKBD_LAYOUT_5_MASK) | ||
212 | sunkbd->type = 5; | ||
199 | } | 213 | } |
200 | 214 | ||
201 | return 0; | 215 | return 0; |
@@ -212,15 +226,19 @@ static void sunkbd_reinit(struct work_struct *work) | |||
212 | 226 | ||
213 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); | 227 | wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); |
214 | 228 | ||
215 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_SETLED); | 229 | serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); |
216 | sunkbd->serio->write(sunkbd->serio, | 230 | serio_write(sunkbd->serio, |
217 | (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) | | 231 | (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | |
218 | (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | !!test_bit(LED_NUML, sunkbd->dev->led)); | 232 | (!!test_bit(LED_SCROLLL, sunkbd->dev->led) << 2) | |
219 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd)); | 233 | (!!test_bit(LED_COMPOSE, sunkbd->dev->led) << 1) | |
220 | sunkbd->serio->write(sunkbd->serio, SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); | 234 | !!test_bit(LED_NUML, sunkbd->dev->led)); |
235 | serio_write(sunkbd->serio, | ||
236 | SUNKBD_CMD_NOCLICK - !!test_bit(SND_CLICK, sunkbd->dev->snd)); | ||
237 | serio_write(sunkbd->serio, | ||
238 | SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); | ||
221 | } | 239 | } |
222 | 240 | ||
223 | static void sunkbd_enable(struct sunkbd *sunkbd, int enable) | 241 | static void sunkbd_enable(struct sunkbd *sunkbd, bool enable) |
224 | { | 242 | { |
225 | serio_pause_rx(sunkbd->serio); | 243 | serio_pause_rx(sunkbd->serio); |
226 | sunkbd->enabled = enable; | 244 | sunkbd->enabled = enable; |
@@ -228,7 +246,8 @@ static void sunkbd_enable(struct sunkbd *sunkbd, int enable) | |||
228 | } | 246 | } |
229 | 247 | ||
230 | /* | 248 | /* |
231 | * sunkbd_connect() probes for a Sun keyboard and fills the necessary structures. | 249 | * sunkbd_connect() probes for a Sun keyboard and fills the necessary |
250 | * structures. | ||
232 | */ | 251 | */ |
233 | 252 | ||
234 | static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | 253 | static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) |
@@ -260,7 +279,8 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
260 | goto fail3; | 279 | goto fail3; |
261 | } | 280 | } |
262 | 281 | ||
263 | snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type); | 282 | snprintf(sunkbd->name, sizeof(sunkbd->name), |
283 | "Sun Type %d keyboard", sunkbd->type); | ||
264 | memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode)); | 284 | memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode)); |
265 | 285 | ||
266 | input_dev->name = sunkbd->name; | 286 | input_dev->name = sunkbd->name; |
@@ -284,11 +304,11 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
284 | input_dev->keycode = sunkbd->keycode; | 304 | input_dev->keycode = sunkbd->keycode; |
285 | input_dev->keycodesize = sizeof(unsigned char); | 305 | input_dev->keycodesize = sizeof(unsigned char); |
286 | input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode); | 306 | input_dev->keycodemax = ARRAY_SIZE(sunkbd_keycode); |
287 | for (i = 0; i < 128; i++) | 307 | for (i = 0; i < ARRAY_SIZE(sunkbd_keycode); i++) |
288 | set_bit(sunkbd->keycode[i], input_dev->keybit); | 308 | __set_bit(sunkbd->keycode[i], input_dev->keybit); |
289 | clear_bit(0, input_dev->keybit); | 309 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
290 | 310 | ||
291 | sunkbd_enable(sunkbd, 1); | 311 | sunkbd_enable(sunkbd, true); |
292 | 312 | ||
293 | err = input_register_device(sunkbd->dev); | 313 | err = input_register_device(sunkbd->dev); |
294 | if (err) | 314 | if (err) |
@@ -296,7 +316,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
296 | 316 | ||
297 | return 0; | 317 | return 0; |
298 | 318 | ||
299 | fail4: sunkbd_enable(sunkbd, 0); | 319 | fail4: sunkbd_enable(sunkbd, false); |
300 | fail3: serio_close(serio); | 320 | fail3: serio_close(serio); |
301 | fail2: serio_set_drvdata(serio, NULL); | 321 | fail2: serio_set_drvdata(serio, NULL); |
302 | fail1: input_free_device(input_dev); | 322 | fail1: input_free_device(input_dev); |
@@ -312,7 +332,7 @@ static void sunkbd_disconnect(struct serio *serio) | |||
312 | { | 332 | { |
313 | struct sunkbd *sunkbd = serio_get_drvdata(serio); | 333 | struct sunkbd *sunkbd = serio_get_drvdata(serio); |
314 | 334 | ||
315 | sunkbd_enable(sunkbd, 0); | 335 | sunkbd_enable(sunkbd, false); |
316 | input_unregister_device(sunkbd->dev); | 336 | input_unregister_device(sunkbd->dev); |
317 | serio_close(serio); | 337 | serio_close(serio); |
318 | serio_set_drvdata(serio, NULL); | 338 | serio_set_drvdata(serio, NULL); |
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c index 677276b12020..42cb3faf7336 100644 --- a/drivers/input/keyboard/tosakbd.c +++ b/drivers/input/keyboard/tosakbd.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #define KB_DISCHARGE_DELAY 10 | 31 | #define KB_DISCHARGE_DELAY 10 |
32 | #define KB_ACTIVATE_DELAY 10 | 32 | #define KB_ACTIVATE_DELAY 10 |
33 | 33 | ||
34 | static unsigned int tosakbd_keycode[NR_SCANCODES] = { | 34 | static unsigned short tosakbd_keycode[NR_SCANCODES] = { |
35 | 0, | 35 | 0, |
36 | 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, | 36 | 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, |
37 | 0, 0, 0, 0, 0, 0, 0, 0, | 37 | 0, 0, 0, 0, 0, 0, 0, 0, |
@@ -50,9 +50,9 @@ KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_ | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | struct tosakbd { | 52 | struct tosakbd { |
53 | unsigned int keycode[ARRAY_SIZE(tosakbd_keycode)]; | 53 | unsigned short keycode[ARRAY_SIZE(tosakbd_keycode)]; |
54 | struct input_dev *input; | 54 | struct input_dev *input; |
55 | int suspended; | 55 | bool suspended; |
56 | spinlock_t lock; /* protect kbd scanning */ | 56 | spinlock_t lock; /* protect kbd scanning */ |
57 | struct timer_list timer; | 57 | struct timer_list timer; |
58 | }; | 58 | }; |
@@ -215,7 +215,7 @@ static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) | |||
215 | unsigned long flags; | 215 | unsigned long flags; |
216 | 216 | ||
217 | spin_lock_irqsave(&tosakbd->lock, flags); | 217 | spin_lock_irqsave(&tosakbd->lock, flags); |
218 | tosakbd->suspended = 1; | 218 | tosakbd->suspended = true; |
219 | spin_unlock_irqrestore(&tosakbd->lock, flags); | 219 | spin_unlock_irqrestore(&tosakbd->lock, flags); |
220 | 220 | ||
221 | del_timer_sync(&tosakbd->timer); | 221 | del_timer_sync(&tosakbd->timer); |
@@ -227,7 +227,7 @@ static int tosakbd_resume(struct platform_device *dev) | |||
227 | { | 227 | { |
228 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | 228 | struct tosakbd *tosakbd = platform_get_drvdata(dev); |
229 | 229 | ||
230 | tosakbd->suspended = 0; | 230 | tosakbd->suspended = false; |
231 | tosakbd_scankeyboard(dev); | 231 | tosakbd_scankeyboard(dev); |
232 | 232 | ||
233 | return 0; | 233 | return 0; |
@@ -277,14 +277,14 @@ static int __devinit tosakbd_probe(struct platform_device *pdev) { | |||
277 | 277 | ||
278 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | 278 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); |
279 | input_dev->keycode = tosakbd->keycode; | 279 | input_dev->keycode = tosakbd->keycode; |
280 | input_dev->keycodesize = sizeof(unsigned int); | 280 | input_dev->keycodesize = sizeof(tosakbd->keycode[0]); |
281 | input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); | 281 | input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); |
282 | 282 | ||
283 | memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); | 283 | memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); |
284 | 284 | ||
285 | for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) | 285 | for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) |
286 | __set_bit(tosakbd->keycode[i], input_dev->keybit); | 286 | __set_bit(tosakbd->keycode[i], input_dev->keybit); |
287 | clear_bit(0, input_dev->keybit); | 287 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
288 | 288 | ||
289 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | 289 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ |
290 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { | 290 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { |
@@ -344,7 +344,7 @@ static int __devinit tosakbd_probe(struct platform_device *pdev) { | |||
344 | " direction for GPIO %d, error %d\n", | 344 | " direction for GPIO %d, error %d\n", |
345 | gpio, error); | 345 | gpio, error); |
346 | gpio_free(gpio); | 346 | gpio_free(gpio); |
347 | goto fail; | 347 | goto fail2; |
348 | } | 348 | } |
349 | 349 | ||
350 | } | 350 | } |
@@ -353,7 +353,7 @@ static int __devinit tosakbd_probe(struct platform_device *pdev) { | |||
353 | if (error) { | 353 | if (error) { |
354 | printk(KERN_ERR "tosakbd: Unable to register input device, " | 354 | printk(KERN_ERR "tosakbd: Unable to register input device, " |
355 | "error: %d\n", error); | 355 | "error: %d\n", error); |
356 | goto fail; | 356 | goto fail2; |
357 | } | 357 | } |
358 | 358 | ||
359 | printk(KERN_INFO "input: Tosa Keyboard Registered\n"); | 359 | printk(KERN_INFO "input: Tosa Keyboard Registered\n"); |
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c new file mode 100644 index 000000000000..9a2977c21696 --- /dev/null +++ b/drivers/input/keyboard/twl4030_keypad.c | |||
@@ -0,0 +1,480 @@ | |||
1 | /* | ||
2 | * twl4030_keypad.c - driver for 8x8 keypad controller in twl4030 chips | ||
3 | * | ||
4 | * Copyright (C) 2007 Texas Instruments, Inc. | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * | ||
7 | * Code re-written for 2430SDP by: | ||
8 | * Syed Mohammed Khasim <x0khasim@ti.com> | ||
9 | * | ||
10 | * Initial Code: | ||
11 | * Manjunatha G K <manjugk@ti.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
26 | */ | ||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/input.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/i2c/twl4030.h> | ||
35 | |||
36 | |||
37 | /* | ||
38 | * The TWL4030 family chips include a keypad controller that supports | ||
39 | * up to an 8x8 switch matrix. The controller can issue system wakeup | ||
40 | * events, since it uses only the always-on 32KiHz oscillator, and has | ||
41 | * an internal state machine that decodes pressed keys, including | ||
42 | * multi-key combinations. | ||
43 | * | ||
44 | * This driver lets boards define what keycodes they wish to report for | ||
45 | * which scancodes, as part of the "struct twl4030_keypad_data" used in | ||
46 | * the probe() routine. | ||
47 | * | ||
48 | * See the TPS65950 documentation; that's the general availability | ||
49 | * version of the TWL5030 second generation part. | ||
50 | */ | ||
51 | #define TWL4030_MAX_ROWS 8 /* TWL4030 hard limit */ | ||
52 | #define TWL4030_MAX_COLS 8 | ||
53 | #define TWL4030_ROW_SHIFT 3 | ||
54 | #define TWL4030_KEYMAP_SIZE (TWL4030_MAX_ROWS * TWL4030_MAX_COLS) | ||
55 | |||
56 | struct twl4030_keypad { | ||
57 | unsigned short keymap[TWL4030_KEYMAP_SIZE]; | ||
58 | u16 kp_state[TWL4030_MAX_ROWS]; | ||
59 | unsigned n_rows; | ||
60 | unsigned n_cols; | ||
61 | unsigned irq; | ||
62 | |||
63 | struct device *dbg_dev; | ||
64 | struct input_dev *input; | ||
65 | }; | ||
66 | |||
67 | /*----------------------------------------------------------------------*/ | ||
68 | |||
69 | /* arbitrary prescaler value 0..7 */ | ||
70 | #define PTV_PRESCALER 4 | ||
71 | |||
72 | /* Register Offsets */ | ||
73 | #define KEYP_CTRL 0x00 | ||
74 | #define KEYP_DEB 0x01 | ||
75 | #define KEYP_LONG_KEY 0x02 | ||
76 | #define KEYP_LK_PTV 0x03 | ||
77 | #define KEYP_TIMEOUT_L 0x04 | ||
78 | #define KEYP_TIMEOUT_H 0x05 | ||
79 | #define KEYP_KBC 0x06 | ||
80 | #define KEYP_KBR 0x07 | ||
81 | #define KEYP_SMS 0x08 | ||
82 | #define KEYP_FULL_CODE_7_0 0x09 /* row 0 column status */ | ||
83 | #define KEYP_FULL_CODE_15_8 0x0a /* ... row 1 ... */ | ||
84 | #define KEYP_FULL_CODE_23_16 0x0b | ||
85 | #define KEYP_FULL_CODE_31_24 0x0c | ||
86 | #define KEYP_FULL_CODE_39_32 0x0d | ||
87 | #define KEYP_FULL_CODE_47_40 0x0e | ||
88 | #define KEYP_FULL_CODE_55_48 0x0f | ||
89 | #define KEYP_FULL_CODE_63_56 0x10 | ||
90 | #define KEYP_ISR1 0x11 | ||
91 | #define KEYP_IMR1 0x12 | ||
92 | #define KEYP_ISR2 0x13 | ||
93 | #define KEYP_IMR2 0x14 | ||
94 | #define KEYP_SIR 0x15 | ||
95 | #define KEYP_EDR 0x16 /* edge triggers */ | ||
96 | #define KEYP_SIH_CTRL 0x17 | ||
97 | |||
98 | /* KEYP_CTRL_REG Fields */ | ||
99 | #define KEYP_CTRL_SOFT_NRST BIT(0) | ||
100 | #define KEYP_CTRL_SOFTMODEN BIT(1) | ||
101 | #define KEYP_CTRL_LK_EN BIT(2) | ||
102 | #define KEYP_CTRL_TOE_EN BIT(3) | ||
103 | #define KEYP_CTRL_TOLE_EN BIT(4) | ||
104 | #define KEYP_CTRL_RP_EN BIT(5) | ||
105 | #define KEYP_CTRL_KBD_ON BIT(6) | ||
106 | |||
107 | /* KEYP_DEB, KEYP_LONG_KEY, KEYP_TIMEOUT_x*/ | ||
108 | #define KEYP_PERIOD_US(t, prescale) ((t) / (31 << (prescale + 1)) - 1) | ||
109 | |||
110 | /* KEYP_LK_PTV_REG Fields */ | ||
111 | #define KEYP_LK_PTV_PTV_SHIFT 5 | ||
112 | |||
113 | /* KEYP_{IMR,ISR,SIR} Fields */ | ||
114 | #define KEYP_IMR1_MIS BIT(3) | ||
115 | #define KEYP_IMR1_TO BIT(2) | ||
116 | #define KEYP_IMR1_LK BIT(1) | ||
117 | #define KEYP_IMR1_KP BIT(0) | ||
118 | |||
119 | /* KEYP_EDR Fields */ | ||
120 | #define KEYP_EDR_KP_FALLING 0x01 | ||
121 | #define KEYP_EDR_KP_RISING 0x02 | ||
122 | #define KEYP_EDR_KP_BOTH 0x03 | ||
123 | #define KEYP_EDR_LK_FALLING 0x04 | ||
124 | #define KEYP_EDR_LK_RISING 0x08 | ||
125 | #define KEYP_EDR_TO_FALLING 0x10 | ||
126 | #define KEYP_EDR_TO_RISING 0x20 | ||
127 | #define KEYP_EDR_MIS_FALLING 0x40 | ||
128 | #define KEYP_EDR_MIS_RISING 0x80 | ||
129 | |||
130 | |||
131 | /*----------------------------------------------------------------------*/ | ||
132 | |||
133 | static int twl4030_kpread(struct twl4030_keypad *kp, | ||
134 | u8 *data, u32 reg, u8 num_bytes) | ||
135 | { | ||
136 | int ret = twl4030_i2c_read(TWL4030_MODULE_KEYPAD, data, reg, num_bytes); | ||
137 | |||
138 | if (ret < 0) | ||
139 | dev_warn(kp->dbg_dev, | ||
140 | "Couldn't read TWL4030: %X - ret %d[%x]\n", | ||
141 | reg, ret, ret); | ||
142 | |||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | static int twl4030_kpwrite_u8(struct twl4030_keypad *kp, u8 data, u32 reg) | ||
147 | { | ||
148 | int ret = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, data, reg); | ||
149 | |||
150 | if (ret < 0) | ||
151 | dev_warn(kp->dbg_dev, | ||
152 | "Could not write TWL4030: %X - ret %d[%x]\n", | ||
153 | reg, ret, ret); | ||
154 | |||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | static inline u16 twl4030_col_xlate(struct twl4030_keypad *kp, u8 col) | ||
159 | { | ||
160 | /* If all bits in a row are active for all coloumns then | ||
161 | * we have that row line connected to gnd. Mark this | ||
162 | * key on as if it was on matrix position n_cols (ie | ||
163 | * one higher than the size of the matrix). | ||
164 | */ | ||
165 | if (col == 0xFF) | ||
166 | return 1 << kp->n_cols; | ||
167 | else | ||
168 | return col & ((1 << kp->n_cols) - 1); | ||
169 | } | ||
170 | |||
171 | static int twl4030_read_kp_matrix_state(struct twl4030_keypad *kp, u16 *state) | ||
172 | { | ||
173 | u8 new_state[TWL4030_MAX_ROWS]; | ||
174 | int row; | ||
175 | int ret = twl4030_kpread(kp, new_state, | ||
176 | KEYP_FULL_CODE_7_0, kp->n_rows); | ||
177 | if (ret >= 0) | ||
178 | for (row = 0; row < kp->n_rows; row++) | ||
179 | state[row] = twl4030_col_xlate(kp, new_state[row]); | ||
180 | |||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static int twl4030_is_in_ghost_state(struct twl4030_keypad *kp, u16 *key_state) | ||
185 | { | ||
186 | int i; | ||
187 | u16 check = 0; | ||
188 | |||
189 | for (i = 0; i < kp->n_rows; i++) { | ||
190 | u16 col = key_state[i]; | ||
191 | |||
192 | if ((col & check) && hweight16(col) > 1) | ||
193 | return 1; | ||
194 | |||
195 | check |= col; | ||
196 | } | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static void twl4030_kp_scan(struct twl4030_keypad *kp, bool release_all) | ||
202 | { | ||
203 | struct input_dev *input = kp->input; | ||
204 | u16 new_state[TWL4030_MAX_ROWS]; | ||
205 | int col, row; | ||
206 | |||
207 | if (release_all) | ||
208 | memset(new_state, 0, sizeof(new_state)); | ||
209 | else { | ||
210 | /* check for any changes */ | ||
211 | int ret = twl4030_read_kp_matrix_state(kp, new_state); | ||
212 | |||
213 | if (ret < 0) /* panic ... */ | ||
214 | return; | ||
215 | |||
216 | if (twl4030_is_in_ghost_state(kp, new_state)) | ||
217 | return; | ||
218 | } | ||
219 | |||
220 | /* check for changes and print those */ | ||
221 | for (row = 0; row < kp->n_rows; row++) { | ||
222 | int changed = new_state[row] ^ kp->kp_state[row]; | ||
223 | |||
224 | if (!changed) | ||
225 | continue; | ||
226 | |||
227 | for (col = 0; col < kp->n_cols; col++) { | ||
228 | int code; | ||
229 | |||
230 | if (!(changed & (1 << col))) | ||
231 | continue; | ||
232 | |||
233 | dev_dbg(kp->dbg_dev, "key [%d:%d] %s\n", row, col, | ||
234 | (new_state[row] & (1 << col)) ? | ||
235 | "press" : "release"); | ||
236 | |||
237 | code = MATRIX_SCAN_CODE(row, col, TWL4030_ROW_SHIFT); | ||
238 | input_event(input, EV_MSC, MSC_SCAN, code); | ||
239 | input_report_key(input, kp->keymap[code], | ||
240 | new_state[row] & (1 << col)); | ||
241 | } | ||
242 | kp->kp_state[row] = new_state[row]; | ||
243 | } | ||
244 | input_sync(input); | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * Keypad interrupt handler | ||
249 | */ | ||
250 | static irqreturn_t do_kp_irq(int irq, void *_kp) | ||
251 | { | ||
252 | struct twl4030_keypad *kp = _kp; | ||
253 | u8 reg; | ||
254 | int ret; | ||
255 | |||
256 | #ifdef CONFIG_LOCKDEP | ||
257 | /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which | ||
258 | * we don't want and can't tolerate. Although it might be | ||
259 | * friendlier not to borrow this thread context... | ||
260 | */ | ||
261 | local_irq_enable(); | ||
262 | #endif | ||
263 | |||
264 | /* Read & Clear TWL4030 pending interrupt */ | ||
265 | ret = twl4030_kpread(kp, ®, KEYP_ISR1, 1); | ||
266 | |||
267 | /* Release all keys if I2C has gone bad or | ||
268 | * the KEYP has gone to idle state */ | ||
269 | if (ret >= 0 && (reg & KEYP_IMR1_KP)) | ||
270 | twl4030_kp_scan(kp, false); | ||
271 | else | ||
272 | twl4030_kp_scan(kp, true); | ||
273 | |||
274 | return IRQ_HANDLED; | ||
275 | } | ||
276 | |||
277 | static int __devinit twl4030_kp_program(struct twl4030_keypad *kp) | ||
278 | { | ||
279 | u8 reg; | ||
280 | int i; | ||
281 | |||
282 | /* Enable controller, with hardware decoding but not autorepeat */ | ||
283 | reg = KEYP_CTRL_SOFT_NRST | KEYP_CTRL_SOFTMODEN | ||
284 | | KEYP_CTRL_TOE_EN | KEYP_CTRL_KBD_ON; | ||
285 | if (twl4030_kpwrite_u8(kp, reg, KEYP_CTRL) < 0) | ||
286 | return -EIO; | ||
287 | |||
288 | /* NOTE: we could use sih_setup() here to package keypad | ||
289 | * event sources as four different IRQs ... but we don't. | ||
290 | */ | ||
291 | |||
292 | /* Enable TO rising and KP rising and falling edge detection */ | ||
293 | reg = KEYP_EDR_KP_BOTH | KEYP_EDR_TO_RISING; | ||
294 | if (twl4030_kpwrite_u8(kp, reg, KEYP_EDR) < 0) | ||
295 | return -EIO; | ||
296 | |||
297 | /* Set PTV prescaler Field */ | ||
298 | reg = (PTV_PRESCALER << KEYP_LK_PTV_PTV_SHIFT); | ||
299 | if (twl4030_kpwrite_u8(kp, reg, KEYP_LK_PTV) < 0) | ||
300 | return -EIO; | ||
301 | |||
302 | /* Set key debounce time to 20 ms */ | ||
303 | i = KEYP_PERIOD_US(20000, PTV_PRESCALER); | ||
304 | if (twl4030_kpwrite_u8(kp, i, KEYP_DEB) < 0) | ||
305 | return -EIO; | ||
306 | |||
307 | /* Set timeout period to 100 ms */ | ||
308 | i = KEYP_PERIOD_US(200000, PTV_PRESCALER); | ||
309 | if (twl4030_kpwrite_u8(kp, (i & 0xFF), KEYP_TIMEOUT_L) < 0) | ||
310 | return -EIO; | ||
311 | |||
312 | if (twl4030_kpwrite_u8(kp, (i >> 8), KEYP_TIMEOUT_H) < 0) | ||
313 | return -EIO; | ||
314 | |||
315 | /* | ||
316 | * Enable Clear-on-Read; disable remembering events that fire | ||
317 | * after the IRQ but before our handler acks (reads) them, | ||
318 | */ | ||
319 | reg = TWL4030_SIH_CTRL_COR_MASK | TWL4030_SIH_CTRL_PENDDIS_MASK; | ||
320 | if (twl4030_kpwrite_u8(kp, reg, KEYP_SIH_CTRL) < 0) | ||
321 | return -EIO; | ||
322 | |||
323 | /* initialize key state; irqs update it from here on */ | ||
324 | if (twl4030_read_kp_matrix_state(kp, kp->kp_state) < 0) | ||
325 | return -EIO; | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * Registers keypad device with input subsystem | ||
332 | * and configures TWL4030 keypad registers | ||
333 | */ | ||
334 | static int __devinit twl4030_kp_probe(struct platform_device *pdev) | ||
335 | { | ||
336 | struct twl4030_keypad_data *pdata = pdev->dev.platform_data; | ||
337 | const struct matrix_keymap_data *keymap_data = pdata->keymap_data; | ||
338 | struct twl4030_keypad *kp; | ||
339 | struct input_dev *input; | ||
340 | u8 reg; | ||
341 | int error; | ||
342 | |||
343 | if (!pdata || !pdata->rows || !pdata->cols || | ||
344 | pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) { | ||
345 | dev_err(&pdev->dev, "Invalid platform_data\n"); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | kp = kzalloc(sizeof(*kp), GFP_KERNEL); | ||
350 | input = input_allocate_device(); | ||
351 | if (!kp || !input) { | ||
352 | error = -ENOMEM; | ||
353 | goto err1; | ||
354 | } | ||
355 | |||
356 | /* Get the debug Device */ | ||
357 | kp->dbg_dev = &pdev->dev; | ||
358 | kp->input = input; | ||
359 | |||
360 | kp->n_rows = pdata->rows; | ||
361 | kp->n_cols = pdata->cols; | ||
362 | kp->irq = platform_get_irq(pdev, 0); | ||
363 | |||
364 | /* setup input device */ | ||
365 | __set_bit(EV_KEY, input->evbit); | ||
366 | |||
367 | /* Enable auto repeat feature of Linux input subsystem */ | ||
368 | if (pdata->rep) | ||
369 | __set_bit(EV_REP, input->evbit); | ||
370 | |||
371 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
372 | |||
373 | input->name = "TWL4030 Keypad"; | ||
374 | input->phys = "twl4030_keypad/input0"; | ||
375 | input->dev.parent = &pdev->dev; | ||
376 | |||
377 | input->id.bustype = BUS_HOST; | ||
378 | input->id.vendor = 0x0001; | ||
379 | input->id.product = 0x0001; | ||
380 | input->id.version = 0x0003; | ||
381 | |||
382 | input->keycode = kp->keymap; | ||
383 | input->keycodesize = sizeof(kp->keymap[0]); | ||
384 | input->keycodemax = ARRAY_SIZE(kp->keymap); | ||
385 | |||
386 | matrix_keypad_build_keymap(keymap_data, TWL4030_ROW_SHIFT, | ||
387 | input->keycode, input->keybit); | ||
388 | |||
389 | error = input_register_device(input); | ||
390 | if (error) { | ||
391 | dev_err(kp->dbg_dev, | ||
392 | "Unable to register twl4030 keypad device\n"); | ||
393 | goto err1; | ||
394 | } | ||
395 | |||
396 | error = twl4030_kp_program(kp); | ||
397 | if (error) | ||
398 | goto err2; | ||
399 | |||
400 | /* | ||
401 | * This ISR will always execute in kernel thread context because of | ||
402 | * the need to access the TWL4030 over the I2C bus. | ||
403 | * | ||
404 | * NOTE: we assume this host is wired to TWL4040 INT1, not INT2 ... | ||
405 | */ | ||
406 | error = request_irq(kp->irq, do_kp_irq, 0, pdev->name, kp); | ||
407 | if (error) { | ||
408 | dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n", | ||
409 | kp->irq); | ||
410 | goto err3; | ||
411 | } | ||
412 | |||
413 | /* Enable KP and TO interrupts now. */ | ||
414 | reg = (u8) ~(KEYP_IMR1_KP | KEYP_IMR1_TO); | ||
415 | if (twl4030_kpwrite_u8(kp, reg, KEYP_IMR1)) { | ||
416 | error = -EIO; | ||
417 | goto err4; | ||
418 | } | ||
419 | |||
420 | platform_set_drvdata(pdev, kp); | ||
421 | return 0; | ||
422 | |||
423 | err4: | ||
424 | /* mask all events - we don't care about the result */ | ||
425 | (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1); | ||
426 | err3: | ||
427 | free_irq(kp->irq, NULL); | ||
428 | err2: | ||
429 | input_unregister_device(input); | ||
430 | input = NULL; | ||
431 | err1: | ||
432 | input_free_device(input); | ||
433 | kfree(kp); | ||
434 | return error; | ||
435 | } | ||
436 | |||
437 | static int __devexit twl4030_kp_remove(struct platform_device *pdev) | ||
438 | { | ||
439 | struct twl4030_keypad *kp = platform_get_drvdata(pdev); | ||
440 | |||
441 | free_irq(kp->irq, kp); | ||
442 | input_unregister_device(kp->input); | ||
443 | platform_set_drvdata(pdev, NULL); | ||
444 | kfree(kp); | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | /* | ||
450 | * NOTE: twl4030 are multi-function devices connected via I2C. | ||
451 | * So this device is a child of an I2C parent, thus it needs to | ||
452 | * support unplug/replug (which most platform devices don't). | ||
453 | */ | ||
454 | |||
455 | static struct platform_driver twl4030_kp_driver = { | ||
456 | .probe = twl4030_kp_probe, | ||
457 | .remove = __devexit_p(twl4030_kp_remove), | ||
458 | .driver = { | ||
459 | .name = "twl4030_keypad", | ||
460 | .owner = THIS_MODULE, | ||
461 | }, | ||
462 | }; | ||
463 | |||
464 | static int __init twl4030_kp_init(void) | ||
465 | { | ||
466 | return platform_driver_register(&twl4030_kp_driver); | ||
467 | } | ||
468 | module_init(twl4030_kp_init); | ||
469 | |||
470 | static void __exit twl4030_kp_exit(void) | ||
471 | { | ||
472 | platform_driver_unregister(&twl4030_kp_driver); | ||
473 | } | ||
474 | module_exit(twl4030_kp_exit); | ||
475 | |||
476 | MODULE_AUTHOR("Texas Instruments"); | ||
477 | MODULE_DESCRIPTION("TWL4030 Keypad Driver"); | ||
478 | MODULE_LICENSE("GPL"); | ||
479 | MODULE_ALIAS("platform:twl4030_keypad"); | ||
480 | |||
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c new file mode 100644 index 000000000000..6032def03707 --- /dev/null +++ b/drivers/input/keyboard/w90p910_keypad.c | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Nuvoton technology corporation. | ||
3 | * | ||
4 | * Wan ZongShun <mcuos.com@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation;version 2 of the License. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/io.h> | ||
22 | |||
23 | #include <mach/w90p910_keypad.h> | ||
24 | |||
25 | /* Keypad Interface Control Registers */ | ||
26 | #define KPI_CONF 0x00 | ||
27 | #define KPI_3KCONF 0x04 | ||
28 | #define KPI_LPCONF 0x08 | ||
29 | #define KPI_STATUS 0x0C | ||
30 | |||
31 | #define IS1KEY (0x01 << 16) | ||
32 | #define INTTR (0x01 << 21) | ||
33 | #define KEY0R (0x0f << 3) | ||
34 | #define KEY0C 0x07 | ||
35 | #define DEBOUNCE_BIT 0x08 | ||
36 | #define KSIZE0 (0x01 << 16) | ||
37 | #define KSIZE1 (0x01 << 17) | ||
38 | #define KPSEL (0x01 << 19) | ||
39 | #define ENKP (0x01 << 18) | ||
40 | |||
41 | #define KGET_RAW(n) (((n) & KEY0R) >> 3) | ||
42 | #define KGET_COLUMN(n) ((n) & KEY0C) | ||
43 | |||
44 | #define W90P910_MAX_KEY_NUM (8 * 8) | ||
45 | #define W90P910_ROW_SHIFT 3 | ||
46 | |||
47 | struct w90p910_keypad { | ||
48 | const struct w90p910_keypad_platform_data *pdata; | ||
49 | struct clk *clk; | ||
50 | struct input_dev *input_dev; | ||
51 | void __iomem *mmio_base; | ||
52 | int irq; | ||
53 | unsigned short keymap[W90P910_MAX_KEY_NUM]; | ||
54 | }; | ||
55 | |||
56 | static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, | ||
57 | unsigned int status) | ||
58 | { | ||
59 | struct input_dev *input_dev = keypad->input_dev; | ||
60 | unsigned int row = KGET_RAW(status); | ||
61 | unsigned int col = KGET_COLUMN(status); | ||
62 | unsigned int code = MATRIX_SCAN_CODE(row, col, W90P910_ROW_SHIFT); | ||
63 | unsigned int key = keypad->keymap[code]; | ||
64 | |||
65 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
66 | input_report_key(input_dev, key, 1); | ||
67 | input_sync(input_dev); | ||
68 | |||
69 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
70 | input_report_key(input_dev, key, 0); | ||
71 | input_sync(input_dev); | ||
72 | } | ||
73 | |||
74 | static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id) | ||
75 | { | ||
76 | struct w90p910_keypad *keypad = dev_id; | ||
77 | unsigned int kstatus, val; | ||
78 | |||
79 | kstatus = __raw_readl(keypad->mmio_base + KPI_STATUS); | ||
80 | |||
81 | val = INTTR | IS1KEY; | ||
82 | |||
83 | if (kstatus & val) | ||
84 | w90p910_keypad_scan_matrix(keypad, kstatus); | ||
85 | |||
86 | return IRQ_HANDLED; | ||
87 | } | ||
88 | |||
89 | static int w90p910_keypad_open(struct input_dev *dev) | ||
90 | { | ||
91 | struct w90p910_keypad *keypad = input_get_drvdata(dev); | ||
92 | const struct w90p910_keypad_platform_data *pdata = keypad->pdata; | ||
93 | unsigned int val, config; | ||
94 | |||
95 | /* Enable unit clock */ | ||
96 | clk_enable(keypad->clk); | ||
97 | |||
98 | val = __raw_readl(keypad->mmio_base + KPI_CONF); | ||
99 | val |= (KPSEL | ENKP); | ||
100 | val &= ~(KSIZE0 | KSIZE1); | ||
101 | |||
102 | config = pdata->prescale | (pdata->debounce << DEBOUNCE_BIT); | ||
103 | |||
104 | val |= config; | ||
105 | |||
106 | __raw_writel(val, keypad->mmio_base + KPI_CONF); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static void w90p910_keypad_close(struct input_dev *dev) | ||
112 | { | ||
113 | struct w90p910_keypad *keypad = input_get_drvdata(dev); | ||
114 | |||
115 | /* Disable clock unit */ | ||
116 | clk_disable(keypad->clk); | ||
117 | } | ||
118 | |||
119 | static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | ||
120 | { | ||
121 | const struct w90p910_keypad_platform_data *pdata = | ||
122 | pdev->dev.platform_data; | ||
123 | const struct matrix_keymap_data *keymap_data; | ||
124 | struct w90p910_keypad *keypad; | ||
125 | struct input_dev *input_dev; | ||
126 | struct resource *res; | ||
127 | int irq; | ||
128 | int error; | ||
129 | |||
130 | if (!pdata) { | ||
131 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
132 | return -EINVAL; | ||
133 | } | ||
134 | |||
135 | keymap_data = pdata->keymap_data; | ||
136 | |||
137 | irq = platform_get_irq(pdev, 0); | ||
138 | if (irq < 0) { | ||
139 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | ||
140 | return -ENXIO; | ||
141 | } | ||
142 | |||
143 | keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL); | ||
144 | input_dev = input_allocate_device(); | ||
145 | if (!keypad || !input_dev) { | ||
146 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
147 | error = -ENOMEM; | ||
148 | goto failed_free; | ||
149 | } | ||
150 | |||
151 | keypad->pdata = pdata; | ||
152 | keypad->input_dev = input_dev; | ||
153 | keypad->irq = irq; | ||
154 | |||
155 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
156 | if (res == NULL) { | ||
157 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
158 | error = -ENXIO; | ||
159 | goto failed_free; | ||
160 | } | ||
161 | |||
162 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
163 | if (res == NULL) { | ||
164 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
165 | error = -EBUSY; | ||
166 | goto failed_free; | ||
167 | } | ||
168 | |||
169 | keypad->mmio_base = ioremap(res->start, resource_size(res)); | ||
170 | if (keypad->mmio_base == NULL) { | ||
171 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
172 | error = -ENXIO; | ||
173 | goto failed_free_res; | ||
174 | } | ||
175 | |||
176 | keypad->clk = clk_get(&pdev->dev, NULL); | ||
177 | if (IS_ERR(keypad->clk)) { | ||
178 | dev_err(&pdev->dev, "failed to get keypad clock\n"); | ||
179 | error = PTR_ERR(keypad->clk); | ||
180 | goto failed_free_io; | ||
181 | } | ||
182 | |||
183 | /* set multi-function pin for w90p910 kpi. */ | ||
184 | mfp_set_groupi(&pdev->dev); | ||
185 | |||
186 | input_dev->name = pdev->name; | ||
187 | input_dev->id.bustype = BUS_HOST; | ||
188 | input_dev->open = w90p910_keypad_open; | ||
189 | input_dev->close = w90p910_keypad_close; | ||
190 | input_dev->dev.parent = &pdev->dev; | ||
191 | |||
192 | input_dev->keycode = keypad->keymap; | ||
193 | input_dev->keycodesize = sizeof(keypad->keymap[0]); | ||
194 | input_dev->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
195 | |||
196 | input_set_drvdata(input_dev, keypad); | ||
197 | |||
198 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
199 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
200 | |||
201 | matrix_keypad_build_keymap(keymap_data, W90P910_ROW_SHIFT, | ||
202 | input_dev->keycode, input_dev->keybit); | ||
203 | |||
204 | error = request_irq(keypad->irq, w90p910_keypad_irq_handler, | ||
205 | IRQF_DISABLED, pdev->name, keypad); | ||
206 | if (error) { | ||
207 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
208 | goto failed_put_clk; | ||
209 | } | ||
210 | |||
211 | /* Register the input device */ | ||
212 | error = input_register_device(input_dev); | ||
213 | if (error) { | ||
214 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
215 | goto failed_free_irq; | ||
216 | } | ||
217 | |||
218 | platform_set_drvdata(pdev, keypad); | ||
219 | return 0; | ||
220 | |||
221 | failed_free_irq: | ||
222 | free_irq(irq, pdev); | ||
223 | failed_put_clk: | ||
224 | clk_put(keypad->clk); | ||
225 | failed_free_io: | ||
226 | iounmap(keypad->mmio_base); | ||
227 | failed_free_res: | ||
228 | release_mem_region(res->start, resource_size(res)); | ||
229 | failed_free: | ||
230 | input_free_device(input_dev); | ||
231 | kfree(keypad); | ||
232 | return error; | ||
233 | } | ||
234 | |||
235 | static int __devexit w90p910_keypad_remove(struct platform_device *pdev) | ||
236 | { | ||
237 | struct w90p910_keypad *keypad = platform_get_drvdata(pdev); | ||
238 | struct resource *res; | ||
239 | |||
240 | free_irq(keypad->irq, pdev); | ||
241 | |||
242 | clk_put(keypad->clk); | ||
243 | |||
244 | input_unregister_device(keypad->input_dev); | ||
245 | |||
246 | iounmap(keypad->mmio_base); | ||
247 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
248 | release_mem_region(res->start, resource_size(res)); | ||
249 | |||
250 | platform_set_drvdata(pdev, NULL); | ||
251 | kfree(keypad); | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static struct platform_driver w90p910_keypad_driver = { | ||
257 | .probe = w90p910_keypad_probe, | ||
258 | .remove = __devexit_p(w90p910_keypad_remove), | ||
259 | .driver = { | ||
260 | .name = "nuc900-keypad", | ||
261 | .owner = THIS_MODULE, | ||
262 | }, | ||
263 | }; | ||
264 | |||
265 | static int __init w90p910_keypad_init(void) | ||
266 | { | ||
267 | return platform_driver_register(&w90p910_keypad_driver); | ||
268 | } | ||
269 | |||
270 | static void __exit w90p910_keypad_exit(void) | ||
271 | { | ||
272 | platform_driver_unregister(&w90p910_keypad_driver); | ||
273 | } | ||
274 | |||
275 | module_init(w90p910_keypad_init); | ||
276 | module_exit(w90p910_keypad_exit); | ||
277 | |||
278 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | ||
279 | MODULE_DESCRIPTION("w90p910 keypad driver"); | ||
280 | MODULE_LICENSE("GPL"); | ||
281 | MODULE_ALIAS("platform:nuc900-keypad"); | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 1acfa3a05aad..76d6751f89a7 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -222,6 +222,22 @@ config INPUT_SGI_BTNS | |||
222 | To compile this driver as a module, choose M here: the | 222 | To compile this driver as a module, choose M here: the |
223 | module will be called sgi_btns. | 223 | module will be called sgi_btns. |
224 | 224 | ||
225 | config INPUT_WINBOND_CIR | ||
226 | tristate "Winbond IR remote control" | ||
227 | depends on X86 && PNP | ||
228 | select LEDS_CLASS | ||
229 | select BITREVERSE | ||
230 | help | ||
231 | Say Y here if you want to use the IR remote functionality found | ||
232 | in some Winbond SuperI/O chips. Currently only the WPCD376I | ||
233 | chip is supported (included in some Intel Media series motherboards). | ||
234 | |||
235 | IR Receive and wake-on-IR from suspend and power-off is currently | ||
236 | supported. | ||
237 | |||
238 | To compile this driver as a module, choose M here: the module will be | ||
239 | called winbond_cir. | ||
240 | |||
225 | config HP_SDC_RTC | 241 | config HP_SDC_RTC |
226 | tristate "HP SDC Real Time Clock" | 242 | tristate "HP SDC Real Time Clock" |
227 | depends on (GSC || HP300) && SERIO | 243 | depends on (GSC || HP300) && SERIO |
@@ -269,4 +285,34 @@ config INPUT_DM355EVM | |||
269 | 285 | ||
270 | To compile this driver as a module, choose M here: the | 286 | To compile this driver as a module, choose M here: the |
271 | module will be called dm355evm_keys. | 287 | module will be called dm355evm_keys. |
288 | |||
289 | config INPUT_BFIN_ROTARY | ||
290 | tristate "Blackfin Rotary support" | ||
291 | depends on BF54x || BF52x | ||
292 | help | ||
293 | Say Y here if you want to use the Blackfin Rotary. | ||
294 | |||
295 | To compile this driver as a module, choose M here: the | ||
296 | module will be called bfin-rotary. | ||
297 | |||
298 | config INPUT_WM831X_ON | ||
299 | tristate "WM831X ON pin" | ||
300 | depends on MFD_WM831X | ||
301 | help | ||
302 | Support the ON pin of WM831X PMICs as an input device | ||
303 | reporting power button status. | ||
304 | |||
305 | To compile this driver as a module, choose M here: the module | ||
306 | will be called wm831x_on. | ||
307 | |||
308 | config INPUT_PCAP | ||
309 | tristate "Motorola EZX PCAP misc input events" | ||
310 | depends on EZX_PCAP | ||
311 | help | ||
312 | Say Y here if you want to use Power key and Headphone button | ||
313 | on Motorola EZX phones. | ||
314 | |||
315 | To compile this driver as a module, choose M here: the | ||
316 | module will be called pcap_keys. | ||
317 | |||
272 | endif | 318 | endif |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 0d979fd4cd57..a8b84854fb7b 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_INPUT_APANEL) += apanel.o | |||
8 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o | 8 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o |
9 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | 9 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o |
10 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o | 10 | obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o |
11 | obj-$(CONFIG_INPUT_BFIN_ROTARY) += bfin_rotary.o | ||
11 | obj-$(CONFIG_INPUT_CM109) += cm109.o | 12 | obj-$(CONFIG_INPUT_CM109) += cm109.o |
12 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o | 13 | obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o |
13 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o | 14 | obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o |
@@ -15,6 +16,7 @@ obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | |||
15 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o | 16 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o |
16 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o | 17 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o |
17 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o | 18 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o |
19 | obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o | ||
18 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o | 20 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o |
19 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o | 21 | obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o |
20 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o | 22 | obj-$(CONFIG_INPUT_POWERMATE) += powermate.o |
@@ -24,5 +26,8 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o | |||
24 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o | 26 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o |
25 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o | 27 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o |
26 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | 28 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o |
29 | obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o | ||
27 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o | 30 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o |
31 | obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o | ||
28 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o | 32 | obj-$(CONFIG_INPUT_YEALINK) += yealink.o |
33 | |||
diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c new file mode 100644 index 000000000000..690f3fafa03b --- /dev/null +++ b/drivers/input/misc/bfin_rotary.c | |||
@@ -0,0 +1,283 @@ | |||
1 | /* | ||
2 | * Rotary counter driver for Analog Devices Blackfin Processors | ||
3 | * | ||
4 | * Copyright 2008-2009 Analog Devices Inc. | ||
5 | * Licensed under the GPL-2 or later. | ||
6 | */ | ||
7 | |||
8 | #include <linux/module.h> | ||
9 | #include <linux/version.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/irq.h> | ||
13 | #include <linux/pm.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/input.h> | ||
16 | |||
17 | #include <asm/portmux.h> | ||
18 | #include <asm/bfin_rotary.h> | ||
19 | |||
20 | static const u16 per_cnt[] = { | ||
21 | P_CNT_CUD, | ||
22 | P_CNT_CDG, | ||
23 | P_CNT_CZM, | ||
24 | 0 | ||
25 | }; | ||
26 | |||
27 | struct bfin_rot { | ||
28 | struct input_dev *input; | ||
29 | int irq; | ||
30 | unsigned int up_key; | ||
31 | unsigned int down_key; | ||
32 | unsigned int button_key; | ||
33 | unsigned int rel_code; | ||
34 | unsigned short cnt_config; | ||
35 | unsigned short cnt_imask; | ||
36 | unsigned short cnt_debounce; | ||
37 | }; | ||
38 | |||
39 | static void report_key_event(struct input_dev *input, int keycode) | ||
40 | { | ||
41 | /* simulate a press-n-release */ | ||
42 | input_report_key(input, keycode, 1); | ||
43 | input_sync(input); | ||
44 | input_report_key(input, keycode, 0); | ||
45 | input_sync(input); | ||
46 | } | ||
47 | |||
48 | static void report_rotary_event(struct bfin_rot *rotary, int delta) | ||
49 | { | ||
50 | struct input_dev *input = rotary->input; | ||
51 | |||
52 | if (rotary->up_key) { | ||
53 | report_key_event(input, | ||
54 | delta > 0 ? rotary->up_key : rotary->down_key); | ||
55 | } else { | ||
56 | input_report_rel(input, rotary->rel_code, delta); | ||
57 | input_sync(input); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static irqreturn_t bfin_rotary_isr(int irq, void *dev_id) | ||
62 | { | ||
63 | struct platform_device *pdev = dev_id; | ||
64 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
65 | int delta; | ||
66 | |||
67 | switch (bfin_read_CNT_STATUS()) { | ||
68 | |||
69 | case ICII: | ||
70 | break; | ||
71 | |||
72 | case UCII: | ||
73 | case DCII: | ||
74 | delta = bfin_read_CNT_COUNTER(); | ||
75 | if (delta) | ||
76 | report_rotary_event(rotary, delta); | ||
77 | break; | ||
78 | |||
79 | case CZMII: | ||
80 | report_key_event(rotary->input, rotary->button_key); | ||
81 | break; | ||
82 | |||
83 | default: | ||
84 | break; | ||
85 | } | ||
86 | |||
87 | bfin_write_CNT_COMMAND(W1LCNT_ZERO); /* Clear COUNTER */ | ||
88 | bfin_write_CNT_STATUS(-1); /* Clear STATUS */ | ||
89 | |||
90 | return IRQ_HANDLED; | ||
91 | } | ||
92 | |||
93 | static int __devinit bfin_rotary_probe(struct platform_device *pdev) | ||
94 | { | ||
95 | struct bfin_rotary_platform_data *pdata = pdev->dev.platform_data; | ||
96 | struct bfin_rot *rotary; | ||
97 | struct input_dev *input; | ||
98 | int error; | ||
99 | |||
100 | /* Basic validation */ | ||
101 | if ((pdata->rotary_up_key && !pdata->rotary_down_key) || | ||
102 | (!pdata->rotary_up_key && pdata->rotary_down_key)) { | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | |||
106 | error = peripheral_request_list(per_cnt, dev_name(&pdev->dev)); | ||
107 | if (error) { | ||
108 | dev_err(&pdev->dev, "requesting peripherals failed\n"); | ||
109 | return error; | ||
110 | } | ||
111 | |||
112 | rotary = kzalloc(sizeof(struct bfin_rot), GFP_KERNEL); | ||
113 | input = input_allocate_device(); | ||
114 | if (!rotary || !input) { | ||
115 | error = -ENOMEM; | ||
116 | goto out1; | ||
117 | } | ||
118 | |||
119 | rotary->input = input; | ||
120 | |||
121 | rotary->up_key = pdata->rotary_up_key; | ||
122 | rotary->down_key = pdata->rotary_down_key; | ||
123 | rotary->button_key = pdata->rotary_button_key; | ||
124 | rotary->rel_code = pdata->rotary_rel_code; | ||
125 | |||
126 | error = rotary->irq = platform_get_irq(pdev, 0); | ||
127 | if (error < 0) | ||
128 | goto out1; | ||
129 | |||
130 | input->name = pdev->name; | ||
131 | input->phys = "bfin-rotary/input0"; | ||
132 | input->dev.parent = &pdev->dev; | ||
133 | |||
134 | input_set_drvdata(input, rotary); | ||
135 | |||
136 | input->id.bustype = BUS_HOST; | ||
137 | input->id.vendor = 0x0001; | ||
138 | input->id.product = 0x0001; | ||
139 | input->id.version = 0x0100; | ||
140 | |||
141 | if (rotary->up_key) { | ||
142 | __set_bit(EV_KEY, input->evbit); | ||
143 | __set_bit(rotary->up_key, input->keybit); | ||
144 | __set_bit(rotary->down_key, input->keybit); | ||
145 | } else { | ||
146 | __set_bit(EV_REL, input->evbit); | ||
147 | __set_bit(rotary->rel_code, input->relbit); | ||
148 | } | ||
149 | |||
150 | if (rotary->button_key) { | ||
151 | __set_bit(EV_KEY, input->evbit); | ||
152 | __set_bit(rotary->button_key, input->keybit); | ||
153 | } | ||
154 | |||
155 | error = request_irq(rotary->irq, bfin_rotary_isr, | ||
156 | 0, dev_name(&pdev->dev), pdev); | ||
157 | if (error) { | ||
158 | dev_err(&pdev->dev, | ||
159 | "unable to claim irq %d; error %d\n", | ||
160 | rotary->irq, error); | ||
161 | goto out1; | ||
162 | } | ||
163 | |||
164 | error = input_register_device(input); | ||
165 | if (error) { | ||
166 | dev_err(&pdev->dev, | ||
167 | "unable to register input device (%d)\n", error); | ||
168 | goto out2; | ||
169 | } | ||
170 | |||
171 | if (pdata->rotary_button_key) | ||
172 | bfin_write_CNT_IMASK(CZMIE); | ||
173 | |||
174 | if (pdata->mode & ROT_DEBE) | ||
175 | bfin_write_CNT_DEBOUNCE(pdata->debounce & DPRESCALE); | ||
176 | |||
177 | if (pdata->mode) | ||
178 | bfin_write_CNT_CONFIG(bfin_read_CNT_CONFIG() | | ||
179 | (pdata->mode & ~CNTE)); | ||
180 | |||
181 | bfin_write_CNT_IMASK(bfin_read_CNT_IMASK() | UCIE | DCIE); | ||
182 | bfin_write_CNT_CONFIG(bfin_read_CNT_CONFIG() | CNTE); | ||
183 | |||
184 | platform_set_drvdata(pdev, rotary); | ||
185 | device_init_wakeup(&pdev->dev, 1); | ||
186 | |||
187 | return 0; | ||
188 | |||
189 | out2: | ||
190 | free_irq(rotary->irq, pdev); | ||
191 | out1: | ||
192 | input_free_device(input); | ||
193 | kfree(rotary); | ||
194 | peripheral_free_list(per_cnt); | ||
195 | |||
196 | return error; | ||
197 | } | ||
198 | |||
199 | static int __devexit bfin_rotary_remove(struct platform_device *pdev) | ||
200 | { | ||
201 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
202 | |||
203 | bfin_write_CNT_CONFIG(0); | ||
204 | bfin_write_CNT_IMASK(0); | ||
205 | |||
206 | free_irq(rotary->irq, pdev); | ||
207 | input_unregister_device(rotary->input); | ||
208 | peripheral_free_list(per_cnt); | ||
209 | |||
210 | kfree(rotary); | ||
211 | platform_set_drvdata(pdev, NULL); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | #ifdef CONFIG_PM | ||
217 | static int bfin_rotary_suspend(struct device *dev) | ||
218 | { | ||
219 | struct platform_device *pdev = to_platform_device(dev); | ||
220 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
221 | |||
222 | rotary->cnt_config = bfin_read_CNT_CONFIG(); | ||
223 | rotary->cnt_imask = bfin_read_CNT_IMASK(); | ||
224 | rotary->cnt_debounce = bfin_read_CNT_DEBOUNCE(); | ||
225 | |||
226 | if (device_may_wakeup(&pdev->dev)) | ||
227 | enable_irq_wake(rotary->irq); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | static int bfin_rotary_resume(struct device *dev) | ||
233 | { | ||
234 | struct platform_device *pdev = to_platform_device(dev); | ||
235 | struct bfin_rot *rotary = platform_get_drvdata(pdev); | ||
236 | |||
237 | bfin_write_CNT_DEBOUNCE(rotary->cnt_debounce); | ||
238 | bfin_write_CNT_IMASK(rotary->cnt_imask); | ||
239 | bfin_write_CNT_CONFIG(rotary->cnt_config & ~CNTE); | ||
240 | |||
241 | if (device_may_wakeup(&pdev->dev)) | ||
242 | disable_irq_wake(rotary->irq); | ||
243 | |||
244 | if (rotary->cnt_config & CNTE) | ||
245 | bfin_write_CNT_CONFIG(rotary->cnt_config); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static struct dev_pm_ops bfin_rotary_pm_ops = { | ||
251 | .suspend = bfin_rotary_suspend, | ||
252 | .resume = bfin_rotary_resume, | ||
253 | }; | ||
254 | #endif | ||
255 | |||
256 | static struct platform_driver bfin_rotary_device_driver = { | ||
257 | .probe = bfin_rotary_probe, | ||
258 | .remove = __devexit_p(bfin_rotary_remove), | ||
259 | .driver = { | ||
260 | .name = "bfin-rotary", | ||
261 | .owner = THIS_MODULE, | ||
262 | #ifdef CONFIG_PM | ||
263 | .pm = &bfin_rotary_pm_ops, | ||
264 | #endif | ||
265 | }, | ||
266 | }; | ||
267 | |||
268 | static int __init bfin_rotary_init(void) | ||
269 | { | ||
270 | return platform_driver_register(&bfin_rotary_device_driver); | ||
271 | } | ||
272 | module_init(bfin_rotary_init); | ||
273 | |||
274 | static void __exit bfin_rotary_exit(void) | ||
275 | { | ||
276 | platform_driver_unregister(&bfin_rotary_device_driver); | ||
277 | } | ||
278 | module_exit(bfin_rotary_exit); | ||
279 | |||
280 | MODULE_LICENSE("GPL"); | ||
281 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
282 | MODULE_DESCRIPTION("Rotary Counter driver for Blackfin Processors"); | ||
283 | MODULE_ALIAS("platform:bfin-rotary"); | ||
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 2adf9cb265da..ee73d7219c92 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Cobalt button interface driver. | 2 | * Cobalt button interface driver. |
3 | * | 3 | * |
4 | * Copyright (C) 2007-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 4 | * Copyright (C) 2007-2008 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -116,7 +116,7 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev) | |||
116 | } | 116 | } |
117 | 117 | ||
118 | bdev->poll_dev = poll_dev; | 118 | bdev->poll_dev = poll_dev; |
119 | bdev->reg = ioremap(res->start, res->end - res->start + 1); | 119 | bdev->reg = ioremap(res->start, resource_size(res)); |
120 | dev_set_drvdata(&pdev->dev, bdev); | 120 | dev_set_drvdata(&pdev->dev, bdev); |
121 | 121 | ||
122 | error = input_register_polled_device(poll_dev); | 122 | error = input_register_polled_device(poll_dev); |
@@ -148,7 +148,7 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev) | |||
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | 150 | ||
151 | MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>"); | 151 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>"); |
152 | MODULE_DESCRIPTION("Cobalt button interface driver"); | 152 | MODULE_DESCRIPTION("Cobalt button interface driver"); |
153 | MODULE_LICENSE("GPL"); | 153 | MODULE_LICENSE("GPL"); |
154 | /* work with hotplug and coldplug */ | 154 | /* work with hotplug and coldplug */ |
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index a63315ce4a6c..0918acae584a 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c | |||
@@ -23,30 +23,16 @@ | |||
23 | * pressed, or its autorepeat kicks in, an event is sent. This driver | 23 | * pressed, or its autorepeat kicks in, an event is sent. This driver |
24 | * read those events from the small (32 event) queue and reports them. | 24 | * read those events from the small (32 event) queue and reports them. |
25 | * | 25 | * |
26 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
27 | * in Linux sleep, we need to cons up a kind of threaded IRQ handler | ||
28 | * using a work_struct. The IRQ is active low, but we use it through | ||
29 | * the GPIO controller so we can trigger on falling edges. | ||
30 | * | ||
31 | * Note that physically there can only be one of these devices. | 26 | * Note that physically there can only be one of these devices. |
32 | * | 27 | * |
33 | * This driver was tested with firmware revision A4. | 28 | * This driver was tested with firmware revision A4. |
34 | */ | 29 | */ |
35 | struct dm355evm_keys { | 30 | struct dm355evm_keys { |
36 | struct work_struct work; | ||
37 | struct input_dev *input; | 31 | struct input_dev *input; |
38 | struct device *dev; | 32 | struct device *dev; |
39 | int irq; | 33 | int irq; |
40 | }; | 34 | }; |
41 | 35 | ||
42 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | ||
43 | { | ||
44 | struct dm355evm_keys *keys = _keys; | ||
45 | |||
46 | schedule_work(&keys->work); | ||
47 | return IRQ_HANDLED; | ||
48 | } | ||
49 | |||
50 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ | 36 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ |
51 | static struct { | 37 | static struct { |
52 | u16 event; | 38 | u16 event; |
@@ -110,13 +96,12 @@ static struct { | |||
110 | { 0x3169, KEY_PAUSE, }, | 96 | { 0x3169, KEY_PAUSE, }, |
111 | }; | 97 | }; |
112 | 98 | ||
113 | static void dm355evm_keys_work(struct work_struct *work) | 99 | /* runs in an IRQ thread -- can (and will!) sleep */ |
100 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | ||
114 | { | 101 | { |
115 | struct dm355evm_keys *keys; | 102 | struct dm355evm_keys *keys = _keys; |
116 | int status; | 103 | int status; |
117 | 104 | ||
118 | keys = container_of(work, struct dm355evm_keys, work); | ||
119 | |||
120 | /* For simplicity we ignore INPUT_COUNT and just read | 105 | /* For simplicity we ignore INPUT_COUNT and just read |
121 | * events until we get the "queue empty" indicator. | 106 | * events until we get the "queue empty" indicator. |
122 | * Reading INPUT_LOW decrements the count. | 107 | * Reading INPUT_LOW decrements the count. |
@@ -183,6 +168,19 @@ static void dm355evm_keys_work(struct work_struct *work) | |||
183 | input_report_key(keys->input, keycode, 0); | 168 | input_report_key(keys->input, keycode, 0); |
184 | input_sync(keys->input); | 169 | input_sync(keys->input); |
185 | } | 170 | } |
171 | return IRQ_HANDLED; | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * Because we communicate with the MSP430 using I2C, and all I2C calls | ||
176 | * in Linux sleep, we use a threaded IRQ handler. The IRQ itself is | ||
177 | * active low, but we go through the GPIO controller so we can trigger | ||
178 | * on falling edges and not worry about enabling/disabling the IRQ in | ||
179 | * the keypress handling path. | ||
180 | */ | ||
181 | static irqreturn_t dm355evm_keys_hardirq(int irq, void *_keys) | ||
182 | { | ||
183 | return IRQ_WAKE_THREAD; | ||
186 | } | 184 | } |
187 | 185 | ||
188 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) | 186 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) |
@@ -233,7 +231,6 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
233 | 231 | ||
234 | keys->dev = &pdev->dev; | 232 | keys->dev = &pdev->dev; |
235 | keys->input = input; | 233 | keys->input = input; |
236 | INIT_WORK(&keys->work, dm355evm_keys_work); | ||
237 | 234 | ||
238 | /* set up "threaded IRQ handler" */ | 235 | /* set up "threaded IRQ handler" */ |
239 | status = platform_get_irq(pdev, 0); | 236 | status = platform_get_irq(pdev, 0); |
@@ -260,9 +257,10 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
260 | 257 | ||
261 | /* REVISIT: flush the event queue? */ | 258 | /* REVISIT: flush the event queue? */ |
262 | 259 | ||
263 | status = request_irq(keys->irq, dm355evm_keys_irq, | 260 | status = request_threaded_irq(keys->irq, |
264 | IRQF_TRIGGER_FALLING, | 261 | dm355evm_keys_hardirq, dm355evm_keys_irq, |
265 | dev_name(&pdev->dev), keys); | 262 | IRQF_TRIGGER_FALLING, |
263 | dev_name(&pdev->dev), keys); | ||
266 | if (status < 0) | 264 | if (status < 0) |
267 | goto fail1; | 265 | goto fail1; |
268 | 266 | ||
diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c new file mode 100644 index 000000000000..7ea969347ca9 --- /dev/null +++ b/drivers/input/misc/pcap_keys.c | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * Input driver for PCAP events: | ||
3 | * * Power key | ||
4 | * * Headphone button | ||
5 | * | ||
6 | * Copyright (c) 2008,2009 Ilya Petrov <ilya.muromec@gmail.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/input.h> | ||
19 | #include <linux/mfd/ezx-pcap.h> | ||
20 | |||
21 | struct pcap_keys { | ||
22 | struct pcap_chip *pcap; | ||
23 | struct input_dev *input; | ||
24 | }; | ||
25 | |||
26 | /* PCAP2 interrupts us on keypress */ | ||
27 | static irqreturn_t pcap_keys_handler(int irq, void *_pcap_keys) | ||
28 | { | ||
29 | struct pcap_keys *pcap_keys = _pcap_keys; | ||
30 | int pirq = irq_to_pcap(pcap_keys->pcap, irq); | ||
31 | u32 pstat; | ||
32 | |||
33 | ezx_pcap_read(pcap_keys->pcap, PCAP_REG_PSTAT, &pstat); | ||
34 | pstat &= 1 << pirq; | ||
35 | |||
36 | switch (pirq) { | ||
37 | case PCAP_IRQ_ONOFF: | ||
38 | input_report_key(pcap_keys->input, KEY_POWER, !pstat); | ||
39 | break; | ||
40 | case PCAP_IRQ_MIC: | ||
41 | input_report_key(pcap_keys->input, KEY_HP, !pstat); | ||
42 | break; | ||
43 | } | ||
44 | |||
45 | input_sync(pcap_keys->input); | ||
46 | |||
47 | return IRQ_HANDLED; | ||
48 | } | ||
49 | |||
50 | static int __devinit pcap_keys_probe(struct platform_device *pdev) | ||
51 | { | ||
52 | int err = -ENOMEM; | ||
53 | struct pcap_keys *pcap_keys; | ||
54 | struct input_dev *input_dev; | ||
55 | |||
56 | pcap_keys = kmalloc(sizeof(struct pcap_keys), GFP_KERNEL); | ||
57 | if (!pcap_keys) | ||
58 | return err; | ||
59 | |||
60 | pcap_keys->pcap = dev_get_drvdata(pdev->dev.parent); | ||
61 | |||
62 | input_dev = input_allocate_device(); | ||
63 | if (!input_dev) | ||
64 | goto fail; | ||
65 | |||
66 | pcap_keys->input = input_dev; | ||
67 | |||
68 | platform_set_drvdata(pdev, pcap_keys); | ||
69 | input_dev->name = pdev->name; | ||
70 | input_dev->phys = "pcap-keys/input0"; | ||
71 | input_dev->id.bustype = BUS_HOST; | ||
72 | input_dev->dev.parent = &pdev->dev; | ||
73 | |||
74 | __set_bit(EV_KEY, input_dev->evbit); | ||
75 | __set_bit(KEY_POWER, input_dev->keybit); | ||
76 | __set_bit(KEY_HP, input_dev->keybit); | ||
77 | |||
78 | err = input_register_device(input_dev); | ||
79 | if (err) | ||
80 | goto fail_allocate; | ||
81 | |||
82 | err = request_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_ONOFF), | ||
83 | pcap_keys_handler, 0, "Power key", pcap_keys); | ||
84 | if (err) | ||
85 | goto fail_register; | ||
86 | |||
87 | err = request_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_MIC), | ||
88 | pcap_keys_handler, 0, "Headphone button", pcap_keys); | ||
89 | if (err) | ||
90 | goto fail_pwrkey; | ||
91 | |||
92 | return 0; | ||
93 | |||
94 | fail_pwrkey: | ||
95 | free_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_ONOFF), pcap_keys); | ||
96 | fail_register: | ||
97 | input_unregister_device(input_dev); | ||
98 | goto fail; | ||
99 | fail_allocate: | ||
100 | input_free_device(input_dev); | ||
101 | fail: | ||
102 | kfree(pcap_keys); | ||
103 | return err; | ||
104 | } | ||
105 | |||
106 | static int __devexit pcap_keys_remove(struct platform_device *pdev) | ||
107 | { | ||
108 | struct pcap_keys *pcap_keys = platform_get_drvdata(pdev); | ||
109 | |||
110 | free_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_ONOFF), pcap_keys); | ||
111 | free_irq(pcap_to_irq(pcap_keys->pcap, PCAP_IRQ_MIC), pcap_keys); | ||
112 | |||
113 | input_unregister_device(pcap_keys->input); | ||
114 | kfree(pcap_keys); | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static struct platform_driver pcap_keys_device_driver = { | ||
120 | .probe = pcap_keys_probe, | ||
121 | .remove = __devexit_p(pcap_keys_remove), | ||
122 | .driver = { | ||
123 | .name = "pcap-keys", | ||
124 | .owner = THIS_MODULE, | ||
125 | } | ||
126 | }; | ||
127 | |||
128 | static int __init pcap_keys_init(void) | ||
129 | { | ||
130 | return platform_driver_register(&pcap_keys_device_driver); | ||
131 | }; | ||
132 | |||
133 | static void __exit pcap_keys_exit(void) | ||
134 | { | ||
135 | platform_driver_unregister(&pcap_keys_device_driver); | ||
136 | }; | ||
137 | |||
138 | module_init(pcap_keys_init); | ||
139 | module_exit(pcap_keys_exit); | ||
140 | |||
141 | MODULE_DESCRIPTION("Motorola PCAP2 input events driver"); | ||
142 | MODULE_AUTHOR("Ilya Petrov <ilya.muromec@gmail.com>"); | ||
143 | MODULE_LICENSE("GPL"); | ||
144 | MODULE_ALIAS("platform:pcap_keys"); | ||
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 6d67af5387ad..21cb755a54fb 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
@@ -114,7 +114,7 @@ static int __devexit pcspkr_remove(struct platform_device *dev) | |||
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | static int pcspkr_suspend(struct platform_device *dev, pm_message_t state) | 117 | static int pcspkr_suspend(struct device *dev) |
118 | { | 118 | { |
119 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); | 119 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); |
120 | 120 | ||
@@ -127,14 +127,18 @@ static void pcspkr_shutdown(struct platform_device *dev) | |||
127 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); | 127 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); |
128 | } | 128 | } |
129 | 129 | ||
130 | static struct dev_pm_ops pcspkr_pm_ops = { | ||
131 | .suspend = pcspkr_suspend, | ||
132 | }; | ||
133 | |||
130 | static struct platform_driver pcspkr_platform_driver = { | 134 | static struct platform_driver pcspkr_platform_driver = { |
131 | .driver = { | 135 | .driver = { |
132 | .name = "pcspkr", | 136 | .name = "pcspkr", |
133 | .owner = THIS_MODULE, | 137 | .owner = THIS_MODULE, |
138 | .pm = &pcspkr_pm_ops, | ||
134 | }, | 139 | }, |
135 | .probe = pcspkr_probe, | 140 | .probe = pcspkr_probe, |
136 | .remove = __devexit_p(pcspkr_remove), | 141 | .remove = __devexit_p(pcspkr_remove), |
137 | .suspend = pcspkr_suspend, | ||
138 | .shutdown = pcspkr_shutdown, | 142 | .shutdown = pcspkr_shutdown, |
139 | }; | 143 | }; |
140 | 144 | ||
diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c new file mode 100644 index 000000000000..33309fe44e20 --- /dev/null +++ b/drivers/input/misc/winbond-cir.c | |||
@@ -0,0 +1,1614 @@ | |||
1 | /* | ||
2 | * winbond-cir.c - Driver for the Consumer IR functionality of Winbond | ||
3 | * SuperI/O chips. | ||
4 | * | ||
5 | * Currently supports the Winbond WPCD376i chip (PNP id WEC1022), but | ||
6 | * could probably support others (Winbond WEC102X, NatSemi, etc) | ||
7 | * with minor modifications. | ||
8 | * | ||
9 | * Original Author: David Härdeman <david@hardeman.nu> | ||
10 | * Copyright (C) 2009 David Härdeman <david@hardeman.nu> | ||
11 | * | ||
12 | * Dedicated to Matilda, my newborn daughter, without whose loving attention | ||
13 | * this driver would have been finished in half the time and with a fraction | ||
14 | * of the bugs. | ||
15 | * | ||
16 | * Written using: | ||
17 | * o Winbond WPCD376I datasheet helpfully provided by Jesse Barnes at Intel | ||
18 | * o NatSemi PC87338/PC97338 datasheet (for the serial port stuff) | ||
19 | * o DSDT dumps | ||
20 | * | ||
21 | * Supported features: | ||
22 | * o RC6 | ||
23 | * o Wake-On-CIR functionality | ||
24 | * | ||
25 | * To do: | ||
26 | * o Test NEC and RC5 | ||
27 | * | ||
28 | * Left as an exercise for the reader: | ||
29 | * o Learning (I have neither the hardware, nor the need) | ||
30 | * o IR Transmit (ibid) | ||
31 | * | ||
32 | * This program is free software; you can redistribute it and/or modify | ||
33 | * it under the terms of the GNU General Public License as published by | ||
34 | * the Free Software Foundation; either version 2 of the License, or | ||
35 | * (at your option) any later version. | ||
36 | * | ||
37 | * This program is distributed in the hope that it will be useful, | ||
38 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
39 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
40 | * GNU General Public License for more details. | ||
41 | * | ||
42 | * You should have received a copy of the GNU General Public License | ||
43 | * along with this program; if not, write to the Free Software | ||
44 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
45 | */ | ||
46 | |||
47 | #include <linux/module.h> | ||
48 | #include <linux/pnp.h> | ||
49 | #include <linux/interrupt.h> | ||
50 | #include <linux/timer.h> | ||
51 | #include <linux/input.h> | ||
52 | #include <linux/leds.h> | ||
53 | #include <linux/list.h> | ||
54 | #include <linux/spinlock.h> | ||
55 | #include <linux/pci_ids.h> | ||
56 | #include <linux/io.h> | ||
57 | #include <linux/bitrev.h> | ||
58 | #include <linux/bitops.h> | ||
59 | |||
60 | #define DRVNAME "winbond-cir" | ||
61 | |||
62 | /* CEIR Wake-Up Registers, relative to data->wbase */ | ||
63 | #define WBCIR_REG_WCEIR_CTL 0x03 /* CEIR Receiver Control */ | ||
64 | #define WBCIR_REG_WCEIR_STS 0x04 /* CEIR Receiver Status */ | ||
65 | #define WBCIR_REG_WCEIR_EV_EN 0x05 /* CEIR Receiver Event Enable */ | ||
66 | #define WBCIR_REG_WCEIR_CNTL 0x06 /* CEIR Receiver Counter Low */ | ||
67 | #define WBCIR_REG_WCEIR_CNTH 0x07 /* CEIR Receiver Counter High */ | ||
68 | #define WBCIR_REG_WCEIR_INDEX 0x08 /* CEIR Receiver Index */ | ||
69 | #define WBCIR_REG_WCEIR_DATA 0x09 /* CEIR Receiver Data */ | ||
70 | #define WBCIR_REG_WCEIR_CSL 0x0A /* CEIR Re. Compare Strlen */ | ||
71 | #define WBCIR_REG_WCEIR_CFG1 0x0B /* CEIR Re. Configuration 1 */ | ||
72 | #define WBCIR_REG_WCEIR_CFG2 0x0C /* CEIR Re. Configuration 2 */ | ||
73 | |||
74 | /* CEIR Enhanced Functionality Registers, relative to data->ebase */ | ||
75 | #define WBCIR_REG_ECEIR_CTS 0x00 /* Enhanced IR Control Status */ | ||
76 | #define WBCIR_REG_ECEIR_CCTL 0x01 /* Infrared Counter Control */ | ||
77 | #define WBCIR_REG_ECEIR_CNT_LO 0x02 /* Infrared Counter LSB */ | ||
78 | #define WBCIR_REG_ECEIR_CNT_HI 0x03 /* Infrared Counter MSB */ | ||
79 | #define WBCIR_REG_ECEIR_IREM 0x04 /* Infrared Emitter Status */ | ||
80 | |||
81 | /* SP3 Banked Registers, relative to data->sbase */ | ||
82 | #define WBCIR_REG_SP3_BSR 0x03 /* Bank Select, all banks */ | ||
83 | /* Bank 0 */ | ||
84 | #define WBCIR_REG_SP3_RXDATA 0x00 /* FIFO RX data (r) */ | ||
85 | #define WBCIR_REG_SP3_TXDATA 0x00 /* FIFO TX data (w) */ | ||
86 | #define WBCIR_REG_SP3_IER 0x01 /* Interrupt Enable */ | ||
87 | #define WBCIR_REG_SP3_EIR 0x02 /* Event Identification (r) */ | ||
88 | #define WBCIR_REG_SP3_FCR 0x02 /* FIFO Control (w) */ | ||
89 | #define WBCIR_REG_SP3_MCR 0x04 /* Mode Control */ | ||
90 | #define WBCIR_REG_SP3_LSR 0x05 /* Link Status */ | ||
91 | #define WBCIR_REG_SP3_MSR 0x06 /* Modem Status */ | ||
92 | #define WBCIR_REG_SP3_ASCR 0x07 /* Aux Status and Control */ | ||
93 | /* Bank 2 */ | ||
94 | #define WBCIR_REG_SP3_BGDL 0x00 /* Baud Divisor LSB */ | ||
95 | #define WBCIR_REG_SP3_BGDH 0x01 /* Baud Divisor MSB */ | ||
96 | #define WBCIR_REG_SP3_EXCR1 0x02 /* Extended Control 1 */ | ||
97 | #define WBCIR_REG_SP3_EXCR2 0x04 /* Extended Control 2 */ | ||
98 | #define WBCIR_REG_SP3_TXFLV 0x06 /* TX FIFO Level */ | ||
99 | #define WBCIR_REG_SP3_RXFLV 0x07 /* RX FIFO Level */ | ||
100 | /* Bank 3 */ | ||
101 | #define WBCIR_REG_SP3_MRID 0x00 /* Module Identification */ | ||
102 | #define WBCIR_REG_SP3_SH_LCR 0x01 /* LCR Shadow */ | ||
103 | #define WBCIR_REG_SP3_SH_FCR 0x02 /* FCR Shadow */ | ||
104 | /* Bank 4 */ | ||
105 | #define WBCIR_REG_SP3_IRCR1 0x02 /* Infrared Control 1 */ | ||
106 | /* Bank 5 */ | ||
107 | #define WBCIR_REG_SP3_IRCR2 0x04 /* Infrared Control 2 */ | ||
108 | /* Bank 6 */ | ||
109 | #define WBCIR_REG_SP3_IRCR3 0x00 /* Infrared Control 3 */ | ||
110 | #define WBCIR_REG_SP3_SIR_PW 0x02 /* SIR Pulse Width */ | ||
111 | /* Bank 7 */ | ||
112 | #define WBCIR_REG_SP3_IRRXDC 0x00 /* IR RX Demod Control */ | ||
113 | #define WBCIR_REG_SP3_IRTXMC 0x01 /* IR TX Mod Control */ | ||
114 | #define WBCIR_REG_SP3_RCCFG 0x02 /* CEIR Config */ | ||
115 | #define WBCIR_REG_SP3_IRCFG1 0x04 /* Infrared Config 1 */ | ||
116 | #define WBCIR_REG_SP3_IRCFG4 0x07 /* Infrared Config 4 */ | ||
117 | |||
118 | /* | ||
119 | * Magic values follow | ||
120 | */ | ||
121 | |||
122 | /* No interrupts for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | ||
123 | #define WBCIR_IRQ_NONE 0x00 | ||
124 | /* RX data bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | ||
125 | #define WBCIR_IRQ_RX 0x01 | ||
126 | /* Over/Under-flow bit for WBCIR_REG_SP3_IER and WBCIR_REG_SP3_EIR */ | ||
127 | #define WBCIR_IRQ_ERR 0x04 | ||
128 | /* Led enable/disable bit for WBCIR_REG_ECEIR_CTS */ | ||
129 | #define WBCIR_LED_ENABLE 0x80 | ||
130 | /* RX data available bit for WBCIR_REG_SP3_LSR */ | ||
131 | #define WBCIR_RX_AVAIL 0x01 | ||
132 | /* RX disable bit for WBCIR_REG_SP3_ASCR */ | ||
133 | #define WBCIR_RX_DISABLE 0x20 | ||
134 | /* Extended mode enable bit for WBCIR_REG_SP3_EXCR1 */ | ||
135 | #define WBCIR_EXT_ENABLE 0x01 | ||
136 | /* Select compare register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ | ||
137 | #define WBCIR_REGSEL_COMPARE 0x10 | ||
138 | /* Select mask register in WBCIR_REG_WCEIR_INDEX (bits 5 & 6) */ | ||
139 | #define WBCIR_REGSEL_MASK 0x20 | ||
140 | /* Starting address of selected register in WBCIR_REG_WCEIR_INDEX */ | ||
141 | #define WBCIR_REG_ADDR0 0x00 | ||
142 | |||
143 | /* Valid banks for the SP3 UART */ | ||
144 | enum wbcir_bank { | ||
145 | WBCIR_BANK_0 = 0x00, | ||
146 | WBCIR_BANK_1 = 0x80, | ||
147 | WBCIR_BANK_2 = 0xE0, | ||
148 | WBCIR_BANK_3 = 0xE4, | ||
149 | WBCIR_BANK_4 = 0xE8, | ||
150 | WBCIR_BANK_5 = 0xEC, | ||
151 | WBCIR_BANK_6 = 0xF0, | ||
152 | WBCIR_BANK_7 = 0xF4, | ||
153 | }; | ||
154 | |||
155 | /* Supported IR Protocols */ | ||
156 | enum wbcir_protocol { | ||
157 | IR_PROTOCOL_RC5 = 0x0, | ||
158 | IR_PROTOCOL_NEC = 0x1, | ||
159 | IR_PROTOCOL_RC6 = 0x2, | ||
160 | }; | ||
161 | |||
162 | /* Misc */ | ||
163 | #define WBCIR_NAME "Winbond CIR" | ||
164 | #define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */ | ||
165 | #define WBCIR_ID_CHIP 0x04 /* Chip ID for the WPCD376I */ | ||
166 | #define IR_KEYPRESS_TIMEOUT 250 /* FIXME: should be per-protocol? */ | ||
167 | #define INVALID_SCANCODE 0x7FFFFFFF /* Invalid with all protos */ | ||
168 | #define WAKEUP_IOMEM_LEN 0x10 /* Wake-Up I/O Reg Len */ | ||
169 | #define EHFUNC_IOMEM_LEN 0x10 /* Enhanced Func I/O Reg Len */ | ||
170 | #define SP_IOMEM_LEN 0x08 /* Serial Port 3 (IR) Reg Len */ | ||
171 | #define WBCIR_MAX_IDLE_BYTES 10 | ||
172 | |||
173 | static DEFINE_SPINLOCK(wbcir_lock); | ||
174 | static DEFINE_RWLOCK(keytable_lock); | ||
175 | |||
176 | struct wbcir_key { | ||
177 | u32 scancode; | ||
178 | unsigned int keycode; | ||
179 | }; | ||
180 | |||
181 | struct wbcir_keyentry { | ||
182 | struct wbcir_key key; | ||
183 | struct list_head list; | ||
184 | }; | ||
185 | |||
186 | static struct wbcir_key rc6_def_keymap[] = { | ||
187 | { 0x800F0400, KEY_NUMERIC_0 }, | ||
188 | { 0x800F0401, KEY_NUMERIC_1 }, | ||
189 | { 0x800F0402, KEY_NUMERIC_2 }, | ||
190 | { 0x800F0403, KEY_NUMERIC_3 }, | ||
191 | { 0x800F0404, KEY_NUMERIC_4 }, | ||
192 | { 0x800F0405, KEY_NUMERIC_5 }, | ||
193 | { 0x800F0406, KEY_NUMERIC_6 }, | ||
194 | { 0x800F0407, KEY_NUMERIC_7 }, | ||
195 | { 0x800F0408, KEY_NUMERIC_8 }, | ||
196 | { 0x800F0409, KEY_NUMERIC_9 }, | ||
197 | { 0x800F041D, KEY_NUMERIC_STAR }, | ||
198 | { 0x800F041C, KEY_NUMERIC_POUND }, | ||
199 | { 0x800F0410, KEY_VOLUMEUP }, | ||
200 | { 0x800F0411, KEY_VOLUMEDOWN }, | ||
201 | { 0x800F0412, KEY_CHANNELUP }, | ||
202 | { 0x800F0413, KEY_CHANNELDOWN }, | ||
203 | { 0x800F040E, KEY_MUTE }, | ||
204 | { 0x800F040D, KEY_VENDOR }, /* Vista Logo Key */ | ||
205 | { 0x800F041E, KEY_UP }, | ||
206 | { 0x800F041F, KEY_DOWN }, | ||
207 | { 0x800F0420, KEY_LEFT }, | ||
208 | { 0x800F0421, KEY_RIGHT }, | ||
209 | { 0x800F0422, KEY_OK }, | ||
210 | { 0x800F0423, KEY_ESC }, | ||
211 | { 0x800F040F, KEY_INFO }, | ||
212 | { 0x800F040A, KEY_CLEAR }, | ||
213 | { 0x800F040B, KEY_ENTER }, | ||
214 | { 0x800F045B, KEY_RED }, | ||
215 | { 0x800F045C, KEY_GREEN }, | ||
216 | { 0x800F045D, KEY_YELLOW }, | ||
217 | { 0x800F045E, KEY_BLUE }, | ||
218 | { 0x800F045A, KEY_TEXT }, | ||
219 | { 0x800F0427, KEY_SWITCHVIDEOMODE }, | ||
220 | { 0x800F040C, KEY_POWER }, | ||
221 | { 0x800F0450, KEY_RADIO }, | ||
222 | { 0x800F0448, KEY_PVR }, | ||
223 | { 0x800F0447, KEY_AUDIO }, | ||
224 | { 0x800F0426, KEY_EPG }, | ||
225 | { 0x800F0449, KEY_CAMERA }, | ||
226 | { 0x800F0425, KEY_TV }, | ||
227 | { 0x800F044A, KEY_VIDEO }, | ||
228 | { 0x800F0424, KEY_DVD }, | ||
229 | { 0x800F0416, KEY_PLAY }, | ||
230 | { 0x800F0418, KEY_PAUSE }, | ||
231 | { 0x800F0419, KEY_STOP }, | ||
232 | { 0x800F0414, KEY_FASTFORWARD }, | ||
233 | { 0x800F041A, KEY_NEXT }, | ||
234 | { 0x800F041B, KEY_PREVIOUS }, | ||
235 | { 0x800F0415, KEY_REWIND }, | ||
236 | { 0x800F0417, KEY_RECORD }, | ||
237 | }; | ||
238 | |||
239 | /* Registers and other state is protected by wbcir_lock */ | ||
240 | struct wbcir_data { | ||
241 | unsigned long wbase; /* Wake-Up Baseaddr */ | ||
242 | unsigned long ebase; /* Enhanced Func. Baseaddr */ | ||
243 | unsigned long sbase; /* Serial Port Baseaddr */ | ||
244 | unsigned int irq; /* Serial Port IRQ */ | ||
245 | |||
246 | struct input_dev *input_dev; | ||
247 | struct timer_list timer_keyup; | ||
248 | struct led_trigger *rxtrigger; | ||
249 | struct led_trigger *txtrigger; | ||
250 | struct led_classdev led; | ||
251 | |||
252 | u32 last_scancode; | ||
253 | unsigned int last_keycode; | ||
254 | u8 last_toggle; | ||
255 | u8 keypressed; | ||
256 | unsigned long keyup_jiffies; | ||
257 | unsigned int idle_count; | ||
258 | |||
259 | /* RX irdata and parsing state */ | ||
260 | unsigned long irdata[30]; | ||
261 | unsigned int irdata_count; | ||
262 | unsigned int irdata_idle; | ||
263 | unsigned int irdata_off; | ||
264 | unsigned int irdata_error; | ||
265 | |||
266 | /* Protected by keytable_lock */ | ||
267 | struct list_head keytable; | ||
268 | }; | ||
269 | |||
270 | static enum wbcir_protocol protocol = IR_PROTOCOL_RC6; | ||
271 | module_param(protocol, uint, 0444); | ||
272 | MODULE_PARM_DESC(protocol, "IR protocol to use " | ||
273 | "(0 = RC5, 1 = NEC, 2 = RC6A, default)"); | ||
274 | |||
275 | static int invert; /* default = 0 */ | ||
276 | module_param(invert, bool, 0444); | ||
277 | MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver"); | ||
278 | |||
279 | static unsigned int wake_sc = 0x800F040C; | ||
280 | module_param(wake_sc, uint, 0644); | ||
281 | MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command"); | ||
282 | |||
283 | static unsigned int wake_rc6mode = 6; | ||
284 | module_param(wake_rc6mode, uint, 0644); | ||
285 | MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command " | ||
286 | "(0 = 0, 6 = 6A, default)"); | ||
287 | |||
288 | |||
289 | |||
290 | /***************************************************************************** | ||
291 | * | ||
292 | * UTILITY FUNCTIONS | ||
293 | * | ||
294 | *****************************************************************************/ | ||
295 | |||
296 | /* Caller needs to hold wbcir_lock */ | ||
297 | static void | ||
298 | wbcir_set_bits(unsigned long addr, u8 bits, u8 mask) | ||
299 | { | ||
300 | u8 val; | ||
301 | |||
302 | val = inb(addr); | ||
303 | val = ((val & ~mask) | (bits & mask)); | ||
304 | outb(val, addr); | ||
305 | } | ||
306 | |||
307 | /* Selects the register bank for the serial port */ | ||
308 | static inline void | ||
309 | wbcir_select_bank(struct wbcir_data *data, enum wbcir_bank bank) | ||
310 | { | ||
311 | outb(bank, data->sbase + WBCIR_REG_SP3_BSR); | ||
312 | } | ||
313 | |||
314 | static enum led_brightness | ||
315 | wbcir_led_brightness_get(struct led_classdev *led_cdev) | ||
316 | { | ||
317 | struct wbcir_data *data = container_of(led_cdev, | ||
318 | struct wbcir_data, | ||
319 | led); | ||
320 | |||
321 | if (inb(data->ebase + WBCIR_REG_ECEIR_CTS) & WBCIR_LED_ENABLE) | ||
322 | return LED_FULL; | ||
323 | else | ||
324 | return LED_OFF; | ||
325 | } | ||
326 | |||
327 | static void | ||
328 | wbcir_led_brightness_set(struct led_classdev *led_cdev, | ||
329 | enum led_brightness brightness) | ||
330 | { | ||
331 | struct wbcir_data *data = container_of(led_cdev, | ||
332 | struct wbcir_data, | ||
333 | led); | ||
334 | |||
335 | wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CTS, | ||
336 | brightness == LED_OFF ? 0x00 : WBCIR_LED_ENABLE, | ||
337 | WBCIR_LED_ENABLE); | ||
338 | } | ||
339 | |||
340 | /* Manchester encodes bits to RC6 message cells (see wbcir_parse_rc6) */ | ||
341 | static u8 | ||
342 | wbcir_to_rc6cells(u8 val) | ||
343 | { | ||
344 | u8 coded = 0x00; | ||
345 | int i; | ||
346 | |||
347 | val &= 0x0F; | ||
348 | for (i = 0; i < 4; i++) { | ||
349 | if (val & 0x01) | ||
350 | coded |= 0x02 << (i * 2); | ||
351 | else | ||
352 | coded |= 0x01 << (i * 2); | ||
353 | val >>= 1; | ||
354 | } | ||
355 | |||
356 | return coded; | ||
357 | } | ||
358 | |||
359 | |||
360 | |||
361 | /***************************************************************************** | ||
362 | * | ||
363 | * INPUT FUNCTIONS | ||
364 | * | ||
365 | *****************************************************************************/ | ||
366 | |||
367 | static unsigned int | ||
368 | wbcir_do_getkeycode(struct wbcir_data *data, u32 scancode) | ||
369 | { | ||
370 | struct wbcir_keyentry *keyentry; | ||
371 | unsigned int keycode = KEY_RESERVED; | ||
372 | unsigned long flags; | ||
373 | |||
374 | read_lock_irqsave(&keytable_lock, flags); | ||
375 | |||
376 | list_for_each_entry(keyentry, &data->keytable, list) { | ||
377 | if (keyentry->key.scancode == scancode) { | ||
378 | keycode = keyentry->key.keycode; | ||
379 | break; | ||
380 | } | ||
381 | } | ||
382 | |||
383 | read_unlock_irqrestore(&keytable_lock, flags); | ||
384 | return keycode; | ||
385 | } | ||
386 | |||
387 | static int | ||
388 | wbcir_getkeycode(struct input_dev *dev, int scancode, int *keycode) | ||
389 | { | ||
390 | struct wbcir_data *data = input_get_drvdata(dev); | ||
391 | |||
392 | *keycode = (int)wbcir_do_getkeycode(data, (u32)scancode); | ||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | static int | ||
397 | wbcir_setkeycode(struct input_dev *dev, int sscancode, int keycode) | ||
398 | { | ||
399 | struct wbcir_data *data = input_get_drvdata(dev); | ||
400 | struct wbcir_keyentry *keyentry; | ||
401 | struct wbcir_keyentry *new_keyentry; | ||
402 | unsigned long flags; | ||
403 | unsigned int old_keycode = KEY_RESERVED; | ||
404 | u32 scancode = (u32)sscancode; | ||
405 | |||
406 | if (keycode < 0 || keycode > KEY_MAX) | ||
407 | return -EINVAL; | ||
408 | |||
409 | new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL); | ||
410 | if (!new_keyentry) | ||
411 | return -ENOMEM; | ||
412 | |||
413 | write_lock_irqsave(&keytable_lock, flags); | ||
414 | |||
415 | list_for_each_entry(keyentry, &data->keytable, list) { | ||
416 | if (keyentry->key.scancode != scancode) | ||
417 | continue; | ||
418 | |||
419 | old_keycode = keyentry->key.keycode; | ||
420 | keyentry->key.keycode = keycode; | ||
421 | |||
422 | if (keyentry->key.keycode == KEY_RESERVED) { | ||
423 | list_del(&keyentry->list); | ||
424 | kfree(keyentry); | ||
425 | } | ||
426 | |||
427 | break; | ||
428 | } | ||
429 | |||
430 | set_bit(keycode, dev->keybit); | ||
431 | |||
432 | if (old_keycode == KEY_RESERVED) { | ||
433 | new_keyentry->key.scancode = scancode; | ||
434 | new_keyentry->key.keycode = keycode; | ||
435 | list_add(&new_keyentry->list, &data->keytable); | ||
436 | } else { | ||
437 | kfree(new_keyentry); | ||
438 | clear_bit(old_keycode, dev->keybit); | ||
439 | list_for_each_entry(keyentry, &data->keytable, list) { | ||
440 | if (keyentry->key.keycode == old_keycode) { | ||
441 | set_bit(old_keycode, dev->keybit); | ||
442 | break; | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | |||
447 | write_unlock_irqrestore(&keytable_lock, flags); | ||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | /* | ||
452 | * Timer function to report keyup event some time after keydown is | ||
453 | * reported by the ISR. | ||
454 | */ | ||
455 | static void | ||
456 | wbcir_keyup(unsigned long cookie) | ||
457 | { | ||
458 | struct wbcir_data *data = (struct wbcir_data *)cookie; | ||
459 | unsigned long flags; | ||
460 | |||
461 | /* | ||
462 | * data->keyup_jiffies is used to prevent a race condition if a | ||
463 | * hardware interrupt occurs at this point and the keyup timer | ||
464 | * event is moved further into the future as a result. | ||
465 | * | ||
466 | * The timer will then be reactivated and this function called | ||
467 | * again in the future. We need to exit gracefully in that case | ||
468 | * to allow the input subsystem to do its auto-repeat magic or | ||
469 | * a keyup event might follow immediately after the keydown. | ||
470 | */ | ||
471 | |||
472 | spin_lock_irqsave(&wbcir_lock, flags); | ||
473 | |||
474 | if (time_is_after_eq_jiffies(data->keyup_jiffies) && data->keypressed) { | ||
475 | data->keypressed = 0; | ||
476 | led_trigger_event(data->rxtrigger, LED_OFF); | ||
477 | input_report_key(data->input_dev, data->last_keycode, 0); | ||
478 | input_sync(data->input_dev); | ||
479 | } | ||
480 | |||
481 | spin_unlock_irqrestore(&wbcir_lock, flags); | ||
482 | } | ||
483 | |||
484 | static void | ||
485 | wbcir_keydown(struct wbcir_data *data, u32 scancode, u8 toggle) | ||
486 | { | ||
487 | unsigned int keycode; | ||
488 | |||
489 | /* Repeat? */ | ||
490 | if (data->last_scancode == scancode && | ||
491 | data->last_toggle == toggle && | ||
492 | data->keypressed) | ||
493 | goto set_timer; | ||
494 | data->last_scancode = scancode; | ||
495 | |||
496 | /* Do we need to release an old keypress? */ | ||
497 | if (data->keypressed) { | ||
498 | input_report_key(data->input_dev, data->last_keycode, 0); | ||
499 | input_sync(data->input_dev); | ||
500 | data->keypressed = 0; | ||
501 | } | ||
502 | |||
503 | /* Report scancode */ | ||
504 | input_event(data->input_dev, EV_MSC, MSC_SCAN, (int)scancode); | ||
505 | |||
506 | /* Do we know this scancode? */ | ||
507 | keycode = wbcir_do_getkeycode(data, scancode); | ||
508 | if (keycode == KEY_RESERVED) | ||
509 | goto set_timer; | ||
510 | |||
511 | /* Register a keypress */ | ||
512 | input_report_key(data->input_dev, keycode, 1); | ||
513 | data->keypressed = 1; | ||
514 | data->last_keycode = keycode; | ||
515 | data->last_toggle = toggle; | ||
516 | |||
517 | set_timer: | ||
518 | input_sync(data->input_dev); | ||
519 | led_trigger_event(data->rxtrigger, | ||
520 | data->keypressed ? LED_FULL : LED_OFF); | ||
521 | data->keyup_jiffies = jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT); | ||
522 | mod_timer(&data->timer_keyup, data->keyup_jiffies); | ||
523 | } | ||
524 | |||
525 | |||
526 | |||
527 | /***************************************************************************** | ||
528 | * | ||
529 | * IR PARSING FUNCTIONS | ||
530 | * | ||
531 | *****************************************************************************/ | ||
532 | |||
533 | /* Resets all irdata */ | ||
534 | static void | ||
535 | wbcir_reset_irdata(struct wbcir_data *data) | ||
536 | { | ||
537 | memset(data->irdata, 0, sizeof(data->irdata)); | ||
538 | data->irdata_count = 0; | ||
539 | data->irdata_off = 0; | ||
540 | data->irdata_error = 0; | ||
541 | } | ||
542 | |||
543 | /* Adds one bit of irdata */ | ||
544 | static void | ||
545 | add_irdata_bit(struct wbcir_data *data, int set) | ||
546 | { | ||
547 | if (data->irdata_count >= sizeof(data->irdata) * 8) { | ||
548 | data->irdata_error = 1; | ||
549 | return; | ||
550 | } | ||
551 | |||
552 | if (set) | ||
553 | __set_bit(data->irdata_count, data->irdata); | ||
554 | data->irdata_count++; | ||
555 | } | ||
556 | |||
557 | /* Gets count bits of irdata */ | ||
558 | static u16 | ||
559 | get_bits(struct wbcir_data *data, int count) | ||
560 | { | ||
561 | u16 val = 0x0; | ||
562 | |||
563 | if (data->irdata_count - data->irdata_off < count) { | ||
564 | data->irdata_error = 1; | ||
565 | return 0x0; | ||
566 | } | ||
567 | |||
568 | while (count > 0) { | ||
569 | val <<= 1; | ||
570 | if (test_bit(data->irdata_off, data->irdata)) | ||
571 | val |= 0x1; | ||
572 | count--; | ||
573 | data->irdata_off++; | ||
574 | } | ||
575 | |||
576 | return val; | ||
577 | } | ||
578 | |||
579 | /* Reads 16 cells and converts them to a byte */ | ||
580 | static u8 | ||
581 | wbcir_rc6cells_to_byte(struct wbcir_data *data) | ||
582 | { | ||
583 | u16 raw = get_bits(data, 16); | ||
584 | u8 val = 0x00; | ||
585 | int bit; | ||
586 | |||
587 | for (bit = 0; bit < 8; bit++) { | ||
588 | switch (raw & 0x03) { | ||
589 | case 0x01: | ||
590 | break; | ||
591 | case 0x02: | ||
592 | val |= (0x01 << bit); | ||
593 | break; | ||
594 | default: | ||
595 | data->irdata_error = 1; | ||
596 | break; | ||
597 | } | ||
598 | raw >>= 2; | ||
599 | } | ||
600 | |||
601 | return val; | ||
602 | } | ||
603 | |||
604 | /* Decodes a number of bits from raw RC5 data */ | ||
605 | static u8 | ||
606 | wbcir_get_rc5bits(struct wbcir_data *data, unsigned int count) | ||
607 | { | ||
608 | u16 raw = get_bits(data, count * 2); | ||
609 | u8 val = 0x00; | ||
610 | int bit; | ||
611 | |||
612 | for (bit = 0; bit < count; bit++) { | ||
613 | switch (raw & 0x03) { | ||
614 | case 0x01: | ||
615 | val |= (0x01 << bit); | ||
616 | break; | ||
617 | case 0x02: | ||
618 | break; | ||
619 | default: | ||
620 | data->irdata_error = 1; | ||
621 | break; | ||
622 | } | ||
623 | raw >>= 2; | ||
624 | } | ||
625 | |||
626 | return val; | ||
627 | } | ||
628 | |||
629 | static void | ||
630 | wbcir_parse_rc6(struct device *dev, struct wbcir_data *data) | ||
631 | { | ||
632 | /* | ||
633 | * Normal bits are manchester coded as follows: | ||
634 | * cell0 + cell1 = logic "0" | ||
635 | * cell1 + cell0 = logic "1" | ||
636 | * | ||
637 | * The IR pulse has the following components: | ||
638 | * | ||
639 | * Leader - 6 * cell1 - discarded | ||
640 | * Gap - 2 * cell0 - discarded | ||
641 | * Start bit - Normal Coding - always "1" | ||
642 | * Mode Bit 2 - 0 - Normal Coding | ||
643 | * Toggle bit - Normal Coding with double bit time, | ||
644 | * e.g. cell0 + cell0 + cell1 + cell1 | ||
645 | * means logic "0". | ||
646 | * | ||
647 | * The rest depends on the mode, the following modes are known: | ||
648 | * | ||
649 | * MODE 0: | ||
650 | * Address Bit 7 - 0 - Normal Coding | ||
651 | * Command Bit 7 - 0 - Normal Coding | ||
652 | * | ||
653 | * MODE 6: | ||
654 | * The above Toggle Bit is used as a submode bit, 0 = A, 1 = B. | ||
655 | * Submode B is for pointing devices, only remotes using submode A | ||
656 | * are supported. | ||
657 | * | ||
658 | * Customer range bit - 0 => Customer = 7 bits, 0...127 | ||
659 | * 1 => Customer = 15 bits, 32768...65535 | ||
660 | * Customer Bits - Normal Coding | ||
661 | * | ||
662 | * Customer codes are allocated by Philips. The rest of the bits | ||
663 | * are customer dependent. The following is commonly used (and the | ||
664 | * only supported config): | ||
665 | * | ||
666 | * Toggle Bit - Normal Coding | ||
667 | * Address Bit 6 - 0 - Normal Coding | ||
668 | * Command Bit 7 - 0 - Normal Coding | ||
669 | * | ||
670 | * All modes are followed by at least 6 * cell0. | ||
671 | * | ||
672 | * MODE 0 msglen: | ||
673 | * 1 * 2 (start bit) + 3 * 2 (mode) + 2 * 2 (toggle) + | ||
674 | * 8 * 2 (address) + 8 * 2 (command) = | ||
675 | * 44 cells | ||
676 | * | ||
677 | * MODE 6A msglen: | ||
678 | * 1 * 2 (start bit) + 3 * 2 (mode) + 2 * 2 (submode) + | ||
679 | * 1 * 2 (customer range bit) + 7/15 * 2 (customer bits) + | ||
680 | * 1 * 2 (toggle bit) + 7 * 2 (address) + 8 * 2 (command) = | ||
681 | * 60 - 76 cells | ||
682 | */ | ||
683 | u8 mode; | ||
684 | u8 toggle; | ||
685 | u16 customer = 0x0; | ||
686 | u8 address; | ||
687 | u8 command; | ||
688 | u32 scancode; | ||
689 | |||
690 | /* Leader mark */ | ||
691 | while (get_bits(data, 1) && !data->irdata_error) | ||
692 | /* Do nothing */; | ||
693 | |||
694 | /* Leader space */ | ||
695 | if (get_bits(data, 1)) { | ||
696 | dev_dbg(dev, "RC6 - Invalid leader space\n"); | ||
697 | return; | ||
698 | } | ||
699 | |||
700 | /* Start bit */ | ||
701 | if (get_bits(data, 2) != 0x02) { | ||
702 | dev_dbg(dev, "RC6 - Invalid start bit\n"); | ||
703 | return; | ||
704 | } | ||
705 | |||
706 | /* Mode */ | ||
707 | mode = get_bits(data, 6); | ||
708 | switch (mode) { | ||
709 | case 0x15: /* 010101 = b000 */ | ||
710 | mode = 0; | ||
711 | break; | ||
712 | case 0x29: /* 101001 = b110 */ | ||
713 | mode = 6; | ||
714 | break; | ||
715 | default: | ||
716 | dev_dbg(dev, "RC6 - Invalid mode\n"); | ||
717 | return; | ||
718 | } | ||
719 | |||
720 | /* Toggle bit / Submode bit */ | ||
721 | toggle = get_bits(data, 4); | ||
722 | switch (toggle) { | ||
723 | case 0x03: | ||
724 | toggle = 0; | ||
725 | break; | ||
726 | case 0x0C: | ||
727 | toggle = 1; | ||
728 | break; | ||
729 | default: | ||
730 | dev_dbg(dev, "RC6 - Toggle bit error\n"); | ||
731 | break; | ||
732 | } | ||
733 | |||
734 | /* Customer */ | ||
735 | if (mode == 6) { | ||
736 | if (toggle != 0) { | ||
737 | dev_dbg(dev, "RC6B - Not Supported\n"); | ||
738 | return; | ||
739 | } | ||
740 | |||
741 | customer = wbcir_rc6cells_to_byte(data); | ||
742 | |||
743 | if (customer & 0x80) { | ||
744 | /* 15 bit customer value */ | ||
745 | customer <<= 8; | ||
746 | customer |= wbcir_rc6cells_to_byte(data); | ||
747 | } | ||
748 | } | ||
749 | |||
750 | /* Address */ | ||
751 | address = wbcir_rc6cells_to_byte(data); | ||
752 | if (mode == 6) { | ||
753 | toggle = address >> 7; | ||
754 | address &= 0x7F; | ||
755 | } | ||
756 | |||
757 | /* Command */ | ||
758 | command = wbcir_rc6cells_to_byte(data); | ||
759 | |||
760 | /* Create scancode */ | ||
761 | scancode = command; | ||
762 | scancode |= address << 8; | ||
763 | scancode |= customer << 16; | ||
764 | |||
765 | /* Last sanity check */ | ||
766 | if (data->irdata_error) { | ||
767 | dev_dbg(dev, "RC6 - Cell error(s)\n"); | ||
768 | return; | ||
769 | } | ||
770 | |||
771 | dev_info(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X " | ||
772 | "toggle %u mode %u scan 0x%08X\n", | ||
773 | address, | ||
774 | command, | ||
775 | customer, | ||
776 | (unsigned int)toggle, | ||
777 | (unsigned int)mode, | ||
778 | scancode); | ||
779 | |||
780 | wbcir_keydown(data, scancode, toggle); | ||
781 | } | ||
782 | |||
783 | static void | ||
784 | wbcir_parse_rc5(struct device *dev, struct wbcir_data *data) | ||
785 | { | ||
786 | /* | ||
787 | * Bits are manchester coded as follows: | ||
788 | * cell1 + cell0 = logic "0" | ||
789 | * cell0 + cell1 = logic "1" | ||
790 | * (i.e. the reverse of RC6) | ||
791 | * | ||
792 | * Start bit 1 - "1" - discarded | ||
793 | * Start bit 2 - Must be inverted to get command bit 6 | ||
794 | * Toggle bit | ||
795 | * Address Bit 4 - 0 | ||
796 | * Command Bit 5 - 0 | ||
797 | */ | ||
798 | u8 toggle; | ||
799 | u8 address; | ||
800 | u8 command; | ||
801 | u32 scancode; | ||
802 | |||
803 | /* Start bit 1 */ | ||
804 | if (!get_bits(data, 1)) { | ||
805 | dev_dbg(dev, "RC5 - Invalid start bit\n"); | ||
806 | return; | ||
807 | } | ||
808 | |||
809 | /* Start bit 2 */ | ||
810 | if (!wbcir_get_rc5bits(data, 1)) | ||
811 | command = 0x40; | ||
812 | else | ||
813 | command = 0x00; | ||
814 | |||
815 | toggle = wbcir_get_rc5bits(data, 1); | ||
816 | address = wbcir_get_rc5bits(data, 5); | ||
817 | command |= wbcir_get_rc5bits(data, 6); | ||
818 | scancode = address << 7 | command; | ||
819 | |||
820 | /* Last sanity check */ | ||
821 | if (data->irdata_error) { | ||
822 | dev_dbg(dev, "RC5 - Invalid message\n"); | ||
823 | return; | ||
824 | } | ||
825 | |||
826 | dev_dbg(dev, "IR-RC5 ad %u cm %u t %u s %u\n", | ||
827 | (unsigned int)address, | ||
828 | (unsigned int)command, | ||
829 | (unsigned int)toggle, | ||
830 | (unsigned int)scancode); | ||
831 | |||
832 | wbcir_keydown(data, scancode, toggle); | ||
833 | } | ||
834 | |||
835 | static void | ||
836 | wbcir_parse_nec(struct device *dev, struct wbcir_data *data) | ||
837 | { | ||
838 | /* | ||
839 | * Each bit represents 560 us. | ||
840 | * | ||
841 | * Leader - 9 ms burst | ||
842 | * Gap - 4.5 ms silence | ||
843 | * Address1 bit 0 - 7 - Address 1 | ||
844 | * Address2 bit 0 - 7 - Address 2 | ||
845 | * Command1 bit 0 - 7 - Command 1 | ||
846 | * Command2 bit 0 - 7 - Command 2 | ||
847 | * | ||
848 | * Note the bit order! | ||
849 | * | ||
850 | * With the old NEC protocol, Address2 was the inverse of Address1 | ||
851 | * and Command2 was the inverse of Command1 and were used as | ||
852 | * an error check. | ||
853 | * | ||
854 | * With NEC extended, Address1 is the LSB of the Address and | ||
855 | * Address2 is the MSB, Command parsing remains unchanged. | ||
856 | * | ||
857 | * A repeat message is coded as: | ||
858 | * Leader - 9 ms burst | ||
859 | * Gap - 2.25 ms silence | ||
860 | * Repeat - 560 us active | ||
861 | */ | ||
862 | u8 address1; | ||
863 | u8 address2; | ||
864 | u8 command1; | ||
865 | u8 command2; | ||
866 | u16 address; | ||
867 | u32 scancode; | ||
868 | |||
869 | /* Leader mark */ | ||
870 | while (get_bits(data, 1) && !data->irdata_error) | ||
871 | /* Do nothing */; | ||
872 | |||
873 | /* Leader space */ | ||
874 | if (get_bits(data, 4)) { | ||
875 | dev_dbg(dev, "NEC - Invalid leader space\n"); | ||
876 | return; | ||
877 | } | ||
878 | |||
879 | /* Repeat? */ | ||
880 | if (get_bits(data, 1)) { | ||
881 | if (!data->keypressed) { | ||
882 | dev_dbg(dev, "NEC - Stray repeat message\n"); | ||
883 | return; | ||
884 | } | ||
885 | |||
886 | dev_dbg(dev, "IR-NEC repeat s %u\n", | ||
887 | (unsigned int)data->last_scancode); | ||
888 | |||
889 | wbcir_keydown(data, data->last_scancode, data->last_toggle); | ||
890 | return; | ||
891 | } | ||
892 | |||
893 | /* Remaining leader space */ | ||
894 | if (get_bits(data, 3)) { | ||
895 | dev_dbg(dev, "NEC - Invalid leader space\n"); | ||
896 | return; | ||
897 | } | ||
898 | |||
899 | address1 = bitrev8(get_bits(data, 8)); | ||
900 | address2 = bitrev8(get_bits(data, 8)); | ||
901 | command1 = bitrev8(get_bits(data, 8)); | ||
902 | command2 = bitrev8(get_bits(data, 8)); | ||
903 | |||
904 | /* Sanity check */ | ||
905 | if (data->irdata_error) { | ||
906 | dev_dbg(dev, "NEC - Invalid message\n"); | ||
907 | return; | ||
908 | } | ||
909 | |||
910 | /* Check command validity */ | ||
911 | if (command1 != ~command2) { | ||
912 | dev_dbg(dev, "NEC - Command bytes mismatch\n"); | ||
913 | return; | ||
914 | } | ||
915 | |||
916 | /* Check for extended NEC protocol */ | ||
917 | address = address1; | ||
918 | if (address1 != ~address2) | ||
919 | address |= address2 << 8; | ||
920 | |||
921 | scancode = address << 8 | command1; | ||
922 | |||
923 | dev_dbg(dev, "IR-NEC ad %u cm %u s %u\n", | ||
924 | (unsigned int)address, | ||
925 | (unsigned int)command1, | ||
926 | (unsigned int)scancode); | ||
927 | |||
928 | wbcir_keydown(data, scancode, !data->last_toggle); | ||
929 | } | ||
930 | |||
931 | |||
932 | |||
933 | /***************************************************************************** | ||
934 | * | ||
935 | * INTERRUPT FUNCTIONS | ||
936 | * | ||
937 | *****************************************************************************/ | ||
938 | |||
939 | static irqreturn_t | ||
940 | wbcir_irq_handler(int irqno, void *cookie) | ||
941 | { | ||
942 | struct pnp_dev *device = cookie; | ||
943 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
944 | struct device *dev = &device->dev; | ||
945 | u8 status; | ||
946 | unsigned long flags; | ||
947 | u8 irdata[8]; | ||
948 | int i; | ||
949 | unsigned int hw; | ||
950 | |||
951 | spin_lock_irqsave(&wbcir_lock, flags); | ||
952 | |||
953 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
954 | |||
955 | status = inb(data->sbase + WBCIR_REG_SP3_EIR); | ||
956 | |||
957 | if (!(status & (WBCIR_IRQ_RX | WBCIR_IRQ_ERR))) { | ||
958 | spin_unlock_irqrestore(&wbcir_lock, flags); | ||
959 | return IRQ_NONE; | ||
960 | } | ||
961 | |||
962 | if (status & WBCIR_IRQ_ERR) | ||
963 | data->irdata_error = 1; | ||
964 | |||
965 | if (!(status & WBCIR_IRQ_RX)) | ||
966 | goto out; | ||
967 | |||
968 | /* Since RXHDLEV is set, at least 8 bytes are in the FIFO */ | ||
969 | insb(data->sbase + WBCIR_REG_SP3_RXDATA, &irdata[0], 8); | ||
970 | |||
971 | for (i = 0; i < sizeof(irdata); i++) { | ||
972 | hw = hweight8(irdata[i]); | ||
973 | if (hw > 4) | ||
974 | add_irdata_bit(data, 0); | ||
975 | else | ||
976 | add_irdata_bit(data, 1); | ||
977 | |||
978 | if (hw == 8) | ||
979 | data->idle_count++; | ||
980 | else | ||
981 | data->idle_count = 0; | ||
982 | } | ||
983 | |||
984 | if (data->idle_count > WBCIR_MAX_IDLE_BYTES) { | ||
985 | /* Set RXINACTIVE... */ | ||
986 | outb(WBCIR_RX_DISABLE, data->sbase + WBCIR_REG_SP3_ASCR); | ||
987 | |||
988 | /* ...and drain the FIFO */ | ||
989 | while (inb(data->sbase + WBCIR_REG_SP3_LSR) & WBCIR_RX_AVAIL) | ||
990 | inb(data->sbase + WBCIR_REG_SP3_RXDATA); | ||
991 | |||
992 | dev_dbg(dev, "IRDATA:\n"); | ||
993 | for (i = 0; i < data->irdata_count; i += BITS_PER_LONG) | ||
994 | dev_dbg(dev, "0x%08lX\n", data->irdata[i/BITS_PER_LONG]); | ||
995 | |||
996 | switch (protocol) { | ||
997 | case IR_PROTOCOL_RC5: | ||
998 | wbcir_parse_rc5(dev, data); | ||
999 | break; | ||
1000 | case IR_PROTOCOL_RC6: | ||
1001 | wbcir_parse_rc6(dev, data); | ||
1002 | break; | ||
1003 | case IR_PROTOCOL_NEC: | ||
1004 | wbcir_parse_nec(dev, data); | ||
1005 | break; | ||
1006 | } | ||
1007 | |||
1008 | wbcir_reset_irdata(data); | ||
1009 | data->idle_count = 0; | ||
1010 | } | ||
1011 | |||
1012 | out: | ||
1013 | spin_unlock_irqrestore(&wbcir_lock, flags); | ||
1014 | return IRQ_HANDLED; | ||
1015 | } | ||
1016 | |||
1017 | |||
1018 | |||
1019 | /***************************************************************************** | ||
1020 | * | ||
1021 | * SUSPEND/RESUME FUNCTIONS | ||
1022 | * | ||
1023 | *****************************************************************************/ | ||
1024 | |||
1025 | static void | ||
1026 | wbcir_shutdown(struct pnp_dev *device) | ||
1027 | { | ||
1028 | struct device *dev = &device->dev; | ||
1029 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
1030 | int do_wake = 1; | ||
1031 | u8 match[11]; | ||
1032 | u8 mask[11]; | ||
1033 | u8 rc6_csl = 0; | ||
1034 | int i; | ||
1035 | |||
1036 | memset(match, 0, sizeof(match)); | ||
1037 | memset(mask, 0, sizeof(mask)); | ||
1038 | |||
1039 | if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) { | ||
1040 | do_wake = 0; | ||
1041 | goto finish; | ||
1042 | } | ||
1043 | |||
1044 | switch (protocol) { | ||
1045 | case IR_PROTOCOL_RC5: | ||
1046 | if (wake_sc > 0xFFF) { | ||
1047 | do_wake = 0; | ||
1048 | dev_err(dev, "RC5 - Invalid wake scancode\n"); | ||
1049 | break; | ||
1050 | } | ||
1051 | |||
1052 | /* Mask = 13 bits, ex toggle */ | ||
1053 | mask[0] = 0xFF; | ||
1054 | mask[1] = 0x17; | ||
1055 | |||
1056 | match[0] = (wake_sc & 0x003F); /* 6 command bits */ | ||
1057 | match[0] |= (wake_sc & 0x0180) >> 1; /* 2 address bits */ | ||
1058 | match[1] = (wake_sc & 0x0E00) >> 9; /* 3 address bits */ | ||
1059 | if (!(wake_sc & 0x0040)) /* 2nd start bit */ | ||
1060 | match[1] |= 0x10; | ||
1061 | |||
1062 | break; | ||
1063 | |||
1064 | case IR_PROTOCOL_NEC: | ||
1065 | if (wake_sc > 0xFFFFFF) { | ||
1066 | do_wake = 0; | ||
1067 | dev_err(dev, "NEC - Invalid wake scancode\n"); | ||
1068 | break; | ||
1069 | } | ||
1070 | |||
1071 | mask[0] = mask[1] = mask[2] = mask[3] = 0xFF; | ||
1072 | |||
1073 | match[1] = bitrev8((wake_sc & 0xFF)); | ||
1074 | match[0] = ~match[1]; | ||
1075 | |||
1076 | match[3] = bitrev8((wake_sc & 0xFF00) >> 8); | ||
1077 | if (wake_sc > 0xFFFF) | ||
1078 | match[2] = bitrev8((wake_sc & 0xFF0000) >> 16); | ||
1079 | else | ||
1080 | match[2] = ~match[3]; | ||
1081 | |||
1082 | break; | ||
1083 | |||
1084 | case IR_PROTOCOL_RC6: | ||
1085 | |||
1086 | if (wake_rc6mode == 0) { | ||
1087 | if (wake_sc > 0xFFFF) { | ||
1088 | do_wake = 0; | ||
1089 | dev_err(dev, "RC6 - Invalid wake scancode\n"); | ||
1090 | break; | ||
1091 | } | ||
1092 | |||
1093 | /* Command */ | ||
1094 | match[0] = wbcir_to_rc6cells(wake_sc >> 0); | ||
1095 | mask[0] = 0xFF; | ||
1096 | match[1] = wbcir_to_rc6cells(wake_sc >> 4); | ||
1097 | mask[1] = 0xFF; | ||
1098 | |||
1099 | /* Address */ | ||
1100 | match[2] = wbcir_to_rc6cells(wake_sc >> 8); | ||
1101 | mask[2] = 0xFF; | ||
1102 | match[3] = wbcir_to_rc6cells(wake_sc >> 12); | ||
1103 | mask[3] = 0xFF; | ||
1104 | |||
1105 | /* Header */ | ||
1106 | match[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */ | ||
1107 | mask[4] = 0xF0; | ||
1108 | match[5] = 0x09; /* start bit = 1, mode2 = 0 */ | ||
1109 | mask[5] = 0x0F; | ||
1110 | |||
1111 | rc6_csl = 44; | ||
1112 | |||
1113 | } else if (wake_rc6mode == 6) { | ||
1114 | i = 0; | ||
1115 | |||
1116 | /* Command */ | ||
1117 | match[i] = wbcir_to_rc6cells(wake_sc >> 0); | ||
1118 | mask[i++] = 0xFF; | ||
1119 | match[i] = wbcir_to_rc6cells(wake_sc >> 4); | ||
1120 | mask[i++] = 0xFF; | ||
1121 | |||
1122 | /* Address + Toggle */ | ||
1123 | match[i] = wbcir_to_rc6cells(wake_sc >> 8); | ||
1124 | mask[i++] = 0xFF; | ||
1125 | match[i] = wbcir_to_rc6cells(wake_sc >> 12); | ||
1126 | mask[i++] = 0x3F; | ||
1127 | |||
1128 | /* Customer bits 7 - 0 */ | ||
1129 | match[i] = wbcir_to_rc6cells(wake_sc >> 16); | ||
1130 | mask[i++] = 0xFF; | ||
1131 | match[i] = wbcir_to_rc6cells(wake_sc >> 20); | ||
1132 | mask[i++] = 0xFF; | ||
1133 | |||
1134 | if (wake_sc & 0x80000000) { | ||
1135 | /* Customer range bit and bits 15 - 8 */ | ||
1136 | match[i] = wbcir_to_rc6cells(wake_sc >> 24); | ||
1137 | mask[i++] = 0xFF; | ||
1138 | match[i] = wbcir_to_rc6cells(wake_sc >> 28); | ||
1139 | mask[i++] = 0xFF; | ||
1140 | rc6_csl = 76; | ||
1141 | } else if (wake_sc <= 0x007FFFFF) { | ||
1142 | rc6_csl = 60; | ||
1143 | } else { | ||
1144 | do_wake = 0; | ||
1145 | dev_err(dev, "RC6 - Invalid wake scancode\n"); | ||
1146 | break; | ||
1147 | } | ||
1148 | |||
1149 | /* Header */ | ||
1150 | match[i] = 0x93; /* mode1 = mode0 = 1, submode = 0 */ | ||
1151 | mask[i++] = 0xFF; | ||
1152 | match[i] = 0x0A; /* start bit = 1, mode2 = 1 */ | ||
1153 | mask[i++] = 0x0F; | ||
1154 | |||
1155 | } else { | ||
1156 | do_wake = 0; | ||
1157 | dev_err(dev, "RC6 - Invalid wake mode\n"); | ||
1158 | } | ||
1159 | |||
1160 | break; | ||
1161 | |||
1162 | default: | ||
1163 | do_wake = 0; | ||
1164 | break; | ||
1165 | } | ||
1166 | |||
1167 | finish: | ||
1168 | if (do_wake) { | ||
1169 | /* Set compare and compare mask */ | ||
1170 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX, | ||
1171 | WBCIR_REGSEL_COMPARE | WBCIR_REG_ADDR0, | ||
1172 | 0x3F); | ||
1173 | outsb(data->wbase + WBCIR_REG_WCEIR_DATA, match, 11); | ||
1174 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_INDEX, | ||
1175 | WBCIR_REGSEL_MASK | WBCIR_REG_ADDR0, | ||
1176 | 0x3F); | ||
1177 | outsb(data->wbase + WBCIR_REG_WCEIR_DATA, mask, 11); | ||
1178 | |||
1179 | /* RC6 Compare String Len */ | ||
1180 | outb(rc6_csl, data->wbase + WBCIR_REG_WCEIR_CSL); | ||
1181 | |||
1182 | /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ | ||
1183 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); | ||
1184 | |||
1185 | /* Clear BUFF_EN, Clear END_EN, Set MATCH_EN */ | ||
1186 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x01, 0x07); | ||
1187 | |||
1188 | /* Set CEIR_EN */ | ||
1189 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x01, 0x01); | ||
1190 | |||
1191 | } else { | ||
1192 | /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ | ||
1193 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); | ||
1194 | |||
1195 | /* Clear CEIR_EN */ | ||
1196 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); | ||
1197 | } | ||
1198 | |||
1199 | /* Disable interrupts */ | ||
1200 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
1201 | } | ||
1202 | |||
1203 | static int | ||
1204 | wbcir_suspend(struct pnp_dev *device, pm_message_t state) | ||
1205 | { | ||
1206 | wbcir_shutdown(device); | ||
1207 | return 0; | ||
1208 | } | ||
1209 | |||
1210 | static int | ||
1211 | wbcir_resume(struct pnp_dev *device) | ||
1212 | { | ||
1213 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
1214 | |||
1215 | /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ | ||
1216 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); | ||
1217 | |||
1218 | /* Clear CEIR_EN */ | ||
1219 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); | ||
1220 | |||
1221 | /* Enable interrupts */ | ||
1222 | wbcir_reset_irdata(data); | ||
1223 | outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); | ||
1224 | |||
1225 | return 0; | ||
1226 | } | ||
1227 | |||
1228 | |||
1229 | |||
1230 | /***************************************************************************** | ||
1231 | * | ||
1232 | * SETUP/INIT FUNCTIONS | ||
1233 | * | ||
1234 | *****************************************************************************/ | ||
1235 | |||
1236 | static void | ||
1237 | wbcir_cfg_ceir(struct wbcir_data *data) | ||
1238 | { | ||
1239 | u8 tmp; | ||
1240 | |||
1241 | /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ | ||
1242 | tmp = protocol << 4; | ||
1243 | if (invert) | ||
1244 | tmp |= 0x08; | ||
1245 | outb(tmp, data->wbase + WBCIR_REG_WCEIR_CTL); | ||
1246 | |||
1247 | /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ | ||
1248 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); | ||
1249 | |||
1250 | /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ | ||
1251 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); | ||
1252 | |||
1253 | /* Set RC5 cell time to correspond to 36 kHz */ | ||
1254 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CFG1, 0x4A, 0x7F); | ||
1255 | |||
1256 | /* Set IRTX_INV */ | ||
1257 | if (invert) | ||
1258 | outb(0x04, data->ebase + WBCIR_REG_ECEIR_CCTL); | ||
1259 | else | ||
1260 | outb(0x00, data->ebase + WBCIR_REG_ECEIR_CCTL); | ||
1261 | |||
1262 | /* | ||
1263 | * Clear IR LED, set SP3 clock to 24Mhz | ||
1264 | * set SP3_IRRX_SW to binary 01, helpfully not documented | ||
1265 | */ | ||
1266 | outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); | ||
1267 | } | ||
1268 | |||
1269 | static int __devinit | ||
1270 | wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) | ||
1271 | { | ||
1272 | struct device *dev = &device->dev; | ||
1273 | struct wbcir_data *data; | ||
1274 | int err; | ||
1275 | |||
1276 | if (!(pnp_port_len(device, 0) == EHFUNC_IOMEM_LEN && | ||
1277 | pnp_port_len(device, 1) == WAKEUP_IOMEM_LEN && | ||
1278 | pnp_port_len(device, 2) == SP_IOMEM_LEN)) { | ||
1279 | dev_err(dev, "Invalid resources\n"); | ||
1280 | return -ENODEV; | ||
1281 | } | ||
1282 | |||
1283 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
1284 | if (!data) { | ||
1285 | err = -ENOMEM; | ||
1286 | goto exit; | ||
1287 | } | ||
1288 | |||
1289 | pnp_set_drvdata(device, data); | ||
1290 | |||
1291 | data->ebase = pnp_port_start(device, 0); | ||
1292 | data->wbase = pnp_port_start(device, 1); | ||
1293 | data->sbase = pnp_port_start(device, 2); | ||
1294 | data->irq = pnp_irq(device, 0); | ||
1295 | |||
1296 | if (data->wbase == 0 || data->ebase == 0 || | ||
1297 | data->sbase == 0 || data->irq == 0) { | ||
1298 | err = -ENODEV; | ||
1299 | dev_err(dev, "Invalid resources\n"); | ||
1300 | goto exit_free_data; | ||
1301 | } | ||
1302 | |||
1303 | dev_dbg(&device->dev, "Found device " | ||
1304 | "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n", | ||
1305 | data->wbase, data->ebase, data->sbase, data->irq); | ||
1306 | |||
1307 | if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) { | ||
1308 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1309 | data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1); | ||
1310 | err = -EBUSY; | ||
1311 | goto exit_free_data; | ||
1312 | } | ||
1313 | |||
1314 | if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) { | ||
1315 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1316 | data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1); | ||
1317 | err = -EBUSY; | ||
1318 | goto exit_release_wbase; | ||
1319 | } | ||
1320 | |||
1321 | if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) { | ||
1322 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1323 | data->sbase, data->sbase + SP_IOMEM_LEN - 1); | ||
1324 | err = -EBUSY; | ||
1325 | goto exit_release_ebase; | ||
1326 | } | ||
1327 | |||
1328 | err = request_irq(data->irq, wbcir_irq_handler, | ||
1329 | IRQF_DISABLED, DRVNAME, device); | ||
1330 | if (err) { | ||
1331 | dev_err(dev, "Failed to claim IRQ %u\n", data->irq); | ||
1332 | err = -EBUSY; | ||
1333 | goto exit_release_sbase; | ||
1334 | } | ||
1335 | |||
1336 | led_trigger_register_simple("cir-tx", &data->txtrigger); | ||
1337 | if (!data->txtrigger) { | ||
1338 | err = -ENOMEM; | ||
1339 | goto exit_free_irq; | ||
1340 | } | ||
1341 | |||
1342 | led_trigger_register_simple("cir-rx", &data->rxtrigger); | ||
1343 | if (!data->rxtrigger) { | ||
1344 | err = -ENOMEM; | ||
1345 | goto exit_unregister_txtrigger; | ||
1346 | } | ||
1347 | |||
1348 | data->led.name = "cir::activity"; | ||
1349 | data->led.default_trigger = "cir-rx"; | ||
1350 | data->led.brightness_set = wbcir_led_brightness_set; | ||
1351 | data->led.brightness_get = wbcir_led_brightness_get; | ||
1352 | err = led_classdev_register(&device->dev, &data->led); | ||
1353 | if (err) | ||
1354 | goto exit_unregister_rxtrigger; | ||
1355 | |||
1356 | data->input_dev = input_allocate_device(); | ||
1357 | if (!data->input_dev) { | ||
1358 | err = -ENOMEM; | ||
1359 | goto exit_unregister_led; | ||
1360 | } | ||
1361 | |||
1362 | data->input_dev->evbit[0] = BIT(EV_KEY); | ||
1363 | data->input_dev->name = WBCIR_NAME; | ||
1364 | data->input_dev->phys = "wbcir/cir0"; | ||
1365 | data->input_dev->id.bustype = BUS_HOST; | ||
1366 | data->input_dev->id.vendor = PCI_VENDOR_ID_WINBOND; | ||
1367 | data->input_dev->id.product = WBCIR_ID_FAMILY; | ||
1368 | data->input_dev->id.version = WBCIR_ID_CHIP; | ||
1369 | data->input_dev->getkeycode = wbcir_getkeycode; | ||
1370 | data->input_dev->setkeycode = wbcir_setkeycode; | ||
1371 | input_set_capability(data->input_dev, EV_MSC, MSC_SCAN); | ||
1372 | input_set_drvdata(data->input_dev, data); | ||
1373 | |||
1374 | err = input_register_device(data->input_dev); | ||
1375 | if (err) | ||
1376 | goto exit_free_input; | ||
1377 | |||
1378 | data->last_scancode = INVALID_SCANCODE; | ||
1379 | INIT_LIST_HEAD(&data->keytable); | ||
1380 | setup_timer(&data->timer_keyup, wbcir_keyup, (unsigned long)data); | ||
1381 | |||
1382 | /* Load default keymaps */ | ||
1383 | if (protocol == IR_PROTOCOL_RC6) { | ||
1384 | int i; | ||
1385 | for (i = 0; i < ARRAY_SIZE(rc6_def_keymap); i++) { | ||
1386 | err = wbcir_setkeycode(data->input_dev, | ||
1387 | (int)rc6_def_keymap[i].scancode, | ||
1388 | (int)rc6_def_keymap[i].keycode); | ||
1389 | if (err) | ||
1390 | goto exit_unregister_keys; | ||
1391 | } | ||
1392 | } | ||
1393 | |||
1394 | device_init_wakeup(&device->dev, 1); | ||
1395 | |||
1396 | wbcir_cfg_ceir(data); | ||
1397 | |||
1398 | /* Disable interrupts */ | ||
1399 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
1400 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
1401 | |||
1402 | /* Enable extended mode */ | ||
1403 | wbcir_select_bank(data, WBCIR_BANK_2); | ||
1404 | outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1); | ||
1405 | |||
1406 | /* | ||
1407 | * Configure baud generator, IR data will be sampled at | ||
1408 | * a bitrate of: (24Mhz * prescaler) / (divisor * 16). | ||
1409 | * | ||
1410 | * The ECIR registers include a flag to change the | ||
1411 | * 24Mhz clock freq to 48Mhz. | ||
1412 | * | ||
1413 | * It's not documented in the specs, but fifo levels | ||
1414 | * other than 16 seems to be unsupported. | ||
1415 | */ | ||
1416 | |||
1417 | /* prescaler 1.0, tx/rx fifo lvl 16 */ | ||
1418 | outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); | ||
1419 | |||
1420 | /* Set baud divisor to generate one byte per bit/cell */ | ||
1421 | switch (protocol) { | ||
1422 | case IR_PROTOCOL_RC5: | ||
1423 | outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); | ||
1424 | break; | ||
1425 | case IR_PROTOCOL_RC6: | ||
1426 | outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); | ||
1427 | break; | ||
1428 | case IR_PROTOCOL_NEC: | ||
1429 | outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); | ||
1430 | break; | ||
1431 | } | ||
1432 | outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); | ||
1433 | |||
1434 | /* Set CEIR mode */ | ||
1435 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
1436 | outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR); | ||
1437 | inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */ | ||
1438 | inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ | ||
1439 | |||
1440 | /* Disable RX demod, run-length encoding/decoding, set freq span */ | ||
1441 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
1442 | outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); | ||
1443 | |||
1444 | /* Disable timer */ | ||
1445 | wbcir_select_bank(data, WBCIR_BANK_4); | ||
1446 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); | ||
1447 | |||
1448 | /* Enable MSR interrupt, Clear AUX_IRX */ | ||
1449 | wbcir_select_bank(data, WBCIR_BANK_5); | ||
1450 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); | ||
1451 | |||
1452 | /* Disable CRC */ | ||
1453 | wbcir_select_bank(data, WBCIR_BANK_6); | ||
1454 | outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); | ||
1455 | |||
1456 | /* Set RX/TX (de)modulation freq, not really used */ | ||
1457 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
1458 | outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); | ||
1459 | outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); | ||
1460 | |||
1461 | /* Set invert and pin direction */ | ||
1462 | if (invert) | ||
1463 | outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
1464 | else | ||
1465 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
1466 | |||
1467 | /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */ | ||
1468 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
1469 | outb(0x97, data->sbase + WBCIR_REG_SP3_FCR); | ||
1470 | |||
1471 | /* Clear AUX status bits */ | ||
1472 | outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); | ||
1473 | |||
1474 | /* Enable interrupts */ | ||
1475 | outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); | ||
1476 | |||
1477 | return 0; | ||
1478 | |||
1479 | exit_unregister_keys: | ||
1480 | if (!list_empty(&data->keytable)) { | ||
1481 | struct wbcir_keyentry *key; | ||
1482 | struct wbcir_keyentry *keytmp; | ||
1483 | |||
1484 | list_for_each_entry_safe(key, keytmp, &data->keytable, list) { | ||
1485 | list_del(&key->list); | ||
1486 | kfree(key); | ||
1487 | } | ||
1488 | } | ||
1489 | input_unregister_device(data->input_dev); | ||
1490 | /* Can't call input_free_device on an unregistered device */ | ||
1491 | data->input_dev = NULL; | ||
1492 | exit_free_input: | ||
1493 | input_free_device(data->input_dev); | ||
1494 | exit_unregister_led: | ||
1495 | led_classdev_unregister(&data->led); | ||
1496 | exit_unregister_rxtrigger: | ||
1497 | led_trigger_unregister_simple(data->rxtrigger); | ||
1498 | exit_unregister_txtrigger: | ||
1499 | led_trigger_unregister_simple(data->txtrigger); | ||
1500 | exit_free_irq: | ||
1501 | free_irq(data->irq, device); | ||
1502 | exit_release_sbase: | ||
1503 | release_region(data->sbase, SP_IOMEM_LEN); | ||
1504 | exit_release_ebase: | ||
1505 | release_region(data->ebase, EHFUNC_IOMEM_LEN); | ||
1506 | exit_release_wbase: | ||
1507 | release_region(data->wbase, WAKEUP_IOMEM_LEN); | ||
1508 | exit_free_data: | ||
1509 | kfree(data); | ||
1510 | pnp_set_drvdata(device, NULL); | ||
1511 | exit: | ||
1512 | return err; | ||
1513 | } | ||
1514 | |||
1515 | static void __devexit | ||
1516 | wbcir_remove(struct pnp_dev *device) | ||
1517 | { | ||
1518 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
1519 | struct wbcir_keyentry *key; | ||
1520 | struct wbcir_keyentry *keytmp; | ||
1521 | |||
1522 | /* Disable interrupts */ | ||
1523 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
1524 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
1525 | |||
1526 | del_timer_sync(&data->timer_keyup); | ||
1527 | |||
1528 | free_irq(data->irq, device); | ||
1529 | |||
1530 | /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ | ||
1531 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); | ||
1532 | |||
1533 | /* Clear CEIR_EN */ | ||
1534 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); | ||
1535 | |||
1536 | /* Clear BUFF_EN, END_EN, MATCH_EN */ | ||
1537 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); | ||
1538 | |||
1539 | /* This will generate a keyup event if necessary */ | ||
1540 | input_unregister_device(data->input_dev); | ||
1541 | |||
1542 | led_trigger_unregister_simple(data->rxtrigger); | ||
1543 | led_trigger_unregister_simple(data->txtrigger); | ||
1544 | led_classdev_unregister(&data->led); | ||
1545 | |||
1546 | /* This is ok since &data->led isn't actually used */ | ||
1547 | wbcir_led_brightness_set(&data->led, LED_OFF); | ||
1548 | |||
1549 | release_region(data->wbase, WAKEUP_IOMEM_LEN); | ||
1550 | release_region(data->ebase, EHFUNC_IOMEM_LEN); | ||
1551 | release_region(data->sbase, SP_IOMEM_LEN); | ||
1552 | |||
1553 | list_for_each_entry_safe(key, keytmp, &data->keytable, list) { | ||
1554 | list_del(&key->list); | ||
1555 | kfree(key); | ||
1556 | } | ||
1557 | |||
1558 | kfree(data); | ||
1559 | |||
1560 | pnp_set_drvdata(device, NULL); | ||
1561 | } | ||
1562 | |||
1563 | static const struct pnp_device_id wbcir_ids[] = { | ||
1564 | { "WEC1022", 0 }, | ||
1565 | { "", 0 } | ||
1566 | }; | ||
1567 | MODULE_DEVICE_TABLE(pnp, wbcir_ids); | ||
1568 | |||
1569 | static struct pnp_driver wbcir_driver = { | ||
1570 | .name = WBCIR_NAME, | ||
1571 | .id_table = wbcir_ids, | ||
1572 | .probe = wbcir_probe, | ||
1573 | .remove = __devexit_p(wbcir_remove), | ||
1574 | .suspend = wbcir_suspend, | ||
1575 | .resume = wbcir_resume, | ||
1576 | .shutdown = wbcir_shutdown | ||
1577 | }; | ||
1578 | |||
1579 | static int __init | ||
1580 | wbcir_init(void) | ||
1581 | { | ||
1582 | int ret; | ||
1583 | |||
1584 | switch (protocol) { | ||
1585 | case IR_PROTOCOL_RC5: | ||
1586 | case IR_PROTOCOL_NEC: | ||
1587 | case IR_PROTOCOL_RC6: | ||
1588 | break; | ||
1589 | default: | ||
1590 | printk(KERN_ERR DRVNAME ": Invalid protocol argument\n"); | ||
1591 | return -EINVAL; | ||
1592 | } | ||
1593 | |||
1594 | ret = pnp_register_driver(&wbcir_driver); | ||
1595 | if (ret) | ||
1596 | printk(KERN_ERR DRVNAME ": Unable to register driver\n"); | ||
1597 | |||
1598 | return ret; | ||
1599 | } | ||
1600 | |||
1601 | static void __exit | ||
1602 | wbcir_exit(void) | ||
1603 | { | ||
1604 | pnp_unregister_driver(&wbcir_driver); | ||
1605 | } | ||
1606 | |||
1607 | MODULE_AUTHOR("David Härdeman <david@hardeman.nu>"); | ||
1608 | MODULE_DESCRIPTION("Winbond SuperI/O Consumer IR Driver"); | ||
1609 | MODULE_LICENSE("GPL"); | ||
1610 | |||
1611 | module_init(wbcir_init); | ||
1612 | module_exit(wbcir_exit); | ||
1613 | |||
1614 | |||
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 7c8957dd22c0..11fd038a078f 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
@@ -243,9 +243,9 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; | |||
243 | #define FE_UNTESTED 0x80 | 243 | #define FE_UNTESTED 0x80 |
244 | 244 | ||
245 | static struct key_entry *keymap; /* = NULL; Current key map */ | 245 | static struct key_entry *keymap; /* = NULL; Current key map */ |
246 | static int have_wifi; | 246 | static bool have_wifi; |
247 | static int have_bluetooth; | 247 | static bool have_bluetooth; |
248 | static int have_leds; | 248 | static int leds_present; /* bitmask of leds present */ |
249 | 249 | ||
250 | static int __init dmi_matched(const struct dmi_system_id *dmi) | 250 | static int __init dmi_matched(const struct dmi_system_id *dmi) |
251 | { | 251 | { |
@@ -254,11 +254,11 @@ static int __init dmi_matched(const struct dmi_system_id *dmi) | |||
254 | keymap = dmi->driver_data; | 254 | keymap = dmi->driver_data; |
255 | for (key = keymap; key->type != KE_END; key++) { | 255 | for (key = keymap; key->type != KE_END; key++) { |
256 | if (key->type == KE_WIFI) | 256 | if (key->type == KE_WIFI) |
257 | have_wifi = 1; | 257 | have_wifi = true; |
258 | else if (key->type == KE_BLUETOOTH) | 258 | else if (key->type == KE_BLUETOOTH) |
259 | have_bluetooth = 1; | 259 | have_bluetooth = true; |
260 | } | 260 | } |
261 | have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED); | 261 | leds_present = key->code & (FE_MAIL_LED | FE_WIFI_LED); |
262 | 262 | ||
263 | return 1; | 263 | return 1; |
264 | } | 264 | } |
@@ -611,6 +611,34 @@ static struct key_entry keymap_wistron_generic[] __initdata = { | |||
611 | { KE_END, 0 } | 611 | { KE_END, 0 } |
612 | }; | 612 | }; |
613 | 613 | ||
614 | static struct key_entry keymap_aopen_1557[] __initdata = { | ||
615 | { KE_KEY, 0x01, {KEY_HELP} }, | ||
616 | { KE_KEY, 0x11, {KEY_PROG1} }, | ||
617 | { KE_KEY, 0x12, {KEY_PROG2} }, | ||
618 | { KE_WIFI, 0x30 }, | ||
619 | { KE_KEY, 0x22, {KEY_REWIND} }, | ||
620 | { KE_KEY, 0x23, {KEY_FORWARD} }, | ||
621 | { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, | ||
622 | { KE_KEY, 0x25, {KEY_STOPCD} }, | ||
623 | { KE_KEY, 0x31, {KEY_MAIL} }, | ||
624 | { KE_KEY, 0x36, {KEY_WWW} }, | ||
625 | { KE_END, 0 } | ||
626 | }; | ||
627 | |||
628 | static struct key_entry keymap_prestigio[] __initdata = { | ||
629 | { KE_KEY, 0x11, {KEY_PROG1} }, | ||
630 | { KE_KEY, 0x12, {KEY_PROG2} }, | ||
631 | { KE_WIFI, 0x30 }, | ||
632 | { KE_KEY, 0x22, {KEY_REWIND} }, | ||
633 | { KE_KEY, 0x23, {KEY_FORWARD} }, | ||
634 | { KE_KEY, 0x24, {KEY_PLAYPAUSE} }, | ||
635 | { KE_KEY, 0x25, {KEY_STOPCD} }, | ||
636 | { KE_KEY, 0x31, {KEY_MAIL} }, | ||
637 | { KE_KEY, 0x36, {KEY_WWW} }, | ||
638 | { KE_END, 0 } | ||
639 | }; | ||
640 | |||
641 | |||
614 | /* | 642 | /* |
615 | * If your machine is not here (which is currently rather likely), please send | 643 | * If your machine is not here (which is currently rather likely), please send |
616 | * a list of buttons and their key codes (reported when loading this module | 644 | * a list of buttons and their key codes (reported when loading this module |
@@ -646,6 +674,15 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
646 | }, | 674 | }, |
647 | { | 675 | { |
648 | .callback = dmi_matched, | 676 | .callback = dmi_matched, |
677 | .ident = "Maxdata Pro 7000 DX", | ||
678 | .matches = { | ||
679 | DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"), | ||
680 | DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"), | ||
681 | }, | ||
682 | .driver_data = keymap_fs_amilo_pro_v2000 | ||
683 | }, | ||
684 | { | ||
685 | .callback = dmi_matched, | ||
649 | .ident = "Fujitsu N3510", | 686 | .ident = "Fujitsu N3510", |
650 | .matches = { | 687 | .matches = { |
651 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 688 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
@@ -962,6 +999,10 @@ static int __init select_keymap(void) | |||
962 | if (keymap_name != NULL) { | 999 | if (keymap_name != NULL) { |
963 | if (strcmp (keymap_name, "1557/MS2141") == 0) | 1000 | if (strcmp (keymap_name, "1557/MS2141") == 0) |
964 | keymap = keymap_wistron_ms2141; | 1001 | keymap = keymap_wistron_ms2141; |
1002 | else if (strcmp (keymap_name, "aopen1557") == 0) | ||
1003 | keymap = keymap_aopen_1557; | ||
1004 | else if (strcmp (keymap_name, "prestigio") == 0) | ||
1005 | keymap = keymap_prestigio; | ||
965 | else if (strcmp (keymap_name, "generic") == 0) | 1006 | else if (strcmp (keymap_name, "generic") == 0) |
966 | keymap = keymap_wistron_generic; | 1007 | keymap = keymap_wistron_generic; |
967 | else { | 1008 | else { |
@@ -984,8 +1025,8 @@ static int __init select_keymap(void) | |||
984 | 1025 | ||
985 | static struct input_polled_dev *wistron_idev; | 1026 | static struct input_polled_dev *wistron_idev; |
986 | static unsigned long jiffies_last_press; | 1027 | static unsigned long jiffies_last_press; |
987 | static int wifi_enabled; | 1028 | static bool wifi_enabled; |
988 | static int bluetooth_enabled; | 1029 | static bool bluetooth_enabled; |
989 | 1030 | ||
990 | static void report_key(struct input_dev *dev, unsigned int keycode) | 1031 | static void report_key(struct input_dev *dev, unsigned int keycode) |
991 | { | 1032 | { |
@@ -1028,24 +1069,24 @@ static struct led_classdev wistron_wifi_led = { | |||
1028 | 1069 | ||
1029 | static void __devinit wistron_led_init(struct device *parent) | 1070 | static void __devinit wistron_led_init(struct device *parent) |
1030 | { | 1071 | { |
1031 | if (have_leds & FE_WIFI_LED) { | 1072 | if (leds_present & FE_WIFI_LED) { |
1032 | u16 wifi = bios_get_default_setting(WIFI); | 1073 | u16 wifi = bios_get_default_setting(WIFI); |
1033 | if (wifi & 1) { | 1074 | if (wifi & 1) { |
1034 | wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; | 1075 | wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF; |
1035 | if (led_classdev_register(parent, &wistron_wifi_led)) | 1076 | if (led_classdev_register(parent, &wistron_wifi_led)) |
1036 | have_leds &= ~FE_WIFI_LED; | 1077 | leds_present &= ~FE_WIFI_LED; |
1037 | else | 1078 | else |
1038 | bios_set_state(WIFI, wistron_wifi_led.brightness); | 1079 | bios_set_state(WIFI, wistron_wifi_led.brightness); |
1039 | 1080 | ||
1040 | } else | 1081 | } else |
1041 | have_leds &= ~FE_WIFI_LED; | 1082 | leds_present &= ~FE_WIFI_LED; |
1042 | } | 1083 | } |
1043 | 1084 | ||
1044 | if (have_leds & FE_MAIL_LED) { | 1085 | if (leds_present & FE_MAIL_LED) { |
1045 | /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ | 1086 | /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ |
1046 | wistron_mail_led.brightness = LED_OFF; | 1087 | wistron_mail_led.brightness = LED_OFF; |
1047 | if (led_classdev_register(parent, &wistron_mail_led)) | 1088 | if (led_classdev_register(parent, &wistron_mail_led)) |
1048 | have_leds &= ~FE_MAIL_LED; | 1089 | leds_present &= ~FE_MAIL_LED; |
1049 | else | 1090 | else |
1050 | bios_set_state(MAIL_LED, wistron_mail_led.brightness); | 1091 | bios_set_state(MAIL_LED, wistron_mail_led.brightness); |
1051 | } | 1092 | } |
@@ -1053,28 +1094,28 @@ static void __devinit wistron_led_init(struct device *parent) | |||
1053 | 1094 | ||
1054 | static void __devexit wistron_led_remove(void) | 1095 | static void __devexit wistron_led_remove(void) |
1055 | { | 1096 | { |
1056 | if (have_leds & FE_MAIL_LED) | 1097 | if (leds_present & FE_MAIL_LED) |
1057 | led_classdev_unregister(&wistron_mail_led); | 1098 | led_classdev_unregister(&wistron_mail_led); |
1058 | 1099 | ||
1059 | if (have_leds & FE_WIFI_LED) | 1100 | if (leds_present & FE_WIFI_LED) |
1060 | led_classdev_unregister(&wistron_wifi_led); | 1101 | led_classdev_unregister(&wistron_wifi_led); |
1061 | } | 1102 | } |
1062 | 1103 | ||
1063 | static inline void wistron_led_suspend(void) | 1104 | static inline void wistron_led_suspend(void) |
1064 | { | 1105 | { |
1065 | if (have_leds & FE_MAIL_LED) | 1106 | if (leds_present & FE_MAIL_LED) |
1066 | led_classdev_suspend(&wistron_mail_led); | 1107 | led_classdev_suspend(&wistron_mail_led); |
1067 | 1108 | ||
1068 | if (have_leds & FE_WIFI_LED) | 1109 | if (leds_present & FE_WIFI_LED) |
1069 | led_classdev_suspend(&wistron_wifi_led); | 1110 | led_classdev_suspend(&wistron_wifi_led); |
1070 | } | 1111 | } |
1071 | 1112 | ||
1072 | static inline void wistron_led_resume(void) | 1113 | static inline void wistron_led_resume(void) |
1073 | { | 1114 | { |
1074 | if (have_leds & FE_MAIL_LED) | 1115 | if (leds_present & FE_MAIL_LED) |
1075 | led_classdev_resume(&wistron_mail_led); | 1116 | led_classdev_resume(&wistron_mail_led); |
1076 | 1117 | ||
1077 | if (have_leds & FE_WIFI_LED) | 1118 | if (leds_present & FE_WIFI_LED) |
1078 | led_classdev_resume(&wistron_wifi_led); | 1119 | led_classdev_resume(&wistron_wifi_led); |
1079 | } | 1120 | } |
1080 | 1121 | ||
@@ -1287,7 +1328,7 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1287 | if (have_wifi) { | 1328 | if (have_wifi) { |
1288 | u16 wifi = bios_get_default_setting(WIFI); | 1329 | u16 wifi = bios_get_default_setting(WIFI); |
1289 | if (wifi & 1) | 1330 | if (wifi & 1) |
1290 | wifi_enabled = (wifi & 2) ? 1 : 0; | 1331 | wifi_enabled = wifi & 2; |
1291 | else | 1332 | else |
1292 | have_wifi = 0; | 1333 | have_wifi = 0; |
1293 | 1334 | ||
@@ -1298,15 +1339,16 @@ static int __devinit wistron_probe(struct platform_device *dev) | |||
1298 | if (have_bluetooth) { | 1339 | if (have_bluetooth) { |
1299 | u16 bt = bios_get_default_setting(BLUETOOTH); | 1340 | u16 bt = bios_get_default_setting(BLUETOOTH); |
1300 | if (bt & 1) | 1341 | if (bt & 1) |
1301 | bluetooth_enabled = (bt & 2) ? 1 : 0; | 1342 | bluetooth_enabled = bt & 2; |
1302 | else | 1343 | else |
1303 | have_bluetooth = 0; | 1344 | have_bluetooth = false; |
1304 | 1345 | ||
1305 | if (have_bluetooth) | 1346 | if (have_bluetooth) |
1306 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1347 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1307 | } | 1348 | } |
1308 | 1349 | ||
1309 | wistron_led_init(&dev->dev); | 1350 | wistron_led_init(&dev->dev); |
1351 | |||
1310 | err = setup_input_dev(); | 1352 | err = setup_input_dev(); |
1311 | if (err) { | 1353 | if (err) { |
1312 | bios_detach(); | 1354 | bios_detach(); |
@@ -1327,7 +1369,7 @@ static int __devexit wistron_remove(struct platform_device *dev) | |||
1327 | } | 1369 | } |
1328 | 1370 | ||
1329 | #ifdef CONFIG_PM | 1371 | #ifdef CONFIG_PM |
1330 | static int wistron_suspend(struct platform_device *dev, pm_message_t state) | 1372 | static int wistron_suspend(struct device *dev) |
1331 | { | 1373 | { |
1332 | if (have_wifi) | 1374 | if (have_wifi) |
1333 | bios_set_state(WIFI, 0); | 1375 | bios_set_state(WIFI, 0); |
@@ -1336,10 +1378,11 @@ static int wistron_suspend(struct platform_device *dev, pm_message_t state) | |||
1336 | bios_set_state(BLUETOOTH, 0); | 1378 | bios_set_state(BLUETOOTH, 0); |
1337 | 1379 | ||
1338 | wistron_led_suspend(); | 1380 | wistron_led_suspend(); |
1381 | |||
1339 | return 0; | 1382 | return 0; |
1340 | } | 1383 | } |
1341 | 1384 | ||
1342 | static int wistron_resume(struct platform_device *dev) | 1385 | static int wistron_resume(struct device *dev) |
1343 | { | 1386 | { |
1344 | if (have_wifi) | 1387 | if (have_wifi) |
1345 | bios_set_state(WIFI, wifi_enabled); | 1388 | bios_set_state(WIFI, wifi_enabled); |
@@ -1348,24 +1391,30 @@ static int wistron_resume(struct platform_device *dev) | |||
1348 | bios_set_state(BLUETOOTH, bluetooth_enabled); | 1391 | bios_set_state(BLUETOOTH, bluetooth_enabled); |
1349 | 1392 | ||
1350 | wistron_led_resume(); | 1393 | wistron_led_resume(); |
1394 | |||
1351 | poll_bios(true); | 1395 | poll_bios(true); |
1352 | 1396 | ||
1353 | return 0; | 1397 | return 0; |
1354 | } | 1398 | } |
1355 | #else | 1399 | |
1356 | #define wistron_suspend NULL | 1400 | static const struct dev_pm_ops wistron_pm_ops = { |
1357 | #define wistron_resume NULL | 1401 | .suspend = wistron_suspend, |
1402 | .resume = wistron_resume, | ||
1403 | .poweroff = wistron_suspend, | ||
1404 | .restore = wistron_resume, | ||
1405 | }; | ||
1358 | #endif | 1406 | #endif |
1359 | 1407 | ||
1360 | static struct platform_driver wistron_driver = { | 1408 | static struct platform_driver wistron_driver = { |
1361 | .driver = { | 1409 | .driver = { |
1362 | .name = "wistron-bios", | 1410 | .name = "wistron-bios", |
1363 | .owner = THIS_MODULE, | 1411 | .owner = THIS_MODULE, |
1412 | #if CONFIG_PM | ||
1413 | .pm = &wistron_pm_ops, | ||
1414 | #endif | ||
1364 | }, | 1415 | }, |
1365 | .probe = wistron_probe, | 1416 | .probe = wistron_probe, |
1366 | .remove = __devexit_p(wistron_remove), | 1417 | .remove = __devexit_p(wistron_remove), |
1367 | .suspend = wistron_suspend, | ||
1368 | .resume = wistron_resume, | ||
1369 | }; | 1418 | }; |
1370 | 1419 | ||
1371 | static int __init wb_module_init(void) | 1420 | static int __init wb_module_init(void) |
diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c new file mode 100644 index 000000000000..ba4f5dd7c60e --- /dev/null +++ b/drivers/input/misc/wm831x-on.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /** | ||
2 | * wm831x-on.c - WM831X ON pin driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General | ||
7 | * Public License. See the file "COPYING" in the main directory of this | ||
8 | * archive for more details. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/input.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/workqueue.h> | ||
28 | #include <linux/mfd/wm831x/core.h> | ||
29 | |||
30 | struct wm831x_on { | ||
31 | struct input_dev *dev; | ||
32 | struct delayed_work work; | ||
33 | struct wm831x *wm831x; | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * The chip gives us an interrupt when the ON pin is asserted but we | ||
38 | * then need to poll to see when the pin is deasserted. | ||
39 | */ | ||
40 | static void wm831x_poll_on(struct work_struct *work) | ||
41 | { | ||
42 | struct wm831x_on *wm831x_on = container_of(work, struct wm831x_on, | ||
43 | work.work); | ||
44 | struct wm831x *wm831x = wm831x_on->wm831x; | ||
45 | int poll, ret; | ||
46 | |||
47 | ret = wm831x_reg_read(wm831x, WM831X_ON_PIN_CONTROL); | ||
48 | if (ret >= 0) { | ||
49 | poll = !(ret & WM831X_ON_PIN_STS); | ||
50 | |||
51 | input_report_key(wm831x_on->dev, KEY_POWER, poll); | ||
52 | input_sync(wm831x_on->dev); | ||
53 | } else { | ||
54 | dev_err(wm831x->dev, "Failed to read ON status: %d\n", ret); | ||
55 | poll = 1; | ||
56 | } | ||
57 | |||
58 | if (poll) | ||
59 | schedule_delayed_work(&wm831x_on->work, 100); | ||
60 | } | ||
61 | |||
62 | static irqreturn_t wm831x_on_irq(int irq, void *data) | ||
63 | { | ||
64 | struct wm831x_on *wm831x_on = data; | ||
65 | |||
66 | schedule_delayed_work(&wm831x_on->work, 0); | ||
67 | |||
68 | return IRQ_HANDLED; | ||
69 | } | ||
70 | |||
71 | static int __devinit wm831x_on_probe(struct platform_device *pdev) | ||
72 | { | ||
73 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | ||
74 | struct wm831x_on *wm831x_on; | ||
75 | int irq = platform_get_irq(pdev, 0); | ||
76 | int ret; | ||
77 | |||
78 | wm831x_on = kzalloc(sizeof(struct wm831x_on), GFP_KERNEL); | ||
79 | if (!wm831x_on) { | ||
80 | dev_err(&pdev->dev, "Can't allocate data\n"); | ||
81 | return -ENOMEM; | ||
82 | } | ||
83 | |||
84 | wm831x_on->wm831x = wm831x; | ||
85 | INIT_DELAYED_WORK(&wm831x_on->work, wm831x_poll_on); | ||
86 | |||
87 | wm831x_on->dev = input_allocate_device(); | ||
88 | if (!wm831x_on->dev) { | ||
89 | dev_err(&pdev->dev, "Can't allocate input dev\n"); | ||
90 | ret = -ENOMEM; | ||
91 | goto err; | ||
92 | } | ||
93 | |||
94 | wm831x_on->dev->evbit[0] = BIT_MASK(EV_KEY); | ||
95 | wm831x_on->dev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); | ||
96 | wm831x_on->dev->name = "wm831x_on"; | ||
97 | wm831x_on->dev->phys = "wm831x_on/input0"; | ||
98 | wm831x_on->dev->dev.parent = &pdev->dev; | ||
99 | |||
100 | ret = wm831x_request_irq(wm831x, irq, wm831x_on_irq, | ||
101 | IRQF_TRIGGER_RISING, "wm831x_on", wm831x_on); | ||
102 | if (ret < 0) { | ||
103 | dev_err(&pdev->dev, "Unable to request IRQ: %d\n", ret); | ||
104 | goto err_input_dev; | ||
105 | } | ||
106 | ret = input_register_device(wm831x_on->dev); | ||
107 | if (ret) { | ||
108 | dev_dbg(&pdev->dev, "Can't register input device: %d\n", ret); | ||
109 | goto err_irq; | ||
110 | } | ||
111 | |||
112 | platform_set_drvdata(pdev, wm831x_on); | ||
113 | |||
114 | return 0; | ||
115 | |||
116 | err_irq: | ||
117 | wm831x_free_irq(wm831x, irq, NULL); | ||
118 | err_input_dev: | ||
119 | input_free_device(wm831x_on->dev); | ||
120 | err: | ||
121 | kfree(wm831x_on); | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static int __devexit wm831x_on_remove(struct platform_device *pdev) | ||
126 | { | ||
127 | struct wm831x_on *wm831x_on = platform_get_drvdata(pdev); | ||
128 | int irq = platform_get_irq(pdev, 0); | ||
129 | |||
130 | wm831x_free_irq(wm831x_on->wm831x, irq, wm831x_on); | ||
131 | cancel_delayed_work_sync(&wm831x_on->work); | ||
132 | input_unregister_device(wm831x_on->dev); | ||
133 | kfree(wm831x_on); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static struct platform_driver wm831x_on_driver = { | ||
139 | .probe = wm831x_on_probe, | ||
140 | .remove = __devexit_p(wm831x_on_remove), | ||
141 | .driver = { | ||
142 | .name = "wm831x-on", | ||
143 | .owner = THIS_MODULE, | ||
144 | }, | ||
145 | }; | ||
146 | |||
147 | static int __init wm831x_on_init(void) | ||
148 | { | ||
149 | return platform_driver_register(&wm831x_on_driver); | ||
150 | } | ||
151 | module_init(wm831x_on_init); | ||
152 | |||
153 | static void __exit wm831x_on_exit(void) | ||
154 | { | ||
155 | platform_driver_unregister(&wm831x_on_driver); | ||
156 | } | ||
157 | module_exit(wm831x_on_exit); | ||
158 | |||
159 | MODULE_ALIAS("platform:wm831x-on"); | ||
160 | MODULE_DESCRIPTION("WM831x ON pin"); | ||
161 | MODULE_LICENSE("GPL"); | ||
162 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
163 | |||
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 8a2c5b14c8d8..3feeb3af8abd 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
@@ -107,6 +107,14 @@ config MOUSE_PS2_ELANTECH | |||
107 | entries. For further information, | 107 | entries. For further information, |
108 | see <file:Documentation/input/elantech.txt>. | 108 | see <file:Documentation/input/elantech.txt>. |
109 | 109 | ||
110 | config MOUSE_PS2_SENTELIC | ||
111 | bool "Sentelic Finger Sensing Pad PS/2 protocol extension" | ||
112 | depends on MOUSE_PS2 | ||
113 | help | ||
114 | Say Y here if you have a laptop (such as MSI WIND Netbook) | ||
115 | with Sentelic Finger Sensing Pad touchpad. | ||
116 | |||
117 | If unsure, say N. | ||
110 | 118 | ||
111 | config MOUSE_PS2_TOUCHKIT | 119 | config MOUSE_PS2_TOUCHKIT |
112 | bool "eGalax TouchKit PS/2 protocol extension" | 120 | bool "eGalax TouchKit PS/2 protocol extension" |
@@ -262,14 +270,6 @@ config MOUSE_VSXXXAA | |||
262 | described in the source file). This driver also works with the | 270 | described in the source file). This driver also works with the |
263 | digitizer (VSXXX-AB) DEC produced. | 271 | digitizer (VSXXX-AB) DEC produced. |
264 | 272 | ||
265 | config MOUSE_HIL | ||
266 | tristate "HIL pointers (mice etc)." | ||
267 | depends on GSC || HP300 | ||
268 | select HP_SDC | ||
269 | select HIL_MLC | ||
270 | help | ||
271 | Say Y here to support HIL pointers. | ||
272 | |||
273 | config MOUSE_GPIO | 273 | config MOUSE_GPIO |
274 | tristate "GPIO mouse" | 274 | tristate "GPIO mouse" |
275 | depends on GENERIC_GPIO | 275 | depends on GENERIC_GPIO |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 010f265ec152..570c84a4a654 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
@@ -9,7 +9,6 @@ obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o | |||
9 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o | 9 | obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o |
10 | obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o | 10 | obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o |
11 | obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o | 11 | obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o |
12 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o | ||
13 | obj-$(CONFIG_MOUSE_INPORT) += inport.o | 12 | obj-$(CONFIG_MOUSE_INPORT) += inport.o |
14 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o | 13 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o |
15 | obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o | 14 | obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o |
@@ -28,5 +27,6 @@ psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o | |||
28 | psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o | 27 | psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o |
29 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o | 28 | psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o |
30 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o | 29 | psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o |
30 | psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o | ||
31 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o | 31 | psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o |
32 | psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o | 32 | psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 5547e2429fbe..f36110689aae 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -279,7 +279,7 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int | |||
279 | * subsequent commands. It looks like glidepad is behind stickpointer, | 279 | * subsequent commands. It looks like glidepad is behind stickpointer, |
280 | * I'd thought it would be other way around... | 280 | * I'd thought it would be other way around... |
281 | */ | 281 | */ |
282 | static int alps_passthrough_mode(struct psmouse *psmouse, int enable) | 282 | static int alps_passthrough_mode(struct psmouse *psmouse, bool enable) |
283 | { | 283 | { |
284 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 284 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
285 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; | 285 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; |
@@ -367,16 +367,16 @@ static int alps_poll(struct psmouse *psmouse) | |||
367 | { | 367 | { |
368 | struct alps_data *priv = psmouse->private; | 368 | struct alps_data *priv = psmouse->private; |
369 | unsigned char buf[6]; | 369 | unsigned char buf[6]; |
370 | int poll_failed; | 370 | bool poll_failed; |
371 | 371 | ||
372 | if (priv->i->flags & ALPS_PASS) | 372 | if (priv->i->flags & ALPS_PASS) |
373 | alps_passthrough_mode(psmouse, 1); | 373 | alps_passthrough_mode(psmouse, true); |
374 | 374 | ||
375 | poll_failed = ps2_command(&psmouse->ps2dev, buf, | 375 | poll_failed = ps2_command(&psmouse->ps2dev, buf, |
376 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; | 376 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; |
377 | 377 | ||
378 | if (priv->i->flags & ALPS_PASS) | 378 | if (priv->i->flags & ALPS_PASS) |
379 | alps_passthrough_mode(psmouse, 0); | 379 | alps_passthrough_mode(psmouse, false); |
380 | 380 | ||
381 | if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) | 381 | if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) |
382 | return -1; | 382 | return -1; |
@@ -401,10 +401,12 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
401 | if (!priv->i) | 401 | if (!priv->i) |
402 | return -1; | 402 | return -1; |
403 | 403 | ||
404 | if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1)) | 404 | if ((priv->i->flags & ALPS_PASS) && |
405 | alps_passthrough_mode(psmouse, true)) { | ||
405 | return -1; | 406 | return -1; |
407 | } | ||
406 | 408 | ||
407 | if (alps_tap_mode(psmouse, 1)) { | 409 | if (alps_tap_mode(psmouse, true)) { |
408 | printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n"); | 410 | printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n"); |
409 | return -1; | 411 | return -1; |
410 | } | 412 | } |
@@ -414,8 +416,10 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
414 | return -1; | 416 | return -1; |
415 | } | 417 | } |
416 | 418 | ||
417 | if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0)) | 419 | if ((priv->i->flags & ALPS_PASS) && |
420 | alps_passthrough_mode(psmouse, false)) { | ||
418 | return -1; | 421 | return -1; |
422 | } | ||
419 | 423 | ||
420 | /* ALPS needs stream mode, otherwise it won't report any data */ | 424 | /* ALPS needs stream mode, otherwise it won't report any data */ |
421 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { | 425 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { |
@@ -519,7 +523,7 @@ init_fail: | |||
519 | return -1; | 523 | return -1; |
520 | } | 524 | } |
521 | 525 | ||
522 | int alps_detect(struct psmouse *psmouse, int set_properties) | 526 | int alps_detect(struct psmouse *psmouse, bool set_properties) |
523 | { | 527 | { |
524 | int version; | 528 | int version; |
525 | const struct alps_model_info *model; | 529 | const struct alps_model_info *model; |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index 4bbddc99962b..bc87936fee1a 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
@@ -26,10 +26,10 @@ struct alps_data { | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | #ifdef CONFIG_MOUSE_PS2_ALPS | 28 | #ifdef CONFIG_MOUSE_PS2_ALPS |
29 | int alps_detect(struct psmouse *psmouse, int set_properties); | 29 | int alps_detect(struct psmouse *psmouse, bool set_properties); |
30 | int alps_init(struct psmouse *psmouse); | 30 | int alps_init(struct psmouse *psmouse); |
31 | #else | 31 | #else |
32 | inline int alps_detect(struct psmouse *psmouse, int set_properties) | 32 | inline int alps_detect(struct psmouse *psmouse, bool set_properties) |
33 | { | 33 | { |
34 | return -ENOSYS; | 34 | return -ENOSYS; |
35 | } | 35 | } |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 2d8fc0bf6923..0d1d33468b43 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
@@ -317,7 +317,7 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
317 | const struct tp_finger *f; | 317 | const struct tp_finger *f; |
318 | struct input_dev *input = dev->input; | 318 | struct input_dev *input = dev->input; |
319 | int raw_p, raw_w, raw_x, raw_y, raw_n; | 319 | int raw_p, raw_w, raw_x, raw_y, raw_n; |
320 | int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0; | 320 | int ptest, origin, ibt = 0, nmin = 0, nmax = 0; |
321 | 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; |
322 | 322 | ||
323 | if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) | 323 | if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0) |
@@ -345,21 +345,22 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
345 | /* set the integrated button if applicable */ | 345 | /* set the integrated button if applicable */ |
346 | if (c->tp_type == TYPE2) | 346 | if (c->tp_type == TYPE2) |
347 | ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); | 347 | ibt = raw2int(dev->tp_data[BUTTON_TYPE2]); |
348 | } | ||
349 | 348 | ||
350 | /* while tracking finger still valid, count all fingers */ | 349 | /* while tracking finger still valid, count all fingers */ |
351 | if (ptest > PRESSURE_LOW && origin) { | 350 | if (ptest > PRESSURE_LOW && origin) { |
352 | abs_p = ptest; | 351 | abs_p = ptest; |
353 | abs_w = int2bound(&c->w, raw_w); | 352 | abs_w = int2bound(&c->w, raw_w); |
354 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); | 353 | abs_x = int2bound(&c->x, raw_x - c->x.devmin); |
355 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); | 354 | abs_y = int2bound(&c->y, c->y.devmax - raw_y); |
356 | while (raw_n--) { | 355 | while (raw_n--) { |
357 | ptest = int2bound(&c->p, raw2int(f->force_major)); | 356 | ptest = int2bound(&c->p, |
358 | if (ptest > PRESSURE_LOW) | 357 | raw2int(f->force_major)); |
359 | nmax++; | 358 | if (ptest > PRESSURE_LOW) |
360 | if (ptest > PRESSURE_HIGH) | 359 | nmax++; |
361 | nmin++; | 360 | if (ptest > PRESSURE_HIGH) |
362 | f++; | 361 | nmin++; |
362 | f++; | ||
363 | } | ||
363 | } | 364 | } |
364 | } | 365 | } |
365 | 366 | ||
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 4bc78892ba91..fda35e615abf 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -553,7 +553,7 @@ static struct attribute_group elantech_attr_group = { | |||
553 | /* | 553 | /* |
554 | * Use magic knock to detect Elantech touchpad | 554 | * Use magic knock to detect Elantech touchpad |
555 | */ | 555 | */ |
556 | int elantech_detect(struct psmouse *psmouse, int set_properties) | 556 | int elantech_detect(struct psmouse *psmouse, bool set_properties) |
557 | { | 557 | { |
558 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 558 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
559 | unsigned char param[3]; | 559 | unsigned char param[3]; |
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index ed848cc80814..feac5f7af966 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -109,10 +109,10 @@ struct elantech_data { | |||
109 | }; | 109 | }; |
110 | 110 | ||
111 | #ifdef CONFIG_MOUSE_PS2_ELANTECH | 111 | #ifdef CONFIG_MOUSE_PS2_ELANTECH |
112 | int elantech_detect(struct psmouse *psmouse, int set_properties); | 112 | int elantech_detect(struct psmouse *psmouse, bool set_properties); |
113 | int elantech_init(struct psmouse *psmouse); | 113 | int elantech_init(struct psmouse *psmouse); |
114 | #else | 114 | #else |
115 | static inline int elantech_detect(struct psmouse *psmouse, int set_properties) | 115 | static inline int elantech_detect(struct psmouse *psmouse, bool set_properties) |
116 | { | 116 | { |
117 | return -ENOSYS; | 117 | return -ENOSYS; |
118 | } | 118 | } |
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 5e5eb88d8d1e..7b6ce178f1b6 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c | |||
@@ -46,7 +46,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev) | |||
46 | input_sync(input); | 46 | input_sync(input); |
47 | } | 47 | } |
48 | 48 | ||
49 | static int __init gpio_mouse_probe(struct platform_device *pdev) | 49 | static int __devinit gpio_mouse_probe(struct platform_device *pdev) |
50 | { | 50 | { |
51 | struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; | 51 | struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; |
52 | struct input_polled_dev *input_poll; | 52 | struct input_polled_dev *input_poll; |
@@ -170,10 +170,8 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev) | |||
170 | return 0; | 170 | return 0; |
171 | } | 171 | } |
172 | 172 | ||
173 | /* work with hotplug and coldplug */ | ||
174 | MODULE_ALIAS("platform:gpio_mouse"); | ||
175 | |||
176 | static struct platform_driver gpio_mouse_device_driver = { | 173 | static struct platform_driver gpio_mouse_device_driver = { |
174 | .probe = gpio_mouse_probe, | ||
177 | .remove = __devexit_p(gpio_mouse_remove), | 175 | .remove = __devexit_p(gpio_mouse_remove), |
178 | .driver = { | 176 | .driver = { |
179 | .name = "gpio_mouse", | 177 | .name = "gpio_mouse", |
@@ -183,8 +181,7 @@ static struct platform_driver gpio_mouse_device_driver = { | |||
183 | 181 | ||
184 | static int __init gpio_mouse_init(void) | 182 | static int __init gpio_mouse_init(void) |
185 | { | 183 | { |
186 | return platform_driver_probe(&gpio_mouse_device_driver, | 184 | return platform_driver_register(&gpio_mouse_device_driver); |
187 | gpio_mouse_probe); | ||
188 | } | 185 | } |
189 | module_init(gpio_mouse_init); | 186 | module_init(gpio_mouse_init); |
190 | 187 | ||
@@ -197,3 +194,5 @@ module_exit(gpio_mouse_exit); | |||
197 | MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); | 194 | MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); |
198 | MODULE_DESCRIPTION("GPIO mouse driver"); | 195 | MODULE_DESCRIPTION("GPIO mouse driver"); |
199 | MODULE_LICENSE("GPL"); | 196 | MODULE_LICENSE("GPL"); |
197 | MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */ | ||
198 | |||
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index a1ad2f1a7bb3..de1e553028b7 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c | |||
@@ -367,7 +367,36 @@ static ssize_t hgpk_set_powered(struct psmouse *psmouse, void *data, | |||
367 | } | 367 | } |
368 | 368 | ||
369 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, | 369 | __PSMOUSE_DEFINE_ATTR(powered, S_IWUSR | S_IRUGO, NULL, |
370 | hgpk_show_powered, hgpk_set_powered, 0); | 370 | hgpk_show_powered, hgpk_set_powered, false); |
371 | |||
372 | static ssize_t hgpk_trigger_recal_show(struct psmouse *psmouse, | ||
373 | void *data, char *buf) | ||
374 | { | ||
375 | return -EINVAL; | ||
376 | } | ||
377 | |||
378 | static ssize_t hgpk_trigger_recal(struct psmouse *psmouse, void *data, | ||
379 | const char *buf, size_t count) | ||
380 | { | ||
381 | struct hgpk_data *priv = psmouse->private; | ||
382 | unsigned long value; | ||
383 | int err; | ||
384 | |||
385 | err = strict_strtoul(buf, 10, &value); | ||
386 | if (err || value != 1) | ||
387 | return -EINVAL; | ||
388 | |||
389 | /* | ||
390 | * We queue work instead of doing recalibration right here | ||
391 | * to avoid adding locking to to hgpk_force_recalibrate() | ||
392 | * since workqueue provides serialization. | ||
393 | */ | ||
394 | psmouse_queue_work(psmouse, &priv->recalib_wq, 0); | ||
395 | return count; | ||
396 | } | ||
397 | |||
398 | __PSMOUSE_DEFINE_ATTR(recalibrate, S_IWUSR | S_IRUGO, NULL, | ||
399 | hgpk_trigger_recal_show, hgpk_trigger_recal, false); | ||
371 | 400 | ||
372 | static void hgpk_disconnect(struct psmouse *psmouse) | 401 | static void hgpk_disconnect(struct psmouse *psmouse) |
373 | { | 402 | { |
@@ -375,6 +404,11 @@ static void hgpk_disconnect(struct psmouse *psmouse) | |||
375 | 404 | ||
376 | device_remove_file(&psmouse->ps2dev.serio->dev, | 405 | device_remove_file(&psmouse->ps2dev.serio->dev, |
377 | &psmouse_attr_powered.dattr); | 406 | &psmouse_attr_powered.dattr); |
407 | |||
408 | if (psmouse->model >= HGPK_MODEL_C) | ||
409 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
410 | &psmouse_attr_recalibrate.dattr); | ||
411 | |||
378 | psmouse_reset(psmouse); | 412 | psmouse_reset(psmouse); |
379 | kfree(priv); | 413 | kfree(priv); |
380 | } | 414 | } |
@@ -423,10 +457,25 @@ static int hgpk_register(struct psmouse *psmouse) | |||
423 | 457 | ||
424 | err = device_create_file(&psmouse->ps2dev.serio->dev, | 458 | err = device_create_file(&psmouse->ps2dev.serio->dev, |
425 | &psmouse_attr_powered.dattr); | 459 | &psmouse_attr_powered.dattr); |
426 | if (err) | 460 | if (err) { |
427 | hgpk_err(psmouse, "Failed to create sysfs attribute\n"); | 461 | hgpk_err(psmouse, "Failed creating 'powered' sysfs node\n"); |
462 | return err; | ||
463 | } | ||
428 | 464 | ||
429 | return err; | 465 | /* C-series touchpads added the recalibrate command */ |
466 | if (psmouse->model >= HGPK_MODEL_C) { | ||
467 | err = device_create_file(&psmouse->ps2dev.serio->dev, | ||
468 | &psmouse_attr_recalibrate.dattr); | ||
469 | if (err) { | ||
470 | hgpk_err(psmouse, | ||
471 | "Failed creating 'recalibrate' sysfs node\n"); | ||
472 | device_remove_file(&psmouse->ps2dev.serio->dev, | ||
473 | &psmouse_attr_powered.dattr); | ||
474 | return err; | ||
475 | } | ||
476 | } | ||
477 | |||
478 | return 0; | ||
430 | } | 479 | } |
431 | 480 | ||
432 | int hgpk_init(struct psmouse *psmouse) | 481 | int hgpk_init(struct psmouse *psmouse) |
@@ -440,7 +489,7 @@ int hgpk_init(struct psmouse *psmouse) | |||
440 | 489 | ||
441 | psmouse->private = priv; | 490 | psmouse->private = priv; |
442 | priv->psmouse = psmouse; | 491 | priv->psmouse = psmouse; |
443 | priv->powered = 1; | 492 | priv->powered = true; |
444 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); | 493 | INIT_DELAYED_WORK(&priv->recalib_wq, hgpk_recalib_work); |
445 | 494 | ||
446 | err = psmouse_reset(psmouse); | 495 | err = psmouse_reset(psmouse); |
@@ -483,7 +532,7 @@ static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse) | |||
483 | return param[2]; | 532 | return param[2]; |
484 | } | 533 | } |
485 | 534 | ||
486 | int hgpk_detect(struct psmouse *psmouse, int set_properties) | 535 | int hgpk_detect(struct psmouse *psmouse, bool set_properties) |
487 | { | 536 | { |
488 | int version; | 537 | int version; |
489 | 538 | ||
diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h index a4b2a96f5f54..d61cfd3ee9cb 100644 --- a/drivers/input/mouse/hgpk.h +++ b/drivers/input/mouse/hgpk.h | |||
@@ -15,7 +15,7 @@ enum hgpk_model_t { | |||
15 | 15 | ||
16 | struct hgpk_data { | 16 | struct hgpk_data { |
17 | struct psmouse *psmouse; | 17 | struct psmouse *psmouse; |
18 | int powered; | 18 | bool powered; |
19 | int count, x_tally, y_tally; /* hardware workaround stuff */ | 19 | int count, x_tally, y_tally; /* hardware workaround stuff */ |
20 | unsigned long recalib_window; | 20 | unsigned long recalib_window; |
21 | struct delayed_work recalib_wq; | 21 | struct delayed_work recalib_wq; |
@@ -33,10 +33,10 @@ struct hgpk_data { | |||
33 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) | 33 | dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg) |
34 | 34 | ||
35 | #ifdef CONFIG_MOUSE_PS2_OLPC | 35 | #ifdef CONFIG_MOUSE_PS2_OLPC |
36 | int hgpk_detect(struct psmouse *psmouse, int set_properties); | 36 | int hgpk_detect(struct psmouse *psmouse, bool set_properties); |
37 | int hgpk_init(struct psmouse *psmouse); | 37 | int hgpk_init(struct psmouse *psmouse); |
38 | #else | 38 | #else |
39 | static inline int hgpk_detect(struct psmouse *psmouse, int set_properties) | 39 | static inline int hgpk_detect(struct psmouse *psmouse, bool set_properties) |
40 | { | 40 | { |
41 | return -ENODEV; | 41 | return -ENODEV; |
42 | } | 42 | } |
diff --git a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c deleted file mode 100644 index 3263ce083bf0..000000000000 --- a/drivers/input/mouse/hil_ptr.c +++ /dev/null | |||
@@ -1,447 +0,0 @@ | |||
1 | /* | ||
2 | * Generic linux-input device driver for axis-bearing devices | ||
3 | * | ||
4 | * Copyright (c) 2001 Brian S. Julin | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions, and the following disclaimer, | ||
12 | * without modification. | ||
13 | * 2. The name of the author may not be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * Alternatively, this software may be distributed under the terms of the | ||
17 | * GNU General Public License ("GPL"). | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR | ||
23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * | ||
29 | * References: | ||
30 | * HP-HIL Technical Reference Manual. Hewlett Packard Product No. 45918A | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | #include <linux/hil.h> | ||
35 | #include <linux/input.h> | ||
36 | #include <linux/serio.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/slab.h> | ||
41 | #include <linux/pci_ids.h> | ||
42 | |||
43 | #define PREFIX "HIL PTR: " | ||
44 | #define HIL_GENERIC_NAME "HIL pointer device" | ||
45 | |||
46 | MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>"); | ||
47 | MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver"); | ||
48 | MODULE_LICENSE("Dual BSD/GPL"); | ||
49 | MODULE_ALIAS("serio:ty03pr25id0Fex*"); | ||
50 | |||
51 | #define TABLET_SIMULATES_MOUSE /* allow tablet to be used as mouse */ | ||
52 | #undef TABLET_AUTOADJUST /* auto-adjust valid tablet ranges */ | ||
53 | |||
54 | |||
55 | #define HIL_PTR_MAX_LENGTH 16 | ||
56 | |||
57 | struct hil_ptr { | ||
58 | struct input_dev *dev; | ||
59 | struct serio *serio; | ||
60 | |||
61 | /* Input buffer and index for packets from HIL bus. */ | ||
62 | hil_packet data[HIL_PTR_MAX_LENGTH]; | ||
63 | int idx4; /* four counts per packet */ | ||
64 | |||
65 | /* Raw device info records from HIL bus, see hil.h for fields. */ | ||
66 | char idd[HIL_PTR_MAX_LENGTH]; /* DID byte and IDD record */ | ||
67 | char rsc[HIL_PTR_MAX_LENGTH]; /* RSC record */ | ||
68 | char exd[HIL_PTR_MAX_LENGTH]; /* EXD record */ | ||
69 | char rnm[HIL_PTR_MAX_LENGTH + 1]; /* RNM record + NULL term. */ | ||
70 | |||
71 | /* Extra device details not contained in struct input_dev. */ | ||
72 | unsigned int nbtn, naxes; | ||
73 | unsigned int btnmap[7]; | ||
74 | |||
75 | /* Something to sleep around with. */ | ||
76 | struct semaphore sem; | ||
77 | }; | ||
78 | |||
79 | /* Process a complete packet after transfer from the HIL */ | ||
80 | static void hil_ptr_process_record(struct hil_ptr *ptr) | ||
81 | { | ||
82 | struct input_dev *dev = ptr->dev; | ||
83 | hil_packet *data = ptr->data; | ||
84 | hil_packet p; | ||
85 | int idx, i, cnt, laxis; | ||
86 | int ax16, absdev; | ||
87 | |||
88 | idx = ptr->idx4/4; | ||
89 | p = data[idx - 1]; | ||
90 | |||
91 | if ((p & ~HIL_CMDCT_POL) == | ||
92 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) | ||
93 | goto report; | ||
94 | if ((p & ~HIL_CMDCT_RPL) == | ||
95 | (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) | ||
96 | goto report; | ||
97 | |||
98 | /* Not a poll response. See if we are loading config records. */ | ||
99 | switch (p & HIL_PKT_DATA_MASK) { | ||
100 | case HIL_CMD_IDD: | ||
101 | for (i = 0; i < idx; i++) | ||
102 | ptr->idd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
103 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
104 | ptr->idd[i] = 0; | ||
105 | break; | ||
106 | |||
107 | case HIL_CMD_RSC: | ||
108 | for (i = 0; i < idx; i++) | ||
109 | ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
110 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
111 | ptr->rsc[i] = 0; | ||
112 | break; | ||
113 | |||
114 | case HIL_CMD_EXD: | ||
115 | for (i = 0; i < idx; i++) | ||
116 | ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
117 | for (; i < HIL_PTR_MAX_LENGTH; i++) | ||
118 | ptr->exd[i] = 0; | ||
119 | break; | ||
120 | |||
121 | case HIL_CMD_RNM: | ||
122 | for (i = 0; i < idx; i++) | ||
123 | ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK; | ||
124 | for (; i < HIL_PTR_MAX_LENGTH + 1; i++) | ||
125 | ptr->rnm[i] = 0; | ||
126 | break; | ||
127 | |||
128 | default: | ||
129 | /* These occur when device isn't present */ | ||
130 | if (p == (HIL_ERR_INT | HIL_PKT_CMD)) | ||
131 | break; | ||
132 | /* Anything else we'd like to know about. */ | ||
133 | printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p); | ||
134 | break; | ||
135 | } | ||
136 | goto out; | ||
137 | |||
138 | report: | ||
139 | if ((p & HIL_CMDCT_POL) != idx - 1) { | ||
140 | printk(KERN_WARNING PREFIX | ||
141 | "Malformed poll packet %x (idx = %i)\n", p, idx); | ||
142 | goto out; | ||
143 | } | ||
144 | |||
145 | i = (ptr->data[0] & HIL_POL_AXIS_ALT) ? 3 : 0; | ||
146 | laxis = ptr->data[0] & HIL_POL_NUM_AXES_MASK; | ||
147 | laxis += i; | ||
148 | |||
149 | ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */ | ||
150 | absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; | ||
151 | |||
152 | for (cnt = 1; i < laxis; i++) { | ||
153 | unsigned int lo,hi,val; | ||
154 | lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK; | ||
155 | hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0; | ||
156 | if (absdev) { | ||
157 | val = lo + (hi<<8); | ||
158 | #ifdef TABLET_AUTOADJUST | ||
159 | if (val < dev->absmin[ABS_X + i]) | ||
160 | dev->absmin[ABS_X + i] = val; | ||
161 | if (val > dev->absmax[ABS_X + i]) | ||
162 | dev->absmax[ABS_X + i] = val; | ||
163 | #endif | ||
164 | if (i%3) val = dev->absmax[ABS_X + i] - val; | ||
165 | input_report_abs(dev, ABS_X + i, val); | ||
166 | } else { | ||
167 | val = (int) (((int8_t)lo) | ((int8_t)hi<<8)); | ||
168 | if (i%3) | ||
169 | val *= -1; | ||
170 | input_report_rel(dev, REL_X + i, val); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | while (cnt < idx - 1) { | ||
175 | unsigned int btn; | ||
176 | int up; | ||
177 | btn = ptr->data[cnt++]; | ||
178 | up = btn & 1; | ||
179 | btn &= 0xfe; | ||
180 | if (btn == 0x8e) | ||
181 | continue; /* TODO: proximity == touch? */ | ||
182 | else | ||
183 | if ((btn > 0x8c) || (btn < 0x80)) | ||
184 | continue; | ||
185 | btn = (btn - 0x80) >> 1; | ||
186 | btn = ptr->btnmap[btn]; | ||
187 | input_report_key(dev, btn, !up); | ||
188 | } | ||
189 | input_sync(dev); | ||
190 | out: | ||
191 | ptr->idx4 = 0; | ||
192 | up(&ptr->sem); | ||
193 | } | ||
194 | |||
195 | static void hil_ptr_process_err(struct hil_ptr *ptr) | ||
196 | { | ||
197 | printk(KERN_WARNING PREFIX "errored HIL packet\n"); | ||
198 | ptr->idx4 = 0; | ||
199 | up(&ptr->sem); | ||
200 | } | ||
201 | |||
202 | static irqreturn_t hil_ptr_interrupt(struct serio *serio, | ||
203 | unsigned char data, unsigned int flags) | ||
204 | { | ||
205 | struct hil_ptr *ptr; | ||
206 | hil_packet packet; | ||
207 | int idx; | ||
208 | |||
209 | ptr = serio_get_drvdata(serio); | ||
210 | BUG_ON(ptr == NULL); | ||
211 | |||
212 | if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) { | ||
213 | hil_ptr_process_err(ptr); | ||
214 | return IRQ_HANDLED; | ||
215 | } | ||
216 | idx = ptr->idx4/4; | ||
217 | if (!(ptr->idx4 % 4)) | ||
218 | ptr->data[idx] = 0; | ||
219 | packet = ptr->data[idx]; | ||
220 | packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8); | ||
221 | ptr->data[idx] = packet; | ||
222 | |||
223 | /* Records of N 4-byte hil_packets must terminate with a command. */ | ||
224 | if ((++(ptr->idx4)) % 4) | ||
225 | return IRQ_HANDLED; | ||
226 | if ((packet & 0xffff0000) != HIL_ERR_INT) { | ||
227 | hil_ptr_process_err(ptr); | ||
228 | return IRQ_HANDLED; | ||
229 | } | ||
230 | if (packet & HIL_PKT_CMD) | ||
231 | hil_ptr_process_record(ptr); | ||
232 | |||
233 | return IRQ_HANDLED; | ||
234 | } | ||
235 | |||
236 | static void hil_ptr_disconnect(struct serio *serio) | ||
237 | { | ||
238 | struct hil_ptr *ptr; | ||
239 | |||
240 | ptr = serio_get_drvdata(serio); | ||
241 | BUG_ON(ptr == NULL); | ||
242 | |||
243 | serio_close(serio); | ||
244 | input_unregister_device(ptr->dev); | ||
245 | kfree(ptr); | ||
246 | } | ||
247 | |||
248 | static int hil_ptr_connect(struct serio *serio, struct serio_driver *driver) | ||
249 | { | ||
250 | struct hil_ptr *ptr; | ||
251 | const char *txt; | ||
252 | unsigned int i, naxsets, btntype; | ||
253 | uint8_t did, *idd; | ||
254 | int error; | ||
255 | |||
256 | ptr = kzalloc(sizeof(struct hil_ptr), GFP_KERNEL); | ||
257 | if (!ptr) | ||
258 | return -ENOMEM; | ||
259 | |||
260 | ptr->dev = input_allocate_device(); | ||
261 | if (!ptr->dev) { | ||
262 | error = -ENOMEM; | ||
263 | goto bail0; | ||
264 | } | ||
265 | |||
266 | error = serio_open(serio, driver); | ||
267 | if (error) | ||
268 | goto bail1; | ||
269 | |||
270 | serio_set_drvdata(serio, ptr); | ||
271 | ptr->serio = serio; | ||
272 | |||
273 | init_MUTEX_LOCKED(&ptr->sem); | ||
274 | |||
275 | /* Get device info. MLC driver supplies devid/status/etc. */ | ||
276 | serio->write(serio, 0); | ||
277 | serio->write(serio, 0); | ||
278 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
279 | serio->write(serio, HIL_CMD_IDD); | ||
280 | down(&ptr->sem); | ||
281 | |||
282 | serio->write(serio, 0); | ||
283 | serio->write(serio, 0); | ||
284 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
285 | serio->write(serio, HIL_CMD_RSC); | ||
286 | down(&ptr->sem); | ||
287 | |||
288 | serio->write(serio, 0); | ||
289 | serio->write(serio, 0); | ||
290 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
291 | serio->write(serio, HIL_CMD_RNM); | ||
292 | down(&ptr->sem); | ||
293 | |||
294 | serio->write(serio, 0); | ||
295 | serio->write(serio, 0); | ||
296 | serio->write(serio, HIL_PKT_CMD >> 8); | ||
297 | serio->write(serio, HIL_CMD_EXD); | ||
298 | down(&ptr->sem); | ||
299 | |||
300 | up(&ptr->sem); | ||
301 | |||
302 | did = ptr->idd[0]; | ||
303 | idd = ptr->idd + 1; | ||
304 | txt = "unknown"; | ||
305 | |||
306 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { | ||
307 | ptr->dev->evbit[0] = BIT_MASK(EV_REL); | ||
308 | txt = "relative"; | ||
309 | } | ||
310 | |||
311 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) { | ||
312 | ptr->dev->evbit[0] = BIT_MASK(EV_ABS); | ||
313 | txt = "absolute"; | ||
314 | } | ||
315 | |||
316 | if (!ptr->dev->evbit[0]) { | ||
317 | error = -ENODEV; | ||
318 | goto bail2; | ||
319 | } | ||
320 | |||
321 | ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd); | ||
322 | if (ptr->nbtn) | ||
323 | ptr->dev->evbit[0] |= BIT_MASK(EV_KEY); | ||
324 | |||
325 | naxsets = HIL_IDD_NUM_AXSETS(*idd); | ||
326 | ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd); | ||
327 | |||
328 | printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)\n", | ||
329 | did, txt); | ||
330 | printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n", | ||
331 | ptr->nbtn, naxsets, ptr->naxes); | ||
332 | |||
333 | btntype = BTN_MISC; | ||
334 | if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET) | ||
335 | #ifdef TABLET_SIMULATES_MOUSE | ||
336 | btntype = BTN_TOUCH; | ||
337 | #else | ||
338 | btntype = BTN_DIGI; | ||
339 | #endif | ||
340 | if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN) | ||
341 | btntype = BTN_TOUCH; | ||
342 | |||
343 | if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE) | ||
344 | btntype = BTN_MOUSE; | ||
345 | |||
346 | for (i = 0; i < ptr->nbtn; i++) { | ||
347 | set_bit(btntype | i, ptr->dev->keybit); | ||
348 | ptr->btnmap[i] = btntype | i; | ||
349 | } | ||
350 | |||
351 | if (btntype == BTN_MOUSE) { | ||
352 | /* Swap buttons 2 and 3 */ | ||
353 | ptr->btnmap[1] = BTN_MIDDLE; | ||
354 | ptr->btnmap[2] = BTN_RIGHT; | ||
355 | } | ||
356 | |||
357 | if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) { | ||
358 | for (i = 0; i < ptr->naxes; i++) | ||
359 | set_bit(REL_X + i, ptr->dev->relbit); | ||
360 | for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) | ||
361 | set_bit(REL_X + i, ptr->dev->relbit); | ||
362 | } else { | ||
363 | for (i = 0; i < ptr->naxes; i++) { | ||
364 | set_bit(ABS_X + i, ptr->dev->absbit); | ||
365 | ptr->dev->absmin[ABS_X + i] = 0; | ||
366 | ptr->dev->absmax[ABS_X + i] = | ||
367 | HIL_IDD_AXIS_MAX((ptr->idd + 1), i); | ||
368 | } | ||
369 | for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) { | ||
370 | set_bit(ABS_X + i, ptr->dev->absbit); | ||
371 | ptr->dev->absmin[ABS_X + i] = 0; | ||
372 | ptr->dev->absmax[ABS_X + i] = | ||
373 | HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3)); | ||
374 | } | ||
375 | #ifdef TABLET_AUTOADJUST | ||
376 | for (i = 0; i < ABS_MAX; i++) { | ||
377 | int diff = ptr->dev->absmax[ABS_X + i] / 10; | ||
378 | ptr->dev->absmin[ABS_X + i] += diff; | ||
379 | ptr->dev->absmax[ABS_X + i] -= diff; | ||
380 | } | ||
381 | #endif | ||
382 | } | ||
383 | |||
384 | ptr->dev->name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME; | ||
385 | |||
386 | ptr->dev->id.bustype = BUS_HIL; | ||
387 | ptr->dev->id.vendor = PCI_VENDOR_ID_HP; | ||
388 | ptr->dev->id.product = 0x0001; /* TODO: get from ptr->rsc */ | ||
389 | ptr->dev->id.version = 0x0100; /* TODO: get from ptr->rsc */ | ||
390 | ptr->dev->dev.parent = &serio->dev; | ||
391 | |||
392 | error = input_register_device(ptr->dev); | ||
393 | if (error) { | ||
394 | printk(KERN_INFO PREFIX "Unable to register input device\n"); | ||
395 | goto bail2; | ||
396 | } | ||
397 | |||
398 | printk(KERN_INFO "input: %s (%s), ID: %d\n", | ||
399 | ptr->dev->name, | ||
400 | (btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad", | ||
401 | did); | ||
402 | |||
403 | return 0; | ||
404 | |||
405 | bail2: | ||
406 | serio_close(serio); | ||
407 | bail1: | ||
408 | input_free_device(ptr->dev); | ||
409 | bail0: | ||
410 | kfree(ptr); | ||
411 | serio_set_drvdata(serio, NULL); | ||
412 | return error; | ||
413 | } | ||
414 | |||
415 | static struct serio_device_id hil_ptr_ids[] = { | ||
416 | { | ||
417 | .type = SERIO_HIL_MLC, | ||
418 | .proto = SERIO_HIL, | ||
419 | .id = SERIO_ANY, | ||
420 | .extra = SERIO_ANY, | ||
421 | }, | ||
422 | { 0 } | ||
423 | }; | ||
424 | |||
425 | static struct serio_driver hil_ptr_serio_driver = { | ||
426 | .driver = { | ||
427 | .name = "hil_ptr", | ||
428 | }, | ||
429 | .description = "HP HIL mouse/tablet driver", | ||
430 | .id_table = hil_ptr_ids, | ||
431 | .connect = hil_ptr_connect, | ||
432 | .disconnect = hil_ptr_disconnect, | ||
433 | .interrupt = hil_ptr_interrupt | ||
434 | }; | ||
435 | |||
436 | static int __init hil_ptr_init(void) | ||
437 | { | ||
438 | return serio_register_driver(&hil_ptr_serio_driver); | ||
439 | } | ||
440 | |||
441 | static void __exit hil_ptr_exit(void) | ||
442 | { | ||
443 | serio_unregister_driver(&hil_ptr_serio_driver); | ||
444 | } | ||
445 | |||
446 | module_init(hil_ptr_init); | ||
447 | module_exit(hil_ptr_exit); | ||
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index dcd4236af1e3..5e6308694408 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
@@ -33,11 +33,11 @@ static int lifebook_set_serio_phys(const struct dmi_system_id *d) | |||
33 | return 0; | 33 | return 0; |
34 | } | 34 | } |
35 | 35 | ||
36 | static unsigned char lifebook_use_6byte_proto; | 36 | static bool lifebook_use_6byte_proto; |
37 | 37 | ||
38 | static int lifebook_set_6byte_proto(const struct dmi_system_id *d) | 38 | static int lifebook_set_6byte_proto(const struct dmi_system_id *d) |
39 | { | 39 | { |
40 | lifebook_use_6byte_proto = 1; | 40 | lifebook_use_6byte_proto = true; |
41 | return 0; | 41 | return 0; |
42 | } | 42 | } |
43 | 43 | ||
@@ -125,7 +125,7 @@ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) | |||
125 | struct input_dev *dev1 = psmouse->dev; | 125 | struct input_dev *dev1 = psmouse->dev; |
126 | struct input_dev *dev2 = priv ? priv->dev2 : NULL; | 126 | struct input_dev *dev2 = priv ? priv->dev2 : NULL; |
127 | unsigned char *packet = psmouse->packet; | 127 | unsigned char *packet = psmouse->packet; |
128 | int relative_packet = packet[0] & 0x08; | 128 | bool relative_packet = packet[0] & 0x08; |
129 | 129 | ||
130 | if (relative_packet || !lifebook_use_6byte_proto) { | 130 | if (relative_packet || !lifebook_use_6byte_proto) { |
131 | if (psmouse->pktcnt != 3) | 131 | if (psmouse->pktcnt != 3) |
@@ -242,7 +242,7 @@ static void lifebook_disconnect(struct psmouse *psmouse) | |||
242 | psmouse->private = NULL; | 242 | psmouse->private = NULL; |
243 | } | 243 | } |
244 | 244 | ||
245 | int lifebook_detect(struct psmouse *psmouse, int set_properties) | 245 | int lifebook_detect(struct psmouse *psmouse, bool set_properties) |
246 | { | 246 | { |
247 | if (!dmi_check_system(lifebook_dmi_table)) | 247 | if (!dmi_check_system(lifebook_dmi_table)) |
248 | return -1; | 248 | return -1; |
diff --git a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h index c1647cf036c2..407cb226bc0a 100644 --- a/drivers/input/mouse/lifebook.h +++ b/drivers/input/mouse/lifebook.h | |||
@@ -12,10 +12,10 @@ | |||
12 | #define _LIFEBOOK_H | 12 | #define _LIFEBOOK_H |
13 | 13 | ||
14 | #ifdef CONFIG_MOUSE_PS2_LIFEBOOK | 14 | #ifdef CONFIG_MOUSE_PS2_LIFEBOOK |
15 | int lifebook_detect(struct psmouse *psmouse, int set_properties); | 15 | int lifebook_detect(struct psmouse *psmouse, bool set_properties); |
16 | int lifebook_init(struct psmouse *psmouse); | 16 | int lifebook_init(struct psmouse *psmouse); |
17 | #else | 17 | #else |
18 | inline int lifebook_detect(struct psmouse *psmouse, int set_properties) | 18 | inline int lifebook_detect(struct psmouse *psmouse, bool set_properties) |
19 | { | 19 | { |
20 | return -ENOSYS; | 20 | return -ENOSYS; |
21 | } | 21 | } |
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 390f1dbb98a4..de745d751162 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
@@ -130,14 +130,11 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha | |||
130 | * 0 - disabled | 130 | * 0 - disabled |
131 | */ | 131 | */ |
132 | 132 | ||
133 | static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscroll) | 133 | static void ps2pp_set_smartscroll(struct psmouse *psmouse, bool smartscroll) |
134 | { | 134 | { |
135 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 135 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
136 | unsigned char param[4]; | 136 | unsigned char param[4]; |
137 | 137 | ||
138 | if (smartscroll > 1) | ||
139 | smartscroll = 1; | ||
140 | |||
141 | ps2pp_cmd(psmouse, param, 0x32); | 138 | ps2pp_cmd(psmouse, param, 0x32); |
142 | 139 | ||
143 | param[0] = 0; | 140 | param[0] = 0; |
@@ -149,12 +146,14 @@ static void ps2pp_set_smartscroll(struct psmouse *psmouse, unsigned int smartscr | |||
149 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); | 146 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); |
150 | } | 147 | } |
151 | 148 | ||
152 | static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data, char *buf) | 149 | static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, |
150 | void *data, char *buf) | ||
153 | { | 151 | { |
154 | return sprintf(buf, "%d\n", psmouse->smartscroll ? 1 : 0); | 152 | return sprintf(buf, "%d\n", psmouse->smartscroll); |
155 | } | 153 | } |
156 | 154 | ||
157 | static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, const char *buf, size_t count) | 155 | static ssize_t ps2pp_attr_set_smartscroll(struct psmouse *psmouse, void *data, |
156 | const char *buf, size_t count) | ||
158 | { | 157 | { |
159 | unsigned long value; | 158 | unsigned long value; |
160 | 159 | ||
@@ -261,29 +260,29 @@ static const struct ps2pp_info *get_model_info(unsigned char model) | |||
261 | 260 | ||
262 | static void ps2pp_set_model_properties(struct psmouse *psmouse, | 261 | static void ps2pp_set_model_properties(struct psmouse *psmouse, |
263 | const struct ps2pp_info *model_info, | 262 | const struct ps2pp_info *model_info, |
264 | int using_ps2pp) | 263 | bool using_ps2pp) |
265 | { | 264 | { |
266 | struct input_dev *input_dev = psmouse->dev; | 265 | struct input_dev *input_dev = psmouse->dev; |
267 | 266 | ||
268 | if (model_info->features & PS2PP_SIDE_BTN) | 267 | if (model_info->features & PS2PP_SIDE_BTN) |
269 | set_bit(BTN_SIDE, input_dev->keybit); | 268 | __set_bit(BTN_SIDE, input_dev->keybit); |
270 | 269 | ||
271 | if (model_info->features & PS2PP_EXTRA_BTN) | 270 | if (model_info->features & PS2PP_EXTRA_BTN) |
272 | set_bit(BTN_EXTRA, input_dev->keybit); | 271 | __set_bit(BTN_EXTRA, input_dev->keybit); |
273 | 272 | ||
274 | if (model_info->features & PS2PP_TASK_BTN) | 273 | if (model_info->features & PS2PP_TASK_BTN) |
275 | set_bit(BTN_TASK, input_dev->keybit); | 274 | __set_bit(BTN_TASK, input_dev->keybit); |
276 | 275 | ||
277 | if (model_info->features & PS2PP_NAV_BTN) { | 276 | if (model_info->features & PS2PP_NAV_BTN) { |
278 | set_bit(BTN_FORWARD, input_dev->keybit); | 277 | __set_bit(BTN_FORWARD, input_dev->keybit); |
279 | set_bit(BTN_BACK, input_dev->keybit); | 278 | __set_bit(BTN_BACK, input_dev->keybit); |
280 | } | 279 | } |
281 | 280 | ||
282 | if (model_info->features & PS2PP_WHEEL) | 281 | if (model_info->features & PS2PP_WHEEL) |
283 | set_bit(REL_WHEEL, input_dev->relbit); | 282 | __set_bit(REL_WHEEL, input_dev->relbit); |
284 | 283 | ||
285 | if (model_info->features & PS2PP_HWHEEL) | 284 | if (model_info->features & PS2PP_HWHEEL) |
286 | set_bit(REL_HWHEEL, input_dev->relbit); | 285 | __set_bit(REL_HWHEEL, input_dev->relbit); |
287 | 286 | ||
288 | switch (model_info->kind) { | 287 | switch (model_info->kind) { |
289 | case PS2PP_KIND_WHEEL: | 288 | case PS2PP_KIND_WHEEL: |
@@ -321,13 +320,13 @@ static void ps2pp_set_model_properties(struct psmouse *psmouse, | |||
321 | * that support it. | 320 | * that support it. |
322 | */ | 321 | */ |
323 | 322 | ||
324 | int ps2pp_init(struct psmouse *psmouse, int set_properties) | 323 | int ps2pp_init(struct psmouse *psmouse, bool set_properties) |
325 | { | 324 | { |
326 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 325 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
327 | unsigned char param[4]; | 326 | unsigned char param[4]; |
328 | unsigned char model, buttons; | 327 | unsigned char model, buttons; |
329 | const struct ps2pp_info *model_info; | 328 | const struct ps2pp_info *model_info; |
330 | int use_ps2pp = 0; | 329 | bool use_ps2pp = false; |
331 | int error; | 330 | int error; |
332 | 331 | ||
333 | param[0] = 0; | 332 | param[0] = 0; |
@@ -364,7 +363,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) | |||
364 | param[0] = 0; | 363 | param[0] = 0; |
365 | if (!ps2_command(ps2dev, param, 0x13d1) && | 364 | if (!ps2_command(ps2dev, param, 0x13d1) && |
366 | param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { | 365 | param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14) { |
367 | use_ps2pp = 1; | 366 | use_ps2pp = true; |
368 | } | 367 | } |
369 | 368 | ||
370 | } else { | 369 | } else { |
@@ -376,8 +375,8 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) | |||
376 | if ((param[0] & 0x78) == 0x48 && | 375 | if ((param[0] & 0x78) == 0x48 && |
377 | (param[1] & 0xf3) == 0xc2 && | 376 | (param[1] & 0xf3) == 0xc2 && |
378 | (param[2] & 0x03) == ((param[1] >> 2) & 3)) { | 377 | (param[2] & 0x03) == ((param[1] >> 2) & 3)) { |
379 | ps2pp_set_smartscroll(psmouse, psmouse->smartscroll); | 378 | ps2pp_set_smartscroll(psmouse, false); |
380 | use_ps2pp = 1; | 379 | use_ps2pp = true; |
381 | } | 380 | } |
382 | } | 381 | } |
383 | } | 382 | } |
@@ -406,7 +405,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties) | |||
406 | } | 405 | } |
407 | 406 | ||
408 | if (buttons < 3) | 407 | if (buttons < 3) |
409 | clear_bit(BTN_MIDDLE, psmouse->dev->keybit); | 408 | __clear_bit(BTN_MIDDLE, psmouse->dev->keybit); |
410 | 409 | ||
411 | if (model_info) | 410 | if (model_info) |
412 | ps2pp_set_model_properties(psmouse, model_info, use_ps2pp); | 411 | ps2pp_set_model_properties(psmouse, model_info, use_ps2pp); |
diff --git a/drivers/input/mouse/logips2pp.h b/drivers/input/mouse/logips2pp.h index 6e5712525fd6..0c186f0282d9 100644 --- a/drivers/input/mouse/logips2pp.h +++ b/drivers/input/mouse/logips2pp.h | |||
@@ -12,9 +12,9 @@ | |||
12 | #define _LOGIPS2PP_H | 12 | #define _LOGIPS2PP_H |
13 | 13 | ||
14 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP | 14 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP |
15 | int ps2pp_init(struct psmouse *psmouse, int set_properties); | 15 | int ps2pp_init(struct psmouse *psmouse, bool set_properties); |
16 | #else | 16 | #else |
17 | inline int ps2pp_init(struct psmouse *psmouse, int set_properties) | 17 | inline int ps2pp_init(struct psmouse *psmouse, bool set_properties) |
18 | { | 18 | { |
19 | return -ENOSYS; | 19 | return -ENOSYS; |
20 | } | 20 | } |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index b407b355dceb..690aed905436 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "trackpoint.h" | 30 | #include "trackpoint.h" |
31 | #include "touchkit_ps2.h" | 31 | #include "touchkit_ps2.h" |
32 | #include "elantech.h" | 32 | #include "elantech.h" |
33 | #include "sentelic.h" | ||
33 | 34 | ||
34 | #define DRIVER_DESC "PS/2 mouse driver" | 35 | #define DRIVER_DESC "PS/2 mouse driver" |
35 | 36 | ||
@@ -108,10 +109,10 @@ static struct workqueue_struct *kpsmoused_wq; | |||
108 | 109 | ||
109 | struct psmouse_protocol { | 110 | struct psmouse_protocol { |
110 | enum psmouse_type type; | 111 | enum psmouse_type type; |
112 | bool maxproto; | ||
111 | const char *name; | 113 | const char *name; |
112 | const char *alias; | 114 | const char *alias; |
113 | int maxproto; | 115 | int (*detect)(struct psmouse *, bool); |
114 | int (*detect)(struct psmouse *, int); | ||
115 | int (*init)(struct psmouse *); | 116 | int (*init)(struct psmouse *); |
116 | }; | 117 | }; |
117 | 118 | ||
@@ -216,7 +217,7 @@ void psmouse_queue_work(struct psmouse *psmouse, struct delayed_work *work, | |||
216 | static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | 217 | static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) |
217 | { | 218 | { |
218 | psmouse->state = new_state; | 219 | psmouse->state = new_state; |
219 | psmouse->pktcnt = psmouse->out_of_sync = 0; | 220 | psmouse->pktcnt = psmouse->out_of_sync_cnt = 0; |
220 | psmouse->ps2dev.flags = 0; | 221 | psmouse->ps2dev.flags = 0; |
221 | psmouse->last = jiffies; | 222 | psmouse->last = jiffies; |
222 | } | 223 | } |
@@ -249,7 +250,7 @@ static int psmouse_handle_byte(struct psmouse *psmouse) | |||
249 | if (psmouse->state == PSMOUSE_ACTIVATED) { | 250 | if (psmouse->state == PSMOUSE_ACTIVATED) { |
250 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | 251 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", |
251 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 252 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
252 | if (++psmouse->out_of_sync == psmouse->resetafter) { | 253 | if (++psmouse->out_of_sync_cnt == psmouse->resetafter) { |
253 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 254 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
254 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | 255 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); |
255 | serio_reconnect(psmouse->ps2dev.serio); | 256 | serio_reconnect(psmouse->ps2dev.serio); |
@@ -261,8 +262,8 @@ static int psmouse_handle_byte(struct psmouse *psmouse) | |||
261 | 262 | ||
262 | case PSMOUSE_FULL_PACKET: | 263 | case PSMOUSE_FULL_PACKET: |
263 | psmouse->pktcnt = 0; | 264 | psmouse->pktcnt = 0; |
264 | if (psmouse->out_of_sync) { | 265 | if (psmouse->out_of_sync_cnt) { |
265 | psmouse->out_of_sync = 0; | 266 | psmouse->out_of_sync_cnt = 0; |
266 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | 267 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", |
267 | psmouse->name, psmouse->phys); | 268 | psmouse->name, psmouse->phys); |
268 | } | 269 | } |
@@ -408,7 +409,7 @@ int psmouse_reset(struct psmouse *psmouse) | |||
408 | /* | 409 | /* |
409 | * Genius NetMouse magic init. | 410 | * Genius NetMouse magic init. |
410 | */ | 411 | */ |
411 | static int genius_detect(struct psmouse *psmouse, int set_properties) | 412 | static int genius_detect(struct psmouse *psmouse, bool set_properties) |
412 | { | 413 | { |
413 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 414 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
414 | unsigned char param[4]; | 415 | unsigned char param[4]; |
@@ -424,9 +425,9 @@ static int genius_detect(struct psmouse *psmouse, int set_properties) | |||
424 | return -1; | 425 | return -1; |
425 | 426 | ||
426 | if (set_properties) { | 427 | if (set_properties) { |
427 | set_bit(BTN_EXTRA, psmouse->dev->keybit); | 428 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
428 | set_bit(BTN_SIDE, psmouse->dev->keybit); | 429 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
429 | set_bit(REL_WHEEL, psmouse->dev->relbit); | 430 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
430 | 431 | ||
431 | psmouse->vendor = "Genius"; | 432 | psmouse->vendor = "Genius"; |
432 | psmouse->name = "Mouse"; | 433 | psmouse->name = "Mouse"; |
@@ -439,7 +440,7 @@ static int genius_detect(struct psmouse *psmouse, int set_properties) | |||
439 | /* | 440 | /* |
440 | * IntelliMouse magic init. | 441 | * IntelliMouse magic init. |
441 | */ | 442 | */ |
442 | static int intellimouse_detect(struct psmouse *psmouse, int set_properties) | 443 | static int intellimouse_detect(struct psmouse *psmouse, bool set_properties) |
443 | { | 444 | { |
444 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 445 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
445 | unsigned char param[2]; | 446 | unsigned char param[2]; |
@@ -456,8 +457,8 @@ static int intellimouse_detect(struct psmouse *psmouse, int set_properties) | |||
456 | return -1; | 457 | return -1; |
457 | 458 | ||
458 | if (set_properties) { | 459 | if (set_properties) { |
459 | set_bit(BTN_MIDDLE, psmouse->dev->keybit); | 460 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); |
460 | set_bit(REL_WHEEL, psmouse->dev->relbit); | 461 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
461 | 462 | ||
462 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 463 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
463 | if (!psmouse->name) psmouse->name = "Wheel Mouse"; | 464 | if (!psmouse->name) psmouse->name = "Wheel Mouse"; |
@@ -470,7 +471,7 @@ static int intellimouse_detect(struct psmouse *psmouse, int set_properties) | |||
470 | /* | 471 | /* |
471 | * Try IntelliMouse/Explorer magic init. | 472 | * Try IntelliMouse/Explorer magic init. |
472 | */ | 473 | */ |
473 | static int im_explorer_detect(struct psmouse *psmouse, int set_properties) | 474 | static int im_explorer_detect(struct psmouse *psmouse, bool set_properties) |
474 | { | 475 | { |
475 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 476 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
476 | unsigned char param[2]; | 477 | unsigned char param[2]; |
@@ -497,11 +498,11 @@ static int im_explorer_detect(struct psmouse *psmouse, int set_properties) | |||
497 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | 498 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); |
498 | 499 | ||
499 | if (set_properties) { | 500 | if (set_properties) { |
500 | set_bit(BTN_MIDDLE, psmouse->dev->keybit); | 501 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); |
501 | set_bit(REL_WHEEL, psmouse->dev->relbit); | 502 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
502 | set_bit(REL_HWHEEL, psmouse->dev->relbit); | 503 | __set_bit(REL_HWHEEL, psmouse->dev->relbit); |
503 | set_bit(BTN_SIDE, psmouse->dev->keybit); | 504 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
504 | set_bit(BTN_EXTRA, psmouse->dev->keybit); | 505 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
505 | 506 | ||
506 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 507 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
507 | if (!psmouse->name) psmouse->name = "Explorer Mouse"; | 508 | if (!psmouse->name) psmouse->name = "Explorer Mouse"; |
@@ -514,7 +515,7 @@ static int im_explorer_detect(struct psmouse *psmouse, int set_properties) | |||
514 | /* | 515 | /* |
515 | * Kensington ThinkingMouse / ExpertMouse magic init. | 516 | * Kensington ThinkingMouse / ExpertMouse magic init. |
516 | */ | 517 | */ |
517 | static int thinking_detect(struct psmouse *psmouse, int set_properties) | 518 | static int thinking_detect(struct psmouse *psmouse, bool set_properties) |
518 | { | 519 | { |
519 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 520 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
520 | unsigned char param[2]; | 521 | unsigned char param[2]; |
@@ -535,7 +536,7 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties) | |||
535 | return -1; | 536 | return -1; |
536 | 537 | ||
537 | if (set_properties) { | 538 | if (set_properties) { |
538 | set_bit(BTN_EXTRA, psmouse->dev->keybit); | 539 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
539 | 540 | ||
540 | psmouse->vendor = "Kensington"; | 541 | psmouse->vendor = "Kensington"; |
541 | psmouse->name = "ThinkingMouse"; | 542 | psmouse->name = "ThinkingMouse"; |
@@ -547,7 +548,7 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties) | |||
547 | /* | 548 | /* |
548 | * Bare PS/2 protocol "detection". Always succeeds. | 549 | * Bare PS/2 protocol "detection". Always succeeds. |
549 | */ | 550 | */ |
550 | static int ps2bare_detect(struct psmouse *psmouse, int set_properties) | 551 | static int ps2bare_detect(struct psmouse *psmouse, bool set_properties) |
551 | { | 552 | { |
552 | if (set_properties) { | 553 | if (set_properties) { |
553 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 554 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
@@ -561,12 +562,12 @@ static int ps2bare_detect(struct psmouse *psmouse, int set_properties) | |||
561 | * Cortron PS/2 protocol detection. There's no special way to detect it, so it | 562 | * Cortron PS/2 protocol detection. There's no special way to detect it, so it |
562 | * must be forced by sysfs protocol writing. | 563 | * must be forced by sysfs protocol writing. |
563 | */ | 564 | */ |
564 | static int cortron_detect(struct psmouse *psmouse, int set_properties) | 565 | static int cortron_detect(struct psmouse *psmouse, bool set_properties) |
565 | { | 566 | { |
566 | if (set_properties) { | 567 | if (set_properties) { |
567 | psmouse->vendor = "Cortron"; | 568 | psmouse->vendor = "Cortron"; |
568 | psmouse->name = "PS/2 Trackball"; | 569 | psmouse->name = "PS/2 Trackball"; |
569 | set_bit(BTN_SIDE, psmouse->dev->keybit); | 570 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
570 | } | 571 | } |
571 | 572 | ||
572 | return 0; | 573 | return 0; |
@@ -578,9 +579,9 @@ static int cortron_detect(struct psmouse *psmouse, int set_properties) | |||
578 | */ | 579 | */ |
579 | 580 | ||
580 | static int psmouse_extensions(struct psmouse *psmouse, | 581 | static int psmouse_extensions(struct psmouse *psmouse, |
581 | unsigned int max_proto, int set_properties) | 582 | unsigned int max_proto, bool set_properties) |
582 | { | 583 | { |
583 | int synaptics_hardware = 0; | 584 | bool synaptics_hardware = true; |
584 | 585 | ||
585 | /* | 586 | /* |
586 | * We always check for lifebook because it does not disturb mouse | 587 | * We always check for lifebook because it does not disturb mouse |
@@ -607,7 +608,7 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
607 | * can reset it properly after probing for intellimouse. | 608 | * can reset it properly after probing for intellimouse. |
608 | */ | 609 | */ |
609 | if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) { | 610 | if (max_proto > PSMOUSE_PS2 && synaptics_detect(psmouse, set_properties) == 0) { |
610 | synaptics_hardware = 1; | 611 | synaptics_hardware = true; |
611 | 612 | ||
612 | if (max_proto > PSMOUSE_IMEX) { | 613 | if (max_proto > PSMOUSE_IMEX) { |
613 | if (!set_properties || synaptics_init(psmouse) == 0) | 614 | if (!set_properties || synaptics_init(psmouse) == 0) |
@@ -666,6 +667,20 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
666 | max_proto = PSMOUSE_IMEX; | 667 | max_proto = PSMOUSE_IMEX; |
667 | } | 668 | } |
668 | 669 | ||
670 | /* | ||
671 | * Try Finger Sensing Pad | ||
672 | */ | ||
673 | if (max_proto > PSMOUSE_IMEX) { | ||
674 | if (fsp_detect(psmouse, set_properties) == 0) { | ||
675 | if (!set_properties || fsp_init(psmouse) == 0) | ||
676 | return PSMOUSE_FSP; | ||
677 | /* | ||
678 | * Init failed, try basic relative protocols | ||
679 | */ | ||
680 | max_proto = PSMOUSE_IMEX; | ||
681 | } | ||
682 | } | ||
683 | |||
669 | if (max_proto > PSMOUSE_IMEX) { | 684 | if (max_proto > PSMOUSE_IMEX) { |
670 | if (genius_detect(psmouse, set_properties) == 0) | 685 | if (genius_detect(psmouse, set_properties) == 0) |
671 | return PSMOUSE_GENPS; | 686 | return PSMOUSE_GENPS; |
@@ -718,7 +733,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
718 | .type = PSMOUSE_PS2, | 733 | .type = PSMOUSE_PS2, |
719 | .name = "PS/2", | 734 | .name = "PS/2", |
720 | .alias = "bare", | 735 | .alias = "bare", |
721 | .maxproto = 1, | 736 | .maxproto = true, |
722 | .detect = ps2bare_detect, | 737 | .detect = ps2bare_detect, |
723 | }, | 738 | }, |
724 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP | 739 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP |
@@ -745,14 +760,14 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
745 | .type = PSMOUSE_IMPS, | 760 | .type = PSMOUSE_IMPS, |
746 | .name = "ImPS/2", | 761 | .name = "ImPS/2", |
747 | .alias = "imps", | 762 | .alias = "imps", |
748 | .maxproto = 1, | 763 | .maxproto = true, |
749 | .detect = intellimouse_detect, | 764 | .detect = intellimouse_detect, |
750 | }, | 765 | }, |
751 | { | 766 | { |
752 | .type = PSMOUSE_IMEX, | 767 | .type = PSMOUSE_IMEX, |
753 | .name = "ImExPS/2", | 768 | .name = "ImExPS/2", |
754 | .alias = "exps", | 769 | .alias = "exps", |
755 | .maxproto = 1, | 770 | .maxproto = true, |
756 | .detect = im_explorer_detect, | 771 | .detect = im_explorer_detect, |
757 | }, | 772 | }, |
758 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS | 773 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS |
@@ -813,7 +828,16 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
813 | .detect = elantech_detect, | 828 | .detect = elantech_detect, |
814 | .init = elantech_init, | 829 | .init = elantech_init, |
815 | }, | 830 | }, |
816 | #endif | 831 | #endif |
832 | #ifdef CONFIG_MOUSE_PS2_SENTELIC | ||
833 | { | ||
834 | .type = PSMOUSE_FSP, | ||
835 | .name = "FSPPS/2", | ||
836 | .alias = "fsp", | ||
837 | .detect = fsp_detect, | ||
838 | .init = fsp_init, | ||
839 | }, | ||
840 | #endif | ||
817 | { | 841 | { |
818 | .type = PSMOUSE_CORTRON, | 842 | .type = PSMOUSE_CORTRON, |
819 | .name = "CortronPS/2", | 843 | .name = "CortronPS/2", |
@@ -824,7 +848,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
824 | .type = PSMOUSE_AUTO, | 848 | .type = PSMOUSE_AUTO, |
825 | .name = "auto", | 849 | .name = "auto", |
826 | .alias = "any", | 850 | .alias = "any", |
827 | .maxproto = 1, | 851 | .maxproto = true, |
828 | }, | 852 | }, |
829 | }; | 853 | }; |
830 | 854 | ||
@@ -990,7 +1014,7 @@ static void psmouse_resync(struct work_struct *work) | |||
990 | container_of(work, struct psmouse, resync_work.work); | 1014 | container_of(work, struct psmouse, resync_work.work); |
991 | struct serio *serio = psmouse->ps2dev.serio; | 1015 | struct serio *serio = psmouse->ps2dev.serio; |
992 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; | 1016 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; |
993 | int failed = 0, enabled = 0; | 1017 | bool failed = false, enabled = false; |
994 | int i; | 1018 | int i; |
995 | 1019 | ||
996 | mutex_lock(&psmouse_mutex); | 1020 | mutex_lock(&psmouse_mutex); |
@@ -1017,9 +1041,9 @@ static void psmouse_resync(struct work_struct *work) | |||
1017 | 1041 | ||
1018 | if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { | 1042 | if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { |
1019 | if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) | 1043 | if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) |
1020 | failed = 1; | 1044 | failed = true; |
1021 | } else | 1045 | } else |
1022 | psmouse->acks_disable_command = 1; | 1046 | psmouse->acks_disable_command = true; |
1023 | 1047 | ||
1024 | /* | 1048 | /* |
1025 | * Poll the mouse. If it was reset the packet will be shorter than | 1049 | * Poll the mouse. If it was reset the packet will be shorter than |
@@ -1030,7 +1054,7 @@ static void psmouse_resync(struct work_struct *work) | |||
1030 | */ | 1054 | */ |
1031 | if (!failed) { | 1055 | if (!failed) { |
1032 | if (psmouse->poll(psmouse)) | 1056 | if (psmouse->poll(psmouse)) |
1033 | failed = 1; | 1057 | failed = true; |
1034 | else { | 1058 | else { |
1035 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 1059 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
1036 | for (i = 0; i < psmouse->pktsize; i++) { | 1060 | for (i = 0; i < psmouse->pktsize; i++) { |
@@ -1040,7 +1064,7 @@ static void psmouse_resync(struct work_struct *work) | |||
1040 | break; | 1064 | break; |
1041 | } | 1065 | } |
1042 | if (rc != PSMOUSE_FULL_PACKET) | 1066 | if (rc != PSMOUSE_FULL_PACKET) |
1043 | failed = 1; | 1067 | failed = true; |
1044 | psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | 1068 | psmouse_set_state(psmouse, PSMOUSE_RESYNCING); |
1045 | } | 1069 | } |
1046 | } | 1070 | } |
@@ -1051,7 +1075,7 @@ static void psmouse_resync(struct work_struct *work) | |||
1051 | */ | 1075 | */ |
1052 | for (i = 0; i < 5; i++) { | 1076 | for (i = 0; i < 5; i++) { |
1053 | if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { | 1077 | if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { |
1054 | enabled = 1; | 1078 | enabled = true; |
1055 | break; | 1079 | break; |
1056 | } | 1080 | } |
1057 | msleep(200); | 1081 | msleep(200); |
@@ -1060,7 +1084,7 @@ static void psmouse_resync(struct work_struct *work) | |||
1060 | if (!enabled) { | 1084 | if (!enabled) { |
1061 | printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", | 1085 | printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", |
1062 | psmouse->ps2dev.serio->phys); | 1086 | psmouse->ps2dev.serio->phys); |
1063 | failed = 1; | 1087 | failed = true; |
1064 | } | 1088 | } |
1065 | 1089 | ||
1066 | if (failed) { | 1090 | if (failed) { |
@@ -1187,7 +1211,8 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse | |||
1187 | psmouse->type = proto->type; | 1211 | psmouse->type = proto->type; |
1188 | } | 1212 | } |
1189 | else | 1213 | else |
1190 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | 1214 | psmouse->type = psmouse_extensions(psmouse, |
1215 | psmouse_max_proto, true); | ||
1191 | 1216 | ||
1192 | /* | 1217 | /* |
1193 | * If mouse's packet size is 3 there is no point in polling the | 1218 | * If mouse's packet size is 3 there is no point in polling the |
@@ -1342,8 +1367,10 @@ static int psmouse_reconnect(struct serio *serio) | |||
1342 | if (psmouse->reconnect(psmouse)) | 1367 | if (psmouse->reconnect(psmouse)) |
1343 | goto out; | 1368 | goto out; |
1344 | } else if (psmouse_probe(psmouse) < 0 || | 1369 | } else if (psmouse_probe(psmouse) < 0 || |
1345 | psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0)) | 1370 | psmouse->type != psmouse_extensions(psmouse, |
1371 | psmouse_max_proto, false)) { | ||
1346 | goto out; | 1372 | goto out; |
1373 | } | ||
1347 | 1374 | ||
1348 | /* ok, the device type (and capabilities) match the old one, | 1375 | /* ok, the device type (and capabilities) match the old one, |
1349 | * we can continue using it, complete intialization | 1376 | * we can continue using it, complete intialization |
@@ -1528,7 +1555,9 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co | |||
1528 | 1555 | ||
1529 | while (serio->child) { | 1556 | while (serio->child) { |
1530 | if (++retry > 3) { | 1557 | if (++retry > 3) { |
1531 | printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n"); | 1558 | printk(KERN_WARNING |
1559 | "psmouse: failed to destroy child port, " | ||
1560 | "protocol change aborted.\n"); | ||
1532 | input_free_device(new_dev); | 1561 | input_free_device(new_dev); |
1533 | return -EIO; | 1562 | return -EIO; |
1534 | } | 1563 | } |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 54ed267894bd..e053bdd137ff 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -47,10 +47,10 @@ struct psmouse { | |||
47 | unsigned char pktcnt; | 47 | unsigned char pktcnt; |
48 | unsigned char pktsize; | 48 | unsigned char pktsize; |
49 | unsigned char type; | 49 | unsigned char type; |
50 | unsigned char acks_disable_command; | 50 | bool acks_disable_command; |
51 | unsigned int model; | 51 | unsigned int model; |
52 | unsigned long last; | 52 | unsigned long last; |
53 | unsigned long out_of_sync; | 53 | unsigned long out_of_sync_cnt; |
54 | unsigned long num_resyncs; | 54 | unsigned long num_resyncs; |
55 | enum psmouse_state state; | 55 | enum psmouse_state state; |
56 | char devname[64]; | 56 | char devname[64]; |
@@ -60,7 +60,7 @@ struct psmouse { | |||
60 | unsigned int resolution; | 60 | unsigned int resolution; |
61 | unsigned int resetafter; | 61 | unsigned int resetafter; |
62 | unsigned int resync_time; | 62 | unsigned int resync_time; |
63 | unsigned int smartscroll; /* Logitech only */ | 63 | bool smartscroll; /* Logitech only */ |
64 | 64 | ||
65 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse); | 65 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse); |
66 | void (*set_rate)(struct psmouse *psmouse, unsigned int rate); | 66 | void (*set_rate)(struct psmouse *psmouse, unsigned int rate); |
@@ -91,6 +91,7 @@ enum psmouse_type { | |||
91 | PSMOUSE_CORTRON, | 91 | PSMOUSE_CORTRON, |
92 | PSMOUSE_HGPK, | 92 | PSMOUSE_HGPK, |
93 | PSMOUSE_ELANTECH, | 93 | PSMOUSE_ELANTECH, |
94 | PSMOUSE_FSP, | ||
94 | PSMOUSE_AUTO /* This one should always be last */ | 95 | PSMOUSE_AUTO /* This one should always be last */ |
95 | }; | 96 | }; |
96 | 97 | ||
@@ -107,7 +108,7 @@ struct psmouse_attribute { | |||
107 | ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); | 108 | ssize_t (*show)(struct psmouse *psmouse, void *data, char *buf); |
108 | ssize_t (*set)(struct psmouse *psmouse, void *data, | 109 | ssize_t (*set)(struct psmouse *psmouse, void *data, |
109 | const char *buf, size_t count); | 110 | const char *buf, size_t count); |
110 | int protect; | 111 | bool protect; |
111 | }; | 112 | }; |
112 | #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) | 113 | #define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr) |
113 | 114 | ||
@@ -116,9 +117,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *at | |||
116 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, | 117 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *attr, |
117 | const char *buf, size_t count); | 118 | const char *buf, size_t count); |
118 | 119 | ||
119 | #define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ | 120 | #define __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect) \ |
120 | static ssize_t _show(struct psmouse *, void *data, char *); \ | ||
121 | static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \ | ||
122 | static struct psmouse_attribute psmouse_attr_##_name = { \ | 121 | static struct psmouse_attribute psmouse_attr_##_name = { \ |
123 | .dattr = { \ | 122 | .dattr = { \ |
124 | .attr = { \ | 123 | .attr = { \ |
@@ -134,7 +133,20 @@ static struct psmouse_attribute psmouse_attr_##_name = { \ | |||
134 | .protect = _protect, \ | 133 | .protect = _protect, \ |
135 | } | 134 | } |
136 | 135 | ||
137 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | 136 | #define __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect) \ |
138 | __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, 1) | 137 | static ssize_t _show(struct psmouse *, void *, char *); \ |
138 | static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ | ||
139 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, _set, _protect) | ||
140 | |||
141 | #define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \ | ||
142 | __PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, true) | ||
143 | |||
144 | #define PSMOUSE_DEFINE_RO_ATTR(_name, _mode, _data, _show) \ | ||
145 | static ssize_t _show(struct psmouse *, void *, char *); \ | ||
146 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, _show, NULL, true) | ||
147 | |||
148 | #define PSMOUSE_DEFINE_WO_ATTR(_name, _mode, _data, _set) \ | ||
149 | static ssize_t _set(struct psmouse *, void *, const char *, size_t); \ | ||
150 | __PSMOUSE_DEFINE_ATTR_VAR(_name, _mode, _data, NULL, _set, true) | ||
139 | 151 | ||
140 | #endif /* _PSMOUSE_H */ | 152 | #endif /* _PSMOUSE_H */ |
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c new file mode 100644 index 000000000000..84e2fc04d11b --- /dev/null +++ b/drivers/input/mouse/sentelic.c | |||
@@ -0,0 +1,867 @@ | |||
1 | /*- | ||
2 | * Finger Sensing Pad PS/2 mouse driver. | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. | ||
5 | * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version 2 | ||
10 | * of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/version.h> | ||
24 | #include <linux/input.h> | ||
25 | #include <linux/ctype.h> | ||
26 | #include <linux/libps2.h> | ||
27 | #include <linux/serio.h> | ||
28 | #include <linux/jiffies.h> | ||
29 | |||
30 | #include "psmouse.h" | ||
31 | #include "sentelic.h" | ||
32 | |||
33 | /* | ||
34 | * Timeout for FSP PS/2 command only (in milliseconds). | ||
35 | */ | ||
36 | #define FSP_CMD_TIMEOUT 200 | ||
37 | #define FSP_CMD_TIMEOUT2 30 | ||
38 | |||
39 | /** Driver version. */ | ||
40 | static const char fsp_drv_ver[] = "1.0.0-K"; | ||
41 | |||
42 | /* | ||
43 | * Make sure that the value being sent to FSP will not conflict with | ||
44 | * possible sample rate values. | ||
45 | */ | ||
46 | static unsigned char fsp_test_swap_cmd(unsigned char reg_val) | ||
47 | { | ||
48 | switch (reg_val) { | ||
49 | case 10: case 20: case 40: case 60: case 80: case 100: case 200: | ||
50 | /* | ||
51 | * The requested value being sent to FSP matched to possible | ||
52 | * sample rates, swap the given value such that the hardware | ||
53 | * wouldn't get confused. | ||
54 | */ | ||
55 | return (reg_val >> 4) | (reg_val << 4); | ||
56 | default: | ||
57 | return reg_val; /* swap isn't necessary */ | ||
58 | } | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Make sure that the value being sent to FSP will not conflict with certain | ||
63 | * commands. | ||
64 | */ | ||
65 | static unsigned char fsp_test_invert_cmd(unsigned char reg_val) | ||
66 | { | ||
67 | switch (reg_val) { | ||
68 | case 0xe9: case 0xee: case 0xf2: case 0xff: | ||
69 | /* | ||
70 | * The requested value being sent to FSP matched to certain | ||
71 | * commands, inverse the given value such that the hardware | ||
72 | * wouldn't get confused. | ||
73 | */ | ||
74 | return ~reg_val; | ||
75 | default: | ||
76 | return reg_val; /* inversion isn't necessary */ | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val) | ||
81 | { | ||
82 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
83 | unsigned char param[3]; | ||
84 | unsigned char addr; | ||
85 | int rc = -1; | ||
86 | |||
87 | /* | ||
88 | * We need to shut off the device and switch it into command | ||
89 | * mode so we don't confuse our protocol handler. We don't need | ||
90 | * to do that for writes because sysfs set helper does this for | ||
91 | * us. | ||
92 | */ | ||
93 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | ||
94 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
95 | mutex_lock(&ps2dev->cmd_mutex); | ||
96 | |||
97 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
98 | goto out; | ||
99 | |||
100 | /* should return 0xfe(request for resending) */ | ||
101 | ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); | ||
102 | /* should return 0xfc(failed) */ | ||
103 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
104 | |||
105 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
106 | goto out; | ||
107 | |||
108 | if ((addr = fsp_test_invert_cmd(reg_addr)) != reg_addr) { | ||
109 | ps2_sendbyte(ps2dev, 0x68, FSP_CMD_TIMEOUT2); | ||
110 | } else if ((addr = fsp_test_swap_cmd(reg_addr)) != reg_addr) { | ||
111 | /* swapping is required */ | ||
112 | ps2_sendbyte(ps2dev, 0xcc, FSP_CMD_TIMEOUT2); | ||
113 | /* expect 0xfe */ | ||
114 | } else { | ||
115 | /* swapping isn't necessary */ | ||
116 | ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); | ||
117 | /* expect 0xfe */ | ||
118 | } | ||
119 | /* should return 0xfc(failed) */ | ||
120 | ps2_sendbyte(ps2dev, addr, FSP_CMD_TIMEOUT); | ||
121 | |||
122 | if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) < 0) | ||
123 | goto out; | ||
124 | |||
125 | *reg_val = param[2]; | ||
126 | rc = 0; | ||
127 | |||
128 | out: | ||
129 | mutex_unlock(&ps2dev->cmd_mutex); | ||
130 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
131 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
132 | dev_dbg(&ps2dev->serio->dev, "READ REG: 0x%02x is 0x%02x (rc = %d)\n", | ||
133 | reg_addr, *reg_val, rc); | ||
134 | return rc; | ||
135 | } | ||
136 | |||
137 | static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val) | ||
138 | { | ||
139 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
140 | unsigned char v; | ||
141 | int rc = -1; | ||
142 | |||
143 | mutex_lock(&ps2dev->cmd_mutex); | ||
144 | |||
145 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
146 | goto out; | ||
147 | |||
148 | if ((v = fsp_test_invert_cmd(reg_addr)) != reg_addr) { | ||
149 | /* inversion is required */ | ||
150 | ps2_sendbyte(ps2dev, 0x74, FSP_CMD_TIMEOUT2); | ||
151 | } else { | ||
152 | if ((v = fsp_test_swap_cmd(reg_addr)) != reg_addr) { | ||
153 | /* swapping is required */ | ||
154 | ps2_sendbyte(ps2dev, 0x77, FSP_CMD_TIMEOUT2); | ||
155 | } else { | ||
156 | /* swapping isn't necessary */ | ||
157 | ps2_sendbyte(ps2dev, 0x55, FSP_CMD_TIMEOUT2); | ||
158 | } | ||
159 | } | ||
160 | /* write the register address in correct order */ | ||
161 | ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); | ||
162 | |||
163 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
164 | return -1; | ||
165 | |||
166 | if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) { | ||
167 | /* inversion is required */ | ||
168 | ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2); | ||
169 | } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) { | ||
170 | /* swapping is required */ | ||
171 | ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2); | ||
172 | } else { | ||
173 | /* swapping isn't necessary */ | ||
174 | ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2); | ||
175 | } | ||
176 | |||
177 | /* write the register value in correct order */ | ||
178 | ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); | ||
179 | rc = 0; | ||
180 | |||
181 | out: | ||
182 | mutex_unlock(&ps2dev->cmd_mutex); | ||
183 | dev_dbg(&ps2dev->serio->dev, "WRITE REG: 0x%02x to 0x%02x (rc = %d)\n", | ||
184 | reg_addr, reg_val, rc); | ||
185 | return rc; | ||
186 | } | ||
187 | |||
188 | /* Enable register clock gating for writing certain registers */ | ||
189 | static int fsp_reg_write_enable(struct psmouse *psmouse, bool enable) | ||
190 | { | ||
191 | int v, nv; | ||
192 | |||
193 | if (fsp_reg_read(psmouse, FSP_REG_SYSCTL1, &v) == -1) | ||
194 | return -1; | ||
195 | |||
196 | if (enable) | ||
197 | nv = v | FSP_BIT_EN_REG_CLK; | ||
198 | else | ||
199 | nv = v & ~FSP_BIT_EN_REG_CLK; | ||
200 | |||
201 | /* only write if necessary */ | ||
202 | if (nv != v) | ||
203 | if (fsp_reg_write(psmouse, FSP_REG_SYSCTL1, nv) == -1) | ||
204 | return -1; | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val) | ||
210 | { | ||
211 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
212 | unsigned char param[3]; | ||
213 | int rc = -1; | ||
214 | |||
215 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE); | ||
216 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
217 | mutex_lock(&ps2dev->cmd_mutex); | ||
218 | |||
219 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
220 | goto out; | ||
221 | |||
222 | ps2_sendbyte(ps2dev, 0x66, FSP_CMD_TIMEOUT2); | ||
223 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
224 | |||
225 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
226 | goto out; | ||
227 | |||
228 | ps2_sendbyte(ps2dev, 0x83, FSP_CMD_TIMEOUT2); | ||
229 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
230 | |||
231 | /* get the returned result */ | ||
232 | if (__ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) | ||
233 | goto out; | ||
234 | |||
235 | *reg_val = param[2]; | ||
236 | rc = 0; | ||
237 | |||
238 | out: | ||
239 | mutex_unlock(&ps2dev->cmd_mutex); | ||
240 | ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); | ||
241 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
242 | dev_dbg(&ps2dev->serio->dev, "READ PAGE REG: 0x%02x (rc = %d)\n", | ||
243 | *reg_val, rc); | ||
244 | return rc; | ||
245 | } | ||
246 | |||
247 | static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val) | ||
248 | { | ||
249 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
250 | unsigned char v; | ||
251 | int rc = -1; | ||
252 | |||
253 | mutex_lock(&ps2dev->cmd_mutex); | ||
254 | |||
255 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
256 | goto out; | ||
257 | |||
258 | ps2_sendbyte(ps2dev, 0x38, FSP_CMD_TIMEOUT2); | ||
259 | ps2_sendbyte(ps2dev, 0x88, FSP_CMD_TIMEOUT2); | ||
260 | |||
261 | if (ps2_sendbyte(ps2dev, 0xf3, FSP_CMD_TIMEOUT) < 0) | ||
262 | return -1; | ||
263 | |||
264 | if ((v = fsp_test_invert_cmd(reg_val)) != reg_val) { | ||
265 | ps2_sendbyte(ps2dev, 0x47, FSP_CMD_TIMEOUT2); | ||
266 | } else if ((v = fsp_test_swap_cmd(reg_val)) != reg_val) { | ||
267 | /* swapping is required */ | ||
268 | ps2_sendbyte(ps2dev, 0x44, FSP_CMD_TIMEOUT2); | ||
269 | } else { | ||
270 | /* swapping isn't necessary */ | ||
271 | ps2_sendbyte(ps2dev, 0x33, FSP_CMD_TIMEOUT2); | ||
272 | } | ||
273 | |||
274 | ps2_sendbyte(ps2dev, v, FSP_CMD_TIMEOUT2); | ||
275 | rc = 0; | ||
276 | |||
277 | out: | ||
278 | mutex_unlock(&ps2dev->cmd_mutex); | ||
279 | dev_dbg(&ps2dev->serio->dev, "WRITE PAGE REG: to 0x%02x (rc = %d)\n", | ||
280 | reg_val, rc); | ||
281 | return rc; | ||
282 | } | ||
283 | |||
284 | static int fsp_get_version(struct psmouse *psmouse, int *version) | ||
285 | { | ||
286 | if (fsp_reg_read(psmouse, FSP_REG_VERSION, version)) | ||
287 | return -EIO; | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int fsp_get_revision(struct psmouse *psmouse, int *rev) | ||
293 | { | ||
294 | if (fsp_reg_read(psmouse, FSP_REG_REVISION, rev)) | ||
295 | return -EIO; | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int fsp_get_buttons(struct psmouse *psmouse, int *btn) | ||
301 | { | ||
302 | static const int buttons[] = { | ||
303 | 0x16, /* Left/Middle/Right/Forward/Backward & Scroll Up/Down */ | ||
304 | 0x06, /* Left/Middle/Right & Scroll Up/Down/Right/Left */ | ||
305 | 0x04, /* Left/Middle/Right & Scroll Up/Down */ | ||
306 | 0x02, /* Left/Middle/Right */ | ||
307 | }; | ||
308 | int val; | ||
309 | |||
310 | if (fsp_reg_read(psmouse, FSP_REG_TMOD_STATUS1, &val) == -1) | ||
311 | return -EIO; | ||
312 | |||
313 | *btn = buttons[(val & 0x30) >> 4]; | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | /* Enable on-pad command tag output */ | ||
318 | static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable) | ||
319 | { | ||
320 | int v, nv; | ||
321 | int res = 0; | ||
322 | |||
323 | if (fsp_reg_read(psmouse, FSP_REG_OPC_QDOWN, &v) == -1) { | ||
324 | dev_err(&psmouse->ps2dev.serio->dev, "Unable get OPC state.\n"); | ||
325 | return -EIO; | ||
326 | } | ||
327 | |||
328 | if (enable) | ||
329 | nv = v | FSP_BIT_EN_OPC_TAG; | ||
330 | else | ||
331 | nv = v & ~FSP_BIT_EN_OPC_TAG; | ||
332 | |||
333 | /* only write if necessary */ | ||
334 | if (nv != v) { | ||
335 | fsp_reg_write_enable(psmouse, true); | ||
336 | res = fsp_reg_write(psmouse, FSP_REG_OPC_QDOWN, nv); | ||
337 | fsp_reg_write_enable(psmouse, false); | ||
338 | } | ||
339 | |||
340 | if (res != 0) { | ||
341 | dev_err(&psmouse->ps2dev.serio->dev, | ||
342 | "Unable to enable OPC tag.\n"); | ||
343 | res = -EIO; | ||
344 | } | ||
345 | |||
346 | return res; | ||
347 | } | ||
348 | |||
349 | static int fsp_onpad_vscr(struct psmouse *psmouse, bool enable) | ||
350 | { | ||
351 | struct fsp_data *pad = psmouse->private; | ||
352 | int val; | ||
353 | |||
354 | if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val)) | ||
355 | return -EIO; | ||
356 | |||
357 | pad->vscroll = enable; | ||
358 | |||
359 | if (enable) | ||
360 | val |= (FSP_BIT_FIX_VSCR | FSP_BIT_ONPAD_ENABLE); | ||
361 | else | ||
362 | val &= ~FSP_BIT_FIX_VSCR; | ||
363 | |||
364 | if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val)) | ||
365 | return -EIO; | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int fsp_onpad_hscr(struct psmouse *psmouse, bool enable) | ||
371 | { | ||
372 | struct fsp_data *pad = psmouse->private; | ||
373 | int val, v2; | ||
374 | |||
375 | if (fsp_reg_read(psmouse, FSP_REG_ONPAD_CTL, &val)) | ||
376 | return -EIO; | ||
377 | |||
378 | if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &v2)) | ||
379 | return -EIO; | ||
380 | |||
381 | pad->hscroll = enable; | ||
382 | |||
383 | if (enable) { | ||
384 | val |= (FSP_BIT_FIX_HSCR | FSP_BIT_ONPAD_ENABLE); | ||
385 | v2 |= FSP_BIT_EN_MSID6; | ||
386 | } else { | ||
387 | val &= ~FSP_BIT_FIX_HSCR; | ||
388 | v2 &= ~(FSP_BIT_EN_MSID6 | FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8); | ||
389 | } | ||
390 | |||
391 | if (fsp_reg_write(psmouse, FSP_REG_ONPAD_CTL, val)) | ||
392 | return -EIO; | ||
393 | |||
394 | /* reconfigure horizontal scrolling packet output */ | ||
395 | if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, v2)) | ||
396 | return -EIO; | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | /* | ||
402 | * Write device specific initial parameters. | ||
403 | * | ||
404 | * ex: 0xab 0xcd - write oxcd into register 0xab | ||
405 | */ | ||
406 | static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data, | ||
407 | const char *buf, size_t count) | ||
408 | { | ||
409 | unsigned long reg, val; | ||
410 | char *rest; | ||
411 | ssize_t retval; | ||
412 | |||
413 | reg = simple_strtoul(buf, &rest, 16); | ||
414 | if (rest == buf || *rest != ' ' || reg > 0xff) | ||
415 | return -EINVAL; | ||
416 | |||
417 | if (strict_strtoul(rest + 1, 16, &val) || val > 0xff) | ||
418 | return -EINVAL; | ||
419 | |||
420 | if (fsp_reg_write_enable(psmouse, true)) | ||
421 | return -EIO; | ||
422 | |||
423 | retval = fsp_reg_write(psmouse, reg, val) < 0 ? -EIO : count; | ||
424 | |||
425 | fsp_reg_write_enable(psmouse, false); | ||
426 | |||
427 | return count; | ||
428 | } | ||
429 | |||
430 | PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg); | ||
431 | |||
432 | static ssize_t fsp_attr_show_getreg(struct psmouse *psmouse, | ||
433 | void *data, char *buf) | ||
434 | { | ||
435 | struct fsp_data *pad = psmouse->private; | ||
436 | |||
437 | return sprintf(buf, "%02x%02x\n", pad->last_reg, pad->last_val); | ||
438 | } | ||
439 | |||
440 | /* | ||
441 | * Read a register from device. | ||
442 | * | ||
443 | * ex: 0xab -- read content from register 0xab | ||
444 | */ | ||
445 | static ssize_t fsp_attr_set_getreg(struct psmouse *psmouse, void *data, | ||
446 | const char *buf, size_t count) | ||
447 | { | ||
448 | struct fsp_data *pad = psmouse->private; | ||
449 | unsigned long reg; | ||
450 | int val; | ||
451 | |||
452 | if (strict_strtoul(buf, 16, ®) || reg > 0xff) | ||
453 | return -EINVAL; | ||
454 | |||
455 | if (fsp_reg_read(psmouse, reg, &val)) | ||
456 | return -EIO; | ||
457 | |||
458 | pad->last_reg = reg; | ||
459 | pad->last_val = val; | ||
460 | |||
461 | return count; | ||
462 | } | ||
463 | |||
464 | PSMOUSE_DEFINE_ATTR(getreg, S_IWUSR | S_IRUGO, NULL, | ||
465 | fsp_attr_show_getreg, fsp_attr_set_getreg); | ||
466 | |||
467 | static ssize_t fsp_attr_show_pagereg(struct psmouse *psmouse, | ||
468 | void *data, char *buf) | ||
469 | { | ||
470 | int val = 0; | ||
471 | |||
472 | if (fsp_page_reg_read(psmouse, &val)) | ||
473 | return -EIO; | ||
474 | |||
475 | return sprintf(buf, "%02x\n", val); | ||
476 | } | ||
477 | |||
478 | static ssize_t fsp_attr_set_pagereg(struct psmouse *psmouse, void *data, | ||
479 | const char *buf, size_t count) | ||
480 | { | ||
481 | unsigned long val; | ||
482 | |||
483 | if (strict_strtoul(buf, 16, &val) || val > 0xff) | ||
484 | return -EINVAL; | ||
485 | |||
486 | if (fsp_page_reg_write(psmouse, val)) | ||
487 | return -EIO; | ||
488 | |||
489 | return count; | ||
490 | } | ||
491 | |||
492 | PSMOUSE_DEFINE_ATTR(page, S_IWUSR | S_IRUGO, NULL, | ||
493 | fsp_attr_show_pagereg, fsp_attr_set_pagereg); | ||
494 | |||
495 | static ssize_t fsp_attr_show_vscroll(struct psmouse *psmouse, | ||
496 | void *data, char *buf) | ||
497 | { | ||
498 | struct fsp_data *pad = psmouse->private; | ||
499 | |||
500 | return sprintf(buf, "%d\n", pad->vscroll); | ||
501 | } | ||
502 | |||
503 | static ssize_t fsp_attr_set_vscroll(struct psmouse *psmouse, void *data, | ||
504 | const char *buf, size_t count) | ||
505 | { | ||
506 | unsigned long val; | ||
507 | |||
508 | if (strict_strtoul(buf, 10, &val) || val > 1) | ||
509 | return -EINVAL; | ||
510 | |||
511 | fsp_onpad_vscr(psmouse, val); | ||
512 | |||
513 | return count; | ||
514 | } | ||
515 | |||
516 | PSMOUSE_DEFINE_ATTR(vscroll, S_IWUSR | S_IRUGO, NULL, | ||
517 | fsp_attr_show_vscroll, fsp_attr_set_vscroll); | ||
518 | |||
519 | static ssize_t fsp_attr_show_hscroll(struct psmouse *psmouse, | ||
520 | void *data, char *buf) | ||
521 | { | ||
522 | struct fsp_data *pad = psmouse->private; | ||
523 | |||
524 | return sprintf(buf, "%d\n", pad->hscroll); | ||
525 | } | ||
526 | |||
527 | static ssize_t fsp_attr_set_hscroll(struct psmouse *psmouse, void *data, | ||
528 | const char *buf, size_t count) | ||
529 | { | ||
530 | unsigned long val; | ||
531 | |||
532 | if (strict_strtoul(buf, 10, &val) || val > 1) | ||
533 | return -EINVAL; | ||
534 | |||
535 | fsp_onpad_hscr(psmouse, val); | ||
536 | |||
537 | return count; | ||
538 | } | ||
539 | |||
540 | PSMOUSE_DEFINE_ATTR(hscroll, S_IWUSR | S_IRUGO, NULL, | ||
541 | fsp_attr_show_hscroll, fsp_attr_set_hscroll); | ||
542 | |||
543 | static ssize_t fsp_attr_show_flags(struct psmouse *psmouse, | ||
544 | void *data, char *buf) | ||
545 | { | ||
546 | struct fsp_data *pad = psmouse->private; | ||
547 | |||
548 | return sprintf(buf, "%c\n", | ||
549 | pad->flags & FSPDRV_FLAG_EN_OPC ? 'C' : 'c'); | ||
550 | } | ||
551 | |||
552 | static ssize_t fsp_attr_set_flags(struct psmouse *psmouse, void *data, | ||
553 | const char *buf, size_t count) | ||
554 | { | ||
555 | struct fsp_data *pad = psmouse->private; | ||
556 | size_t i; | ||
557 | |||
558 | for (i = 0; i < count; i++) { | ||
559 | switch (buf[i]) { | ||
560 | case 'C': | ||
561 | pad->flags |= FSPDRV_FLAG_EN_OPC; | ||
562 | break; | ||
563 | case 'c': | ||
564 | pad->flags &= ~FSPDRV_FLAG_EN_OPC; | ||
565 | break; | ||
566 | default: | ||
567 | return -EINVAL; | ||
568 | } | ||
569 | } | ||
570 | return count; | ||
571 | } | ||
572 | |||
573 | PSMOUSE_DEFINE_ATTR(flags, S_IWUSR | S_IRUGO, NULL, | ||
574 | fsp_attr_show_flags, fsp_attr_set_flags); | ||
575 | |||
576 | static ssize_t fsp_attr_show_ver(struct psmouse *psmouse, | ||
577 | void *data, char *buf) | ||
578 | { | ||
579 | return sprintf(buf, "Sentelic FSP kernel module %s\n", fsp_drv_ver); | ||
580 | } | ||
581 | |||
582 | PSMOUSE_DEFINE_RO_ATTR(ver, S_IRUGO, NULL, fsp_attr_show_ver); | ||
583 | |||
584 | static struct attribute *fsp_attributes[] = { | ||
585 | &psmouse_attr_setreg.dattr.attr, | ||
586 | &psmouse_attr_getreg.dattr.attr, | ||
587 | &psmouse_attr_page.dattr.attr, | ||
588 | &psmouse_attr_vscroll.dattr.attr, | ||
589 | &psmouse_attr_hscroll.dattr.attr, | ||
590 | &psmouse_attr_flags.dattr.attr, | ||
591 | &psmouse_attr_ver.dattr.attr, | ||
592 | NULL | ||
593 | }; | ||
594 | |||
595 | static struct attribute_group fsp_attribute_group = { | ||
596 | .attrs = fsp_attributes, | ||
597 | }; | ||
598 | |||
599 | #ifdef FSP_DEBUG | ||
600 | static void fsp_packet_debug(unsigned char packet[]) | ||
601 | { | ||
602 | static unsigned int ps2_packet_cnt; | ||
603 | static unsigned int ps2_last_second; | ||
604 | unsigned int jiffies_msec; | ||
605 | |||
606 | ps2_packet_cnt++; | ||
607 | jiffies_msec = jiffies_to_msecs(jiffies); | ||
608 | printk(KERN_DEBUG "%08dms PS/2 packets: %02x, %02x, %02x, %02x\n", | ||
609 | jiffies_msec, packet[0], packet[1], packet[2], packet[3]); | ||
610 | |||
611 | if (jiffies_msec - ps2_last_second > 1000) { | ||
612 | printk(KERN_DEBUG "PS/2 packets/sec = %d\n", ps2_packet_cnt); | ||
613 | ps2_packet_cnt = 0; | ||
614 | ps2_last_second = jiffies_msec; | ||
615 | } | ||
616 | } | ||
617 | #else | ||
618 | static void fsp_packet_debug(unsigned char packet[]) | ||
619 | { | ||
620 | } | ||
621 | #endif | ||
622 | |||
623 | static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) | ||
624 | { | ||
625 | struct input_dev *dev = psmouse->dev; | ||
626 | struct fsp_data *ad = psmouse->private; | ||
627 | unsigned char *packet = psmouse->packet; | ||
628 | unsigned char button_status = 0, lscroll = 0, rscroll = 0; | ||
629 | int rel_x, rel_y; | ||
630 | |||
631 | if (psmouse->pktcnt < 4) | ||
632 | return PSMOUSE_GOOD_DATA; | ||
633 | |||
634 | /* | ||
635 | * Full packet accumulated, process it | ||
636 | */ | ||
637 | |||
638 | switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) { | ||
639 | case FSP_PKT_TYPE_ABS: | ||
640 | dev_warn(&psmouse->ps2dev.serio->dev, | ||
641 | "Unexpected absolute mode packet, ignored.\n"); | ||
642 | break; | ||
643 | |||
644 | case FSP_PKT_TYPE_NORMAL_OPC: | ||
645 | /* on-pad click, filter it if necessary */ | ||
646 | if ((ad->flags & FSPDRV_FLAG_EN_OPC) != FSPDRV_FLAG_EN_OPC) | ||
647 | packet[0] &= ~BIT(0); | ||
648 | /* fall through */ | ||
649 | |||
650 | case FSP_PKT_TYPE_NORMAL: | ||
651 | /* normal packet */ | ||
652 | /* special packet data translation from on-pad packets */ | ||
653 | if (packet[3] != 0) { | ||
654 | if (packet[3] & BIT(0)) | ||
655 | button_status |= 0x01; /* wheel down */ | ||
656 | if (packet[3] & BIT(1)) | ||
657 | button_status |= 0x0f; /* wheel up */ | ||
658 | if (packet[3] & BIT(2)) | ||
659 | button_status |= BIT(5);/* horizontal left */ | ||
660 | if (packet[3] & BIT(3)) | ||
661 | button_status |= BIT(4);/* horizontal right */ | ||
662 | /* push back to packet queue */ | ||
663 | if (button_status != 0) | ||
664 | packet[3] = button_status; | ||
665 | rscroll = (packet[3] >> 4) & 1; | ||
666 | lscroll = (packet[3] >> 5) & 1; | ||
667 | } | ||
668 | /* | ||
669 | * Processing wheel up/down and extra button events | ||
670 | */ | ||
671 | input_report_rel(dev, REL_WHEEL, | ||
672 | (int)(packet[3] & 8) - (int)(packet[3] & 7)); | ||
673 | input_report_rel(dev, REL_HWHEEL, lscroll - rscroll); | ||
674 | input_report_key(dev, BTN_BACK, lscroll); | ||
675 | input_report_key(dev, BTN_FORWARD, rscroll); | ||
676 | |||
677 | /* | ||
678 | * Standard PS/2 Mouse | ||
679 | */ | ||
680 | input_report_key(dev, BTN_LEFT, packet[0] & 1); | ||
681 | input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1); | ||
682 | input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1); | ||
683 | |||
684 | rel_x = packet[1] ? (int)packet[1] - (int)((packet[0] << 4) & 0x100) : 0; | ||
685 | rel_y = packet[2] ? (int)((packet[0] << 3) & 0x100) - (int)packet[2] : 0; | ||
686 | |||
687 | input_report_rel(dev, REL_X, rel_x); | ||
688 | input_report_rel(dev, REL_Y, rel_y); | ||
689 | break; | ||
690 | } | ||
691 | |||
692 | input_sync(dev); | ||
693 | |||
694 | fsp_packet_debug(packet); | ||
695 | |||
696 | return PSMOUSE_FULL_PACKET; | ||
697 | } | ||
698 | |||
699 | static int fsp_activate_protocol(struct psmouse *psmouse) | ||
700 | { | ||
701 | struct fsp_data *pad = psmouse->private; | ||
702 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
703 | unsigned char param[2]; | ||
704 | int val; | ||
705 | |||
706 | /* | ||
707 | * Standard procedure to enter FSP Intellimouse mode | ||
708 | * (scrolling wheel, 4th and 5th buttons) | ||
709 | */ | ||
710 | param[0] = 200; | ||
711 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | ||
712 | param[0] = 200; | ||
713 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | ||
714 | param[0] = 80; | ||
715 | ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); | ||
716 | |||
717 | ps2_command(ps2dev, param, PSMOUSE_CMD_GETID); | ||
718 | if (param[0] != 0x04) { | ||
719 | dev_err(&psmouse->ps2dev.serio->dev, | ||
720 | "Unable to enable 4 bytes packet format.\n"); | ||
721 | return -EIO; | ||
722 | } | ||
723 | |||
724 | if (fsp_reg_read(psmouse, FSP_REG_SYSCTL5, &val)) { | ||
725 | dev_err(&psmouse->ps2dev.serio->dev, | ||
726 | "Unable to read SYSCTL5 register.\n"); | ||
727 | return -EIO; | ||
728 | } | ||
729 | |||
730 | val &= ~(FSP_BIT_EN_MSID7 | FSP_BIT_EN_MSID8 | FSP_BIT_EN_AUTO_MSID8); | ||
731 | /* Ensure we are not in absolute mode */ | ||
732 | val &= ~FSP_BIT_EN_PKT_G0; | ||
733 | if (pad->buttons == 0x06) { | ||
734 | /* Left/Middle/Right & Scroll Up/Down/Right/Left */ | ||
735 | val |= FSP_BIT_EN_MSID6; | ||
736 | } | ||
737 | |||
738 | if (fsp_reg_write(psmouse, FSP_REG_SYSCTL5, val)) { | ||
739 | dev_err(&psmouse->ps2dev.serio->dev, | ||
740 | "Unable to set up required mode bits.\n"); | ||
741 | return -EIO; | ||
742 | } | ||
743 | |||
744 | /* | ||
745 | * Enable OPC tags such that driver can tell the difference between | ||
746 | * on-pad and real button click | ||
747 | */ | ||
748 | if (fsp_opc_tag_enable(psmouse, true)) | ||
749 | dev_warn(&psmouse->ps2dev.serio->dev, | ||
750 | "Failed to enable OPC tag mode.\n"); | ||
751 | |||
752 | /* Enable on-pad vertical and horizontal scrolling */ | ||
753 | fsp_onpad_vscr(psmouse, true); | ||
754 | fsp_onpad_hscr(psmouse, true); | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | int fsp_detect(struct psmouse *psmouse, bool set_properties) | ||
760 | { | ||
761 | int id; | ||
762 | |||
763 | if (fsp_reg_read(psmouse, FSP_REG_DEVICE_ID, &id)) | ||
764 | return -EIO; | ||
765 | |||
766 | if (id != 0x01) | ||
767 | return -ENODEV; | ||
768 | |||
769 | if (set_properties) { | ||
770 | psmouse->vendor = "Sentelic"; | ||
771 | psmouse->name = "FingerSensingPad"; | ||
772 | } | ||
773 | |||
774 | return 0; | ||
775 | } | ||
776 | |||
777 | static void fsp_reset(struct psmouse *psmouse) | ||
778 | { | ||
779 | fsp_opc_tag_enable(psmouse, false); | ||
780 | fsp_onpad_vscr(psmouse, false); | ||
781 | fsp_onpad_hscr(psmouse, false); | ||
782 | } | ||
783 | |||
784 | static void fsp_disconnect(struct psmouse *psmouse) | ||
785 | { | ||
786 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, | ||
787 | &fsp_attribute_group); | ||
788 | |||
789 | fsp_reset(psmouse); | ||
790 | kfree(psmouse->private); | ||
791 | } | ||
792 | |||
793 | static int fsp_reconnect(struct psmouse *psmouse) | ||
794 | { | ||
795 | int version; | ||
796 | |||
797 | if (fsp_detect(psmouse, 0)) | ||
798 | return -ENODEV; | ||
799 | |||
800 | if (fsp_get_version(psmouse, &version)) | ||
801 | return -ENODEV; | ||
802 | |||
803 | if (fsp_activate_protocol(psmouse)) | ||
804 | return -EIO; | ||
805 | |||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | int fsp_init(struct psmouse *psmouse) | ||
810 | { | ||
811 | struct fsp_data *priv; | ||
812 | int ver, rev, buttons; | ||
813 | int error; | ||
814 | |||
815 | if (fsp_get_version(psmouse, &ver) || | ||
816 | fsp_get_revision(psmouse, &rev) || | ||
817 | fsp_get_buttons(psmouse, &buttons)) { | ||
818 | return -ENODEV; | ||
819 | } | ||
820 | |||
821 | printk(KERN_INFO | ||
822 | "Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d\n", | ||
823 | ver >> 4, ver & 0x0F, rev, fsp_drv_ver, buttons & 7); | ||
824 | |||
825 | psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); | ||
826 | if (!priv) | ||
827 | return -ENOMEM; | ||
828 | |||
829 | priv->ver = ver; | ||
830 | priv->rev = rev; | ||
831 | priv->buttons = buttons; | ||
832 | |||
833 | /* enable on-pad click by default */ | ||
834 | priv->flags |= FSPDRV_FLAG_EN_OPC; | ||
835 | |||
836 | /* Set up various supported input event bits */ | ||
837 | __set_bit(BTN_BACK, psmouse->dev->keybit); | ||
838 | __set_bit(BTN_FORWARD, psmouse->dev->keybit); | ||
839 | __set_bit(REL_WHEEL, psmouse->dev->relbit); | ||
840 | __set_bit(REL_HWHEEL, psmouse->dev->relbit); | ||
841 | |||
842 | psmouse->protocol_handler = fsp_process_byte; | ||
843 | psmouse->disconnect = fsp_disconnect; | ||
844 | psmouse->reconnect = fsp_reconnect; | ||
845 | psmouse->cleanup = fsp_reset; | ||
846 | psmouse->pktsize = 4; | ||
847 | |||
848 | /* set default packet output based on number of buttons we found */ | ||
849 | error = fsp_activate_protocol(psmouse); | ||
850 | if (error) | ||
851 | goto err_out; | ||
852 | |||
853 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, | ||
854 | &fsp_attribute_group); | ||
855 | if (error) { | ||
856 | dev_err(&psmouse->ps2dev.serio->dev, | ||
857 | "Failed to create sysfs attributes (%d)", error); | ||
858 | goto err_out; | ||
859 | } | ||
860 | |||
861 | return 0; | ||
862 | |||
863 | err_out: | ||
864 | kfree(psmouse->private); | ||
865 | psmouse->private = NULL; | ||
866 | return error; | ||
867 | } | ||
diff --git a/drivers/input/mouse/sentelic.h b/drivers/input/mouse/sentelic.h new file mode 100644 index 000000000000..ed1395ac7b8b --- /dev/null +++ b/drivers/input/mouse/sentelic.h | |||
@@ -0,0 +1,98 @@ | |||
1 | /*- | ||
2 | * Finger Sensing Pad PS/2 mouse driver. | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. | ||
5 | * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version 2 | ||
10 | * of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | */ | ||
21 | |||
22 | #ifndef __SENTELIC_H | ||
23 | #define __SENTELIC_H | ||
24 | |||
25 | /* Finger-sensing Pad information registers */ | ||
26 | #define FSP_REG_DEVICE_ID 0x00 | ||
27 | #define FSP_REG_VERSION 0x01 | ||
28 | #define FSP_REG_REVISION 0x04 | ||
29 | #define FSP_REG_TMOD_STATUS1 0x0B | ||
30 | #define FSP_BIT_NO_ROTATION BIT(3) | ||
31 | #define FSP_REG_PAGE_CTRL 0x0F | ||
32 | |||
33 | /* Finger-sensing Pad control registers */ | ||
34 | #define FSP_REG_SYSCTL1 0x10 | ||
35 | #define FSP_BIT_EN_REG_CLK BIT(5) | ||
36 | #define FSP_REG_OPC_QDOWN 0x31 | ||
37 | #define FSP_BIT_EN_OPC_TAG BIT(7) | ||
38 | #define FSP_REG_OPTZ_XLO 0x34 | ||
39 | #define FSP_REG_OPTZ_XHI 0x35 | ||
40 | #define FSP_REG_OPTZ_YLO 0x36 | ||
41 | #define FSP_REG_OPTZ_YHI 0x37 | ||
42 | #define FSP_REG_SYSCTL5 0x40 | ||
43 | #define FSP_BIT_90_DEGREE BIT(0) | ||
44 | #define FSP_BIT_EN_MSID6 BIT(1) | ||
45 | #define FSP_BIT_EN_MSID7 BIT(2) | ||
46 | #define FSP_BIT_EN_MSID8 BIT(3) | ||
47 | #define FSP_BIT_EN_AUTO_MSID8 BIT(5) | ||
48 | #define FSP_BIT_EN_PKT_G0 BIT(6) | ||
49 | |||
50 | #define FSP_REG_ONPAD_CTL 0x43 | ||
51 | #define FSP_BIT_ONPAD_ENABLE BIT(0) | ||
52 | #define FSP_BIT_ONPAD_FBBB BIT(1) | ||
53 | #define FSP_BIT_FIX_VSCR BIT(3) | ||
54 | #define FSP_BIT_FIX_HSCR BIT(5) | ||
55 | #define FSP_BIT_DRAG_LOCK BIT(6) | ||
56 | |||
57 | /* Finger-sensing Pad packet formating related definitions */ | ||
58 | |||
59 | /* absolute packet type */ | ||
60 | #define FSP_PKT_TYPE_NORMAL (0x00) | ||
61 | #define FSP_PKT_TYPE_ABS (0x01) | ||
62 | #define FSP_PKT_TYPE_NOTIFY (0x02) | ||
63 | #define FSP_PKT_TYPE_NORMAL_OPC (0x03) | ||
64 | #define FSP_PKT_TYPE_SHIFT (6) | ||
65 | |||
66 | #ifdef __KERNEL__ | ||
67 | |||
68 | struct fsp_data { | ||
69 | unsigned char ver; /* hardware version */ | ||
70 | unsigned char rev; /* hardware revison */ | ||
71 | unsigned char buttons; /* Number of buttons */ | ||
72 | unsigned int flags; | ||
73 | #define FSPDRV_FLAG_EN_OPC (0x001) /* enable on-pad clicking */ | ||
74 | |||
75 | bool vscroll; /* Vertical scroll zone enabled */ | ||
76 | bool hscroll; /* Horizontal scroll zone enabled */ | ||
77 | |||
78 | unsigned char last_reg; /* Last register we requested read from */ | ||
79 | unsigned char last_val; | ||
80 | }; | ||
81 | |||
82 | #ifdef CONFIG_MOUSE_PS2_SENTELIC | ||
83 | extern int fsp_detect(struct psmouse *psmouse, bool set_properties); | ||
84 | extern int fsp_init(struct psmouse *psmouse); | ||
85 | #else | ||
86 | inline int fsp_detect(struct psmouse *psmouse, bool set_properties) | ||
87 | { | ||
88 | return -ENOSYS; | ||
89 | } | ||
90 | inline int fsp_init(struct psmouse *psmouse) | ||
91 | { | ||
92 | return -ENOSYS; | ||
93 | } | ||
94 | #endif | ||
95 | |||
96 | #endif /* __KERNEL__ */ | ||
97 | |||
98 | #endif /* !__SENTELIC_H */ | ||
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 19984bf06cad..b66ff1ac7dea 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -60,7 +60,7 @@ static int synaptics_mode_cmd(struct psmouse *psmouse, unsigned char mode) | |||
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | int synaptics_detect(struct psmouse *psmouse, int set_properties) | 63 | int synaptics_detect(struct psmouse *psmouse, bool set_properties) |
64 | { | 64 | { |
65 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 65 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
66 | unsigned char param[4]; | 66 | unsigned char param[4]; |
@@ -556,38 +556,38 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
556 | { | 556 | { |
557 | int i; | 557 | int i; |
558 | 558 | ||
559 | set_bit(EV_ABS, dev->evbit); | 559 | __set_bit(EV_ABS, dev->evbit); |
560 | input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); | 560 | input_set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0); |
561 | input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); | 561 | input_set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0); |
562 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 562 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
563 | set_bit(ABS_TOOL_WIDTH, dev->absbit); | 563 | __set_bit(ABS_TOOL_WIDTH, dev->absbit); |
564 | 564 | ||
565 | set_bit(EV_KEY, dev->evbit); | 565 | __set_bit(EV_KEY, dev->evbit); |
566 | set_bit(BTN_TOUCH, dev->keybit); | 566 | __set_bit(BTN_TOUCH, dev->keybit); |
567 | set_bit(BTN_TOOL_FINGER, dev->keybit); | 567 | __set_bit(BTN_TOOL_FINGER, dev->keybit); |
568 | set_bit(BTN_LEFT, dev->keybit); | 568 | __set_bit(BTN_LEFT, dev->keybit); |
569 | set_bit(BTN_RIGHT, dev->keybit); | 569 | __set_bit(BTN_RIGHT, dev->keybit); |
570 | 570 | ||
571 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { | 571 | if (SYN_CAP_MULTIFINGER(priv->capabilities)) { |
572 | set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); | 572 | __set_bit(BTN_TOOL_DOUBLETAP, dev->keybit); |
573 | set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); | 573 | __set_bit(BTN_TOOL_TRIPLETAP, dev->keybit); |
574 | } | 574 | } |
575 | 575 | ||
576 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) | 576 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) |
577 | set_bit(BTN_MIDDLE, dev->keybit); | 577 | __set_bit(BTN_MIDDLE, dev->keybit); |
578 | 578 | ||
579 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities) || | 579 | if (SYN_CAP_FOUR_BUTTON(priv->capabilities) || |
580 | SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { | 580 | SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { |
581 | set_bit(BTN_FORWARD, dev->keybit); | 581 | __set_bit(BTN_FORWARD, dev->keybit); |
582 | set_bit(BTN_BACK, dev->keybit); | 582 | __set_bit(BTN_BACK, dev->keybit); |
583 | } | 583 | } |
584 | 584 | ||
585 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) | 585 | for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) |
586 | set_bit(BTN_0 + i, dev->keybit); | 586 | __set_bit(BTN_0 + i, dev->keybit); |
587 | 587 | ||
588 | clear_bit(EV_REL, dev->evbit); | 588 | __clear_bit(EV_REL, dev->evbit); |
589 | clear_bit(REL_X, dev->relbit); | 589 | __clear_bit(REL_X, dev->relbit); |
590 | clear_bit(REL_Y, dev->relbit); | 590 | __clear_bit(REL_Y, dev->relbit); |
591 | 591 | ||
592 | dev->absres[ABS_X] = priv->x_res; | 592 | dev->absres[ABS_X] = priv->x_res; |
593 | dev->absres[ABS_Y] = priv->y_res; | 593 | dev->absres[ABS_Y] = priv->y_res; |
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 302382151752..871f6fe377f9 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
@@ -105,7 +105,7 @@ struct synaptics_data { | |||
105 | int scroll; | 105 | int scroll; |
106 | }; | 106 | }; |
107 | 107 | ||
108 | int synaptics_detect(struct psmouse *psmouse, int set_properties); | 108 | int synaptics_detect(struct psmouse *psmouse, bool set_properties); |
109 | int synaptics_init(struct psmouse *psmouse); | 109 | int synaptics_init(struct psmouse *psmouse); |
110 | void synaptics_reset(struct psmouse *psmouse); | 110 | void synaptics_reset(struct psmouse *psmouse); |
111 | 111 | ||
diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c index 3fadb2accac0..0308a0faa94d 100644 --- a/drivers/input/mouse/touchkit_ps2.c +++ b/drivers/input/mouse/touchkit_ps2.c | |||
@@ -67,7 +67,7 @@ static psmouse_ret_t touchkit_ps2_process_byte(struct psmouse *psmouse) | |||
67 | return PSMOUSE_FULL_PACKET; | 67 | return PSMOUSE_FULL_PACKET; |
68 | } | 68 | } |
69 | 69 | ||
70 | int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties) | 70 | int touchkit_ps2_detect(struct psmouse *psmouse, bool set_properties) |
71 | { | 71 | { |
72 | struct input_dev *dev = psmouse->dev; | 72 | struct input_dev *dev = psmouse->dev; |
73 | unsigned char param[3]; | 73 | unsigned char param[3]; |
@@ -86,7 +86,7 @@ int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties) | |||
86 | 86 | ||
87 | if (set_properties) { | 87 | if (set_properties) { |
88 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 88 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
89 | set_bit(BTN_TOUCH, dev->keybit); | 89 | __set_bit(BTN_TOUCH, dev->keybit); |
90 | input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0); | 90 | input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0); |
91 | input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0); | 91 | input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0); |
92 | 92 | ||
diff --git a/drivers/input/mouse/touchkit_ps2.h b/drivers/input/mouse/touchkit_ps2.h index 8a0dd3574aef..2efe9ea29d0c 100644 --- a/drivers/input/mouse/touchkit_ps2.h +++ b/drivers/input/mouse/touchkit_ps2.h | |||
@@ -13,10 +13,10 @@ | |||
13 | #define _TOUCHKIT_PS2_H | 13 | #define _TOUCHKIT_PS2_H |
14 | 14 | ||
15 | #ifdef CONFIG_MOUSE_PS2_TOUCHKIT | 15 | #ifdef CONFIG_MOUSE_PS2_TOUCHKIT |
16 | int touchkit_ps2_detect(struct psmouse *psmouse, int set_properties); | 16 | int touchkit_ps2_detect(struct psmouse *psmouse, bool set_properties); |
17 | #else | 17 | #else |
18 | static inline int touchkit_ps2_detect(struct psmouse *psmouse, | 18 | static inline int touchkit_ps2_detect(struct psmouse *psmouse, |
19 | int set_properties) | 19 | bool set_properties) |
20 | { | 20 | { |
21 | return -ENOSYS; | 21 | return -ENOSYS; |
22 | } | 22 | } |
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index e68c814c4361..e354362f2971 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
@@ -282,7 +282,7 @@ static int trackpoint_reconnect(struct psmouse *psmouse) | |||
282 | return 0; | 282 | return 0; |
283 | } | 283 | } |
284 | 284 | ||
285 | int trackpoint_detect(struct psmouse *psmouse, int set_properties) | 285 | int trackpoint_detect(struct psmouse *psmouse, bool set_properties) |
286 | { | 286 | { |
287 | struct trackpoint_data *priv; | 287 | struct trackpoint_data *priv; |
288 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 288 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h index c10a6e7d0101..e558a7096618 100644 --- a/drivers/input/mouse/trackpoint.h +++ b/drivers/input/mouse/trackpoint.h | |||
@@ -143,9 +143,9 @@ struct trackpoint_data | |||
143 | }; | 143 | }; |
144 | 144 | ||
145 | #ifdef CONFIG_MOUSE_PS2_TRACKPOINT | 145 | #ifdef CONFIG_MOUSE_PS2_TRACKPOINT |
146 | int trackpoint_detect(struct psmouse *psmouse, int set_properties); | 146 | int trackpoint_detect(struct psmouse *psmouse, bool set_properties); |
147 | #else | 147 | #else |
148 | inline int trackpoint_detect(struct psmouse *psmouse, int set_properties) | 148 | inline int trackpoint_detect(struct psmouse *psmouse, bool set_properties) |
149 | { | 149 | { |
150 | return -ENOSYS; | 150 | return -ENOSYS; |
151 | } | 151 | } |
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index 404eedd5ffa2..70111443678e 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c | |||
@@ -384,11 +384,11 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse) | |||
384 | printk (KERN_NOTICE "%s on %s: Forceing standard packet format, " | 384 | printk (KERN_NOTICE "%s on %s: Forceing standard packet format, " |
385 | "incremental streaming mode and 72 samples/sec\n", | 385 | "incremental streaming mode and 72 samples/sec\n", |
386 | mouse->name, mouse->phys); | 386 | mouse->name, mouse->phys); |
387 | mouse->serio->write (mouse->serio, 'S'); /* Standard format */ | 387 | serio_write (mouse->serio, 'S'); /* Standard format */ |
388 | mdelay (50); | 388 | mdelay (50); |
389 | mouse->serio->write (mouse->serio, 'R'); /* Incremental */ | 389 | serio_write (mouse->serio, 'R'); /* Incremental */ |
390 | mdelay (50); | 390 | mdelay (50); |
391 | mouse->serio->write (mouse->serio, 'L'); /* 72 samples/sec */ | 391 | serio_write (mouse->serio, 'L'); /* 72 samples/sec */ |
392 | } | 392 | } |
393 | 393 | ||
394 | static void | 394 | static void |
@@ -532,7 +532,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) | |||
532 | * Request selftest. Standard packet format and differential | 532 | * Request selftest. Standard packet format and differential |
533 | * mode will be requested after the device ID'ed successfully. | 533 | * mode will be requested after the device ID'ed successfully. |
534 | */ | 534 | */ |
535 | serio->write (serio, 'T'); /* Test */ | 535 | serio_write (serio, 'T'); /* Test */ |
536 | 536 | ||
537 | err = input_register_device (input_dev); | 537 | err = input_register_device (input_dev); |
538 | if (err) | 538 | if (err) |
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index 41fda8c67b1e..a6fb7a3dcc46 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c | |||
@@ -231,7 +231,7 @@ static int __init psif_probe(struct platform_device *pdev) | |||
231 | goto out_free_io; | 231 | goto out_free_io; |
232 | } | 232 | } |
233 | 233 | ||
234 | psif->regs = ioremap(regs->start, regs->end - regs->start + 1); | 234 | psif->regs = ioremap(regs->start, resource_size(regs)); |
235 | if (!psif->regs) { | 235 | if (!psif->regs) { |
236 | ret = -ENOMEM; | 236 | ret = -ENOMEM; |
237 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); | 237 | dev_dbg(&pdev->dev, "could not map I/O memory\n"); |
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c index b587e2d576ac..820e51673b26 100644 --- a/drivers/input/serio/hp_sdc_mlc.c +++ b/drivers/input/serio/hp_sdc_mlc.c | |||
@@ -296,7 +296,7 @@ static void hp_sdc_mlc_out(hil_mlc *mlc) | |||
296 | priv->tseq[3] = 0; | 296 | priv->tseq[3] = 0; |
297 | if (mlc->opacket & HIL_CTRL_APE) { | 297 | if (mlc->opacket & HIL_CTRL_APE) { |
298 | priv->tseq[3] |= HP_SDC_LPC_APE_IPF; | 298 | priv->tseq[3] |= HP_SDC_LPC_APE_IPF; |
299 | down_trylock(&mlc->csem); | 299 | BUG_ON(down_trylock(&mlc->csem)); |
300 | } | 300 | } |
301 | enqueue: | 301 | enqueue: |
302 | hp_sdc_enqueue_transaction(&priv->trans); | 302 | hp_sdc_enqueue_transaction(&priv->trans); |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index fb8a3cd3ffd0..a39bc4eb902b 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -78,6 +78,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
78 | }, | 78 | }, |
79 | }, | 79 | }, |
80 | { | 80 | { |
81 | .ident = "ASUS G1S", | ||
82 | .matches = { | ||
83 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), | ||
84 | DMI_MATCH(DMI_BOARD_NAME, "G1S"), | ||
85 | DMI_MATCH(DMI_BOARD_VERSION, "1.0"), | ||
86 | }, | ||
87 | }, | ||
88 | { | ||
81 | /* AUX LOOP command does not raise AUX IRQ */ | 89 | /* AUX LOOP command does not raise AUX IRQ */ |
82 | .ident = "ASUS P65UP5", | 90 | .ident = "ASUS P65UP5", |
83 | .matches = { | 91 | .matches = { |
@@ -374,6 +382,14 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
374 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"), | 382 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"), |
375 | }, | 383 | }, |
376 | }, | 384 | }, |
385 | { | ||
386 | .ident = "Acer Aspire 5536", | ||
387 | .matches = { | ||
388 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
389 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"), | ||
390 | DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), | ||
391 | }, | ||
392 | }, | ||
377 | { } | 393 | { } |
378 | }; | 394 | }; |
379 | 395 | ||
@@ -392,6 +408,34 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { | |||
392 | DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), | 408 | DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), |
393 | }, | 409 | }, |
394 | }, | 410 | }, |
411 | { | ||
412 | .ident = "Acer Aspire One 150", | ||
413 | .matches = { | ||
414 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
415 | DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"), | ||
416 | }, | ||
417 | }, | ||
418 | { | ||
419 | .ident = "Advent 4211", | ||
420 | .matches = { | ||
421 | DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"), | ||
422 | DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"), | ||
423 | }, | ||
424 | }, | ||
425 | { | ||
426 | .ident = "Medion Akoya Mini E1210", | ||
427 | .matches = { | ||
428 | DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), | ||
429 | DMI_MATCH(DMI_PRODUCT_NAME, "E1210"), | ||
430 | }, | ||
431 | }, | ||
432 | { | ||
433 | .ident = "Mivvy M310", | ||
434 | .matches = { | ||
435 | DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), | ||
436 | DMI_MATCH(DMI_PRODUCT_NAME, "N10"), | ||
437 | }, | ||
438 | }, | ||
395 | { } | 439 | { } |
396 | }; | 440 | }; |
397 | 441 | ||
@@ -413,6 +457,34 @@ static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { | |||
413 | }, | 457 | }, |
414 | { } | 458 | { } |
415 | }; | 459 | }; |
460 | |||
461 | static struct dmi_system_id __initdata i8042_dmi_laptop_table[] = { | ||
462 | { | ||
463 | .ident = "Portable", | ||
464 | .matches = { | ||
465 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ | ||
466 | }, | ||
467 | }, | ||
468 | { | ||
469 | .ident = "Laptop", | ||
470 | .matches = { | ||
471 | DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */ | ||
472 | }, | ||
473 | }, | ||
474 | { | ||
475 | .ident = "Notebook", | ||
476 | .matches = { | ||
477 | DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ | ||
478 | }, | ||
479 | }, | ||
480 | { | ||
481 | .ident = "Sub-Notebook", | ||
482 | .matches = { | ||
483 | DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */ | ||
484 | }, | ||
485 | }, | ||
486 | { } | ||
487 | }; | ||
416 | #endif | 488 | #endif |
417 | 489 | ||
418 | /* | 490 | /* |
@@ -486,9 +558,9 @@ static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = { | |||
486 | #ifdef CONFIG_PNP | 558 | #ifdef CONFIG_PNP |
487 | #include <linux/pnp.h> | 559 | #include <linux/pnp.h> |
488 | 560 | ||
489 | static int i8042_pnp_kbd_registered; | 561 | static bool i8042_pnp_kbd_registered; |
490 | static unsigned int i8042_pnp_kbd_devices; | 562 | static unsigned int i8042_pnp_kbd_devices; |
491 | static int i8042_pnp_aux_registered; | 563 | static bool i8042_pnp_aux_registered; |
492 | static unsigned int i8042_pnp_aux_devices; | 564 | static unsigned int i8042_pnp_aux_devices; |
493 | 565 | ||
494 | static int i8042_pnp_command_reg; | 566 | static int i8042_pnp_command_reg; |
@@ -576,12 +648,12 @@ static struct pnp_driver i8042_pnp_aux_driver = { | |||
576 | static void i8042_pnp_exit(void) | 648 | static void i8042_pnp_exit(void) |
577 | { | 649 | { |
578 | if (i8042_pnp_kbd_registered) { | 650 | if (i8042_pnp_kbd_registered) { |
579 | i8042_pnp_kbd_registered = 0; | 651 | i8042_pnp_kbd_registered = false; |
580 | pnp_unregister_driver(&i8042_pnp_kbd_driver); | 652 | pnp_unregister_driver(&i8042_pnp_kbd_driver); |
581 | } | 653 | } |
582 | 654 | ||
583 | if (i8042_pnp_aux_registered) { | 655 | if (i8042_pnp_aux_registered) { |
584 | i8042_pnp_aux_registered = 0; | 656 | i8042_pnp_aux_registered = false; |
585 | pnp_unregister_driver(&i8042_pnp_aux_driver); | 657 | pnp_unregister_driver(&i8042_pnp_aux_driver); |
586 | } | 658 | } |
587 | } | 659 | } |
@@ -589,12 +661,12 @@ static void i8042_pnp_exit(void) | |||
589 | static int __init i8042_pnp_init(void) | 661 | static int __init i8042_pnp_init(void) |
590 | { | 662 | { |
591 | char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 }; | 663 | char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 }; |
592 | int pnp_data_busted = 0; | 664 | int pnp_data_busted = false; |
593 | int err; | 665 | int err; |
594 | 666 | ||
595 | #ifdef CONFIG_X86 | 667 | #ifdef CONFIG_X86 |
596 | if (dmi_check_system(i8042_dmi_nopnp_table)) | 668 | if (dmi_check_system(i8042_dmi_nopnp_table)) |
597 | i8042_nopnp = 1; | 669 | i8042_nopnp = true; |
598 | #endif | 670 | #endif |
599 | 671 | ||
600 | if (i8042_nopnp) { | 672 | if (i8042_nopnp) { |
@@ -604,11 +676,11 @@ static int __init i8042_pnp_init(void) | |||
604 | 676 | ||
605 | err = pnp_register_driver(&i8042_pnp_kbd_driver); | 677 | err = pnp_register_driver(&i8042_pnp_kbd_driver); |
606 | if (!err) | 678 | if (!err) |
607 | i8042_pnp_kbd_registered = 1; | 679 | i8042_pnp_kbd_registered = true; |
608 | 680 | ||
609 | err = pnp_register_driver(&i8042_pnp_aux_driver); | 681 | err = pnp_register_driver(&i8042_pnp_aux_driver); |
610 | if (!err) | 682 | if (!err) |
611 | i8042_pnp_aux_registered = 1; | 683 | i8042_pnp_aux_registered = true; |
612 | 684 | ||
613 | if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) { | 685 | if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) { |
614 | i8042_pnp_exit(); | 686 | i8042_pnp_exit(); |
@@ -636,9 +708,9 @@ static int __init i8042_pnp_init(void) | |||
636 | 708 | ||
637 | #if defined(__ia64__) | 709 | #if defined(__ia64__) |
638 | if (!i8042_pnp_kbd_devices) | 710 | if (!i8042_pnp_kbd_devices) |
639 | i8042_nokbd = 1; | 711 | i8042_nokbd = true; |
640 | if (!i8042_pnp_aux_devices) | 712 | if (!i8042_pnp_aux_devices) |
641 | i8042_noaux = 1; | 713 | i8042_noaux = true; |
642 | #endif | 714 | #endif |
643 | 715 | ||
644 | if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && | 716 | if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) && |
@@ -649,7 +721,7 @@ static int __init i8042_pnp_init(void) | |||
649 | "using default %#x\n", | 721 | "using default %#x\n", |
650 | i8042_pnp_data_reg, i8042_data_reg); | 722 | i8042_pnp_data_reg, i8042_data_reg); |
651 | i8042_pnp_data_reg = i8042_data_reg; | 723 | i8042_pnp_data_reg = i8042_data_reg; |
652 | pnp_data_busted = 1; | 724 | pnp_data_busted = true; |
653 | } | 725 | } |
654 | 726 | ||
655 | if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) && | 727 | if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) && |
@@ -660,7 +732,7 @@ static int __init i8042_pnp_init(void) | |||
660 | "using default %#x\n", | 732 | "using default %#x\n", |
661 | i8042_pnp_command_reg, i8042_command_reg); | 733 | i8042_pnp_command_reg, i8042_command_reg); |
662 | i8042_pnp_command_reg = i8042_command_reg; | 734 | i8042_pnp_command_reg = i8042_command_reg; |
663 | pnp_data_busted = 1; | 735 | pnp_data_busted = true; |
664 | } | 736 | } |
665 | 737 | ||
666 | if (!i8042_nokbd && !i8042_pnp_kbd_irq) { | 738 | if (!i8042_nokbd && !i8042_pnp_kbd_irq) { |
@@ -668,7 +740,7 @@ static int __init i8042_pnp_init(void) | |||
668 | "PNP: PS/2 controller doesn't have KBD irq; " | 740 | "PNP: PS/2 controller doesn't have KBD irq; " |
669 | "using default %d\n", i8042_kbd_irq); | 741 | "using default %d\n", i8042_kbd_irq); |
670 | i8042_pnp_kbd_irq = i8042_kbd_irq; | 742 | i8042_pnp_kbd_irq = i8042_kbd_irq; |
671 | pnp_data_busted = 1; | 743 | pnp_data_busted = true; |
672 | } | 744 | } |
673 | 745 | ||
674 | if (!i8042_noaux && !i8042_pnp_aux_irq) { | 746 | if (!i8042_noaux && !i8042_pnp_aux_irq) { |
@@ -677,7 +749,7 @@ static int __init i8042_pnp_init(void) | |||
677 | "PNP: PS/2 appears to have AUX port disabled, " | 749 | "PNP: PS/2 appears to have AUX port disabled, " |
678 | "if this is incorrect please boot with " | 750 | "if this is incorrect please boot with " |
679 | "i8042.nopnp\n"); | 751 | "i8042.nopnp\n"); |
680 | i8042_noaux = 1; | 752 | i8042_noaux = true; |
681 | } else { | 753 | } else { |
682 | printk(KERN_WARNING | 754 | printk(KERN_WARNING |
683 | "PNP: PS/2 controller doesn't have AUX irq; " | 755 | "PNP: PS/2 controller doesn't have AUX irq; " |
@@ -691,6 +763,11 @@ static int __init i8042_pnp_init(void) | |||
691 | i8042_kbd_irq = i8042_pnp_kbd_irq; | 763 | i8042_kbd_irq = i8042_pnp_kbd_irq; |
692 | i8042_aux_irq = i8042_pnp_aux_irq; | 764 | i8042_aux_irq = i8042_pnp_aux_irq; |
693 | 765 | ||
766 | #ifdef CONFIG_X86 | ||
767 | i8042_bypass_aux_irq_test = !pnp_data_busted && | ||
768 | dmi_check_system(i8042_dmi_laptop_table); | ||
769 | #endif | ||
770 | |||
694 | return 0; | 771 | return 0; |
695 | } | 772 | } |
696 | 773 | ||
@@ -719,21 +796,21 @@ static int __init i8042_platform_init(void) | |||
719 | return retval; | 796 | return retval; |
720 | 797 | ||
721 | #if defined(__ia64__) | 798 | #if defined(__ia64__) |
722 | i8042_reset = 1; | 799 | i8042_reset = true; |
723 | #endif | 800 | #endif |
724 | 801 | ||
725 | #ifdef CONFIG_X86 | 802 | #ifdef CONFIG_X86 |
726 | if (dmi_check_system(i8042_dmi_reset_table)) | 803 | if (dmi_check_system(i8042_dmi_reset_table)) |
727 | i8042_reset = 1; | 804 | i8042_reset = true; |
728 | 805 | ||
729 | if (dmi_check_system(i8042_dmi_noloop_table)) | 806 | if (dmi_check_system(i8042_dmi_noloop_table)) |
730 | i8042_noloop = 1; | 807 | i8042_noloop = true; |
731 | 808 | ||
732 | if (dmi_check_system(i8042_dmi_nomux_table)) | 809 | if (dmi_check_system(i8042_dmi_nomux_table)) |
733 | i8042_nomux = 1; | 810 | i8042_nomux = true; |
734 | 811 | ||
735 | if (dmi_check_system(i8042_dmi_dritek_table)) | 812 | if (dmi_check_system(i8042_dmi_dritek_table)) |
736 | i8042_dritek = 1; | 813 | i8042_dritek = true; |
737 | #endif /* CONFIG_X86 */ | 814 | #endif /* CONFIG_X86 */ |
738 | 815 | ||
739 | return retval; | 816 | return retval; |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index f919bf57293c..eb3ff94af58c 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -28,35 +28,35 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | |||
28 | MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); | 28 | MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver"); |
29 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
30 | 30 | ||
31 | static unsigned int i8042_nokbd; | 31 | static bool i8042_nokbd; |
32 | module_param_named(nokbd, i8042_nokbd, bool, 0); | 32 | module_param_named(nokbd, i8042_nokbd, bool, 0); |
33 | MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port."); | 33 | MODULE_PARM_DESC(nokbd, "Do not probe or use KBD port."); |
34 | 34 | ||
35 | static unsigned int i8042_noaux; | 35 | static bool i8042_noaux; |
36 | module_param_named(noaux, i8042_noaux, bool, 0); | 36 | module_param_named(noaux, i8042_noaux, bool, 0); |
37 | MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); | 37 | MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); |
38 | 38 | ||
39 | static unsigned int i8042_nomux; | 39 | static bool i8042_nomux; |
40 | module_param_named(nomux, i8042_nomux, bool, 0); | 40 | module_param_named(nomux, i8042_nomux, bool, 0); |
41 | MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present."); | 41 | MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present."); |
42 | 42 | ||
43 | static unsigned int i8042_unlock; | 43 | static bool i8042_unlock; |
44 | module_param_named(unlock, i8042_unlock, bool, 0); | 44 | module_param_named(unlock, i8042_unlock, bool, 0); |
45 | MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); | 45 | MODULE_PARM_DESC(unlock, "Ignore keyboard lock."); |
46 | 46 | ||
47 | static unsigned int i8042_reset; | 47 | static bool i8042_reset; |
48 | module_param_named(reset, i8042_reset, bool, 0); | 48 | module_param_named(reset, i8042_reset, bool, 0); |
49 | MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); | 49 | MODULE_PARM_DESC(reset, "Reset controller during init and cleanup."); |
50 | 50 | ||
51 | static unsigned int i8042_direct; | 51 | static bool i8042_direct; |
52 | module_param_named(direct, i8042_direct, bool, 0); | 52 | module_param_named(direct, i8042_direct, bool, 0); |
53 | MODULE_PARM_DESC(direct, "Put keyboard port into non-translated mode."); | 53 | MODULE_PARM_DESC(direct, "Put keyboard port into non-translated mode."); |
54 | 54 | ||
55 | static unsigned int i8042_dumbkbd; | 55 | static bool i8042_dumbkbd; |
56 | module_param_named(dumbkbd, i8042_dumbkbd, bool, 0); | 56 | module_param_named(dumbkbd, i8042_dumbkbd, bool, 0); |
57 | MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard"); | 57 | MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard"); |
58 | 58 | ||
59 | static unsigned int i8042_noloop; | 59 | static bool i8042_noloop; |
60 | module_param_named(noloop, i8042_noloop, bool, 0); | 60 | module_param_named(noloop, i8042_noloop, bool, 0); |
61 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); | 61 | MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port"); |
62 | 62 | ||
@@ -65,24 +65,26 @@ module_param_named(panicblink, i8042_blink_frequency, uint, 0600); | |||
65 | MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); | 65 | MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics"); |
66 | 66 | ||
67 | #ifdef CONFIG_X86 | 67 | #ifdef CONFIG_X86 |
68 | static unsigned int i8042_dritek; | 68 | static bool i8042_dritek; |
69 | module_param_named(dritek, i8042_dritek, bool, 0); | 69 | module_param_named(dritek, i8042_dritek, bool, 0); |
70 | MODULE_PARM_DESC(dritek, "Force enable the Dritek keyboard extension"); | 70 | MODULE_PARM_DESC(dritek, "Force enable the Dritek keyboard extension"); |
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | #ifdef CONFIG_PNP | 73 | #ifdef CONFIG_PNP |
74 | static int i8042_nopnp; | 74 | static bool i8042_nopnp; |
75 | module_param_named(nopnp, i8042_nopnp, bool, 0); | 75 | module_param_named(nopnp, i8042_nopnp, bool, 0); |
76 | MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); | 76 | MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); |
77 | #endif | 77 | #endif |
78 | 78 | ||
79 | #define DEBUG | 79 | #define DEBUG |
80 | #ifdef DEBUG | 80 | #ifdef DEBUG |
81 | static int i8042_debug; | 81 | static bool i8042_debug; |
82 | module_param_named(debug, i8042_debug, bool, 0600); | 82 | module_param_named(debug, i8042_debug, bool, 0600); |
83 | MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); | 83 | MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off"); |
84 | #endif | 84 | #endif |
85 | 85 | ||
86 | static bool i8042_bypass_aux_irq_test; | ||
87 | |||
86 | #include "i8042.h" | 88 | #include "i8042.h" |
87 | 89 | ||
88 | static DEFINE_SPINLOCK(i8042_lock); | 90 | static DEFINE_SPINLOCK(i8042_lock); |
@@ -90,7 +92,7 @@ static DEFINE_SPINLOCK(i8042_lock); | |||
90 | struct i8042_port { | 92 | struct i8042_port { |
91 | struct serio *serio; | 93 | struct serio *serio; |
92 | int irq; | 94 | int irq; |
93 | unsigned char exists; | 95 | bool exists; |
94 | signed char mux; | 96 | signed char mux; |
95 | }; | 97 | }; |
96 | 98 | ||
@@ -103,9 +105,9 @@ static struct i8042_port i8042_ports[I8042_NUM_PORTS]; | |||
103 | 105 | ||
104 | static unsigned char i8042_initial_ctr; | 106 | static unsigned char i8042_initial_ctr; |
105 | static unsigned char i8042_ctr; | 107 | static unsigned char i8042_ctr; |
106 | static unsigned char i8042_mux_present; | 108 | static bool i8042_mux_present; |
107 | static unsigned char i8042_kbd_irq_registered; | 109 | static bool i8042_kbd_irq_registered; |
108 | static unsigned char i8042_aux_irq_registered; | 110 | static bool i8042_aux_irq_registered; |
109 | static unsigned char i8042_suppress_kbd_ack; | 111 | static unsigned char i8042_suppress_kbd_ack; |
110 | static struct platform_device *i8042_platform_device; | 112 | static struct platform_device *i8042_platform_device; |
111 | 113 | ||
@@ -262,6 +264,49 @@ static int i8042_aux_write(struct serio *serio, unsigned char c) | |||
262 | I8042_CMD_MUX_SEND + port->mux); | 264 | I8042_CMD_MUX_SEND + port->mux); |
263 | } | 265 | } |
264 | 266 | ||
267 | |||
268 | /* | ||
269 | * i8042_aux_close attempts to clear AUX or KBD port state by disabling | ||
270 | * and then re-enabling it. | ||
271 | */ | ||
272 | |||
273 | static void i8042_port_close(struct serio *serio) | ||
274 | { | ||
275 | int irq_bit; | ||
276 | int disable_bit; | ||
277 | const char *port_name; | ||
278 | |||
279 | if (serio == i8042_ports[I8042_AUX_PORT_NO].serio) { | ||
280 | irq_bit = I8042_CTR_AUXINT; | ||
281 | disable_bit = I8042_CTR_AUXDIS; | ||
282 | port_name = "AUX"; | ||
283 | } else { | ||
284 | irq_bit = I8042_CTR_KBDINT; | ||
285 | disable_bit = I8042_CTR_KBDDIS; | ||
286 | port_name = "KBD"; | ||
287 | } | ||
288 | |||
289 | i8042_ctr &= ~irq_bit; | ||
290 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | ||
291 | printk(KERN_WARNING | ||
292 | "i8042.c: Can't write CTR while closing %s port.\n", | ||
293 | port_name); | ||
294 | |||
295 | udelay(50); | ||
296 | |||
297 | i8042_ctr &= ~disable_bit; | ||
298 | i8042_ctr |= irq_bit; | ||
299 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | ||
300 | printk(KERN_ERR "i8042.c: Can't reactivate %s port.\n", | ||
301 | port_name); | ||
302 | |||
303 | /* | ||
304 | * See if there is any data appeared while we were messing with | ||
305 | * port state. | ||
306 | */ | ||
307 | i8042_interrupt(0, NULL); | ||
308 | } | ||
309 | |||
265 | /* | 310 | /* |
266 | * i8042_start() is called by serio core when port is about to finish | 311 | * i8042_start() is called by serio core when port is about to finish |
267 | * registering. It will mark port as existing so i8042_interrupt can | 312 | * registering. It will mark port as existing so i8042_interrupt can |
@@ -271,7 +316,7 @@ static int i8042_start(struct serio *serio) | |||
271 | { | 316 | { |
272 | struct i8042_port *port = serio->port_data; | 317 | struct i8042_port *port = serio->port_data; |
273 | 318 | ||
274 | port->exists = 1; | 319 | port->exists = true; |
275 | mb(); | 320 | mb(); |
276 | return 0; | 321 | return 0; |
277 | } | 322 | } |
@@ -285,7 +330,7 @@ static void i8042_stop(struct serio *serio) | |||
285 | { | 330 | { |
286 | struct i8042_port *port = serio->port_data; | 331 | struct i8042_port *port = serio->port_data; |
287 | 332 | ||
288 | port->exists = 0; | 333 | port->exists = false; |
289 | 334 | ||
290 | /* | 335 | /* |
291 | * We synchronize with both AUX and KBD IRQs because there is | 336 | * We synchronize with both AUX and KBD IRQs because there is |
@@ -391,7 +436,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
391 | } | 436 | } |
392 | 437 | ||
393 | /* | 438 | /* |
394 | * i8042_enable_kbd_port enables keybaord port on chip | 439 | * i8042_enable_kbd_port enables keyboard port on chip |
395 | */ | 440 | */ |
396 | 441 | ||
397 | static int i8042_enable_kbd_port(void) | 442 | static int i8042_enable_kbd_port(void) |
@@ -447,14 +492,15 @@ static int i8042_enable_mux_ports(void) | |||
447 | } | 492 | } |
448 | 493 | ||
449 | /* | 494 | /* |
450 | * i8042_set_mux_mode checks whether the controller has an active | 495 | * i8042_set_mux_mode checks whether the controller has an |
451 | * multiplexor and puts the chip into Multiplexed (1) or Legacy (0) mode. | 496 | * active multiplexor and puts the chip into Multiplexed (true) |
497 | * or Legacy (false) mode. | ||
452 | */ | 498 | */ |
453 | 499 | ||
454 | static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | 500 | static int i8042_set_mux_mode(bool multiplex, unsigned char *mux_version) |
455 | { | 501 | { |
456 | 502 | ||
457 | unsigned char param; | 503 | unsigned char param, val; |
458 | /* | 504 | /* |
459 | * Get rid of bytes in the queue. | 505 | * Get rid of bytes in the queue. |
460 | */ | 506 | */ |
@@ -466,14 +512,21 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | |||
466 | * mouse interface, the last should be version. | 512 | * mouse interface, the last should be version. |
467 | */ | 513 | */ |
468 | 514 | ||
469 | param = 0xf0; | 515 | param = val = 0xf0; |
470 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != 0xf0) | 516 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) |
471 | return -1; | 517 | return -1; |
472 | param = mode ? 0x56 : 0xf6; | 518 | param = val = multiplex ? 0x56 : 0xf6; |
473 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != (mode ? 0x56 : 0xf6)) | 519 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param != val) |
474 | return -1; | 520 | return -1; |
475 | param = mode ? 0xa4 : 0xa5; | 521 | param = val = multiplex ? 0xa4 : 0xa5; |
476 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == (mode ? 0xa4 : 0xa5)) | 522 | if (i8042_command(¶m, I8042_CMD_AUX_LOOP) || param == val) |
523 | return -1; | ||
524 | |||
525 | /* | ||
526 | * Workaround for interference with USB Legacy emulation | ||
527 | * that causes a v10.12 MUX to be found. | ||
528 | */ | ||
529 | if (param == 0xac) | ||
477 | return -1; | 530 | return -1; |
478 | 531 | ||
479 | if (mux_version) | 532 | if (mux_version) |
@@ -488,18 +541,11 @@ static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version) | |||
488 | * LCS/Telegraphics. | 541 | * LCS/Telegraphics. |
489 | */ | 542 | */ |
490 | 543 | ||
491 | static int __devinit i8042_check_mux(void) | 544 | static int __init i8042_check_mux(void) |
492 | { | 545 | { |
493 | unsigned char mux_version; | 546 | unsigned char mux_version; |
494 | 547 | ||
495 | if (i8042_set_mux_mode(1, &mux_version)) | 548 | if (i8042_set_mux_mode(true, &mux_version)) |
496 | return -1; | ||
497 | |||
498 | /* | ||
499 | * Workaround for interference with USB Legacy emulation | ||
500 | * that causes a v10.12 MUX to be found. | ||
501 | */ | ||
502 | if (mux_version == 0xAC) | ||
503 | return -1; | 549 | return -1; |
504 | 550 | ||
505 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", | 551 | printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n", |
@@ -516,7 +562,7 @@ static int __devinit i8042_check_mux(void) | |||
516 | return -EIO; | 562 | return -EIO; |
517 | } | 563 | } |
518 | 564 | ||
519 | i8042_mux_present = 1; | 565 | i8042_mux_present = true; |
520 | 566 | ||
521 | return 0; | 567 | return 0; |
522 | } | 568 | } |
@@ -524,10 +570,10 @@ static int __devinit i8042_check_mux(void) | |||
524 | /* | 570 | /* |
525 | * The following is used to test AUX IRQ delivery. | 571 | * The following is used to test AUX IRQ delivery. |
526 | */ | 572 | */ |
527 | static struct completion i8042_aux_irq_delivered __devinitdata; | 573 | static struct completion i8042_aux_irq_delivered __initdata; |
528 | static int i8042_irq_being_tested __devinitdata; | 574 | static bool i8042_irq_being_tested __initdata; |
529 | 575 | ||
530 | static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) | 576 | static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id) |
531 | { | 577 | { |
532 | unsigned long flags; | 578 | unsigned long flags; |
533 | unsigned char str, data; | 579 | unsigned char str, data; |
@@ -552,7 +598,7 @@ static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) | |||
552 | * verifies success by readinng CTR. Used when testing for presence of AUX | 598 | * verifies success by readinng CTR. Used when testing for presence of AUX |
553 | * port. | 599 | * port. |
554 | */ | 600 | */ |
555 | static int __devinit i8042_toggle_aux(int on) | 601 | static int __init i8042_toggle_aux(bool on) |
556 | { | 602 | { |
557 | unsigned char param; | 603 | unsigned char param; |
558 | int i; | 604 | int i; |
@@ -580,11 +626,11 @@ static int __devinit i8042_toggle_aux(int on) | |||
580 | * the presence of an AUX interface. | 626 | * the presence of an AUX interface. |
581 | */ | 627 | */ |
582 | 628 | ||
583 | static int __devinit i8042_check_aux(void) | 629 | static int __init i8042_check_aux(void) |
584 | { | 630 | { |
585 | int retval = -1; | 631 | int retval = -1; |
586 | int irq_registered = 0; | 632 | bool irq_registered = false; |
587 | int aux_loop_broken = 0; | 633 | bool aux_loop_broken = false; |
588 | unsigned long flags; | 634 | unsigned long flags; |
589 | unsigned char param; | 635 | unsigned char param; |
590 | 636 | ||
@@ -621,19 +667,19 @@ static int __devinit i8042_check_aux(void) | |||
621 | * mark it as broken | 667 | * mark it as broken |
622 | */ | 668 | */ |
623 | if (!retval) | 669 | if (!retval) |
624 | aux_loop_broken = 1; | 670 | aux_loop_broken = true; |
625 | } | 671 | } |
626 | 672 | ||
627 | /* | 673 | /* |
628 | * Bit assignment test - filters out PS/2 i8042's in AT mode | 674 | * Bit assignment test - filters out PS/2 i8042's in AT mode |
629 | */ | 675 | */ |
630 | 676 | ||
631 | if (i8042_toggle_aux(0)) { | 677 | if (i8042_toggle_aux(false)) { |
632 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); | 678 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); |
633 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); | 679 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); |
634 | } | 680 | } |
635 | 681 | ||
636 | if (i8042_toggle_aux(1)) | 682 | if (i8042_toggle_aux(true)) |
637 | return -1; | 683 | return -1; |
638 | 684 | ||
639 | /* | 685 | /* |
@@ -641,7 +687,7 @@ static int __devinit i8042_check_aux(void) | |||
641 | * used it for a PCI card or somethig else. | 687 | * used it for a PCI card or somethig else. |
642 | */ | 688 | */ |
643 | 689 | ||
644 | if (i8042_noloop || aux_loop_broken) { | 690 | if (i8042_noloop || i8042_bypass_aux_irq_test || aux_loop_broken) { |
645 | /* | 691 | /* |
646 | * Without LOOP command we can't test AUX IRQ delivery. Assume the port | 692 | * Without LOOP command we can't test AUX IRQ delivery. Assume the port |
647 | * is working and hope we are right. | 693 | * is working and hope we are right. |
@@ -654,7 +700,7 @@ static int __devinit i8042_check_aux(void) | |||
654 | "i8042", i8042_platform_device)) | 700 | "i8042", i8042_platform_device)) |
655 | goto out; | 701 | goto out; |
656 | 702 | ||
657 | irq_registered = 1; | 703 | irq_registered = true; |
658 | 704 | ||
659 | if (i8042_enable_aux_port()) | 705 | if (i8042_enable_aux_port()) |
660 | goto out; | 706 | goto out; |
@@ -662,7 +708,7 @@ static int __devinit i8042_check_aux(void) | |||
662 | spin_lock_irqsave(&i8042_lock, flags); | 708 | spin_lock_irqsave(&i8042_lock, flags); |
663 | 709 | ||
664 | init_completion(&i8042_aux_irq_delivered); | 710 | init_completion(&i8042_aux_irq_delivered); |
665 | i8042_irq_being_tested = 1; | 711 | i8042_irq_being_tested = true; |
666 | 712 | ||
667 | param = 0xa5; | 713 | param = 0xa5; |
668 | retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); | 714 | retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); |
@@ -799,7 +845,7 @@ static int i8042_controller_init(void) | |||
799 | */ | 845 | */ |
800 | 846 | ||
801 | if (~i8042_ctr & I8042_CTR_XLATE) | 847 | if (~i8042_ctr & I8042_CTR_XLATE) |
802 | i8042_direct = 1; | 848 | i8042_direct = true; |
803 | 849 | ||
804 | /* | 850 | /* |
805 | * Set nontranslated mode for the kbd interface if requested by an option. | 851 | * Set nontranslated mode for the kbd interface if requested by an option. |
@@ -839,12 +885,15 @@ static void i8042_controller_reset(void) | |||
839 | i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; | 885 | i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; |
840 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); | 886 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); |
841 | 887 | ||
888 | if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) | ||
889 | printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); | ||
890 | |||
842 | /* | 891 | /* |
843 | * Disable MUX mode if present. | 892 | * Disable MUX mode if present. |
844 | */ | 893 | */ |
845 | 894 | ||
846 | if (i8042_mux_present) | 895 | if (i8042_mux_present) |
847 | i8042_set_mux_mode(0, NULL); | 896 | i8042_set_mux_mode(false, NULL); |
848 | 897 | ||
849 | /* | 898 | /* |
850 | * Reset the controller if requested. | 899 | * Reset the controller if requested. |
@@ -923,40 +972,27 @@ static void i8042_dritek_enable(void) | |||
923 | 972 | ||
924 | #ifdef CONFIG_PM | 973 | #ifdef CONFIG_PM |
925 | 974 | ||
926 | static bool i8042_suspended; | ||
927 | |||
928 | /* | 975 | /* |
929 | * Here we try to restore the original BIOS settings. We only want to | 976 | * Here we try to restore the original BIOS settings to avoid |
930 | * do that once, when we really suspend, not when we taking memory | 977 | * upsetting it. |
931 | * snapshot for swsusp (in this case we'll perform required cleanup | ||
932 | * as part of shutdown process). | ||
933 | */ | 978 | */ |
934 | 979 | ||
935 | static int i8042_suspend(struct platform_device *dev, pm_message_t state) | 980 | static int i8042_pm_reset(struct device *dev) |
936 | { | 981 | { |
937 | if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) { | 982 | i8042_controller_reset(); |
938 | i8042_controller_reset(); | ||
939 | i8042_suspended = true; | ||
940 | } | ||
941 | 983 | ||
942 | return 0; | 984 | return 0; |
943 | } | 985 | } |
944 | 986 | ||
945 | |||
946 | /* | 987 | /* |
947 | * Here we try to reset everything back to a state in which suspended | 988 | * Here we try to reset everything back to a state we had |
989 | * before suspending. | ||
948 | */ | 990 | */ |
949 | 991 | ||
950 | static int i8042_resume(struct platform_device *dev) | 992 | static int i8042_pm_restore(struct device *dev) |
951 | { | 993 | { |
952 | int error; | 994 | int error; |
953 | 995 | ||
954 | /* | ||
955 | * Do not bother with restoring state if we haven't suspened yet | ||
956 | */ | ||
957 | if (!i8042_suspended) | ||
958 | return 0; | ||
959 | |||
960 | error = i8042_controller_check(); | 996 | error = i8042_controller_check(); |
961 | if (error) | 997 | if (error) |
962 | return error; | 998 | return error; |
@@ -990,7 +1026,7 @@ static int i8042_resume(struct platform_device *dev) | |||
990 | #endif | 1026 | #endif |
991 | 1027 | ||
992 | if (i8042_mux_present) { | 1028 | if (i8042_mux_present) { |
993 | if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports()) | 1029 | if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) |
994 | printk(KERN_WARNING | 1030 | printk(KERN_WARNING |
995 | "i8042: failed to resume active multiplexor, " | 1031 | "i8042: failed to resume active multiplexor, " |
996 | "mouse won't work.\n"); | 1032 | "mouse won't work.\n"); |
@@ -1000,11 +1036,18 @@ static int i8042_resume(struct platform_device *dev) | |||
1000 | if (i8042_ports[I8042_KBD_PORT_NO].serio) | 1036 | if (i8042_ports[I8042_KBD_PORT_NO].serio) |
1001 | i8042_enable_kbd_port(); | 1037 | i8042_enable_kbd_port(); |
1002 | 1038 | ||
1003 | i8042_suspended = false; | ||
1004 | i8042_interrupt(0, NULL); | 1039 | i8042_interrupt(0, NULL); |
1005 | 1040 | ||
1006 | return 0; | 1041 | return 0; |
1007 | } | 1042 | } |
1043 | |||
1044 | static const struct dev_pm_ops i8042_pm_ops = { | ||
1045 | .suspend = i8042_pm_reset, | ||
1046 | .resume = i8042_pm_restore, | ||
1047 | .poweroff = i8042_pm_reset, | ||
1048 | .restore = i8042_pm_restore, | ||
1049 | }; | ||
1050 | |||
1008 | #endif /* CONFIG_PM */ | 1051 | #endif /* CONFIG_PM */ |
1009 | 1052 | ||
1010 | /* | 1053 | /* |
@@ -1017,7 +1060,7 @@ static void i8042_shutdown(struct platform_device *dev) | |||
1017 | i8042_controller_reset(); | 1060 | i8042_controller_reset(); |
1018 | } | 1061 | } |
1019 | 1062 | ||
1020 | static int __devinit i8042_create_kbd_port(void) | 1063 | static int __init i8042_create_kbd_port(void) |
1021 | { | 1064 | { |
1022 | struct serio *serio; | 1065 | struct serio *serio; |
1023 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; | 1066 | struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; |
@@ -1030,6 +1073,7 @@ static int __devinit i8042_create_kbd_port(void) | |||
1030 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; | 1073 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; |
1031 | serio->start = i8042_start; | 1074 | serio->start = i8042_start; |
1032 | serio->stop = i8042_stop; | 1075 | serio->stop = i8042_stop; |
1076 | serio->close = i8042_port_close; | ||
1033 | serio->port_data = port; | 1077 | serio->port_data = port; |
1034 | serio->dev.parent = &i8042_platform_device->dev; | 1078 | serio->dev.parent = &i8042_platform_device->dev; |
1035 | strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); | 1079 | strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); |
@@ -1041,7 +1085,7 @@ static int __devinit i8042_create_kbd_port(void) | |||
1041 | return 0; | 1085 | return 0; |
1042 | } | 1086 | } |
1043 | 1087 | ||
1044 | static int __devinit i8042_create_aux_port(int idx) | 1088 | static int __init i8042_create_aux_port(int idx) |
1045 | { | 1089 | { |
1046 | struct serio *serio; | 1090 | struct serio *serio; |
1047 | int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; | 1091 | int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; |
@@ -1060,6 +1104,7 @@ static int __devinit i8042_create_aux_port(int idx) | |||
1060 | if (idx < 0) { | 1104 | if (idx < 0) { |
1061 | strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); | 1105 | strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); |
1062 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | 1106 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); |
1107 | serio->close = i8042_port_close; | ||
1063 | } else { | 1108 | } else { |
1064 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); | 1109 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); |
1065 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); | 1110 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); |
@@ -1072,13 +1117,13 @@ static int __devinit i8042_create_aux_port(int idx) | |||
1072 | return 0; | 1117 | return 0; |
1073 | } | 1118 | } |
1074 | 1119 | ||
1075 | static void __devinit i8042_free_kbd_port(void) | 1120 | static void __init i8042_free_kbd_port(void) |
1076 | { | 1121 | { |
1077 | kfree(i8042_ports[I8042_KBD_PORT_NO].serio); | 1122 | kfree(i8042_ports[I8042_KBD_PORT_NO].serio); |
1078 | i8042_ports[I8042_KBD_PORT_NO].serio = NULL; | 1123 | i8042_ports[I8042_KBD_PORT_NO].serio = NULL; |
1079 | } | 1124 | } |
1080 | 1125 | ||
1081 | static void __devinit i8042_free_aux_ports(void) | 1126 | static void __init i8042_free_aux_ports(void) |
1082 | { | 1127 | { |
1083 | int i; | 1128 | int i; |
1084 | 1129 | ||
@@ -1088,7 +1133,7 @@ static void __devinit i8042_free_aux_ports(void) | |||
1088 | } | 1133 | } |
1089 | } | 1134 | } |
1090 | 1135 | ||
1091 | static void __devinit i8042_register_ports(void) | 1136 | static void __init i8042_register_ports(void) |
1092 | { | 1137 | { |
1093 | int i; | 1138 | int i; |
1094 | 1139 | ||
@@ -1123,10 +1168,10 @@ static void i8042_free_irqs(void) | |||
1123 | if (i8042_kbd_irq_registered) | 1168 | if (i8042_kbd_irq_registered) |
1124 | free_irq(I8042_KBD_IRQ, i8042_platform_device); | 1169 | free_irq(I8042_KBD_IRQ, i8042_platform_device); |
1125 | 1170 | ||
1126 | i8042_aux_irq_registered = i8042_kbd_irq_registered = 0; | 1171 | i8042_aux_irq_registered = i8042_kbd_irq_registered = false; |
1127 | } | 1172 | } |
1128 | 1173 | ||
1129 | static int __devinit i8042_setup_aux(void) | 1174 | static int __init i8042_setup_aux(void) |
1130 | { | 1175 | { |
1131 | int (*aux_enable)(void); | 1176 | int (*aux_enable)(void); |
1132 | int error; | 1177 | int error; |
@@ -1157,7 +1202,7 @@ static int __devinit i8042_setup_aux(void) | |||
1157 | if (aux_enable()) | 1202 | if (aux_enable()) |
1158 | goto err_free_irq; | 1203 | goto err_free_irq; |
1159 | 1204 | ||
1160 | i8042_aux_irq_registered = 1; | 1205 | i8042_aux_irq_registered = true; |
1161 | return 0; | 1206 | return 0; |
1162 | 1207 | ||
1163 | err_free_irq: | 1208 | err_free_irq: |
@@ -1167,7 +1212,7 @@ static int __devinit i8042_setup_aux(void) | |||
1167 | return error; | 1212 | return error; |
1168 | } | 1213 | } |
1169 | 1214 | ||
1170 | static int __devinit i8042_setup_kbd(void) | 1215 | static int __init i8042_setup_kbd(void) |
1171 | { | 1216 | { |
1172 | int error; | 1217 | int error; |
1173 | 1218 | ||
@@ -1184,7 +1229,7 @@ static int __devinit i8042_setup_kbd(void) | |||
1184 | if (error) | 1229 | if (error) |
1185 | goto err_free_irq; | 1230 | goto err_free_irq; |
1186 | 1231 | ||
1187 | i8042_kbd_irq_registered = 1; | 1232 | i8042_kbd_irq_registered = true; |
1188 | return 0; | 1233 | return 0; |
1189 | 1234 | ||
1190 | err_free_irq: | 1235 | err_free_irq: |
@@ -1194,7 +1239,7 @@ static int __devinit i8042_setup_kbd(void) | |||
1194 | return error; | 1239 | return error; |
1195 | } | 1240 | } |
1196 | 1241 | ||
1197 | static int __devinit i8042_probe(struct platform_device *dev) | 1242 | static int __init i8042_probe(struct platform_device *dev) |
1198 | { | 1243 | { |
1199 | int error; | 1244 | int error; |
1200 | 1245 | ||
@@ -1250,14 +1295,12 @@ static struct platform_driver i8042_driver = { | |||
1250 | .driver = { | 1295 | .driver = { |
1251 | .name = "i8042", | 1296 | .name = "i8042", |
1252 | .owner = THIS_MODULE, | 1297 | .owner = THIS_MODULE, |
1298 | #ifdef CONFIG_PM | ||
1299 | .pm = &i8042_pm_ops, | ||
1300 | #endif | ||
1253 | }, | 1301 | }, |
1254 | .probe = i8042_probe, | ||
1255 | .remove = __devexit_p(i8042_remove), | 1302 | .remove = __devexit_p(i8042_remove), |
1256 | .shutdown = i8042_shutdown, | 1303 | .shutdown = i8042_shutdown, |
1257 | #ifdef CONFIG_PM | ||
1258 | .suspend = i8042_suspend, | ||
1259 | .resume = i8042_resume, | ||
1260 | #endif | ||
1261 | }; | 1304 | }; |
1262 | 1305 | ||
1263 | static int __init i8042_init(void) | 1306 | static int __init i8042_init(void) |
@@ -1274,28 +1317,28 @@ static int __init i8042_init(void) | |||
1274 | if (err) | 1317 | if (err) |
1275 | goto err_platform_exit; | 1318 | goto err_platform_exit; |
1276 | 1319 | ||
1277 | err = platform_driver_register(&i8042_driver); | ||
1278 | if (err) | ||
1279 | goto err_platform_exit; | ||
1280 | |||
1281 | i8042_platform_device = platform_device_alloc("i8042", -1); | 1320 | i8042_platform_device = platform_device_alloc("i8042", -1); |
1282 | if (!i8042_platform_device) { | 1321 | if (!i8042_platform_device) { |
1283 | err = -ENOMEM; | 1322 | err = -ENOMEM; |
1284 | goto err_unregister_driver; | 1323 | goto err_platform_exit; |
1285 | } | 1324 | } |
1286 | 1325 | ||
1287 | err = platform_device_add(i8042_platform_device); | 1326 | err = platform_device_add(i8042_platform_device); |
1288 | if (err) | 1327 | if (err) |
1289 | goto err_free_device; | 1328 | goto err_free_device; |
1290 | 1329 | ||
1330 | err = platform_driver_probe(&i8042_driver, i8042_probe); | ||
1331 | if (err) | ||
1332 | goto err_del_device; | ||
1333 | |||
1291 | panic_blink = i8042_panic_blink; | 1334 | panic_blink = i8042_panic_blink; |
1292 | 1335 | ||
1293 | return 0; | 1336 | return 0; |
1294 | 1337 | ||
1338 | err_del_device: | ||
1339 | platform_device_del(i8042_platform_device); | ||
1295 | err_free_device: | 1340 | err_free_device: |
1296 | platform_device_put(i8042_platform_device); | 1341 | platform_device_put(i8042_platform_device); |
1297 | err_unregister_driver: | ||
1298 | platform_driver_unregister(&i8042_driver); | ||
1299 | err_platform_exit: | 1342 | err_platform_exit: |
1300 | i8042_platform_exit(); | 1343 | i8042_platform_exit(); |
1301 | 1344 | ||
@@ -1304,8 +1347,8 @@ static int __init i8042_init(void) | |||
1304 | 1347 | ||
1305 | static void __exit i8042_exit(void) | 1348 | static void __exit i8042_exit(void) |
1306 | { | 1349 | { |
1307 | platform_device_unregister(i8042_platform_device); | ||
1308 | platform_driver_unregister(&i8042_driver); | 1350 | platform_driver_unregister(&i8042_driver); |
1351 | platform_device_unregister(i8042_platform_device); | ||
1309 | i8042_platform_exit(); | 1352 | i8042_platform_exit(); |
1310 | 1353 | ||
1311 | panic_blink = NULL; | 1354 | panic_blink = NULL; |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index be5bbbb8ae4e..3a95b508bf27 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
@@ -161,7 +161,7 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout) | |||
161 | * ps2_command() can only be called from a process context | 161 | * ps2_command() can only be called from a process context |
162 | */ | 162 | */ |
163 | 163 | ||
164 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | 164 | int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) |
165 | { | 165 | { |
166 | int timeout; | 166 | int timeout; |
167 | int send = (command >> 12) & 0xf; | 167 | int send = (command >> 12) & 0xf; |
@@ -179,8 +179,6 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
179 | return -1; | 179 | return -1; |
180 | } | 180 | } |
181 | 181 | ||
182 | mutex_lock(&ps2dev->cmd_mutex); | ||
183 | |||
184 | serio_pause_rx(ps2dev->serio); | 182 | serio_pause_rx(ps2dev->serio); |
185 | ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; | 183 | ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; |
186 | ps2dev->cmdcnt = receive; | 184 | ps2dev->cmdcnt = receive; |
@@ -231,7 +229,18 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
231 | ps2dev->flags = 0; | 229 | ps2dev->flags = 0; |
232 | serio_continue_rx(ps2dev->serio); | 230 | serio_continue_rx(ps2dev->serio); |
233 | 231 | ||
232 | return rc; | ||
233 | } | ||
234 | EXPORT_SYMBOL(__ps2_command); | ||
235 | |||
236 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | ||
237 | { | ||
238 | int rc; | ||
239 | |||
240 | mutex_lock(&ps2dev->cmd_mutex); | ||
241 | rc = __ps2_command(ps2dev, param, command); | ||
234 | mutex_unlock(&ps2dev->cmd_mutex); | 242 | mutex_unlock(&ps2dev->cmd_mutex); |
243 | |||
235 | return rc; | 244 | return rc; |
236 | } | 245 | } |
237 | EXPORT_SYMBOL(ps2_command); | 246 | EXPORT_SYMBOL(ps2_command); |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index fb17573f8f2d..0236f0d5fd91 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -931,14 +931,11 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
931 | #endif /* CONFIG_HOTPLUG */ | 931 | #endif /* CONFIG_HOTPLUG */ |
932 | 932 | ||
933 | #ifdef CONFIG_PM | 933 | #ifdef CONFIG_PM |
934 | static int serio_suspend(struct device *dev, pm_message_t state) | 934 | static int serio_suspend(struct device *dev) |
935 | { | 935 | { |
936 | struct serio *serio = to_serio_port(dev); | 936 | struct serio *serio = to_serio_port(dev); |
937 | 937 | ||
938 | if (!serio->suspended && state.event == PM_EVENT_SUSPEND) { | 938 | serio_cleanup(serio); |
939 | serio_cleanup(serio); | ||
940 | serio->suspended = true; | ||
941 | } | ||
942 | 939 | ||
943 | return 0; | 940 | return 0; |
944 | } | 941 | } |
@@ -951,13 +948,17 @@ static int serio_resume(struct device *dev) | |||
951 | * Driver reconnect can take a while, so better let kseriod | 948 | * Driver reconnect can take a while, so better let kseriod |
952 | * deal with it. | 949 | * deal with it. |
953 | */ | 950 | */ |
954 | if (serio->suspended) { | 951 | serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); |
955 | serio->suspended = false; | ||
956 | serio_queue_event(serio, NULL, SERIO_RECONNECT_PORT); | ||
957 | } | ||
958 | 952 | ||
959 | return 0; | 953 | return 0; |
960 | } | 954 | } |
955 | |||
956 | static const struct dev_pm_ops serio_pm_ops = { | ||
957 | .suspend = serio_suspend, | ||
958 | .resume = serio_resume, | ||
959 | .poweroff = serio_suspend, | ||
960 | .restore = serio_resume, | ||
961 | }; | ||
961 | #endif /* CONFIG_PM */ | 962 | #endif /* CONFIG_PM */ |
962 | 963 | ||
963 | /* called from serio_driver->connect/disconnect methods under serio_mutex */ | 964 | /* called from serio_driver->connect/disconnect methods under serio_mutex */ |
@@ -1014,8 +1015,7 @@ static struct bus_type serio_bus = { | |||
1014 | .remove = serio_driver_remove, | 1015 | .remove = serio_driver_remove, |
1015 | .shutdown = serio_shutdown, | 1016 | .shutdown = serio_shutdown, |
1016 | #ifdef CONFIG_PM | 1017 | #ifdef CONFIG_PM |
1017 | .suspend = serio_suspend, | 1018 | .pm = &serio_pm_ops, |
1018 | .resume = serio_resume, | ||
1019 | #endif | 1019 | #endif |
1020 | }; | 1020 | }; |
1021 | 1021 | ||
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index a9d5031b855e..ea30c983a33e 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -388,6 +388,32 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
388 | return result; | 388 | return result; |
389 | } | 389 | } |
390 | 390 | ||
391 | static int wacom_query_tablet_data(struct usb_interface *intf) | ||
392 | { | ||
393 | unsigned char *rep_data; | ||
394 | int limit = 0; | ||
395 | int error; | ||
396 | |||
397 | rep_data = kmalloc(2, GFP_KERNEL); | ||
398 | if (!rep_data) | ||
399 | return -ENOMEM; | ||
400 | |||
401 | do { | ||
402 | rep_data[0] = 2; | ||
403 | rep_data[1] = 2; | ||
404 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, | ||
405 | 2, rep_data, 2); | ||
406 | if (error >= 0) | ||
407 | error = usb_get_report(intf, | ||
408 | WAC_HID_FEATURE_REPORT, 2, | ||
409 | rep_data, 2); | ||
410 | } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); | ||
411 | |||
412 | kfree(rep_data); | ||
413 | |||
414 | return error < 0 ? error : 0; | ||
415 | } | ||
416 | |||
391 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 417 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) |
392 | { | 418 | { |
393 | struct usb_device *dev = interface_to_usbdev(intf); | 419 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -398,7 +424,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
398 | struct wacom_features *features; | 424 | struct wacom_features *features; |
399 | struct input_dev *input_dev; | 425 | struct input_dev *input_dev; |
400 | int error = -ENOMEM; | 426 | int error = -ENOMEM; |
401 | char rep_data[2], limit = 0; | ||
402 | struct hid_descriptor *hid_desc; | 427 | struct hid_descriptor *hid_desc; |
403 | 428 | ||
404 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); | 429 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); |
@@ -489,20 +514,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
489 | 514 | ||
490 | /* | 515 | /* |
491 | * Ask the tablet to report tablet data if it is not a Tablet PC. | 516 | * Ask the tablet to report tablet data if it is not a Tablet PC. |
492 | * Repeat until it succeeds | 517 | * Note that if query fails it is not a hard failure. |
493 | */ | 518 | */ |
494 | if (wacom_wac->features->type != TABLETPC) { | 519 | if (wacom_wac->features->type != TABLETPC) |
495 | do { | 520 | wacom_query_tablet_data(intf); |
496 | rep_data[0] = 2; | ||
497 | rep_data[1] = 2; | ||
498 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, | ||
499 | 2, rep_data, 2); | ||
500 | if (error >= 0) | ||
501 | error = usb_get_report(intf, | ||
502 | WAC_HID_FEATURE_REPORT, 2, | ||
503 | rep_data, 2); | ||
504 | } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); | ||
505 | } | ||
506 | 521 | ||
507 | usb_set_intfdata(intf, wacom); | 522 | usb_set_intfdata(intf, wacom); |
508 | return 0; | 523 | return 0; |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 38bf86384aeb..c896d6a21b7e 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -384,6 +384,8 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
384 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | 384 | wacom_report_key(wcombo, BTN_STYLUS2, 0); |
385 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 385 | wacom_report_key(wcombo, BTN_TOUCH, 0); |
386 | wacom_report_abs(wcombo, ABS_WHEEL, 0); | 386 | wacom_report_abs(wcombo, ABS_WHEEL, 0); |
387 | if (wacom->features->type >= INTUOS3S) | ||
388 | wacom_report_abs(wcombo, ABS_Z, 0); | ||
387 | } | 389 | } |
388 | wacom_report_key(wcombo, wacom->tool[idx], 0); | 390 | wacom_report_key(wcombo, wacom->tool[idx], 0); |
389 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | 391 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ |
@@ -836,6 +838,7 @@ static struct wacom_features wacom_features[] = { | |||
836 | { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, | 838 | { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, |
837 | { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, | 839 | { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, |
838 | { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, | 840 | { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, |
841 | { "Wacom DTF720a", 8, 6858, 5506, 511, 0, PL }, | ||
839 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, | 842 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, |
840 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, | 843 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, |
841 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | 844 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, |
@@ -897,8 +900,9 @@ static struct usb_device_id wacom_ids[] = { | |||
897 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, | 900 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, |
898 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, | 901 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, |
899 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, | 902 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, |
900 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, | ||
901 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, | 903 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, |
904 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, | ||
905 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC2) }, | ||
902 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, | 906 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, |
903 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, | 907 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, |
904 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, | 908 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 72e2712c7e2a..ab02d72afbf3 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -366,11 +366,11 @@ config TOUCHSCREEN_WM97XX_ATMEL | |||
366 | be called atmel-wm97xx. | 366 | be called atmel-wm97xx. |
367 | 367 | ||
368 | config TOUCHSCREEN_WM97XX_MAINSTONE | 368 | config TOUCHSCREEN_WM97XX_MAINSTONE |
369 | tristate "WM97xx Mainstone accelerated touch" | 369 | tristate "WM97xx Mainstone/Palm accelerated touch" |
370 | depends on TOUCHSCREEN_WM97XX && ARCH_PXA | 370 | depends on TOUCHSCREEN_WM97XX && ARCH_PXA |
371 | help | 371 | help |
372 | Say Y here for support for streaming mode with WM97xx touchscreens | 372 | Say Y here for support for streaming mode with WM97xx touchscreens |
373 | on Mainstone systems. | 373 | on Mainstone, Palm Tungsten T5, TX and LifeDrive systems. |
374 | 374 | ||
375 | If unsure, say N. | 375 | If unsure, say N. |
376 | 376 | ||
@@ -406,6 +406,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
406 | - IRTOUCHSYSTEMS/UNITOP | 406 | - IRTOUCHSYSTEMS/UNITOP |
407 | - IdealTEK URTC1000 | 407 | - IdealTEK URTC1000 |
408 | - GoTop Super_Q2/GogoPen/PenPower tablets | 408 | - GoTop Super_Q2/GogoPen/PenPower tablets |
409 | - JASTEC USB Touch Controller/DigiTech DTR-02U | ||
409 | 410 | ||
410 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 411 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
411 | a usage description and the required user-space stuff. | 412 | a usage description and the required user-space stuff. |
@@ -468,6 +469,16 @@ config TOUCHSCREEN_USB_GOTOP | |||
468 | bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED | 469 | bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED |
469 | depends on TOUCHSCREEN_USB_COMPOSITE | 470 | depends on TOUCHSCREEN_USB_COMPOSITE |
470 | 471 | ||
472 | config TOUCHSCREEN_USB_JASTEC | ||
473 | default y | ||
474 | bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EMBEDDED | ||
475 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
476 | |||
477 | config TOUCHSCREEN_USB_E2I | ||
478 | default y | ||
479 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" | ||
480 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
481 | |||
471 | config TOUCHSCREEN_TOUCHIT213 | 482 | config TOUCHSCREEN_TOUCHIT213 |
472 | tristate "Sahara TouchIT-213 touchscreen" | 483 | tristate "Sahara TouchIT-213 touchscreen" |
473 | select SERIO | 484 | select SERIO |
@@ -492,10 +503,20 @@ config TOUCHSCREEN_TSC2007 | |||
492 | 503 | ||
493 | config TOUCHSCREEN_W90X900 | 504 | config TOUCHSCREEN_W90X900 |
494 | tristate "W90P910 touchscreen driver" | 505 | tristate "W90P910 touchscreen driver" |
506 | depends on HAVE_CLK | ||
495 | help | 507 | help |
496 | Say Y here if you have a W90P910 based touchscreen. | 508 | Say Y here if you have a W90P910 based touchscreen. |
497 | 509 | ||
498 | To compile this driver as a module, choose M here: the | 510 | To compile this driver as a module, choose M here: the |
499 | module will be called w90p910_ts. | 511 | module will be called w90p910_ts. |
500 | 512 | ||
513 | config TOUCHSCREEN_PCAP | ||
514 | tristate "Motorola PCAP touchscreen" | ||
515 | depends on EZX_PCAP | ||
516 | help | ||
517 | Say Y here if you have a Motorola EZX telephone and | ||
518 | want to enable support for the built-in touchscreen. | ||
519 | |||
520 | To compile this driver as a module, choose M here: the | ||
521 | module will be called pcap_ts. | ||
501 | endif | 522 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 3e1c5e0b952f..4599bf7ad819 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -40,3 +40,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o | |||
40 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o | 40 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o |
41 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o | 41 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o |
42 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o | 42 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o |
43 | obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | ||
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 055969e8be13..9c7fce4d74d0 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
@@ -204,14 +204,14 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
204 | goto err_free_dev; | 204 | goto err_free_dev; |
205 | } | 205 | } |
206 | 206 | ||
207 | if (!request_mem_region(res->start, res->end - res->start + 1, | 207 | if (!request_mem_region(res->start, resource_size(res), |
208 | "atmel tsadcc regs")) { | 208 | "atmel tsadcc regs")) { |
209 | dev_err(&pdev->dev, "resources is unavailable.\n"); | 209 | dev_err(&pdev->dev, "resources is unavailable.\n"); |
210 | err = -EBUSY; | 210 | err = -EBUSY; |
211 | goto err_free_dev; | 211 | goto err_free_dev; |
212 | } | 212 | } |
213 | 213 | ||
214 | tsc_base = ioremap(res->start, res->end - res->start + 1); | 214 | tsc_base = ioremap(res->start, resource_size(res)); |
215 | if (!tsc_base) { | 215 | if (!tsc_base) { |
216 | dev_err(&pdev->dev, "failed to map registers.\n"); | 216 | dev_err(&pdev->dev, "failed to map registers.\n"); |
217 | err = -ENOMEM; | 217 | err = -ENOMEM; |
@@ -286,7 +286,7 @@ err_free_irq: | |||
286 | err_unmap_regs: | 286 | err_unmap_regs: |
287 | iounmap(tsc_base); | 287 | iounmap(tsc_base); |
288 | err_release_mem: | 288 | err_release_mem: |
289 | release_mem_region(res->start, res->end - res->start + 1); | 289 | release_mem_region(res->start, resource_size(res)); |
290 | err_free_dev: | 290 | err_free_dev: |
291 | input_free_device(ts_dev->input); | 291 | input_free_device(ts_dev->input); |
292 | err_free_mem: | 292 | err_free_mem: |
@@ -305,7 +305,7 @@ static int __devexit atmel_tsadcc_remove(struct platform_device *pdev) | |||
305 | 305 | ||
306 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 306 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
307 | iounmap(tsc_base); | 307 | iounmap(tsc_base); |
308 | release_mem_region(res->start, res->end - res->start + 1); | 308 | release_mem_region(res->start, resource_size(res)); |
309 | 309 | ||
310 | clk_disable(ts_dev->clk); | 310 | clk_disable(ts_dev->clk); |
311 | clk_put(ts_dev->clk); | 311 | clk_put(ts_dev->clk); |
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 3ab92222a525..9029bd3f34e5 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
33 | #include <linux/timer.h> | 33 | #include <linux/timer.h> |
34 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
35 | #include <linux/input/eeti_ts.h> | ||
35 | 36 | ||
36 | static int flip_x; | 37 | static int flip_x; |
37 | module_param(flip_x, bool, 0644); | 38 | module_param(flip_x, bool, 0644); |
@@ -46,7 +47,7 @@ struct eeti_ts_priv { | |||
46 | struct input_dev *input; | 47 | struct input_dev *input; |
47 | struct work_struct work; | 48 | struct work_struct work; |
48 | struct mutex mutex; | 49 | struct mutex mutex; |
49 | int irq; | 50 | int irq, irq_active_high; |
50 | }; | 51 | }; |
51 | 52 | ||
52 | #define EETI_TS_BITDEPTH (11) | 53 | #define EETI_TS_BITDEPTH (11) |
@@ -58,6 +59,11 @@ struct eeti_ts_priv { | |||
58 | #define REPORT_BIT_HAS_PRESSURE (1 << 6) | 59 | #define REPORT_BIT_HAS_PRESSURE (1 << 6) |
59 | #define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH) | 60 | #define REPORT_RES_BITS(v) (((v) >> 1) + EETI_TS_BITDEPTH) |
60 | 61 | ||
62 | static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv) | ||
63 | { | ||
64 | return gpio_get_value(irq_to_gpio(priv->irq)) == priv->irq_active_high; | ||
65 | } | ||
66 | |||
61 | static void eeti_ts_read(struct work_struct *work) | 67 | static void eeti_ts_read(struct work_struct *work) |
62 | { | 68 | { |
63 | char buf[6]; | 69 | char buf[6]; |
@@ -67,7 +73,7 @@ static void eeti_ts_read(struct work_struct *work) | |||
67 | 73 | ||
68 | mutex_lock(&priv->mutex); | 74 | mutex_lock(&priv->mutex); |
69 | 75 | ||
70 | while (!gpio_get_value(irq_to_gpio(priv->irq)) && --to) | 76 | while (eeti_ts_irq_active(priv) && --to) |
71 | i2c_master_recv(priv->client, buf, sizeof(buf)); | 77 | i2c_master_recv(priv->client, buf, sizeof(buf)); |
72 | 78 | ||
73 | if (!to) { | 79 | if (!to) { |
@@ -140,8 +146,10 @@ static void eeti_ts_close(struct input_dev *dev) | |||
140 | static int __devinit eeti_ts_probe(struct i2c_client *client, | 146 | static int __devinit eeti_ts_probe(struct i2c_client *client, |
141 | const struct i2c_device_id *idp) | 147 | const struct i2c_device_id *idp) |
142 | { | 148 | { |
149 | struct eeti_ts_platform_data *pdata; | ||
143 | struct eeti_ts_priv *priv; | 150 | struct eeti_ts_priv *priv; |
144 | struct input_dev *input; | 151 | struct input_dev *input; |
152 | unsigned int irq_flags; | ||
145 | int err = -ENOMEM; | 153 | int err = -ENOMEM; |
146 | 154 | ||
147 | /* In contrast to what's described in the datasheet, there seems | 155 | /* In contrast to what's described in the datasheet, there seems |
@@ -180,6 +188,14 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
180 | priv->input = input; | 188 | priv->input = input; |
181 | priv->irq = client->irq; | 189 | priv->irq = client->irq; |
182 | 190 | ||
191 | pdata = client->dev.platform_data; | ||
192 | |||
193 | if (pdata) | ||
194 | priv->irq_active_high = pdata->irq_active_high; | ||
195 | |||
196 | irq_flags = priv->irq_active_high ? | ||
197 | IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING; | ||
198 | |||
183 | INIT_WORK(&priv->work, eeti_ts_read); | 199 | INIT_WORK(&priv->work, eeti_ts_read); |
184 | i2c_set_clientdata(client, priv); | 200 | i2c_set_clientdata(client, priv); |
185 | input_set_drvdata(input, priv); | 201 | input_set_drvdata(input, priv); |
@@ -188,7 +204,7 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
188 | if (err) | 204 | if (err) |
189 | goto err1; | 205 | goto err1; |
190 | 206 | ||
191 | err = request_irq(priv->irq, eeti_ts_isr, IRQF_TRIGGER_FALLING, | 207 | err = request_irq(priv->irq, eeti_ts_isr, irq_flags, |
192 | client->name, priv); | 208 | client->name, priv); |
193 | if (err) { | 209 | if (err) { |
194 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); | 210 | dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); |
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index 4d3139e2099d..b4d7f63deff1 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
@@ -148,9 +148,10 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) | |||
148 | struct h3600_dev *ts = input_get_drvdata(dev); | 148 | struct h3600_dev *ts = input_get_drvdata(dev); |
149 | 149 | ||
150 | /* Must be in this order */ | 150 | /* Must be in this order */ |
151 | ts->serio->write(ts->serio, 1); | 151 | serio_write(ts->serio, 1); |
152 | ts->serio->write(ts->serio, pwr); | 152 | serio_write(ts->serio, pwr); |
153 | ts->serio->write(ts->serio, brightness); | 153 | serio_write(ts->serio, brightness); |
154 | |||
154 | return 0; | 155 | return 0; |
155 | } | 156 | } |
156 | 157 | ||
@@ -262,7 +263,7 @@ static int h3600ts_event(struct input_dev *dev, unsigned int type, | |||
262 | 263 | ||
263 | switch (type) { | 264 | switch (type) { |
264 | case EV_LED: { | 265 | case EV_LED: { |
265 | // ts->serio->write(ts->serio, SOME_CMD); | 266 | // serio_write(ts->serio, SOME_CMD); |
266 | return 0; | 267 | return 0; |
267 | } | 268 | } |
268 | } | 269 | } |
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 4cc047a5116e..8fc3b08deb3b 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c | |||
@@ -31,9 +31,11 @@ | |||
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/wm97xx.h> | 32 | #include <linux/wm97xx.h> |
33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
34 | #include <linux/gpio.h> | ||
35 | |||
34 | #include <mach/regs-ac97.h> | 36 | #include <mach/regs-ac97.h> |
35 | 37 | ||
36 | #define VERSION "0.13" | 38 | #include <asm/mach-types.h> |
37 | 39 | ||
38 | struct continuous { | 40 | struct continuous { |
39 | u16 id; /* codec id */ | 41 | u16 id; /* codec id */ |
@@ -62,6 +64,7 @@ static const struct continuous cinfo[] = { | |||
62 | /* continuous speed index */ | 64 | /* continuous speed index */ |
63 | static int sp_idx; | 65 | static int sp_idx; |
64 | static u16 last, tries; | 66 | static u16 last, tries; |
67 | static int irq; | ||
65 | 68 | ||
66 | /* | 69 | /* |
67 | * Pen sampling frequency (Hz) in continuous mode. | 70 | * Pen sampling frequency (Hz) in continuous mode. |
@@ -171,7 +174,7 @@ up: | |||
171 | 174 | ||
172 | static int wm97xx_acc_startup(struct wm97xx *wm) | 175 | static int wm97xx_acc_startup(struct wm97xx *wm) |
173 | { | 176 | { |
174 | int idx = 0; | 177 | int idx = 0, ret = 0; |
175 | 178 | ||
176 | /* check we have a codec */ | 179 | /* check we have a codec */ |
177 | if (wm->ac97 == NULL) | 180 | if (wm->ac97 == NULL) |
@@ -191,18 +194,40 @@ static int wm97xx_acc_startup(struct wm97xx *wm) | |||
191 | "mainstone accelerated touchscreen driver, %d samples/sec\n", | 194 | "mainstone accelerated touchscreen driver, %d samples/sec\n", |
192 | cinfo[sp_idx].speed); | 195 | cinfo[sp_idx].speed); |
193 | 196 | ||
197 | /* IRQ driven touchscreen is used on Palm hardware */ | ||
198 | if (machine_is_palmt5() || machine_is_palmtx() || machine_is_palmld()) { | ||
199 | pen_int = 1; | ||
200 | irq = 27; | ||
201 | /* There is some obscure mutant of WM9712 interbred with WM9713 | ||
202 | * used on Palm HW */ | ||
203 | wm->variant = WM97xx_WM1613; | ||
204 | } else if (machine_is_mainstone() && pen_int) | ||
205 | irq = 4; | ||
206 | |||
207 | if (irq) { | ||
208 | ret = gpio_request(irq, "Touchscreen IRQ"); | ||
209 | if (ret) | ||
210 | goto out; | ||
211 | |||
212 | ret = gpio_direction_input(irq); | ||
213 | if (ret) { | ||
214 | gpio_free(irq); | ||
215 | goto out; | ||
216 | } | ||
217 | |||
218 | wm->pen_irq = gpio_to_irq(irq); | ||
219 | set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH); | ||
220 | } else /* pen irq not supported */ | ||
221 | pen_int = 0; | ||
222 | |||
194 | /* codec specific irq config */ | 223 | /* codec specific irq config */ |
195 | if (pen_int) { | 224 | if (pen_int) { |
196 | switch (wm->id) { | 225 | switch (wm->id) { |
197 | case WM9705_ID2: | 226 | case WM9705_ID2: |
198 | wm->pen_irq = IRQ_GPIO(4); | ||
199 | set_irq_type(IRQ_GPIO(4), IRQ_TYPE_EDGE_BOTH); | ||
200 | break; | 227 | break; |
201 | case WM9712_ID2: | 228 | case WM9712_ID2: |
202 | case WM9713_ID2: | 229 | case WM9713_ID2: |
203 | /* enable pen down interrupt */ | ||
204 | /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */ | 230 | /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */ |
205 | wm->pen_irq = MAINSTONE_AC97_IRQ; | ||
206 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, | 231 | wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, |
207 | WM97XX_GPIO_POL_HIGH, | 232 | WM97XX_GPIO_POL_HIGH, |
208 | WM97XX_GPIO_STICKY, | 233 | WM97XX_GPIO_STICKY, |
@@ -220,23 +245,17 @@ static int wm97xx_acc_startup(struct wm97xx *wm) | |||
220 | } | 245 | } |
221 | } | 246 | } |
222 | 247 | ||
223 | return 0; | 248 | out: |
249 | return ret; | ||
224 | } | 250 | } |
225 | 251 | ||
226 | static void wm97xx_acc_shutdown(struct wm97xx *wm) | 252 | static void wm97xx_acc_shutdown(struct wm97xx *wm) |
227 | { | 253 | { |
228 | /* codec specific deconfig */ | 254 | /* codec specific deconfig */ |
229 | if (pen_int) { | 255 | if (pen_int) { |
230 | switch (wm->id & 0xffff) { | 256 | if (irq) |
231 | case WM9705_ID2: | 257 | gpio_free(irq); |
232 | wm->pen_irq = 0; | 258 | wm->pen_irq = 0; |
233 | break; | ||
234 | case WM9712_ID2: | ||
235 | case WM9713_ID2: | ||
236 | /* disable interrupt */ | ||
237 | wm->pen_irq = 0; | ||
238 | break; | ||
239 | } | ||
240 | } | 259 | } |
241 | } | 260 | } |
242 | 261 | ||
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c new file mode 100644 index 000000000000..67fcd33595de --- /dev/null +++ b/drivers/input/touchscreen/pcap_ts.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * Driver for Motorola PCAP2 touchscreen as found in the EZX phone platform. | ||
3 | * | ||
4 | * Copyright (C) 2006 Harald Welte <laforge@openezx.org> | ||
5 | * Copyright (C) 2009 Daniel Ribeiro <drwyrm@gmail.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/fs.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/timer.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/mfd/ezx-pcap.h> | ||
23 | |||
24 | struct pcap_ts { | ||
25 | struct pcap_chip *pcap; | ||
26 | struct input_dev *input; | ||
27 | struct delayed_work work; | ||
28 | u16 x, y; | ||
29 | u16 pressure; | ||
30 | u8 read_state; | ||
31 | }; | ||
32 | |||
33 | #define SAMPLE_DELAY 20 /* msecs */ | ||
34 | |||
35 | #define X_AXIS_MIN 0 | ||
36 | #define X_AXIS_MAX 1023 | ||
37 | #define Y_AXIS_MAX X_AXIS_MAX | ||
38 | #define Y_AXIS_MIN X_AXIS_MIN | ||
39 | #define PRESSURE_MAX X_AXIS_MAX | ||
40 | #define PRESSURE_MIN X_AXIS_MIN | ||
41 | |||
42 | static void pcap_ts_read_xy(void *data, u16 res[2]) | ||
43 | { | ||
44 | struct pcap_ts *pcap_ts = data; | ||
45 | |||
46 | switch (pcap_ts->read_state) { | ||
47 | case PCAP_ADC_TS_M_PRESSURE: | ||
48 | /* pressure reading is unreliable */ | ||
49 | if (res[0] > PRESSURE_MIN && res[0] < PRESSURE_MAX) | ||
50 | pcap_ts->pressure = res[0]; | ||
51 | pcap_ts->read_state = PCAP_ADC_TS_M_XY; | ||
52 | schedule_delayed_work(&pcap_ts->work, 0); | ||
53 | break; | ||
54 | case PCAP_ADC_TS_M_XY: | ||
55 | pcap_ts->y = res[0]; | ||
56 | pcap_ts->x = res[1]; | ||
57 | if (pcap_ts->x <= X_AXIS_MIN || pcap_ts->x >= X_AXIS_MAX || | ||
58 | pcap_ts->y <= Y_AXIS_MIN || pcap_ts->y >= Y_AXIS_MAX) { | ||
59 | /* pen has been released */ | ||
60 | input_report_abs(pcap_ts->input, ABS_PRESSURE, 0); | ||
61 | input_report_key(pcap_ts->input, BTN_TOUCH, 0); | ||
62 | |||
63 | pcap_ts->read_state = PCAP_ADC_TS_M_STANDBY; | ||
64 | schedule_delayed_work(&pcap_ts->work, 0); | ||
65 | } else { | ||
66 | /* pen is touching the screen */ | ||
67 | input_report_abs(pcap_ts->input, ABS_X, pcap_ts->x); | ||
68 | input_report_abs(pcap_ts->input, ABS_Y, pcap_ts->y); | ||
69 | input_report_key(pcap_ts->input, BTN_TOUCH, 1); | ||
70 | input_report_abs(pcap_ts->input, ABS_PRESSURE, | ||
71 | pcap_ts->pressure); | ||
72 | |||
73 | /* switch back to pressure read mode */ | ||
74 | pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE; | ||
75 | schedule_delayed_work(&pcap_ts->work, | ||
76 | msecs_to_jiffies(SAMPLE_DELAY)); | ||
77 | } | ||
78 | input_sync(pcap_ts->input); | ||
79 | break; | ||
80 | default: | ||
81 | dev_warn(&pcap_ts->input->dev, | ||
82 | "pcap_ts: Warning, unhandled read_state %d\n", | ||
83 | pcap_ts->read_state); | ||
84 | break; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static void pcap_ts_work(struct work_struct *work) | ||
89 | { | ||
90 | struct delayed_work *dw = container_of(work, struct delayed_work, work); | ||
91 | struct pcap_ts *pcap_ts = container_of(dw, struct pcap_ts, work); | ||
92 | u8 ch[2]; | ||
93 | |||
94 | pcap_set_ts_bits(pcap_ts->pcap, | ||
95 | pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT); | ||
96 | |||
97 | if (pcap_ts->read_state == PCAP_ADC_TS_M_STANDBY) | ||
98 | return; | ||
99 | |||
100 | /* start adc conversion */ | ||
101 | ch[0] = PCAP_ADC_CH_TS_X1; | ||
102 | ch[1] = PCAP_ADC_CH_TS_Y1; | ||
103 | pcap_adc_async(pcap_ts->pcap, PCAP_ADC_BANK_1, 0, ch, | ||
104 | pcap_ts_read_xy, pcap_ts); | ||
105 | } | ||
106 | |||
107 | static irqreturn_t pcap_ts_event_touch(int pirq, void *data) | ||
108 | { | ||
109 | struct pcap_ts *pcap_ts = data; | ||
110 | |||
111 | if (pcap_ts->read_state == PCAP_ADC_TS_M_STANDBY) { | ||
112 | pcap_ts->read_state = PCAP_ADC_TS_M_PRESSURE; | ||
113 | schedule_delayed_work(&pcap_ts->work, 0); | ||
114 | } | ||
115 | return IRQ_HANDLED; | ||
116 | } | ||
117 | |||
118 | static int pcap_ts_open(struct input_dev *dev) | ||
119 | { | ||
120 | struct pcap_ts *pcap_ts = input_get_drvdata(dev); | ||
121 | |||
122 | pcap_ts->read_state = PCAP_ADC_TS_M_STANDBY; | ||
123 | schedule_delayed_work(&pcap_ts->work, 0); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static void pcap_ts_close(struct input_dev *dev) | ||
129 | { | ||
130 | struct pcap_ts *pcap_ts = input_get_drvdata(dev); | ||
131 | |||
132 | cancel_delayed_work_sync(&pcap_ts->work); | ||
133 | |||
134 | pcap_ts->read_state = PCAP_ADC_TS_M_NONTS; | ||
135 | pcap_set_ts_bits(pcap_ts->pcap, | ||
136 | pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT); | ||
137 | } | ||
138 | |||
139 | static int __devinit pcap_ts_probe(struct platform_device *pdev) | ||
140 | { | ||
141 | struct input_dev *input_dev; | ||
142 | struct pcap_ts *pcap_ts; | ||
143 | int err = -ENOMEM; | ||
144 | |||
145 | pcap_ts = kzalloc(sizeof(*pcap_ts), GFP_KERNEL); | ||
146 | if (!pcap_ts) | ||
147 | return err; | ||
148 | |||
149 | pcap_ts->pcap = dev_get_drvdata(pdev->dev.parent); | ||
150 | platform_set_drvdata(pdev, pcap_ts); | ||
151 | |||
152 | input_dev = input_allocate_device(); | ||
153 | if (!input_dev) | ||
154 | goto fail; | ||
155 | |||
156 | INIT_DELAYED_WORK(&pcap_ts->work, pcap_ts_work); | ||
157 | |||
158 | pcap_ts->read_state = PCAP_ADC_TS_M_NONTS; | ||
159 | pcap_set_ts_bits(pcap_ts->pcap, | ||
160 | pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT); | ||
161 | |||
162 | pcap_ts->input = input_dev; | ||
163 | input_set_drvdata(input_dev, pcap_ts); | ||
164 | |||
165 | input_dev->name = "pcap-touchscreen"; | ||
166 | input_dev->phys = "pcap_ts/input0"; | ||
167 | input_dev->id.bustype = BUS_HOST; | ||
168 | input_dev->id.vendor = 0x0001; | ||
169 | input_dev->id.product = 0x0002; | ||
170 | input_dev->id.version = 0x0100; | ||
171 | input_dev->dev.parent = &pdev->dev; | ||
172 | input_dev->open = pcap_ts_open; | ||
173 | input_dev->close = pcap_ts_close; | ||
174 | |||
175 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
176 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
177 | input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0); | ||
178 | input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0); | ||
179 | input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, | ||
180 | PRESSURE_MAX, 0, 0); | ||
181 | |||
182 | err = input_register_device(pcap_ts->input); | ||
183 | if (err) | ||
184 | goto fail_allocate; | ||
185 | |||
186 | err = request_irq(pcap_to_irq(pcap_ts->pcap, PCAP_IRQ_TS), | ||
187 | pcap_ts_event_touch, 0, "Touch Screen", pcap_ts); | ||
188 | if (err) | ||
189 | goto fail_register; | ||
190 | |||
191 | return 0; | ||
192 | |||
193 | fail_register: | ||
194 | input_unregister_device(input_dev); | ||
195 | goto fail; | ||
196 | fail_allocate: | ||
197 | input_free_device(input_dev); | ||
198 | fail: | ||
199 | kfree(pcap_ts); | ||
200 | |||
201 | return err; | ||
202 | } | ||
203 | |||
204 | static int __devexit pcap_ts_remove(struct platform_device *pdev) | ||
205 | { | ||
206 | struct pcap_ts *pcap_ts = platform_get_drvdata(pdev); | ||
207 | |||
208 | free_irq(pcap_to_irq(pcap_ts->pcap, PCAP_IRQ_TS), pcap_ts); | ||
209 | cancel_delayed_work_sync(&pcap_ts->work); | ||
210 | |||
211 | input_unregister_device(pcap_ts->input); | ||
212 | |||
213 | kfree(pcap_ts); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | #ifdef CONFIG_PM | ||
219 | static int pcap_ts_suspend(struct device *dev) | ||
220 | { | ||
221 | struct pcap_ts *pcap_ts = dev_get_drvdata(dev); | ||
222 | |||
223 | pcap_set_ts_bits(pcap_ts->pcap, PCAP_ADC_TS_REF_LOWPWR); | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int pcap_ts_resume(struct device *dev) | ||
228 | { | ||
229 | struct pcap_ts *pcap_ts = dev_get_drvdata(dev); | ||
230 | |||
231 | pcap_set_ts_bits(pcap_ts->pcap, | ||
232 | pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static struct dev_pm_ops pcap_ts_pm_ops = { | ||
237 | .suspend = pcap_ts_suspend, | ||
238 | .resume = pcap_ts_resume, | ||
239 | }; | ||
240 | #define PCAP_TS_PM_OPS (&pcap_ts_pm_ops) | ||
241 | #else | ||
242 | #define PCAP_TS_PM_OPS NULL | ||
243 | #endif | ||
244 | |||
245 | static struct platform_driver pcap_ts_driver = { | ||
246 | .probe = pcap_ts_probe, | ||
247 | .remove = __devexit_p(pcap_ts_remove), | ||
248 | .driver = { | ||
249 | .name = "pcap-ts", | ||
250 | .owner = THIS_MODULE, | ||
251 | .pm = PCAP_TS_PM_OPS, | ||
252 | }, | ||
253 | }; | ||
254 | |||
255 | static int __init pcap_ts_init(void) | ||
256 | { | ||
257 | return platform_driver_register(&pcap_ts_driver); | ||
258 | } | ||
259 | |||
260 | static void __exit pcap_ts_exit(void) | ||
261 | { | ||
262 | platform_driver_unregister(&pcap_ts_driver); | ||
263 | } | ||
264 | |||
265 | module_init(pcap_ts_init); | ||
266 | module_exit(pcap_ts_exit); | ||
267 | |||
268 | MODULE_DESCRIPTION("Motorola PCAP2 touchscreen driver"); | ||
269 | MODULE_AUTHOR("Daniel Ribeiro / Harald Welte"); | ||
270 | MODULE_LICENSE("GPL"); | ||
271 | MODULE_ALIAS("platform:pcap_ts"); | ||
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 880f58c6a7c4..7ef0d1420d3c 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
@@ -21,15 +21,14 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/hrtimer.h> | ||
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
26 | #include <linux/input.h> | 25 | #include <linux/input.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
28 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
29 | #include <linux/i2c/tsc2007.h> | 28 | #include <linux/i2c/tsc2007.h> |
30 | 29 | ||
31 | #define TS_POLL_DELAY (10 * 1000) /* ns delay before the first sample */ | 30 | #define TS_POLL_DELAY 1 /* ms delay between samples */ |
32 | #define TS_POLL_PERIOD (5 * 1000) /* ns delay between samples */ | 31 | #define TS_POLL_PERIOD 1 /* ms delay between samples */ |
33 | 32 | ||
34 | #define TSC2007_MEASURE_TEMP0 (0x0 << 4) | 33 | #define TSC2007_MEASURE_TEMP0 (0x0 << 4) |
35 | #define TSC2007_MEASURE_AUX (0x2 << 4) | 34 | #define TSC2007_MEASURE_AUX (0x2 << 4) |
@@ -70,17 +69,14 @@ struct ts_event { | |||
70 | struct tsc2007 { | 69 | struct tsc2007 { |
71 | struct input_dev *input; | 70 | struct input_dev *input; |
72 | char phys[32]; | 71 | char phys[32]; |
73 | struct hrtimer timer; | 72 | struct delayed_work work; |
74 | struct ts_event tc; | ||
75 | 73 | ||
76 | struct i2c_client *client; | 74 | struct i2c_client *client; |
77 | 75 | ||
78 | spinlock_t lock; | ||
79 | |||
80 | u16 model; | 76 | u16 model; |
81 | u16 x_plate_ohms; | 77 | u16 x_plate_ohms; |
82 | 78 | ||
83 | unsigned pendown; | 79 | bool pendown; |
84 | int irq; | 80 | int irq; |
85 | 81 | ||
86 | int (*get_pendown_state)(void); | 82 | int (*get_pendown_state)(void); |
@@ -109,52 +105,96 @@ static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd) | |||
109 | return val; | 105 | return val; |
110 | } | 106 | } |
111 | 107 | ||
112 | static void tsc2007_send_event(void *tsc) | 108 | static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc) |
113 | { | 109 | { |
114 | struct tsc2007 *ts = tsc; | 110 | /* y- still on; turn on only y+ (and ADC) */ |
115 | u32 rt; | 111 | tc->y = tsc2007_xfer(tsc, READ_Y); |
116 | u16 x, y, z1, z2; | 112 | |
113 | /* turn y- off, x+ on, then leave in lowpower */ | ||
114 | tc->x = tsc2007_xfer(tsc, READ_X); | ||
115 | |||
116 | /* turn y+ off, x- on; we'll use formula #1 */ | ||
117 | tc->z1 = tsc2007_xfer(tsc, READ_Z1); | ||
118 | tc->z2 = tsc2007_xfer(tsc, READ_Z2); | ||
117 | 119 | ||
118 | x = ts->tc.x; | 120 | /* Prepare for next touch reading - power down ADC, enable PENIRQ */ |
119 | y = ts->tc.y; | 121 | tsc2007_xfer(tsc, PWRDOWN); |
120 | z1 = ts->tc.z1; | 122 | } |
121 | z2 = ts->tc.z2; | 123 | |
124 | static u32 tsc2007_calculate_pressure(struct tsc2007 *tsc, struct ts_event *tc) | ||
125 | { | ||
126 | u32 rt = 0; | ||
122 | 127 | ||
123 | /* range filtering */ | 128 | /* range filtering */ |
124 | if (x == MAX_12BIT) | 129 | if (tc->x == MAX_12BIT) |
125 | x = 0; | 130 | tc->x = 0; |
126 | 131 | ||
127 | if (likely(x && z1)) { | 132 | if (likely(tc->x && tc->z1)) { |
128 | /* compute touch pressure resistance using equation #1 */ | 133 | /* compute touch pressure resistance using equation #1 */ |
129 | rt = z2; | 134 | rt = tc->z2 - tc->z1; |
130 | rt -= z1; | 135 | rt *= tc->x; |
131 | rt *= x; | 136 | rt *= tsc->x_plate_ohms; |
132 | rt *= ts->x_plate_ohms; | 137 | rt /= tc->z1; |
133 | rt /= z1; | ||
134 | rt = (rt + 2047) >> 12; | 138 | rt = (rt + 2047) >> 12; |
135 | } else | 139 | } |
136 | rt = 0; | 140 | |
141 | return rt; | ||
142 | } | ||
143 | |||
144 | static void tsc2007_send_up_event(struct tsc2007 *tsc) | ||
145 | { | ||
146 | struct input_dev *input = tsc->input; | ||
137 | 147 | ||
138 | /* Sample found inconsistent by debouncing or pressure is beyond | 148 | dev_dbg(&tsc->client->dev, "UP\n"); |
139 | * the maximum. Don't report it to user space, repeat at least | 149 | |
140 | * once more the measurement | 150 | input_report_key(input, BTN_TOUCH, 0); |
151 | input_report_abs(input, ABS_PRESSURE, 0); | ||
152 | input_sync(input); | ||
153 | } | ||
154 | |||
155 | static void tsc2007_work(struct work_struct *work) | ||
156 | { | ||
157 | struct tsc2007 *ts = | ||
158 | container_of(to_delayed_work(work), struct tsc2007, work); | ||
159 | struct ts_event tc; | ||
160 | u32 rt; | ||
161 | |||
162 | /* | ||
163 | * NOTE: We can't rely on the pressure to determine the pen down | ||
164 | * state, even though this controller has a pressure sensor. | ||
165 | * The pressure value can fluctuate for quite a while after | ||
166 | * lifting the pen and in some cases may not even settle at the | ||
167 | * expected value. | ||
168 | * | ||
169 | * The only safe way to check for the pen up condition is in the | ||
170 | * work function by reading the pen signal state (it's a GPIO | ||
171 | * and IRQ). Unfortunately such callback is not always available, | ||
172 | * in that case we have rely on the pressure anyway. | ||
141 | */ | 173 | */ |
174 | if (ts->get_pendown_state) { | ||
175 | if (unlikely(!ts->get_pendown_state())) { | ||
176 | tsc2007_send_up_event(ts); | ||
177 | ts->pendown = false; | ||
178 | goto out; | ||
179 | } | ||
180 | |||
181 | dev_dbg(&ts->client->dev, "pen is still down\n"); | ||
182 | } | ||
183 | |||
184 | tsc2007_read_values(ts, &tc); | ||
185 | |||
186 | rt = tsc2007_calculate_pressure(ts, &tc); | ||
142 | if (rt > MAX_12BIT) { | 187 | if (rt > MAX_12BIT) { |
188 | /* | ||
189 | * Sample found inconsistent by debouncing or pressure is | ||
190 | * beyond the maximum. Don't report it to user space, | ||
191 | * repeat at least once more the measurement. | ||
192 | */ | ||
143 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); | 193 | dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt); |
194 | goto out; | ||
144 | 195 | ||
145 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | ||
146 | HRTIMER_MODE_REL); | ||
147 | return; | ||
148 | } | 196 | } |
149 | 197 | ||
150 | /* NOTE: We can't rely on the pressure to determine the pen down | ||
151 | * state, even this controller has a pressure sensor. The pressure | ||
152 | * value can fluctuate for quite a while after lifting the pen and | ||
153 | * in some cases may not even settle at the expected value. | ||
154 | * | ||
155 | * The only safe way to check for the pen up condition is in the | ||
156 | * timer by reading the pen signal state (it's a GPIO _and_ IRQ). | ||
157 | */ | ||
158 | if (rt) { | 198 | if (rt) { |
159 | struct input_dev *input = ts->input; | 199 | struct input_dev *input = ts->input; |
160 | 200 | ||
@@ -162,102 +202,74 @@ static void tsc2007_send_event(void *tsc) | |||
162 | dev_dbg(&ts->client->dev, "DOWN\n"); | 202 | dev_dbg(&ts->client->dev, "DOWN\n"); |
163 | 203 | ||
164 | input_report_key(input, BTN_TOUCH, 1); | 204 | input_report_key(input, BTN_TOUCH, 1); |
165 | ts->pendown = 1; | 205 | ts->pendown = true; |
166 | } | 206 | } |
167 | 207 | ||
168 | input_report_abs(input, ABS_X, x); | 208 | input_report_abs(input, ABS_X, tc.x); |
169 | input_report_abs(input, ABS_Y, y); | 209 | input_report_abs(input, ABS_Y, tc.y); |
170 | input_report_abs(input, ABS_PRESSURE, rt); | 210 | input_report_abs(input, ABS_PRESSURE, rt); |
171 | 211 | ||
172 | input_sync(input); | 212 | input_sync(input); |
173 | 213 | ||
174 | dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", | 214 | dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n", |
175 | x, y, rt); | 215 | tc.x, tc.y, rt); |
216 | |||
217 | } else if (!ts->get_pendown_state && ts->pendown) { | ||
218 | /* | ||
219 | * We don't have callback to check pendown state, so we | ||
220 | * have to assume that since pressure reported is 0 the | ||
221 | * pen was lifted up. | ||
222 | */ | ||
223 | tsc2007_send_up_event(ts); | ||
224 | ts->pendown = false; | ||
176 | } | 225 | } |
177 | 226 | ||
178 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 227 | out: |
179 | HRTIMER_MODE_REL); | 228 | if (ts->pendown) |
180 | } | 229 | schedule_delayed_work(&ts->work, |
181 | 230 | msecs_to_jiffies(TS_POLL_PERIOD)); | |
182 | static int tsc2007_read_values(struct tsc2007 *tsc) | 231 | else |
183 | { | ||
184 | /* y- still on; turn on only y+ (and ADC) */ | ||
185 | tsc->tc.y = tsc2007_xfer(tsc, READ_Y); | ||
186 | |||
187 | /* turn y- off, x+ on, then leave in lowpower */ | ||
188 | tsc->tc.x = tsc2007_xfer(tsc, READ_X); | ||
189 | |||
190 | /* turn y+ off, x- on; we'll use formula #1 */ | ||
191 | tsc->tc.z1 = tsc2007_xfer(tsc, READ_Z1); | ||
192 | tsc->tc.z2 = tsc2007_xfer(tsc, READ_Z2); | ||
193 | |||
194 | /* power down */ | ||
195 | tsc2007_xfer(tsc, PWRDOWN); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle) | ||
201 | { | ||
202 | struct tsc2007 *ts = container_of(handle, struct tsc2007, timer); | ||
203 | unsigned long flags; | ||
204 | |||
205 | spin_lock_irqsave(&ts->lock, flags); | ||
206 | |||
207 | if (unlikely(!ts->get_pendown_state() && ts->pendown)) { | ||
208 | struct input_dev *input = ts->input; | ||
209 | |||
210 | dev_dbg(&ts->client->dev, "UP\n"); | ||
211 | |||
212 | input_report_key(input, BTN_TOUCH, 0); | ||
213 | input_report_abs(input, ABS_PRESSURE, 0); | ||
214 | input_sync(input); | ||
215 | |||
216 | ts->pendown = 0; | ||
217 | enable_irq(ts->irq); | 232 | enable_irq(ts->irq); |
218 | } else { | ||
219 | /* pen is still down, continue with the measurement */ | ||
220 | dev_dbg(&ts->client->dev, "pen is still down\n"); | ||
221 | |||
222 | tsc2007_read_values(ts); | ||
223 | tsc2007_send_event(ts); | ||
224 | } | ||
225 | |||
226 | spin_unlock_irqrestore(&ts->lock, flags); | ||
227 | |||
228 | return HRTIMER_NORESTART; | ||
229 | } | 233 | } |
230 | 234 | ||
231 | static irqreturn_t tsc2007_irq(int irq, void *handle) | 235 | static irqreturn_t tsc2007_irq(int irq, void *handle) |
232 | { | 236 | { |
233 | struct tsc2007 *ts = handle; | 237 | struct tsc2007 *ts = handle; |
234 | unsigned long flags; | ||
235 | |||
236 | spin_lock_irqsave(&ts->lock, flags); | ||
237 | 238 | ||
238 | if (likely(ts->get_pendown_state())) { | 239 | if (!ts->get_pendown_state || likely(ts->get_pendown_state())) { |
239 | disable_irq_nosync(ts->irq); | 240 | disable_irq_nosync(ts->irq); |
240 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), | 241 | schedule_delayed_work(&ts->work, |
241 | HRTIMER_MODE_REL); | 242 | msecs_to_jiffies(TS_POLL_DELAY)); |
242 | } | 243 | } |
243 | 244 | ||
244 | if (ts->clear_penirq) | 245 | if (ts->clear_penirq) |
245 | ts->clear_penirq(); | 246 | ts->clear_penirq(); |
246 | 247 | ||
247 | spin_unlock_irqrestore(&ts->lock, flags); | ||
248 | |||
249 | return IRQ_HANDLED; | 248 | return IRQ_HANDLED; |
250 | } | 249 | } |
251 | 250 | ||
252 | static int tsc2007_probe(struct i2c_client *client, | 251 | static void tsc2007_free_irq(struct tsc2007 *ts) |
253 | const struct i2c_device_id *id) | 252 | { |
253 | free_irq(ts->irq, ts); | ||
254 | if (cancel_delayed_work_sync(&ts->work)) { | ||
255 | /* | ||
256 | * Work was pending, therefore we need to enable | ||
257 | * IRQ here to balance the disable_irq() done in the | ||
258 | * interrupt handler. | ||
259 | */ | ||
260 | enable_irq(ts->irq); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | static int __devinit tsc2007_probe(struct i2c_client *client, | ||
265 | const struct i2c_device_id *id) | ||
254 | { | 266 | { |
255 | struct tsc2007 *ts; | 267 | struct tsc2007 *ts; |
256 | struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data; | 268 | struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data; |
257 | struct input_dev *input_dev; | 269 | struct input_dev *input_dev; |
258 | int err; | 270 | int err; |
259 | 271 | ||
260 | if (!pdata || !pdata->get_pendown_state) { | 272 | if (!pdata) { |
261 | dev_err(&client->dev, "platform data is required!\n"); | 273 | dev_err(&client->dev, "platform data is required!\n"); |
262 | return -EINVAL; | 274 | return -EINVAL; |
263 | } | 275 | } |
@@ -274,22 +286,15 @@ static int tsc2007_probe(struct i2c_client *client, | |||
274 | } | 286 | } |
275 | 287 | ||
276 | ts->client = client; | 288 | ts->client = client; |
277 | i2c_set_clientdata(client, ts); | 289 | ts->irq = client->irq; |
278 | |||
279 | ts->input = input_dev; | 290 | ts->input = input_dev; |
280 | 291 | INIT_DELAYED_WORK(&ts->work, tsc2007_work); | |
281 | hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
282 | ts->timer.function = tsc2007_timer; | ||
283 | |||
284 | spin_lock_init(&ts->lock); | ||
285 | 292 | ||
286 | ts->model = pdata->model; | 293 | ts->model = pdata->model; |
287 | ts->x_plate_ohms = pdata->x_plate_ohms; | 294 | ts->x_plate_ohms = pdata->x_plate_ohms; |
288 | ts->get_pendown_state = pdata->get_pendown_state; | 295 | ts->get_pendown_state = pdata->get_pendown_state; |
289 | ts->clear_penirq = pdata->clear_penirq; | 296 | ts->clear_penirq = pdata->clear_penirq; |
290 | 297 | ||
291 | pdata->init_platform_hw(); | ||
292 | |||
293 | snprintf(ts->phys, sizeof(ts->phys), | 298 | snprintf(ts->phys, sizeof(ts->phys), |
294 | "%s/input0", dev_name(&client->dev)); | 299 | "%s/input0", dev_name(&client->dev)); |
295 | 300 | ||
@@ -304,9 +309,8 @@ static int tsc2007_probe(struct i2c_client *client, | |||
304 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); | 309 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); |
305 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); | 310 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); |
306 | 311 | ||
307 | tsc2007_read_values(ts); | 312 | if (pdata->init_platform_hw) |
308 | 313 | pdata->init_platform_hw(); | |
309 | ts->irq = client->irq; | ||
310 | 314 | ||
311 | err = request_irq(ts->irq, tsc2007_irq, 0, | 315 | err = request_irq(ts->irq, tsc2007_irq, 0, |
312 | client->dev.driver->name, ts); | 316 | client->dev.driver->name, ts); |
@@ -315,33 +319,39 @@ static int tsc2007_probe(struct i2c_client *client, | |||
315 | goto err_free_mem; | 319 | goto err_free_mem; |
316 | } | 320 | } |
317 | 321 | ||
322 | /* Prepare for touch readings - power down ADC and enable PENIRQ */ | ||
323 | err = tsc2007_xfer(ts, PWRDOWN); | ||
324 | if (err < 0) | ||
325 | goto err_free_irq; | ||
326 | |||
318 | err = input_register_device(input_dev); | 327 | err = input_register_device(input_dev); |
319 | if (err) | 328 | if (err) |
320 | goto err_free_irq; | 329 | goto err_free_irq; |
321 | 330 | ||
322 | dev_info(&client->dev, "registered with irq (%d)\n", ts->irq); | 331 | i2c_set_clientdata(client, ts); |
323 | 332 | ||
324 | return 0; | 333 | return 0; |
325 | 334 | ||
326 | err_free_irq: | 335 | err_free_irq: |
327 | free_irq(ts->irq, ts); | 336 | tsc2007_free_irq(ts); |
328 | hrtimer_cancel(&ts->timer); | 337 | if (pdata->exit_platform_hw) |
338 | pdata->exit_platform_hw(); | ||
329 | err_free_mem: | 339 | err_free_mem: |
330 | input_free_device(input_dev); | 340 | input_free_device(input_dev); |
331 | kfree(ts); | 341 | kfree(ts); |
332 | return err; | 342 | return err; |
333 | } | 343 | } |
334 | 344 | ||
335 | static int tsc2007_remove(struct i2c_client *client) | 345 | static int __devexit tsc2007_remove(struct i2c_client *client) |
336 | { | 346 | { |
337 | struct tsc2007 *ts = i2c_get_clientdata(client); | 347 | struct tsc2007 *ts = i2c_get_clientdata(client); |
338 | struct tsc2007_platform_data *pdata; | 348 | struct tsc2007_platform_data *pdata = client->dev.platform_data; |
339 | 349 | ||
340 | pdata = client->dev.platform_data; | 350 | tsc2007_free_irq(ts); |
341 | pdata->exit_platform_hw(); | 351 | |
352 | if (pdata->exit_platform_hw) | ||
353 | pdata->exit_platform_hw(); | ||
342 | 354 | ||
343 | free_irq(ts->irq, ts); | ||
344 | hrtimer_cancel(&ts->timer); | ||
345 | input_unregister_device(ts->input); | 355 | input_unregister_device(ts->input); |
346 | kfree(ts); | 356 | kfree(ts); |
347 | 357 | ||
@@ -362,7 +372,7 @@ static struct i2c_driver tsc2007_driver = { | |||
362 | }, | 372 | }, |
363 | .id_table = tsc2007_idtable, | 373 | .id_table = tsc2007_idtable, |
364 | .probe = tsc2007_probe, | 374 | .probe = tsc2007_probe, |
365 | .remove = tsc2007_remove, | 375 | .remove = __devexit_p(tsc2007_remove), |
366 | }; | 376 | }; |
367 | 377 | ||
368 | static int __init tsc2007_init(void) | 378 | static int __init tsc2007_init(void) |
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 6954f5500108..095f84b1f56e 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
@@ -128,9 +128,10 @@ static inline unsigned int ucb1400_ts_read_yres(struct ucb1400_ts *ucb) | |||
128 | return ucb1400_adc_read(ucb->ac97, 0, adcsync); | 128 | return ucb1400_adc_read(ucb->ac97, 0, adcsync); |
129 | } | 129 | } |
130 | 130 | ||
131 | static inline int ucb1400_ts_pen_down(struct snd_ac97 *ac97) | 131 | static inline int ucb1400_ts_pen_up(struct snd_ac97 *ac97) |
132 | { | 132 | { |
133 | unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR); | 133 | unsigned short val = ucb1400_reg_read(ac97, UCB_TS_CR); |
134 | |||
134 | return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW); | 135 | return val & (UCB_TS_CR_TSPX_LOW | UCB_TS_CR_TSMX_LOW); |
135 | } | 136 | } |
136 | 137 | ||
@@ -170,11 +171,11 @@ static void ucb1400_handle_pending_irq(struct ucb1400_ts *ucb) | |||
170 | ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, isr); | 171 | ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, isr); |
171 | ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0); | 172 | ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0); |
172 | 173 | ||
173 | if (isr & UCB_IE_TSPX) { | 174 | if (isr & UCB_IE_TSPX) |
174 | ucb1400_ts_irq_disable(ucb->ac97); | 175 | ucb1400_ts_irq_disable(ucb->ac97); |
175 | enable_irq(ucb->irq); | 176 | else |
176 | } else | 177 | dev_dbg(&ucb->ts_idev->dev, "ucb1400: unexpected IE_STATUS = %#x\n", isr); |
177 | printk(KERN_ERR "ucb1400: unexpected IE_STATUS = %#x\n", isr); | 178 | enable_irq(ucb->irq); |
178 | } | 179 | } |
179 | 180 | ||
180 | static int ucb1400_ts_thread(void *_ucb) | 181 | static int ucb1400_ts_thread(void *_ucb) |
@@ -209,7 +210,7 @@ static int ucb1400_ts_thread(void *_ucb) | |||
209 | 210 | ||
210 | msleep(10); | 211 | msleep(10); |
211 | 212 | ||
212 | if (ucb1400_ts_pen_down(ucb->ac97)) { | 213 | if (ucb1400_ts_pen_up(ucb->ac97)) { |
213 | ucb1400_ts_irq_enable(ucb->ac97); | 214 | ucb1400_ts_irq_enable(ucb->ac97); |
214 | 215 | ||
215 | /* | 216 | /* |
@@ -345,6 +346,7 @@ static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb) | |||
345 | static int ucb1400_ts_probe(struct platform_device *dev) | 346 | static int ucb1400_ts_probe(struct platform_device *dev) |
346 | { | 347 | { |
347 | int error, x_res, y_res; | 348 | int error, x_res, y_res; |
349 | u16 fcsr; | ||
348 | struct ucb1400_ts *ucb = dev->dev.platform_data; | 350 | struct ucb1400_ts *ucb = dev->dev.platform_data; |
349 | 351 | ||
350 | ucb->ts_idev = input_allocate_device(); | 352 | ucb->ts_idev = input_allocate_device(); |
@@ -382,6 +384,14 @@ static int ucb1400_ts_probe(struct platform_device *dev) | |||
382 | ucb->ts_idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); | 384 | ucb->ts_idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); |
383 | ucb->ts_idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 385 | ucb->ts_idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
384 | 386 | ||
387 | /* | ||
388 | * Enable ADC filter to prevent horrible jitter on Colibri. | ||
389 | * This also further reduces jitter on boards where ADCSYNC | ||
390 | * pin is connected. | ||
391 | */ | ||
392 | fcsr = ucb1400_reg_read(ucb->ac97, UCB_FCSR); | ||
393 | ucb1400_reg_write(ucb->ac97, UCB_FCSR, fcsr | UCB_FCSR_AVE); | ||
394 | |||
385 | ucb1400_adc_enable(ucb->ac97); | 395 | ucb1400_adc_enable(ucb->ac97); |
386 | x_res = ucb1400_ts_read_xres(ucb); | 396 | x_res = ucb1400_ts_read_xres(ucb); |
387 | y_res = ucb1400_ts_read_yres(ucb); | 397 | y_res = ucb1400_ts_read_yres(ucb); |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index fb7cb9bdfbd5..68ece5801a58 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -13,6 +13,7 @@ | |||
13 | * - IdealTEK URTC1000 | 13 | * - IdealTEK URTC1000 |
14 | * - General Touch | 14 | * - General Touch |
15 | * - GoTop Super_Q2/GogoPen/PenPower tablets | 15 | * - GoTop Super_Q2/GogoPen/PenPower tablets |
16 | * - JASTEC USB touch controller/DigiTech DTR-02U | ||
16 | * | 17 | * |
17 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> | 18 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> |
18 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 19 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
@@ -118,6 +119,8 @@ enum { | |||
118 | DEVTYPE_IDEALTEK, | 119 | DEVTYPE_IDEALTEK, |
119 | DEVTYPE_GENERAL_TOUCH, | 120 | DEVTYPE_GENERAL_TOUCH, |
120 | DEVTYPE_GOTOP, | 121 | DEVTYPE_GOTOP, |
122 | DEVTYPE_JASTEC, | ||
123 | DEVTYPE_E2I, | ||
121 | }; | 124 | }; |
122 | 125 | ||
123 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 126 | #define USB_DEVICE_HID_CLASS(vend, prod) \ |
@@ -191,11 +194,51 @@ static struct usb_device_id usbtouch_devices[] = { | |||
191 | {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, | 194 | {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, |
192 | #endif | 195 | #endif |
193 | 196 | ||
197 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
198 | {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, | ||
199 | #endif | ||
200 | |||
201 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
202 | {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, | ||
203 | #endif | ||
194 | {} | 204 | {} |
195 | }; | 205 | }; |
196 | 206 | ||
197 | 207 | ||
198 | /***************************************************************************** | 208 | /***************************************************************************** |
209 | * e2i Part | ||
210 | */ | ||
211 | |||
212 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
213 | static int e2i_init(struct usbtouch_usb *usbtouch) | ||
214 | { | ||
215 | int ret; | ||
216 | |||
217 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | ||
218 | 0x01, 0x02, 0x0000, 0x0081, | ||
219 | NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
220 | |||
221 | dbg("%s - usb_control_msg - E2I_RESET - bytes|err: %d", | ||
222 | __func__, ret); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
227 | { | ||
228 | int tmp = (pkt[0] << 8) | pkt[1]; | ||
229 | dev->x = (pkt[2] << 8) | pkt[3]; | ||
230 | dev->y = (pkt[4] << 8) | pkt[5]; | ||
231 | |||
232 | tmp = tmp - 0xA000; | ||
233 | dev->touch = (tmp > 0); | ||
234 | dev->press = (tmp > 0 ? tmp : 0); | ||
235 | |||
236 | return 1; | ||
237 | } | ||
238 | #endif | ||
239 | |||
240 | |||
241 | /***************************************************************************** | ||
199 | * eGalax part | 242 | * eGalax part |
200 | */ | 243 | */ |
201 | 244 | ||
@@ -559,6 +602,21 @@ static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
559 | dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; | 602 | dev->x = ((pkt[1] & 0x38) << 4) | pkt[2]; |
560 | dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; | 603 | dev->y = ((pkt[1] & 0x07) << 7) | pkt[3]; |
561 | dev->touch = pkt[0] & 0x01; | 604 | dev->touch = pkt[0] & 0x01; |
605 | |||
606 | return 1; | ||
607 | } | ||
608 | #endif | ||
609 | |||
610 | /***************************************************************************** | ||
611 | * JASTEC Part | ||
612 | */ | ||
613 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
614 | static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
615 | { | ||
616 | dev->x = ((pkt[0] & 0x3f) << 6) | (pkt[2] & 0x3f); | ||
617 | dev->y = ((pkt[1] & 0x3f) << 6) | (pkt[3] & 0x3f); | ||
618 | dev->touch = (pkt[0] & 0x40) >> 6; | ||
619 | |||
562 | return 1; | 620 | return 1; |
563 | } | 621 | } |
564 | #endif | 622 | #endif |
@@ -702,6 +760,29 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
702 | .read_data = gotop_read_data, | 760 | .read_data = gotop_read_data, |
703 | }, | 761 | }, |
704 | #endif | 762 | #endif |
763 | |||
764 | #ifdef CONFIG_TOUCHSCREEN_USB_JASTEC | ||
765 | [DEVTYPE_JASTEC] = { | ||
766 | .min_xc = 0x0, | ||
767 | .max_xc = 0x0fff, | ||
768 | .min_yc = 0x0, | ||
769 | .max_yc = 0x0fff, | ||
770 | .rept_size = 4, | ||
771 | .read_data = jastec_read_data, | ||
772 | }, | ||
773 | #endif | ||
774 | |||
775 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | ||
776 | [DEVTYPE_E2I] = { | ||
777 | .min_xc = 0x0, | ||
778 | .max_xc = 0x7fff, | ||
779 | .min_yc = 0x0, | ||
780 | .max_yc = 0x7fff, | ||
781 | .rept_size = 6, | ||
782 | .init = e2i_init, | ||
783 | .read_data = e2i_read_data, | ||
784 | }, | ||
785 | #endif | ||
705 | }; | 786 | }; |
706 | 787 | ||
707 | 788 | ||
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index 6071f5882572..6ccbdbbf33fe 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/clk.h> | ||
16 | #include <linux/input.h> | 17 | #include <linux/input.h> |
17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
18 | 19 | ||
@@ -47,8 +48,8 @@ enum ts_state { | |||
47 | struct w90p910_ts { | 48 | struct w90p910_ts { |
48 | struct input_dev *input; | 49 | struct input_dev *input; |
49 | struct timer_list timer; | 50 | struct timer_list timer; |
51 | struct clk *clk; | ||
50 | int irq_num; | 52 | int irq_num; |
51 | void __iomem *clocken; | ||
52 | void __iomem *ts_reg; | 53 | void __iomem *ts_reg; |
53 | spinlock_t lock; | 54 | spinlock_t lock; |
54 | enum ts_state state; | 55 | enum ts_state state; |
@@ -166,8 +167,7 @@ static int w90p910_open(struct input_dev *dev) | |||
166 | unsigned long val; | 167 | unsigned long val; |
167 | 168 | ||
168 | /* enable the ADC clock */ | 169 | /* enable the ADC clock */ |
169 | val = __raw_readl(w90p910_ts->clocken); | 170 | clk_enable(w90p910_ts->clk); |
170 | __raw_writel(val | ADC_CLK_EN, w90p910_ts->clocken); | ||
171 | 171 | ||
172 | __raw_writel(ADC_RST1, w90p910_ts->ts_reg); | 172 | __raw_writel(ADC_RST1, w90p910_ts->ts_reg); |
173 | msleep(1); | 173 | msleep(1); |
@@ -211,8 +211,7 @@ static void w90p910_close(struct input_dev *dev) | |||
211 | del_timer_sync(&w90p910_ts->timer); | 211 | del_timer_sync(&w90p910_ts->timer); |
212 | 212 | ||
213 | /* stop the ADC clock */ | 213 | /* stop the ADC clock */ |
214 | val = __raw_readl(w90p910_ts->clocken); | 214 | clk_disable(w90p910_ts->clk); |
215 | __raw_writel(val & ~ADC_CLK_EN, w90p910_ts->clocken); | ||
216 | } | 215 | } |
217 | 216 | ||
218 | static int __devinit w90x900ts_probe(struct platform_device *pdev) | 217 | static int __devinit w90x900ts_probe(struct platform_device *pdev) |
@@ -241,26 +240,24 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev) | |||
241 | goto fail1; | 240 | goto fail1; |
242 | } | 241 | } |
243 | 242 | ||
244 | if (!request_mem_region(res->start, res->end - res->start + 1, | 243 | if (!request_mem_region(res->start, resource_size(res), |
245 | pdev->name)) { | 244 | pdev->name)) { |
246 | err = -EBUSY; | 245 | err = -EBUSY; |
247 | goto fail1; | 246 | goto fail1; |
248 | } | 247 | } |
249 | 248 | ||
250 | w90p910_ts->ts_reg = ioremap(res->start, res->end - res->start + 1); | 249 | w90p910_ts->ts_reg = ioremap(res->start, resource_size(res)); |
251 | if (!w90p910_ts->ts_reg) { | 250 | if (!w90p910_ts->ts_reg) { |
252 | err = -ENOMEM; | 251 | err = -ENOMEM; |
253 | goto fail2; | 252 | goto fail2; |
254 | } | 253 | } |
255 | 254 | ||
256 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 255 | w90p910_ts->clk = clk_get(&pdev->dev, NULL); |
257 | if (!res) { | 256 | if (IS_ERR(w90p910_ts->clk)) { |
258 | err = -ENXIO; | 257 | err = PTR_ERR(w90p910_ts->clk); |
259 | goto fail3; | 258 | goto fail3; |
260 | } | 259 | } |
261 | 260 | ||
262 | w90p910_ts->clocken = (void __iomem *)res->start; | ||
263 | |||
264 | input_dev->name = "W90P910 TouchScreen"; | 261 | input_dev->name = "W90P910 TouchScreen"; |
265 | input_dev->phys = "w90p910ts/event0"; | 262 | input_dev->phys = "w90p910ts/event0"; |
266 | input_dev->id.bustype = BUS_HOST; | 263 | input_dev->id.bustype = BUS_HOST; |
@@ -283,20 +280,21 @@ static int __devinit w90x900ts_probe(struct platform_device *pdev) | |||
283 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, | 280 | if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt, |
284 | IRQF_DISABLED, "w90p910ts", w90p910_ts)) { | 281 | IRQF_DISABLED, "w90p910ts", w90p910_ts)) { |
285 | err = -EBUSY; | 282 | err = -EBUSY; |
286 | goto fail3; | 283 | goto fail4; |
287 | } | 284 | } |
288 | 285 | ||
289 | err = input_register_device(w90p910_ts->input); | 286 | err = input_register_device(w90p910_ts->input); |
290 | if (err) | 287 | if (err) |
291 | goto fail4; | 288 | goto fail5; |
292 | 289 | ||
293 | platform_set_drvdata(pdev, w90p910_ts); | 290 | platform_set_drvdata(pdev, w90p910_ts); |
294 | 291 | ||
295 | return 0; | 292 | return 0; |
296 | 293 | ||
297 | fail4: free_irq(w90p910_ts->irq_num, w90p910_ts); | 294 | fail5: free_irq(w90p910_ts->irq_num, w90p910_ts); |
295 | fail4: clk_put(w90p910_ts->clk); | ||
298 | fail3: iounmap(w90p910_ts->ts_reg); | 296 | fail3: iounmap(w90p910_ts->ts_reg); |
299 | fail2: release_mem_region(res->start, res->end - res->start + 1); | 297 | fail2: release_mem_region(res->start, resource_size(res)); |
300 | fail1: input_free_device(input_dev); | 298 | fail1: input_free_device(input_dev); |
301 | kfree(w90p910_ts); | 299 | kfree(w90p910_ts); |
302 | return err; | 300 | return err; |
@@ -311,8 +309,10 @@ static int __devexit w90x900ts_remove(struct platform_device *pdev) | |||
311 | del_timer_sync(&w90p910_ts->timer); | 309 | del_timer_sync(&w90p910_ts->timer); |
312 | iounmap(w90p910_ts->ts_reg); | 310 | iounmap(w90p910_ts->ts_reg); |
313 | 311 | ||
312 | clk_put(w90p910_ts->clk); | ||
313 | |||
314 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 314 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
315 | release_mem_region(res->start, res->end - res->start + 1); | 315 | release_mem_region(res->start, resource_size(res)); |
316 | 316 | ||
317 | input_unregister_device(w90p910_ts->input); | 317 | input_unregister_device(w90p910_ts->input); |
318 | kfree(w90p910_ts); | 318 | kfree(w90p910_ts); |
@@ -326,7 +326,7 @@ static struct platform_driver w90x900ts_driver = { | |||
326 | .probe = w90x900ts_probe, | 326 | .probe = w90x900ts_probe, |
327 | .remove = __devexit_p(w90x900ts_remove), | 327 | .remove = __devexit_p(w90x900ts_remove), |
328 | .driver = { | 328 | .driver = { |
329 | .name = "w90x900-ts", | 329 | .name = "nuc900-ts", |
330 | .owner = THIS_MODULE, | 330 | .owner = THIS_MODULE, |
331 | }, | 331 | }, |
332 | }; | 332 | }; |
@@ -347,4 +347,4 @@ module_exit(w90x900ts_exit); | |||
347 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); | 347 | MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); |
348 | MODULE_DESCRIPTION("w90p910 touch screen driver!"); | 348 | MODULE_DESCRIPTION("w90p910 touch screen driver!"); |
349 | MODULE_LICENSE("GPL"); | 349 | MODULE_LICENSE("GPL"); |
350 | MODULE_ALIAS("platform:w90p910-ts"); | 350 | MODULE_ALIAS("platform:nuc900-ts"); |
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 2f33a0167644..56dc35c94bb1 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
@@ -25,18 +25,16 @@ MODULE_AUTHOR("Jaya Kumar <jayakumar.lkml@gmail.com>"); | |||
25 | MODULE_DESCRIPTION(DRIVER_DESC); | 25 | MODULE_DESCRIPTION(DRIVER_DESC); |
26 | MODULE_LICENSE("GPL"); | 26 | MODULE_LICENSE("GPL"); |
27 | 27 | ||
28 | /* | ||
29 | * Definitions & global arrays. | ||
30 | */ | ||
31 | |||
32 | #define W8001_MAX_LENGTH 11 | 28 | #define W8001_MAX_LENGTH 11 |
33 | #define W8001_PACKET_LEN 11 | 29 | #define W8001_LEAD_MASK 0x80 |
34 | #define W8001_LEAD_MASK 0x80 | 30 | #define W8001_LEAD_BYTE 0x80 |
35 | #define W8001_LEAD_BYTE 0x80 | 31 | #define W8001_TAB_MASK 0x40 |
36 | #define W8001_TAB_MASK 0x40 | 32 | #define W8001_TAB_BYTE 0x40 |
37 | #define W8001_TAB_BYTE 0x40 | ||
38 | 33 | ||
39 | #define W8001_QUERY_PACKET 0x20 | 34 | #define W8001_QUERY_PACKET 0x20 |
35 | |||
36 | #define W8001_CMD_START '1' | ||
37 | #define W8001_CMD_QUERY '*' | ||
40 | 38 | ||
41 | struct w8001_coord { | 39 | struct w8001_coord { |
42 | u8 rdy; | 40 | u8 rdy; |
@@ -57,18 +55,19 @@ struct w8001_coord { | |||
57 | struct w8001 { | 55 | struct w8001 { |
58 | struct input_dev *dev; | 56 | struct input_dev *dev; |
59 | struct serio *serio; | 57 | struct serio *serio; |
60 | struct mutex cmd_mutex; | ||
61 | struct completion cmd_done; | 58 | struct completion cmd_done; |
62 | int id; | 59 | int id; |
63 | int idx; | 60 | int idx; |
64 | unsigned char expected_packet; | 61 | unsigned char response_type; |
62 | unsigned char response[W8001_MAX_LENGTH]; | ||
65 | unsigned char data[W8001_MAX_LENGTH]; | 63 | unsigned char data[W8001_MAX_LENGTH]; |
66 | unsigned char response[W8001_PACKET_LEN]; | ||
67 | char phys[32]; | 64 | char phys[32]; |
68 | }; | 65 | }; |
69 | 66 | ||
70 | static int parse_data(u8 *data, struct w8001_coord *coord) | 67 | static void parse_data(u8 *data, struct w8001_coord *coord) |
71 | { | 68 | { |
69 | memset(coord, 0, sizeof(*coord)); | ||
70 | |||
72 | coord->rdy = data[0] & 0x20; | 71 | coord->rdy = data[0] & 0x20; |
73 | coord->tsw = data[0] & 0x01; | 72 | coord->tsw = data[0] & 0x01; |
74 | coord->f1 = data[0] & 0x02; | 73 | coord->f1 = data[0] & 0x02; |
@@ -87,15 +86,15 @@ static int parse_data(u8 *data, struct w8001_coord *coord) | |||
87 | 86 | ||
88 | coord->tilt_x = data[7] & 0x7F; | 87 | coord->tilt_x = data[7] & 0x7F; |
89 | coord->tilt_y = data[8] & 0x7F; | 88 | coord->tilt_y = data[8] & 0x7F; |
90 | |||
91 | return 0; | ||
92 | } | 89 | } |
93 | 90 | ||
94 | static void w8001_process_data(struct w8001 *w8001, unsigned char data) | 91 | static irqreturn_t w8001_interrupt(struct serio *serio, |
92 | unsigned char data, unsigned int flags) | ||
95 | { | 93 | { |
94 | struct w8001 *w8001 = serio_get_drvdata(serio); | ||
96 | struct input_dev *dev = w8001->dev; | 95 | struct input_dev *dev = w8001->dev; |
97 | u8 tmp; | ||
98 | struct w8001_coord coord; | 96 | struct w8001_coord coord; |
97 | unsigned char tmp; | ||
99 | 98 | ||
100 | w8001->data[w8001->idx] = data; | 99 | w8001->data[w8001->idx] = data; |
101 | switch (w8001->idx++) { | 100 | switch (w8001->idx++) { |
@@ -105,12 +104,13 @@ static void w8001_process_data(struct w8001 *w8001, unsigned char data) | |||
105 | w8001->idx = 0; | 104 | w8001->idx = 0; |
106 | } | 105 | } |
107 | break; | 106 | break; |
107 | |||
108 | case 8: | 108 | case 8: |
109 | tmp = w8001->data[0] & W8001_TAB_MASK; | 109 | tmp = w8001->data[0] & W8001_TAB_MASK; |
110 | if (unlikely(tmp == W8001_TAB_BYTE)) | 110 | if (unlikely(tmp == W8001_TAB_BYTE)) |
111 | break; | 111 | break; |
112 | |||
112 | w8001->idx = 0; | 113 | w8001->idx = 0; |
113 | memset(&coord, 0, sizeof(coord)); | ||
114 | parse_data(w8001->data, &coord); | 114 | parse_data(w8001->data, &coord); |
115 | input_report_abs(dev, ABS_X, coord.x); | 115 | input_report_abs(dev, ABS_X, coord.x); |
116 | input_report_abs(dev, ABS_Y, coord.y); | 116 | input_report_abs(dev, ABS_Y, coord.y); |
@@ -118,86 +118,48 @@ static void w8001_process_data(struct w8001 *w8001, unsigned char data) | |||
118 | input_report_key(dev, BTN_TOUCH, coord.tsw); | 118 | input_report_key(dev, BTN_TOUCH, coord.tsw); |
119 | input_sync(dev); | 119 | input_sync(dev); |
120 | break; | 120 | break; |
121 | |||
121 | case 10: | 122 | case 10: |
122 | w8001->idx = 0; | 123 | w8001->idx = 0; |
123 | memcpy(w8001->response, &w8001->data, W8001_PACKET_LEN); | 124 | memcpy(w8001->response, w8001->data, W8001_MAX_LENGTH); |
124 | w8001->expected_packet = W8001_QUERY_PACKET; | 125 | w8001->response_type = W8001_QUERY_PACKET; |
125 | complete(&w8001->cmd_done); | 126 | complete(&w8001->cmd_done); |
126 | break; | 127 | break; |
127 | } | 128 | } |
128 | } | ||
129 | |||
130 | |||
131 | static irqreturn_t w8001_interrupt(struct serio *serio, | ||
132 | unsigned char data, unsigned int flags) | ||
133 | { | ||
134 | struct w8001 *w8001 = serio_get_drvdata(serio); | ||
135 | |||
136 | w8001_process_data(w8001, data); | ||
137 | 129 | ||
138 | return IRQ_HANDLED; | 130 | return IRQ_HANDLED; |
139 | } | 131 | } |
140 | 132 | ||
141 | static int w8001_async_command(struct w8001 *w8001, unsigned char *packet, | 133 | static int w8001_command(struct w8001 *w8001, unsigned char command, |
142 | int len) | 134 | bool wait_response) |
143 | { | ||
144 | int rc = -1; | ||
145 | int i; | ||
146 | |||
147 | mutex_lock(&w8001->cmd_mutex); | ||
148 | |||
149 | for (i = 0; i < len; i++) { | ||
150 | if (serio_write(w8001->serio, packet[i])) | ||
151 | goto out; | ||
152 | } | ||
153 | rc = 0; | ||
154 | |||
155 | out: | ||
156 | mutex_unlock(&w8001->cmd_mutex); | ||
157 | return rc; | ||
158 | } | ||
159 | |||
160 | static int w8001_command(struct w8001 *w8001, unsigned char *packet, int len) | ||
161 | { | 135 | { |
162 | int rc = -1; | 136 | int rc; |
163 | int i; | ||
164 | 137 | ||
165 | mutex_lock(&w8001->cmd_mutex); | 138 | w8001->response_type = 0; |
166 | |||
167 | serio_pause_rx(w8001->serio); | ||
168 | init_completion(&w8001->cmd_done); | 139 | init_completion(&w8001->cmd_done); |
169 | serio_continue_rx(w8001->serio); | ||
170 | |||
171 | for (i = 0; i < len; i++) { | ||
172 | if (serio_write(w8001->serio, packet[i])) | ||
173 | goto out; | ||
174 | } | ||
175 | 140 | ||
176 | wait_for_completion_timeout(&w8001->cmd_done, HZ); | 141 | rc = serio_write(w8001->serio, command); |
142 | if (rc == 0 && wait_response) { | ||
177 | 143 | ||
178 | if (w8001->expected_packet == W8001_QUERY_PACKET) { | 144 | wait_for_completion_timeout(&w8001->cmd_done, HZ); |
179 | /* We are back in reporting mode, the query was ACKed */ | 145 | if (w8001->response_type != W8001_QUERY_PACKET) |
180 | memcpy(packet, w8001->response, W8001_PACKET_LEN); | 146 | rc = -EIO; |
181 | rc = 0; | ||
182 | } | 147 | } |
183 | 148 | ||
184 | out: | ||
185 | mutex_unlock(&w8001->cmd_mutex); | ||
186 | return rc; | 149 | return rc; |
187 | } | 150 | } |
188 | 151 | ||
189 | static int w8001_setup(struct w8001 *w8001) | 152 | static int w8001_setup(struct w8001 *w8001) |
190 | { | 153 | { |
191 | struct w8001_coord coord; | ||
192 | struct input_dev *dev = w8001->dev; | 154 | struct input_dev *dev = w8001->dev; |
193 | unsigned char start[1] = { '1' }; | 155 | struct w8001_coord coord; |
194 | unsigned char query[11] = { '*' }; | 156 | int error; |
195 | 157 | ||
196 | if (w8001_command(w8001, query, 1)) | 158 | error = w8001_command(w8001, W8001_CMD_QUERY, true); |
197 | return -1; | 159 | if (error) |
160 | return error; | ||
198 | 161 | ||
199 | memset(&coord, 0, sizeof(coord)); | 162 | parse_data(w8001->response, &coord); |
200 | parse_data(query, &coord); | ||
201 | 163 | ||
202 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); | 164 | input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); |
203 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); | 165 | input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); |
@@ -205,10 +167,7 @@ static int w8001_setup(struct w8001 *w8001) | |||
205 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); | 167 | input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); |
206 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); | 168 | input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); |
207 | 169 | ||
208 | if (w8001_async_command(w8001, start, 1)) | 170 | return w8001_command(w8001, W8001_CMD_START, false); |
209 | return -1; | ||
210 | |||
211 | return 0; | ||
212 | } | 171 | } |
213 | 172 | ||
214 | /* | 173 | /* |
@@ -249,7 +208,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
249 | w8001->serio = serio; | 208 | w8001->serio = serio; |
250 | w8001->id = serio->id.id; | 209 | w8001->id = serio->id.id; |
251 | w8001->dev = input_dev; | 210 | w8001->dev = input_dev; |
252 | mutex_init(&w8001->cmd_mutex); | ||
253 | init_completion(&w8001->cmd_done); | 211 | init_completion(&w8001->cmd_done); |
254 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); | 212 | snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); |
255 | 213 | ||
@@ -269,7 +227,8 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) | |||
269 | if (err) | 227 | if (err) |
270 | goto fail2; | 228 | goto fail2; |
271 | 229 | ||
272 | if (w8001_setup(w8001)) | 230 | err = w8001_setup(w8001); |
231 | if (err) | ||
273 | goto fail3; | 232 | goto fail3; |
274 | 233 | ||
275 | err = input_register_device(w8001->dev); | 234 | err = input_register_device(w8001->dev); |
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index cf8cbc60d5ce..f944918466e5 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
@@ -204,7 +204,7 @@ void wm97xx_set_gpio(struct wm97xx *wm, u32 gpio, | |||
204 | else | 204 | else |
205 | reg &= ~gpio; | 205 | reg &= ~gpio; |
206 | 206 | ||
207 | if (wm->id == WM9712_ID2) | 207 | if (wm->id == WM9712_ID2 && wm->variant != WM97xx_WM1613) |
208 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1); | 208 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg << 1); |
209 | else | 209 | else |
210 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg); | 210 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, reg); |
@@ -307,7 +307,7 @@ static void wm97xx_pen_irq_worker(struct work_struct *work) | |||
307 | WM97XX_GPIO_13); | 307 | WM97XX_GPIO_13); |
308 | } | 308 | } |
309 | 309 | ||
310 | if (wm->id == WM9712_ID2) | 310 | if (wm->id == WM9712_ID2 && wm->variant != WM97xx_WM1613) |
311 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & | 311 | wm97xx_reg_write(wm, AC97_GPIO_STATUS, (status & |
312 | ~WM97XX_GPIO_13) << 1); | 312 | ~WM97XX_GPIO_13) << 1); |
313 | else | 313 | else |
@@ -583,6 +583,8 @@ static int wm97xx_probe(struct device *dev) | |||
583 | 583 | ||
584 | wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2); | 584 | wm->id = wm97xx_reg_read(wm, AC97_VENDOR_ID2); |
585 | 585 | ||
586 | wm->variant = WM97xx_GENERIC; | ||
587 | |||
586 | dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff); | 588 | dev_info(wm->dev, "detected a wm97%02x codec\n", wm->id & 0xff); |
587 | 589 | ||
588 | switch (wm->id & 0xff) { | 590 | switch (wm->id & 0xff) { |