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) { |
