diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-24 13:34:29 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-24 13:34:29 -0400 |
| commit | 2c01e7bc46f10e9190818437e564f7e0db875ae9 (patch) | |
| tree | 8b06c85d69754f7df27f7fb42520f6e2ceaea907 /drivers | |
| parent | ab11ca34eea8fda7a1a9302d86f6ef6108ffd68f (diff) | |
| parent | e644dae645e167d154c0526358940986682a72b0 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input layer updates from Dmitry Torokhov:
- a bunch of new drivers (DA9052/53 touchscreenn controller, Synaptics
Navpoint, LM8333 keypads, Wacom I2C touhscreen);
- updates to existing touchpad drivers (ALPS, Sntelic);
- Wacom driver now supports Intuos5;
- device-tree bindings in numerous drivers;
- other cleanups and fixes.
Fix annoying conflict in drivers/input/tablet/wacom_wac.c that I think
implies that the input layer device naming is broken, but let's see. I
brough it up with Dmitry.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (57 commits)
Input: matrix-keymap - fix building keymaps
Input: spear-keyboard - document DT bindings
Input: spear-keyboard - add device tree bindings
Input: matrix-keymap - wire up device tree support
Input: matrix-keymap - uninline and prepare for device tree support
Input: adp5588 - add support for gpio names
Input: omap-keypad - dynamically handle register offsets
Input: synaptics - fix compile warning
MAINTAINERS: adjust input-related patterns
Input: ALPS - switch to using input_mt_report_finger_count
Input: ALPS - add semi-MT support for v4 protocol
Input: Add Synaptics NavPoint (PXA27x SSP/SPI) driver
Input: atmel_mxt_ts - dump each message on just 1 line
Input: atmel_mxt_ts - do not read extra (checksum) byte
Input: atmel_mxt_ts - verify object size in mxt_write_object
Input: atmel_mxt_ts - only allow root to update firmware
Input: atmel_mxt_ts - use CONFIG_PM_SLEEP
Input: sentelic - report device's production serial number
Input: tl6040-vibra - Device Tree support
Input: evdev - properly handle read/write with count 0
...
Diffstat (limited to 'drivers')
95 files changed, 2694 insertions, 1249 deletions
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 332597980817..55f7e57d4e42 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig | |||
| @@ -25,10 +25,6 @@ config INPUT | |||
| 25 | 25 | ||
| 26 | if INPUT | 26 | if INPUT |
| 27 | 27 | ||
| 28 | config INPUT_OF_MATRIX_KEYMAP | ||
| 29 | depends on USE_OF | ||
| 30 | bool | ||
| 31 | |||
| 32 | config INPUT_FF_MEMLESS | 28 | config INPUT_FF_MEMLESS |
| 33 | tristate "Support for memoryless force-feedback devices" | 29 | tristate "Support for memoryless force-feedback devices" |
| 34 | help | 30 | help |
| @@ -68,6 +64,19 @@ config INPUT_SPARSEKMAP | |||
| 68 | To compile this driver as a module, choose M here: the | 64 | To compile this driver as a module, choose M here: the |
| 69 | module will be called sparse-keymap. | 65 | module will be called sparse-keymap. |
| 70 | 66 | ||
| 67 | config INPUT_MATRIXKMAP | ||
| 68 | tristate "Matrix keymap support library" | ||
| 69 | help | ||
| 70 | Say Y here if you are using a driver for an input | ||
| 71 | device that uses matrix keymap. This option is only | ||
| 72 | useful for out-of-tree drivers since in-tree drivers | ||
| 73 | select it automatically. | ||
| 74 | |||
| 75 | If unsure, say N. | ||
| 76 | |||
| 77 | To compile this driver as a module, choose M here: the | ||
| 78 | module will be called matrix-keymap. | ||
| 79 | |||
| 71 | comment "Userland interfaces" | 80 | comment "Userland interfaces" |
| 72 | 81 | ||
| 73 | config INPUT_MOUSEDEV | 82 | config INPUT_MOUSEDEV |
diff --git a/drivers/input/Makefile b/drivers/input/Makefile index b173a13a73ca..5ca3f631497f 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile | |||
| @@ -10,6 +10,7 @@ input-core-y := input.o input-compat.o input-mt.o ff-core.o | |||
| 10 | obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o | 10 | obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o |
| 11 | obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o | 11 | obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o |
| 12 | obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o | 12 | obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o |
| 13 | obj-$(CONFIG_INPUT_MATRIXKMAP) += matrix-keymap.o | ||
| 13 | 14 | ||
| 14 | obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o | 15 | obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o |
| 15 | obj-$(CONFIG_INPUT_JOYDEV) += joydev.o | 16 | obj-$(CONFIG_INPUT_JOYDEV) += joydev.o |
| @@ -24,4 +25,3 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/ | |||
| 24 | obj-$(CONFIG_INPUT_MISC) += misc/ | 25 | obj-$(CONFIG_INPUT_MISC) += misc/ |
| 25 | 26 | ||
| 26 | obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o | 27 | obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o |
| 27 | obj-$(CONFIG_INPUT_OF_MATRIX_KEYMAP) += of_keymap.o | ||
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 4b2e10d5d641..6c58bfff01a3 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
| @@ -180,7 +180,10 @@ static int evdev_grab(struct evdev *evdev, struct evdev_client *client) | |||
| 180 | 180 | ||
| 181 | static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client) | 181 | static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client) |
| 182 | { | 182 | { |
| 183 | if (evdev->grab != client) | 183 | struct evdev_client *grab = rcu_dereference_protected(evdev->grab, |
| 184 | lockdep_is_held(&evdev->mutex)); | ||
| 185 | |||
| 186 | if (grab != client) | ||
| 184 | return -EINVAL; | 187 | return -EINVAL; |
| 185 | 188 | ||
| 186 | rcu_assign_pointer(evdev->grab, NULL); | 189 | rcu_assign_pointer(evdev->grab, NULL); |
| @@ -259,8 +262,7 @@ static int evdev_release(struct inode *inode, struct file *file) | |||
| 259 | struct evdev *evdev = client->evdev; | 262 | struct evdev *evdev = client->evdev; |
| 260 | 263 | ||
| 261 | mutex_lock(&evdev->mutex); | 264 | mutex_lock(&evdev->mutex); |
| 262 | if (evdev->grab == client) | 265 | evdev_ungrab(evdev, client); |
| 263 | evdev_ungrab(evdev, client); | ||
| 264 | mutex_unlock(&evdev->mutex); | 266 | mutex_unlock(&evdev->mutex); |
| 265 | 267 | ||
| 266 | evdev_detach_client(evdev, client); | 268 | evdev_detach_client(evdev, client); |
| @@ -343,7 +345,7 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, | |||
| 343 | struct input_event event; | 345 | struct input_event event; |
| 344 | int retval = 0; | 346 | int retval = 0; |
| 345 | 347 | ||
| 346 | if (count < input_event_size()) | 348 | if (count != 0 && count < input_event_size()) |
| 347 | return -EINVAL; | 349 | return -EINVAL; |
| 348 | 350 | ||
| 349 | retval = mutex_lock_interruptible(&evdev->mutex); | 351 | retval = mutex_lock_interruptible(&evdev->mutex); |
| @@ -355,7 +357,8 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, | |||
| 355 | goto out; | 357 | goto out; |
| 356 | } | 358 | } |
| 357 | 359 | ||
| 358 | do { | 360 | while (retval + input_event_size() <= count) { |
| 361 | |||
| 359 | if (input_event_from_user(buffer + retval, &event)) { | 362 | if (input_event_from_user(buffer + retval, &event)) { |
| 360 | retval = -EFAULT; | 363 | retval = -EFAULT; |
| 361 | goto out; | 364 | goto out; |
| @@ -364,7 +367,7 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, | |||
| 364 | 367 | ||
| 365 | input_inject_event(&evdev->handle, | 368 | input_inject_event(&evdev->handle, |
| 366 | event.type, event.code, event.value); | 369 | event.type, event.code, event.value); |
| 367 | } while (retval + input_event_size() <= count); | 370 | } |
| 368 | 371 | ||
| 369 | out: | 372 | out: |
| 370 | mutex_unlock(&evdev->mutex); | 373 | mutex_unlock(&evdev->mutex); |
| @@ -395,35 +398,49 @@ static ssize_t evdev_read(struct file *file, char __user *buffer, | |||
| 395 | struct evdev_client *client = file->private_data; | 398 | struct evdev_client *client = file->private_data; |
| 396 | struct evdev *evdev = client->evdev; | 399 | struct evdev *evdev = client->evdev; |
| 397 | struct input_event event; | 400 | struct input_event event; |
| 398 | int retval = 0; | 401 | size_t read = 0; |
| 402 | int error; | ||
| 399 | 403 | ||
| 400 | if (count < input_event_size()) | 404 | if (count != 0 && count < input_event_size()) |
| 401 | return -EINVAL; | 405 | return -EINVAL; |
| 402 | 406 | ||
| 403 | if (!(file->f_flags & O_NONBLOCK)) { | 407 | for (;;) { |
| 404 | retval = wait_event_interruptible(evdev->wait, | 408 | if (!evdev->exist) |
| 405 | client->packet_head != client->tail || | 409 | return -ENODEV; |
| 406 | !evdev->exist); | ||
| 407 | if (retval) | ||
| 408 | return retval; | ||
| 409 | } | ||
| 410 | 410 | ||
| 411 | if (!evdev->exist) | 411 | if (client->packet_head == client->tail && |
| 412 | return -ENODEV; | 412 | (file->f_flags & O_NONBLOCK)) |
| 413 | return -EAGAIN; | ||
| 413 | 414 | ||
| 414 | while (retval + input_event_size() <= count && | 415 | /* |
| 415 | evdev_fetch_next_event(client, &event)) { | 416 | * count == 0 is special - no IO is done but we check |
| 417 | * for error conditions (see above). | ||
| 418 | */ | ||
| 419 | if (count == 0) | ||
| 420 | break; | ||
| 416 | 421 | ||
| 417 | if (input_event_to_user(buffer + retval, &event)) | 422 | while (read + input_event_size() <= count && |
| 418 | return -EFAULT; | 423 | evdev_fetch_next_event(client, &event)) { |
| 419 | 424 | ||
| 420 | retval += input_event_size(); | 425 | if (input_event_to_user(buffer + read, &event)) |
| 421 | } | 426 | return -EFAULT; |
| 422 | 427 | ||
| 423 | if (retval == 0 && (file->f_flags & O_NONBLOCK)) | 428 | read += input_event_size(); |
| 424 | return -EAGAIN; | 429 | } |
| 425 | 430 | ||
| 426 | return retval; | 431 | if (read) |
| 432 | break; | ||
| 433 | |||
| 434 | if (!(file->f_flags & O_NONBLOCK)) { | ||
| 435 | error = wait_event_interruptible(evdev->wait, | ||
| 436 | client->packet_head != client->tail || | ||
| 437 | !evdev->exist); | ||
| 438 | if (error) | ||
| 439 | return error; | ||
| 440 | } | ||
| 441 | } | ||
| 442 | |||
| 443 | return read; | ||
| 427 | } | 444 | } |
| 428 | 445 | ||
| 429 | /* No kernel lock - fine */ | 446 | /* No kernel lock - fine */ |
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c index 422aa0a6b77f..daceafe7ee7d 100644 --- a/drivers/input/gameport/emu10k1-gp.c +++ b/drivers/input/gameport/emu10k1-gp.c | |||
| @@ -125,15 +125,4 @@ static struct pci_driver emu_driver = { | |||
| 125 | .remove = __devexit_p(emu_remove), | 125 | .remove = __devexit_p(emu_remove), |
| 126 | }; | 126 | }; |
| 127 | 127 | ||
| 128 | static int __init emu_init(void) | 128 | module_pci_driver(emu_driver); |
| 129 | { | ||
| 130 | return pci_register_driver(&emu_driver); | ||
| 131 | } | ||
| 132 | |||
| 133 | static void __exit emu_exit(void) | ||
| 134 | { | ||
| 135 | pci_unregister_driver(&emu_driver); | ||
| 136 | } | ||
| 137 | |||
| 138 | module_init(emu_init); | ||
| 139 | module_exit(emu_exit); | ||
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index a3b70ff21018..48ad3829ff20 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c | |||
| @@ -144,6 +144,7 @@ static const struct pci_device_id fm801_gp_id_table[] = { | |||
| 144 | { PCI_VENDOR_ID_FORTEMEDIA, PCI_DEVICE_ID_FM801_GP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 144 | { PCI_VENDOR_ID_FORTEMEDIA, PCI_DEVICE_ID_FM801_GP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
| 145 | { 0 } | 145 | { 0 } |
| 146 | }; | 146 | }; |
| 147 | MODULE_DEVICE_TABLE(pci, fm801_gp_id_table); | ||
| 147 | 148 | ||
| 148 | static struct pci_driver fm801_gp_driver = { | 149 | static struct pci_driver fm801_gp_driver = { |
| 149 | .name = "FM801_gameport", | 150 | .name = "FM801_gameport", |
| @@ -152,20 +153,7 @@ static struct pci_driver fm801_gp_driver = { | |||
| 152 | .remove = __devexit_p(fm801_gp_remove), | 153 | .remove = __devexit_p(fm801_gp_remove), |
| 153 | }; | 154 | }; |
| 154 | 155 | ||
| 155 | static int __init fm801_gp_init(void) | 156 | module_pci_driver(fm801_gp_driver); |
| 156 | { | ||
| 157 | return pci_register_driver(&fm801_gp_driver); | ||
| 158 | } | ||
| 159 | |||
| 160 | static void __exit fm801_gp_exit(void) | ||
| 161 | { | ||
| 162 | pci_unregister_driver(&fm801_gp_driver); | ||
| 163 | } | ||
| 164 | |||
| 165 | module_init(fm801_gp_init); | ||
| 166 | module_exit(fm801_gp_exit); | ||
| 167 | |||
| 168 | MODULE_DEVICE_TABLE(pci, fm801_gp_id_table); | ||
| 169 | 157 | ||
| 170 | MODULE_DESCRIPTION("FM801 gameport driver"); | 158 | MODULE_DESCRIPTION("FM801 gameport driver"); |
| 171 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); | 159 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); |
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index 1639ab2b94b7..85bc8dc07cfc 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c | |||
| @@ -413,15 +413,4 @@ static struct gameport_driver a3d_drv = { | |||
| 413 | .disconnect = a3d_disconnect, | 413 | .disconnect = a3d_disconnect, |
| 414 | }; | 414 | }; |
| 415 | 415 | ||
| 416 | static int __init a3d_init(void) | 416 | module_gameport_driver(a3d_drv); |
| 417 | { | ||
| 418 | return gameport_register_driver(&a3d_drv); | ||
| 419 | } | ||
| 420 | |||
| 421 | static void __exit a3d_exit(void) | ||
| 422 | { | ||
| 423 | gameport_unregister_driver(&a3d_drv); | ||
| 424 | } | ||
| 425 | |||
| 426 | module_init(a3d_init); | ||
| 427 | module_exit(a3d_exit); | ||
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index b992fbf91f2f..0cbfd2dfabf4 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c | |||
| @@ -557,10 +557,6 @@ static void adi_disconnect(struct gameport *gameport) | |||
| 557 | kfree(port); | 557 | kfree(port); |
| 558 | } | 558 | } |
| 559 | 559 | ||
| 560 | /* | ||
| 561 | * The gameport device structure. | ||
| 562 | */ | ||
| 563 | |||
| 564 | static struct gameport_driver adi_drv = { | 560 | static struct gameport_driver adi_drv = { |
| 565 | .driver = { | 561 | .driver = { |
| 566 | .name = "adi", | 562 | .name = "adi", |
| @@ -570,15 +566,4 @@ static struct gameport_driver adi_drv = { | |||
| 570 | .disconnect = adi_disconnect, | 566 | .disconnect = adi_disconnect, |
| 571 | }; | 567 | }; |
| 572 | 568 | ||
| 573 | static int __init adi_init(void) | 569 | module_gameport_driver(adi_drv); |
| 574 | { | ||
| 575 | return gameport_register_driver(&adi_drv); | ||
| 576 | } | ||
| 577 | |||
| 578 | static void __exit adi_exit(void) | ||
| 579 | { | ||
| 580 | gameport_unregister_driver(&adi_drv); | ||
| 581 | } | ||
| 582 | |||
| 583 | module_init(adi_init); | ||
| 584 | module_exit(adi_exit); | ||
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index 3497b87c3d05..65367e44d715 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c | |||
| @@ -261,15 +261,4 @@ static struct gameport_driver cobra_drv = { | |||
| 261 | .disconnect = cobra_disconnect, | 261 | .disconnect = cobra_disconnect, |
| 262 | }; | 262 | }; |
| 263 | 263 | ||
| 264 | static int __init cobra_init(void) | 264 | module_gameport_driver(cobra_drv); |
| 265 | { | ||
| 266 | return gameport_register_driver(&cobra_drv); | ||
| 267 | } | ||
| 268 | |||
| 269 | static void __exit cobra_exit(void) | ||
| 270 | { | ||
| 271 | gameport_unregister_driver(&cobra_drv); | ||
| 272 | } | ||
| 273 | |||
| 274 | module_init(cobra_init); | ||
| 275 | module_exit(cobra_exit); | ||
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index 0536b1b2f018..ab1cf2882004 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c | |||
| @@ -373,15 +373,4 @@ static struct gameport_driver gf2k_drv = { | |||
| 373 | .disconnect = gf2k_disconnect, | 373 | .disconnect = gf2k_disconnect, |
| 374 | }; | 374 | }; |
| 375 | 375 | ||
| 376 | static int __init gf2k_init(void) | 376 | module_gameport_driver(gf2k_drv); |
| 377 | { | ||
| 378 | return gameport_register_driver(&gf2k_drv); | ||
| 379 | } | ||
| 380 | |||
| 381 | static void __exit gf2k_exit(void) | ||
| 382 | { | ||
| 383 | gameport_unregister_driver(&gf2k_drv); | ||
| 384 | } | ||
| 385 | |||
| 386 | module_init(gf2k_init); | ||
| 387 | module_exit(gf2k_exit); | ||
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index fc55899ba6c5..9e1beff57c33 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c | |||
| @@ -424,15 +424,4 @@ static struct gameport_driver grip_drv = { | |||
| 424 | .disconnect = grip_disconnect, | 424 | .disconnect = grip_disconnect, |
| 425 | }; | 425 | }; |
| 426 | 426 | ||
| 427 | static int __init grip_init(void) | 427 | module_gameport_driver(grip_drv); |
| 428 | { | ||
| 429 | return gameport_register_driver(&grip_drv); | ||
| 430 | } | ||
| 431 | |||
| 432 | static void __exit grip_exit(void) | ||
| 433 | { | ||
| 434 | gameport_unregister_driver(&grip_drv); | ||
| 435 | } | ||
| 436 | |||
| 437 | module_init(grip_init); | ||
| 438 | module_exit(grip_exit); | ||
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 2d47baf47769..c0f9c7b7eb4e 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c | |||
| @@ -687,15 +687,4 @@ static struct gameport_driver grip_drv = { | |||
| 687 | .disconnect = grip_disconnect, | 687 | .disconnect = grip_disconnect, |
| 688 | }; | 688 | }; |
| 689 | 689 | ||
| 690 | static int __init grip_init(void) | 690 | module_gameport_driver(grip_drv); |
| 691 | { | ||
| 692 | return gameport_register_driver(&grip_drv); | ||
| 693 | } | ||
| 694 | |||
| 695 | static void __exit grip_exit(void) | ||
| 696 | { | ||
| 697 | gameport_unregister_driver(&grip_drv); | ||
| 698 | } | ||
| 699 | |||
| 700 | module_init(grip_init); | ||
| 701 | module_exit(grip_exit); | ||
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index 4058d4b272fe..55196f730af6 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c | |||
| @@ -281,15 +281,4 @@ static struct gameport_driver guillemot_drv = { | |||
| 281 | .disconnect = guillemot_disconnect, | 281 | .disconnect = guillemot_disconnect, |
| 282 | }; | 282 | }; |
| 283 | 283 | ||
| 284 | static int __init guillemot_init(void) | 284 | module_gameport_driver(guillemot_drv); |
| 285 | { | ||
| 286 | return gameport_register_driver(&guillemot_drv); | ||
| 287 | } | ||
| 288 | |||
| 289 | static void __exit guillemot_exit(void) | ||
| 290 | { | ||
| 291 | gameport_unregister_driver(&guillemot_drv); | ||
| 292 | } | ||
| 293 | |||
| 294 | module_init(guillemot_init); | ||
| 295 | module_exit(guillemot_exit); | ||
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index 16fb19d1ca25..88c22623a2e8 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c | |||
| @@ -311,15 +311,4 @@ static struct gameport_driver interact_drv = { | |||
| 311 | .disconnect = interact_disconnect, | 311 | .disconnect = interact_disconnect, |
| 312 | }; | 312 | }; |
| 313 | 313 | ||
| 314 | static int __init interact_init(void) | 314 | module_gameport_driver(interact_drv); |
| 315 | { | ||
| 316 | return gameport_register_driver(&interact_drv); | ||
| 317 | } | ||
| 318 | |||
| 319 | static void __exit interact_exit(void) | ||
| 320 | { | ||
| 321 | gameport_unregister_driver(&interact_drv); | ||
| 322 | } | ||
| 323 | |||
| 324 | module_init(interact_init); | ||
| 325 | module_exit(interact_exit); | ||
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c index cd894a0564a2..7eb878bab968 100644 --- a/drivers/input/joystick/joydump.c +++ b/drivers/input/joystick/joydump.c | |||
| @@ -159,15 +159,4 @@ static struct gameport_driver joydump_drv = { | |||
| 159 | .disconnect = joydump_disconnect, | 159 | .disconnect = joydump_disconnect, |
| 160 | }; | 160 | }; |
| 161 | 161 | ||
| 162 | static int __init joydump_init(void) | 162 | module_gameport_driver(joydump_drv); |
| 163 | { | ||
| 164 | return gameport_register_driver(&joydump_drv); | ||
| 165 | } | ||
| 166 | |||
| 167 | static void __exit joydump_exit(void) | ||
| 168 | { | ||
| 169 | gameport_unregister_driver(&joydump_drv); | ||
| 170 | } | ||
| 171 | |||
| 172 | module_init(joydump_init); | ||
| 173 | module_exit(joydump_exit); | ||
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c index 40e40780747d..9fb153eef2fc 100644 --- a/drivers/input/joystick/magellan.c +++ b/drivers/input/joystick/magellan.c | |||
| @@ -222,19 +222,4 @@ static struct serio_driver magellan_drv = { | |||
| 222 | .disconnect = magellan_disconnect, | 222 | .disconnect = magellan_disconnect, |
| 223 | }; | 223 | }; |
| 224 | 224 | ||
| 225 | /* | 225 | module_serio_driver(magellan_drv); |
| 226 | * The functions for inserting/removing us as a module. | ||
| 227 | */ | ||
| 228 | |||
| 229 | static int __init magellan_init(void) | ||
| 230 | { | ||
| 231 | return serio_register_driver(&magellan_drv); | ||
| 232 | } | ||
| 233 | |||
| 234 | static void __exit magellan_exit(void) | ||
| 235 | { | ||
| 236 | serio_unregister_driver(&magellan_drv); | ||
| 237 | } | ||
| 238 | |||
| 239 | module_init(magellan_init); | ||
| 240 | module_exit(magellan_exit); | ||
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index b8d86115644b..04c69af37148 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c | |||
| @@ -820,15 +820,4 @@ static struct gameport_driver sw_drv = { | |||
| 820 | .disconnect = sw_disconnect, | 820 | .disconnect = sw_disconnect, |
| 821 | }; | 821 | }; |
| 822 | 822 | ||
| 823 | static int __init sw_init(void) | 823 | module_gameport_driver(sw_drv); |
| 824 | { | ||
| 825 | return gameport_register_driver(&sw_drv); | ||
| 826 | } | ||
| 827 | |||
| 828 | static void __exit sw_exit(void) | ||
| 829 | { | ||
| 830 | gameport_unregister_driver(&sw_drv); | ||
| 831 | } | ||
| 832 | |||
| 833 | module_init(sw_init); | ||
| 834 | module_exit(sw_exit); | ||
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index 0cd9b29356a8..80a7b27a457a 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c | |||
| @@ -296,19 +296,4 @@ static struct serio_driver spaceball_drv = { | |||
| 296 | .disconnect = spaceball_disconnect, | 296 | .disconnect = spaceball_disconnect, |
| 297 | }; | 297 | }; |
| 298 | 298 | ||
| 299 | /* | 299 | module_serio_driver(spaceball_drv); |
| 300 | * The functions for inserting/removing us as a module. | ||
| 301 | */ | ||
| 302 | |||
| 303 | static int __init spaceball_init(void) | ||
| 304 | { | ||
| 305 | return serio_register_driver(&spaceball_drv); | ||
| 306 | } | ||
| 307 | |||
| 308 | static void __exit spaceball_exit(void) | ||
| 309 | { | ||
| 310 | serio_unregister_driver(&spaceball_drv); | ||
| 311 | } | ||
| 312 | |||
| 313 | module_init(spaceball_init); | ||
| 314 | module_exit(spaceball_exit); | ||
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index a694bf8e557b..a41f291652e6 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c | |||
| @@ -237,19 +237,4 @@ static struct serio_driver spaceorb_drv = { | |||
| 237 | .disconnect = spaceorb_disconnect, | 237 | .disconnect = spaceorb_disconnect, |
| 238 | }; | 238 | }; |
| 239 | 239 | ||
| 240 | /* | 240 | module_serio_driver(spaceorb_drv); |
| 241 | * The functions for inserting/removing us as a module. | ||
| 242 | */ | ||
| 243 | |||
| 244 | static int __init spaceorb_init(void) | ||
| 245 | { | ||
| 246 | return serio_register_driver(&spaceorb_drv); | ||
| 247 | } | ||
| 248 | |||
| 249 | static void __exit spaceorb_exit(void) | ||
| 250 | { | ||
| 251 | serio_unregister_driver(&spaceorb_drv); | ||
| 252 | } | ||
| 253 | |||
| 254 | module_init(spaceorb_init); | ||
| 255 | module_exit(spaceorb_exit); | ||
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c index e0db9f5e4b41..0f51a60e14a7 100644 --- a/drivers/input/joystick/stinger.c +++ b/drivers/input/joystick/stinger.c | |||
| @@ -208,19 +208,4 @@ static struct serio_driver stinger_drv = { | |||
| 208 | .disconnect = stinger_disconnect, | 208 | .disconnect = stinger_disconnect, |
| 209 | }; | 209 | }; |
| 210 | 210 | ||
| 211 | /* | 211 | module_serio_driver(stinger_drv); |
| 212 | * The functions for inserting/removing us as a module. | ||
| 213 | */ | ||
| 214 | |||
| 215 | static int __init stinger_init(void) | ||
| 216 | { | ||
| 217 | return serio_register_driver(&stinger_drv); | ||
| 218 | } | ||
| 219 | |||
| 220 | static void __exit stinger_exit(void) | ||
| 221 | { | ||
| 222 | serio_unregister_driver(&stinger_drv); | ||
| 223 | } | ||
| 224 | |||
| 225 | module_init(stinger_init); | ||
| 226 | module_exit(stinger_exit); | ||
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index d6c609807115..5ef9bcdb0345 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c | |||
| @@ -436,15 +436,4 @@ static struct gameport_driver tmdc_drv = { | |||
| 436 | .disconnect = tmdc_disconnect, | 436 | .disconnect = tmdc_disconnect, |
| 437 | }; | 437 | }; |
| 438 | 438 | ||
| 439 | static int __init tmdc_init(void) | 439 | module_gameport_driver(tmdc_drv); |
| 440 | { | ||
| 441 | return gameport_register_driver(&tmdc_drv); | ||
| 442 | } | ||
| 443 | |||
| 444 | static void __exit tmdc_exit(void) | ||
| 445 | { | ||
| 446 | gameport_unregister_driver(&tmdc_drv); | ||
| 447 | } | ||
| 448 | |||
| 449 | module_init(tmdc_init); | ||
| 450 | module_exit(tmdc_exit); | ||
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c index 3f4ec73c9553..2556a8193579 100644 --- a/drivers/input/joystick/twidjoy.c +++ b/drivers/input/joystick/twidjoy.c | |||
| @@ -257,19 +257,4 @@ static struct serio_driver twidjoy_drv = { | |||
| 257 | .disconnect = twidjoy_disconnect, | 257 | .disconnect = twidjoy_disconnect, |
| 258 | }; | 258 | }; |
| 259 | 259 | ||
| 260 | /* | 260 | module_serio_driver(twidjoy_drv); |
| 261 | * The functions for inserting/removing us as a module. | ||
| 262 | */ | ||
| 263 | |||
| 264 | static int __init twidjoy_init(void) | ||
| 265 | { | ||
| 266 | return serio_register_driver(&twidjoy_drv); | ||
| 267 | } | ||
| 268 | |||
| 269 | static void __exit twidjoy_exit(void) | ||
| 270 | { | ||
| 271 | serio_unregister_driver(&twidjoy_drv); | ||
| 272 | } | ||
| 273 | |||
| 274 | module_init(twidjoy_init); | ||
| 275 | module_exit(twidjoy_exit); | ||
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c index f72c83e15e60..23b3071abb6e 100644 --- a/drivers/input/joystick/warrior.c +++ b/drivers/input/joystick/warrior.c | |||
| @@ -217,19 +217,4 @@ static struct serio_driver warrior_drv = { | |||
| 217 | .disconnect = warrior_disconnect, | 217 | .disconnect = warrior_disconnect, |
| 218 | }; | 218 | }; |
| 219 | 219 | ||
| 220 | /* | 220 | module_serio_driver(warrior_drv); |
| 221 | * The functions for inserting/removing us as a module. | ||
| 222 | */ | ||
| 223 | |||
| 224 | static int __init warrior_init(void) | ||
| 225 | { | ||
| 226 | return serio_register_driver(&warrior_drv); | ||
| 227 | } | ||
| 228 | |||
| 229 | static void __exit warrior_exit(void) | ||
| 230 | { | ||
| 231 | serio_unregister_driver(&warrior_drv); | ||
| 232 | } | ||
| 233 | |||
| 234 | module_init(warrior_init); | ||
| 235 | module_exit(warrior_exit); | ||
diff --git a/drivers/input/joystick/zhenhua.c b/drivers/input/joystick/zhenhua.c index b5853125c898..c4de4388fd7f 100644 --- a/drivers/input/joystick/zhenhua.c +++ b/drivers/input/joystick/zhenhua.c | |||
| @@ -225,19 +225,4 @@ static struct serio_driver zhenhua_drv = { | |||
| 225 | .disconnect = zhenhua_disconnect, | 225 | .disconnect = zhenhua_disconnect, |
| 226 | }; | 226 | }; |
| 227 | 227 | ||
| 228 | /* | 228 | module_serio_driver(zhenhua_drv); |
| 229 | * The functions for inserting/removing us as a module. | ||
| 230 | */ | ||
| 231 | |||
| 232 | static int __init zhenhua_init(void) | ||
| 233 | { | ||
| 234 | return serio_register_driver(&zhenhua_drv); | ||
| 235 | } | ||
| 236 | |||
| 237 | static void __exit zhenhua_exit(void) | ||
| 238 | { | ||
| 239 | serio_unregister_driver(&zhenhua_drv); | ||
| 240 | } | ||
| 241 | |||
| 242 | module_init(zhenhua_init); | ||
| 243 | module_exit(zhenhua_exit); | ||
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index f354813a13e8..c0e11ecc646f 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
| @@ -166,6 +166,7 @@ config KEYBOARD_LKKBD | |||
| 166 | config KEYBOARD_EP93XX | 166 | config KEYBOARD_EP93XX |
| 167 | tristate "EP93xx Matrix Keypad support" | 167 | tristate "EP93xx Matrix Keypad support" |
| 168 | depends on ARCH_EP93XX | 168 | depends on ARCH_EP93XX |
| 169 | select INPUT_MATRIXKMAP | ||
| 169 | help | 170 | help |
| 170 | Say Y here to enable the matrix keypad on the Cirrus EP93XX. | 171 | Say Y here to enable the matrix keypad on the Cirrus EP93XX. |
| 171 | 172 | ||
| @@ -224,6 +225,7 @@ config KEYBOARD_TCA6416 | |||
| 224 | config KEYBOARD_TCA8418 | 225 | config KEYBOARD_TCA8418 |
| 225 | tristate "TCA8418 Keypad Support" | 226 | tristate "TCA8418 Keypad Support" |
| 226 | depends on I2C | 227 | depends on I2C |
| 228 | select INPUT_MATRIXKMAP | ||
| 227 | help | 229 | help |
| 228 | This driver implements basic keypad functionality | 230 | This driver implements basic keypad functionality |
| 229 | for keys connected through TCA8418 keypad decoder. | 231 | for keys connected through TCA8418 keypad decoder. |
| @@ -240,6 +242,7 @@ config KEYBOARD_TCA8418 | |||
| 240 | config KEYBOARD_MATRIX | 242 | config KEYBOARD_MATRIX |
| 241 | tristate "GPIO driven matrix keypad support" | 243 | tristate "GPIO driven matrix keypad support" |
| 242 | depends on GENERIC_GPIO | 244 | depends on GENERIC_GPIO |
| 245 | select INPUT_MATRIXKMAP | ||
| 243 | help | 246 | help |
| 244 | Enable support for GPIO driven matrix keypad. | 247 | Enable support for GPIO driven matrix keypad. |
| 245 | 248 | ||
| @@ -309,6 +312,17 @@ config KEYBOARD_LM8323 | |||
| 309 | To compile this driver as a module, choose M here: the | 312 | To compile this driver as a module, choose M here: the |
| 310 | module will be called lm8323. | 313 | module will be called lm8323. |
| 311 | 314 | ||
| 315 | config KEYBOARD_LM8333 | ||
| 316 | tristate "LM8333 keypad chip" | ||
| 317 | depends on I2C | ||
| 318 | select INPUT_MATRIXKMAP | ||
| 319 | help | ||
| 320 | If you say yes here you get support for the National Semiconductor | ||
| 321 | LM8333 keypad controller. | ||
| 322 | |||
| 323 | To compile this driver as a module, choose M here: the | ||
| 324 | module will be called lm8333. | ||
| 325 | |||
| 312 | config KEYBOARD_LOCOMO | 326 | config KEYBOARD_LOCOMO |
| 313 | tristate "LoCoMo Keyboard Support" | 327 | tristate "LoCoMo Keyboard Support" |
| 314 | depends on SHARP_LOCOMO | 328 | depends on SHARP_LOCOMO |
| @@ -366,6 +380,7 @@ config KEYBOARD_MPR121 | |||
| 366 | config KEYBOARD_IMX | 380 | config KEYBOARD_IMX |
| 367 | tristate "IMX keypad support" | 381 | tristate "IMX keypad support" |
| 368 | depends on ARCH_MXC | 382 | depends on ARCH_MXC |
| 383 | select INPUT_MATRIXKMAP | ||
| 369 | help | 384 | help |
| 370 | Enable support for IMX keypad port. | 385 | Enable support for IMX keypad port. |
| 371 | 386 | ||
| @@ -384,6 +399,7 @@ config KEYBOARD_NEWTON | |||
| 384 | config KEYBOARD_NOMADIK | 399 | config KEYBOARD_NOMADIK |
| 385 | tristate "ST-Ericsson Nomadik SKE keyboard" | 400 | tristate "ST-Ericsson Nomadik SKE keyboard" |
| 386 | depends on PLAT_NOMADIK | 401 | depends on PLAT_NOMADIK |
| 402 | select INPUT_MATRIXKMAP | ||
| 387 | help | 403 | help |
| 388 | Say Y here if you want to use a keypad provided on the SKE controller | 404 | Say Y here if you want to use a keypad provided on the SKE controller |
| 389 | used on the Ux500 and Nomadik platforms | 405 | used on the Ux500 and Nomadik platforms |
| @@ -394,7 +410,7 @@ config KEYBOARD_NOMADIK | |||
| 394 | config KEYBOARD_TEGRA | 410 | config KEYBOARD_TEGRA |
| 395 | tristate "NVIDIA Tegra internal matrix keyboard controller support" | 411 | tristate "NVIDIA Tegra internal matrix keyboard controller support" |
| 396 | depends on ARCH_TEGRA | 412 | depends on ARCH_TEGRA |
| 397 | select INPUT_OF_MATRIX_KEYMAP if USE_OF | 413 | select INPUT_MATRIXKMAP |
| 398 | help | 414 | help |
| 399 | Say Y here if you want to use a matrix keyboard connected directly | 415 | Say Y here if you want to use a matrix keyboard connected directly |
| 400 | to the internal keyboard controller on Tegra SoCs. | 416 | to the internal keyboard controller on Tegra SoCs. |
| @@ -432,6 +448,7 @@ config KEYBOARD_PXA930_ROTARY | |||
| 432 | config KEYBOARD_PMIC8XXX | 448 | config KEYBOARD_PMIC8XXX |
| 433 | tristate "Qualcomm PMIC8XXX keypad support" | 449 | tristate "Qualcomm PMIC8XXX keypad support" |
| 434 | depends on MFD_PM8XXX | 450 | depends on MFD_PM8XXX |
| 451 | select INPUT_MATRIXKMAP | ||
| 435 | help | 452 | help |
| 436 | Say Y here if you want to enable the driver for the PMIC8XXX | 453 | Say Y here if you want to enable the driver for the PMIC8XXX |
| 437 | keypad provided as a reference design from Qualcomm. This is intended | 454 | keypad provided as a reference design from Qualcomm. This is intended |
| @@ -443,6 +460,7 @@ config KEYBOARD_PMIC8XXX | |||
| 443 | config KEYBOARD_SAMSUNG | 460 | config KEYBOARD_SAMSUNG |
| 444 | tristate "Samsung keypad support" | 461 | tristate "Samsung keypad support" |
| 445 | depends on HAVE_CLK | 462 | depends on HAVE_CLK |
| 463 | select INPUT_MATRIXKMAP | ||
| 446 | help | 464 | help |
| 447 | Say Y here if you want to use the keypad on your Samsung mobile | 465 | Say Y here if you want to use the keypad on your Samsung mobile |
| 448 | device. | 466 | device. |
| @@ -485,6 +503,7 @@ config KEYBOARD_SH_KEYSC | |||
| 485 | config KEYBOARD_STMPE | 503 | config KEYBOARD_STMPE |
| 486 | tristate "STMPE keypad support" | 504 | tristate "STMPE keypad support" |
| 487 | depends on MFD_STMPE | 505 | depends on MFD_STMPE |
| 506 | select INPUT_MATRIXKMAP | ||
| 488 | help | 507 | help |
| 489 | Say Y here if you want to use the keypad controller on STMPE I/O | 508 | Say Y here if you want to use the keypad controller on STMPE I/O |
| 490 | expanders. | 509 | expanders. |
| @@ -505,6 +524,7 @@ config KEYBOARD_DAVINCI | |||
| 505 | config KEYBOARD_OMAP | 524 | config KEYBOARD_OMAP |
| 506 | tristate "TI OMAP keypad support" | 525 | tristate "TI OMAP keypad support" |
| 507 | depends on (ARCH_OMAP1 || ARCH_OMAP2) | 526 | depends on (ARCH_OMAP1 || ARCH_OMAP2) |
| 527 | select INPUT_MATRIXKMAP | ||
| 508 | help | 528 | help |
| 509 | Say Y here if you want to use the OMAP keypad. | 529 | Say Y here if you want to use the OMAP keypad. |
| 510 | 530 | ||
| @@ -512,9 +532,10 @@ config KEYBOARD_OMAP | |||
| 512 | module will be called omap-keypad. | 532 | module will be called omap-keypad. |
| 513 | 533 | ||
| 514 | config KEYBOARD_OMAP4 | 534 | config KEYBOARD_OMAP4 |
| 515 | tristate "TI OMAP4 keypad support" | 535 | tristate "TI OMAP4+ keypad support" |
| 536 | select INPUT_MATRIXKMAP | ||
| 516 | help | 537 | help |
| 517 | Say Y here if you want to use the OMAP4 keypad. | 538 | Say Y here if you want to use the OMAP4+ keypad. |
| 518 | 539 | ||
| 519 | To compile this driver as a module, choose M here: the | 540 | To compile this driver as a module, choose M here: the |
| 520 | module will be called omap4-keypad. | 541 | module will be called omap4-keypad. |
| @@ -522,6 +543,7 @@ config KEYBOARD_OMAP4 | |||
| 522 | config KEYBOARD_SPEAR | 543 | config KEYBOARD_SPEAR |
| 523 | tristate "ST SPEAR keyboard support" | 544 | tristate "ST SPEAR keyboard support" |
| 524 | depends on PLAT_SPEAR | 545 | depends on PLAT_SPEAR |
| 546 | select INPUT_MATRIXKMAP | ||
| 525 | help | 547 | help |
| 526 | Say Y here if you want to use the SPEAR keyboard. | 548 | Say Y here if you want to use the SPEAR keyboard. |
| 527 | 549 | ||
| @@ -531,6 +553,7 @@ config KEYBOARD_SPEAR | |||
| 531 | config KEYBOARD_TC3589X | 553 | config KEYBOARD_TC3589X |
| 532 | tristate "TC3589X Keypad support" | 554 | tristate "TC3589X Keypad support" |
| 533 | depends on MFD_TC3589X | 555 | depends on MFD_TC3589X |
| 556 | select INPUT_MATRIXKMAP | ||
| 534 | help | 557 | help |
| 535 | Say Y here if you want to use the keypad controller on | 558 | Say Y here if you want to use the keypad controller on |
| 536 | TC35892/3 I/O expander. | 559 | TC35892/3 I/O expander. |
| @@ -541,6 +564,7 @@ config KEYBOARD_TC3589X | |||
| 541 | config KEYBOARD_TNETV107X | 564 | config KEYBOARD_TNETV107X |
| 542 | tristate "TI TNETV107X keypad support" | 565 | tristate "TI TNETV107X keypad support" |
| 543 | depends on ARCH_DAVINCI_TNETV107X | 566 | depends on ARCH_DAVINCI_TNETV107X |
| 567 | select INPUT_MATRIXKMAP | ||
| 544 | help | 568 | help |
| 545 | Say Y here if you want to use the TNETV107X keypad. | 569 | Say Y here if you want to use the TNETV107X keypad. |
| 546 | 570 | ||
| @@ -550,6 +574,7 @@ config KEYBOARD_TNETV107X | |||
| 550 | config KEYBOARD_TWL4030 | 574 | config KEYBOARD_TWL4030 |
| 551 | tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" | 575 | tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" |
| 552 | depends on TWL4030_CORE | 576 | depends on TWL4030_CORE |
| 577 | select INPUT_MATRIXKMAP | ||
| 553 | help | 578 | help |
| 554 | Say Y here if your board use the keypad controller on | 579 | Say Y here if your board use the keypad controller on |
| 555 | TWL4030 family chips. It's safe to say enable this | 580 | TWL4030 family chips. It's safe to say enable this |
| @@ -573,6 +598,7 @@ config KEYBOARD_XTKBD | |||
| 573 | config KEYBOARD_W90P910 | 598 | config KEYBOARD_W90P910 |
| 574 | tristate "W90P910 Matrix Keypad support" | 599 | tristate "W90P910 Matrix Keypad support" |
| 575 | depends on ARCH_W90X900 | 600 | depends on ARCH_W90X900 |
| 601 | select INPUT_MATRIXKMAP | ||
| 576 | help | 602 | help |
| 577 | Say Y here to enable the matrix keypad on evaluation board | 603 | Say Y here to enable the matrix keypad on evaluation board |
| 578 | based on W90P910. | 604 | based on W90P910. |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index df7061f12918..b03b02456a82 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
| @@ -24,6 +24,7 @@ obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | |||
| 24 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | 24 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o |
| 25 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o | 25 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o |
| 26 | obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o | 26 | obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o |
| 27 | obj-$(CONFIG_KEYBOARD_LM8333) += lm8333.o | ||
| 27 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o | 28 | obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o |
| 28 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o | 29 | obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o |
| 29 | obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o | 30 | obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o |
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 39ebffac207e..b083bf10f139 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c | |||
| @@ -197,6 +197,7 @@ static int __devinit adp5588_gpio_add(struct adp5588_kpad *kpad) | |||
| 197 | kpad->gc.base = gpio_data->gpio_start; | 197 | kpad->gc.base = gpio_data->gpio_start; |
| 198 | kpad->gc.label = kpad->client->name; | 198 | kpad->gc.label = kpad->client->name; |
| 199 | kpad->gc.owner = THIS_MODULE; | 199 | kpad->gc.owner = THIS_MODULE; |
| 200 | kpad->gc.names = gpio_data->names; | ||
| 200 | 201 | ||
| 201 | mutex_init(&kpad->gpio_lock); | 202 | mutex_init(&kpad->gpio_lock); |
| 202 | 203 | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index e05a2e7073c6..add5ffd9fe26 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
| @@ -433,7 +433,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
| 433 | if (printk_ratelimit()) | 433 | if (printk_ratelimit()) |
| 434 | dev_warn(&serio->dev, | 434 | dev_warn(&serio->dev, |
| 435 | "Spurious %s on %s. " | 435 | "Spurious %s on %s. " |
| 436 | "Some program might be trying access hardware directly.\n", | 436 | "Some program might be trying to access hardware directly.\n", |
| 437 | data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); | 437 | data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); |
| 438 | goto out; | 438 | goto out; |
| 439 | case ATKBD_RET_ERR: | 439 | case ATKBD_RET_ERR: |
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 0ba69f3fcb52..c46fc8185469 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c | |||
| @@ -182,16 +182,10 @@ static void ep93xx_keypad_close(struct input_dev *pdev) | |||
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | 184 | ||
| 185 | #ifdef CONFIG_PM | 185 | #ifdef CONFIG_PM_SLEEP |
| 186 | /* | 186 | static int ep93xx_keypad_suspend(struct device *dev) |
| 187 | * NOTE: I don't know if this is correct, or will work on the ep93xx. | ||
| 188 | * | ||
| 189 | * None of the existing ep93xx drivers have power management support. | ||
| 190 | * But, this is basically what the pxa27x_keypad driver does. | ||
| 191 | */ | ||
| 192 | static int ep93xx_keypad_suspend(struct platform_device *pdev, | ||
| 193 | pm_message_t state) | ||
| 194 | { | 187 | { |
| 188 | struct platform_device *pdev = to_platform_device(dev); | ||
| 195 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); | 189 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); |
| 196 | struct input_dev *input_dev = keypad->input_dev; | 190 | struct input_dev *input_dev = keypad->input_dev; |
| 197 | 191 | ||
| @@ -210,8 +204,9 @@ static int ep93xx_keypad_suspend(struct platform_device *pdev, | |||
| 210 | return 0; | 204 | return 0; |
| 211 | } | 205 | } |
| 212 | 206 | ||
| 213 | static int ep93xx_keypad_resume(struct platform_device *pdev) | 207 | static int ep93xx_keypad_resume(struct device *dev) |
| 214 | { | 208 | { |
| 209 | struct platform_device *pdev = to_platform_device(dev); | ||
| 215 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); | 210 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); |
| 216 | struct input_dev *input_dev = keypad->input_dev; | 211 | struct input_dev *input_dev = keypad->input_dev; |
| 217 | 212 | ||
| @@ -232,10 +227,10 @@ static int ep93xx_keypad_resume(struct platform_device *pdev) | |||
| 232 | 227 | ||
| 233 | return 0; | 228 | return 0; |
| 234 | } | 229 | } |
| 235 | #else /* !CONFIG_PM */ | 230 | #endif |
| 236 | #define ep93xx_keypad_suspend NULL | 231 | |
| 237 | #define ep93xx_keypad_resume NULL | 232 | static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops, |
| 238 | #endif /* !CONFIG_PM */ | 233 | ep93xx_keypad_suspend, ep93xx_keypad_resume); |
| 239 | 234 | ||
| 240 | static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) | 235 | static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) |
| 241 | { | 236 | { |
| @@ -308,19 +303,16 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) | |||
| 308 | input_dev->open = ep93xx_keypad_open; | 303 | input_dev->open = ep93xx_keypad_open; |
| 309 | input_dev->close = ep93xx_keypad_close; | 304 | input_dev->close = ep93xx_keypad_close; |
| 310 | input_dev->dev.parent = &pdev->dev; | 305 | input_dev->dev.parent = &pdev->dev; |
| 311 | input_dev->keycode = keypad->keycodes; | ||
| 312 | input_dev->keycodesize = sizeof(keypad->keycodes[0]); | ||
| 313 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
| 314 | 306 | ||
| 315 | input_set_drvdata(input_dev, keypad); | 307 | err = matrix_keypad_build_keymap(keymap_data, NULL, |
| 308 | EP93XX_MATRIX_ROWS, EP93XX_MATRIX_COLS, | ||
| 309 | keypad->keycodes, input_dev); | ||
| 310 | if (err) | ||
| 311 | goto failed_free_dev; | ||
| 316 | 312 | ||
| 317 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
| 318 | if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT) | 313 | if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT) |
| 319 | input_dev->evbit[0] |= BIT_MASK(EV_REP); | 314 | __set_bit(EV_REP, input_dev->evbit); |
| 320 | 315 | input_set_drvdata(input_dev, keypad); | |
| 321 | matrix_keypad_build_keymap(keymap_data, 3, | ||
| 322 | input_dev->keycode, input_dev->keybit); | ||
| 323 | platform_set_drvdata(pdev, keypad); | ||
| 324 | 316 | ||
| 325 | err = request_irq(keypad->irq, ep93xx_keypad_irq_handler, | 317 | err = request_irq(keypad->irq, ep93xx_keypad_irq_handler, |
| 326 | 0, pdev->name, keypad); | 318 | 0, pdev->name, keypad); |
| @@ -331,6 +323,7 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) | |||
| 331 | if (err) | 323 | if (err) |
| 332 | goto failed_free_irq; | 324 | goto failed_free_irq; |
| 333 | 325 | ||
| 326 | platform_set_drvdata(pdev, keypad); | ||
| 334 | device_init_wakeup(&pdev->dev, 1); | 327 | device_init_wakeup(&pdev->dev, 1); |
| 335 | 328 | ||
| 336 | return 0; | 329 | return 0; |
| @@ -384,11 +377,10 @@ static struct platform_driver ep93xx_keypad_driver = { | |||
| 384 | .driver = { | 377 | .driver = { |
| 385 | .name = "ep93xx-keypad", | 378 | .name = "ep93xx-keypad", |
| 386 | .owner = THIS_MODULE, | 379 | .owner = THIS_MODULE, |
| 380 | .pm = &ep93xx_keypad_pm_ops, | ||
| 387 | }, | 381 | }, |
| 388 | .probe = ep93xx_keypad_probe, | 382 | .probe = ep93xx_keypad_probe, |
| 389 | .remove = __devexit_p(ep93xx_keypad_remove), | 383 | .remove = __devexit_p(ep93xx_keypad_remove), |
| 390 | .suspend = ep93xx_keypad_suspend, | ||
| 391 | .resume = ep93xx_keypad_resume, | ||
| 392 | }; | 384 | }; |
| 393 | module_platform_driver(ep93xx_keypad_driver); | 385 | module_platform_driver(ep93xx_keypad_driver); |
| 394 | 386 | ||
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index fed31e0947a1..589e3c258f3f 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c | |||
| @@ -583,15 +583,4 @@ static struct serio_driver hil_serio_drv = { | |||
| 583 | .interrupt = hil_dev_interrupt | 583 | .interrupt = hil_dev_interrupt |
| 584 | }; | 584 | }; |
| 585 | 585 | ||
| 586 | static int __init hil_dev_init(void) | 586 | module_serio_driver(hil_serio_drv); |
| 587 | { | ||
| 588 | return serio_register_driver(&hil_serio_drv); | ||
| 589 | } | ||
| 590 | |||
| 591 | static void __exit hil_dev_exit(void) | ||
| 592 | { | ||
| 593 | serio_unregister_driver(&hil_serio_drv); | ||
| 594 | } | ||
| 595 | |||
| 596 | module_init(hil_dev_init); | ||
| 597 | module_exit(hil_dev_exit); | ||
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index fb87b3bcadb9..6ee7421e2321 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c | |||
| @@ -481,7 +481,7 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) | |||
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | if (keypad->rows_en_mask > ((1 << MAX_MATRIX_KEY_ROWS) - 1) || | 483 | if (keypad->rows_en_mask > ((1 << MAX_MATRIX_KEY_ROWS) - 1) || |
| 484 | keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) { | 484 | keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) { |
| 485 | dev_err(&pdev->dev, | 485 | dev_err(&pdev->dev, |
| 486 | "invalid key data (too many rows or colums)\n"); | 486 | "invalid key data (too many rows or colums)\n"); |
| 487 | error = -EINVAL; | 487 | error = -EINVAL; |
| @@ -496,14 +496,17 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) | |||
| 496 | input_dev->dev.parent = &pdev->dev; | 496 | input_dev->dev.parent = &pdev->dev; |
| 497 | input_dev->open = imx_keypad_open; | 497 | input_dev->open = imx_keypad_open; |
| 498 | input_dev->close = imx_keypad_close; | 498 | input_dev->close = imx_keypad_close; |
| 499 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
| 500 | input_dev->keycode = keypad->keycodes; | ||
| 501 | input_dev->keycodesize = sizeof(keypad->keycodes[0]); | ||
| 502 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
| 503 | 499 | ||
| 504 | matrix_keypad_build_keymap(keymap_data, MATRIX_ROW_SHIFT, | 500 | error = matrix_keypad_build_keymap(keymap_data, NULL, |
| 505 | keypad->keycodes, input_dev->keybit); | 501 | MAX_MATRIX_KEY_ROWS, |
| 502 | MAX_MATRIX_KEY_COLS, | ||
| 503 | keypad->keycodes, input_dev); | ||
| 504 | if (error) { | ||
| 505 | dev_err(&pdev->dev, "failed to build keymap\n"); | ||
| 506 | goto failed_clock_put; | ||
| 507 | } | ||
| 506 | 508 | ||
| 509 | __set_bit(EV_REP, input_dev->evbit); | ||
| 507 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 510 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
| 508 | input_set_drvdata(input_dev, keypad); | 511 | input_set_drvdata(input_dev, keypad); |
| 509 | 512 | ||
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index fa9bb6d235e2..fc0a63c2f278 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c | |||
| @@ -731,19 +731,4 @@ static struct serio_driver lkkbd_drv = { | |||
| 731 | .interrupt = lkkbd_interrupt, | 731 | .interrupt = lkkbd_interrupt, |
| 732 | }; | 732 | }; |
| 733 | 733 | ||
| 734 | /* | 734 | module_serio_driver(lkkbd_drv); |
| 735 | * The functions for insering/removing us as a module. | ||
| 736 | */ | ||
| 737 | static int __init lkkbd_init(void) | ||
| 738 | { | ||
| 739 | return serio_register_driver(&lkkbd_drv); | ||
| 740 | } | ||
| 741 | |||
| 742 | static void __exit lkkbd_exit(void) | ||
| 743 | { | ||
| 744 | serio_unregister_driver(&lkkbd_drv); | ||
| 745 | } | ||
| 746 | |||
| 747 | module_init(lkkbd_init); | ||
| 748 | module_exit(lkkbd_exit); | ||
| 749 | |||
diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c new file mode 100644 index 000000000000..ca168a6679de --- /dev/null +++ b/drivers/input/keyboard/lm8333.c | |||
| @@ -0,0 +1,235 @@ | |||
| 1 | /* | ||
| 2 | * LM8333 keypad driver | ||
| 3 | * Copyright (C) 2012 Wolfram Sang, Pengutronix <w.sang@pengutronix.de> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/slab.h> | ||
| 12 | #include <linux/irq.h> | ||
| 13 | #include <linux/i2c.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/input/matrix_keypad.h> | ||
| 16 | #include <linux/input/lm8333.h> | ||
| 17 | |||
| 18 | #define LM8333_FIFO_READ 0x20 | ||
| 19 | #define LM8333_DEBOUNCE 0x22 | ||
| 20 | #define LM8333_READ_INT 0xD0 | ||
| 21 | #define LM8333_ACTIVE 0xE4 | ||
| 22 | #define LM8333_READ_ERROR 0xF0 | ||
| 23 | |||
| 24 | #define LM8333_KEYPAD_IRQ (1 << 0) | ||
| 25 | #define LM8333_ERROR_IRQ (1 << 3) | ||
| 26 | |||
| 27 | #define LM8333_ERROR_KEYOVR 0x04 | ||
| 28 | #define LM8333_ERROR_FIFOOVR 0x40 | ||
| 29 | |||
| 30 | #define LM8333_FIFO_TRANSFER_SIZE 16 | ||
| 31 | |||
| 32 | #define LM8333_NUM_ROWS 8 | ||
| 33 | #define LM8333_NUM_COLS 16 | ||
| 34 | #define LM8333_ROW_SHIFT 4 | ||
| 35 | |||
| 36 | struct lm8333 { | ||
| 37 | struct i2c_client *client; | ||
| 38 | struct input_dev *input; | ||
| 39 | unsigned short keycodes[LM8333_NUM_ROWS << LM8333_ROW_SHIFT]; | ||
| 40 | }; | ||
| 41 | |||
| 42 | /* The accessors try twice because the first access may be needed for wakeup */ | ||
| 43 | #define LM8333_READ_RETRIES 2 | ||
| 44 | |||
| 45 | int lm8333_read8(struct lm8333 *lm8333, u8 cmd) | ||
| 46 | { | ||
| 47 | int retries = 0, ret; | ||
| 48 | |||
| 49 | do { | ||
| 50 | ret = i2c_smbus_read_byte_data(lm8333->client, cmd); | ||
| 51 | } while (ret < 0 && retries++ < LM8333_READ_RETRIES); | ||
| 52 | |||
| 53 | return ret; | ||
| 54 | } | ||
| 55 | |||
| 56 | int lm8333_write8(struct lm8333 *lm8333, u8 cmd, u8 val) | ||
| 57 | { | ||
| 58 | int retries = 0, ret; | ||
| 59 | |||
| 60 | do { | ||
| 61 | ret = i2c_smbus_write_byte_data(lm8333->client, cmd, val); | ||
| 62 | } while (ret < 0 && retries++ < LM8333_READ_RETRIES); | ||
| 63 | |||
| 64 | return ret; | ||
| 65 | } | ||
| 66 | |||
| 67 | int lm8333_read_block(struct lm8333 *lm8333, u8 cmd, u8 len, u8 *buf) | ||
| 68 | { | ||
| 69 | int retries = 0, ret; | ||
| 70 | |||
| 71 | do { | ||
| 72 | ret = i2c_smbus_read_i2c_block_data(lm8333->client, | ||
| 73 | cmd, len, buf); | ||
| 74 | } while (ret < 0 && retries++ < LM8333_READ_RETRIES); | ||
| 75 | |||
| 76 | return ret; | ||
| 77 | } | ||
| 78 | |||
| 79 | static void lm8333_key_handler(struct lm8333 *lm8333) | ||
| 80 | { | ||
| 81 | struct input_dev *input = lm8333->input; | ||
| 82 | u8 keys[LM8333_FIFO_TRANSFER_SIZE]; | ||
| 83 | u8 code, pressed; | ||
| 84 | int i, ret; | ||
| 85 | |||
| 86 | ret = lm8333_read_block(lm8333, LM8333_FIFO_READ, | ||
| 87 | LM8333_FIFO_TRANSFER_SIZE, keys); | ||
| 88 | if (ret != LM8333_FIFO_TRANSFER_SIZE) { | ||
| 89 | dev_err(&lm8333->client->dev, | ||
| 90 | "Error %d while reading FIFO\n", ret); | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | |||
| 94 | for (i = 0; keys[i] && i < LM8333_FIFO_TRANSFER_SIZE; i++) { | ||
| 95 | pressed = keys[i] & 0x80; | ||
| 96 | code = keys[i] & 0x7f; | ||
| 97 | |||
| 98 | input_event(input, EV_MSC, MSC_SCAN, code); | ||
| 99 | input_report_key(input, lm8333->keycodes[code], pressed); | ||
| 100 | } | ||
| 101 | |||
| 102 | input_sync(input); | ||
| 103 | } | ||
| 104 | |||
| 105 | static irqreturn_t lm8333_irq_thread(int irq, void *data) | ||
| 106 | { | ||
| 107 | struct lm8333 *lm8333 = data; | ||
| 108 | u8 status = lm8333_read8(lm8333, LM8333_READ_INT); | ||
| 109 | |||
| 110 | if (!status) | ||
| 111 | return IRQ_NONE; | ||
| 112 | |||
| 113 | if (status & LM8333_ERROR_IRQ) { | ||
| 114 | u8 err = lm8333_read8(lm8333, LM8333_READ_ERROR); | ||
| 115 | |||
| 116 | if (err & (LM8333_ERROR_KEYOVR | LM8333_ERROR_FIFOOVR)) { | ||
| 117 | u8 dummy[LM8333_FIFO_TRANSFER_SIZE]; | ||
| 118 | |||
| 119 | lm8333_read_block(lm8333, LM8333_FIFO_READ, | ||
| 120 | LM8333_FIFO_TRANSFER_SIZE, dummy); | ||
| 121 | } | ||
| 122 | dev_err(&lm8333->client->dev, "Got error %02x\n", err); | ||
| 123 | } | ||
| 124 | |||
| 125 | if (status & LM8333_KEYPAD_IRQ) | ||
| 126 | lm8333_key_handler(lm8333); | ||
| 127 | |||
| 128 | return IRQ_HANDLED; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int __devinit lm8333_probe(struct i2c_client *client, | ||
| 132 | const struct i2c_device_id *id) | ||
| 133 | { | ||
| 134 | const struct lm8333_platform_data *pdata = client->dev.platform_data; | ||
| 135 | struct lm8333 *lm8333; | ||
| 136 | struct input_dev *input; | ||
| 137 | int err, active_time; | ||
| 138 | |||
| 139 | if (!pdata) | ||
| 140 | return -EINVAL; | ||
| 141 | |||
| 142 | active_time = pdata->active_time ?: 500; | ||
| 143 | if (active_time / 3 <= pdata->debounce_time / 3) { | ||
| 144 | dev_err(&client->dev, "Active time not big enough!\n"); | ||
| 145 | return -EINVAL; | ||
| 146 | } | ||
| 147 | |||
| 148 | lm8333 = kzalloc(sizeof(*lm8333), GFP_KERNEL); | ||
| 149 | input = input_allocate_device(); | ||
| 150 | if (!lm8333 || !input) { | ||
| 151 | err = -ENOMEM; | ||
| 152 | goto free_mem; | ||
| 153 | } | ||
| 154 | |||
| 155 | lm8333->client = client; | ||
| 156 | lm8333->input = input; | ||
| 157 | |||
| 158 | input->name = client->name; | ||
| 159 | input->dev.parent = &client->dev; | ||
| 160 | input->id.bustype = BUS_I2C; | ||
| 161 | |||
| 162 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
| 163 | |||
| 164 | err = matrix_keypad_build_keymap(pdata->matrix_data, NULL, | ||
| 165 | LM8333_NUM_ROWS, LM8333_NUM_COLS, | ||
| 166 | lm8333->keycodes, input); | ||
| 167 | if (err) | ||
| 168 | goto free_mem; | ||
| 169 | |||
| 170 | if (pdata->debounce_time) { | ||
| 171 | err = lm8333_write8(lm8333, LM8333_DEBOUNCE, | ||
| 172 | pdata->debounce_time / 3); | ||
| 173 | if (err) | ||
| 174 | dev_warn(&client->dev, "Unable to set debounce time\n"); | ||
| 175 | } | ||
| 176 | |||
| 177 | if (pdata->active_time) { | ||
| 178 | err = lm8333_write8(lm8333, LM8333_ACTIVE, | ||
| 179 | pdata->active_time / 3); | ||
| 180 | if (err) | ||
| 181 | dev_warn(&client->dev, "Unable to set active time\n"); | ||
| 182 | } | ||
| 183 | |||
| 184 | err = request_threaded_irq(client->irq, NULL, lm8333_irq_thread, | ||
| 185 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
| 186 | "lm8333", lm8333); | ||
| 187 | if (err) | ||
| 188 | goto free_mem; | ||
| 189 | |||
| 190 | err = input_register_device(input); | ||
| 191 | if (err) | ||
| 192 | goto free_irq; | ||
| 193 | |||
| 194 | i2c_set_clientdata(client, lm8333); | ||
| 195 | return 0; | ||
| 196 | |||
| 197 | free_irq: | ||
| 198 | free_irq(client->irq, lm8333); | ||
| 199 | free_mem: | ||
| 200 | input_free_device(input); | ||
| 201 | kfree(lm8333); | ||
| 202 | return err; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int __devexit lm8333_remove(struct i2c_client *client) | ||
| 206 | { | ||
| 207 | struct lm8333 *lm8333 = i2c_get_clientdata(client); | ||
| 208 | |||
| 209 | free_irq(client->irq, lm8333); | ||
| 210 | input_unregister_device(lm8333->input); | ||
| 211 | kfree(lm8333); | ||
| 212 | |||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 216 | static const struct i2c_device_id lm8333_id[] = { | ||
| 217 | { "lm8333", 0 }, | ||
| 218 | { } | ||
| 219 | }; | ||
| 220 | MODULE_DEVICE_TABLE(i2c, lm8333_id); | ||
| 221 | |||
| 222 | static struct i2c_driver lm8333_driver = { | ||
| 223 | .driver = { | ||
| 224 | .name = "lm8333", | ||
| 225 | .owner = THIS_MODULE, | ||
| 226 | }, | ||
| 227 | .probe = lm8333_probe, | ||
| 228 | .remove = __devexit_p(lm8333_remove), | ||
| 229 | .id_table = lm8333_id, | ||
| 230 | }; | ||
| 231 | module_i2c_driver(lm8333_driver); | ||
| 232 | |||
| 233 | MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); | ||
| 234 | MODULE_DESCRIPTION("LM8333 keyboard driver"); | ||
| 235 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 9b223d73de32..18b72372028a 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | struct matrix_keypad { | 27 | struct matrix_keypad { |
| 28 | const struct matrix_keypad_platform_data *pdata; | 28 | const struct matrix_keypad_platform_data *pdata; |
| 29 | struct input_dev *input_dev; | 29 | struct input_dev *input_dev; |
| 30 | unsigned short *keycodes; | ||
| 31 | unsigned int row_shift; | 30 | unsigned int row_shift; |
| 32 | 31 | ||
| 33 | DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS); | 32 | DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS); |
| @@ -38,6 +37,8 @@ struct matrix_keypad { | |||
| 38 | bool scan_pending; | 37 | bool scan_pending; |
| 39 | bool stopped; | 38 | bool stopped; |
| 40 | bool gpio_all_disabled; | 39 | bool gpio_all_disabled; |
| 40 | |||
| 41 | unsigned short keycodes[]; | ||
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| 43 | /* | 44 | /* |
| @@ -224,7 +225,7 @@ static void matrix_keypad_stop(struct input_dev *dev) | |||
| 224 | disable_row_irqs(keypad); | 225 | disable_row_irqs(keypad); |
| 225 | } | 226 | } |
| 226 | 227 | ||
| 227 | #ifdef CONFIG_PM | 228 | #ifdef CONFIG_PM_SLEEP |
| 228 | static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad) | 229 | static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad) |
| 229 | { | 230 | { |
| 230 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | 231 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; |
| @@ -293,16 +294,16 @@ static int matrix_keypad_resume(struct device *dev) | |||
| 293 | 294 | ||
| 294 | return 0; | 295 | return 0; |
| 295 | } | 296 | } |
| 296 | |||
| 297 | static const SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, | ||
| 298 | matrix_keypad_suspend, matrix_keypad_resume); | ||
| 299 | #endif | 297 | #endif |
| 300 | 298 | ||
| 301 | static int __devinit init_matrix_gpio(struct platform_device *pdev, | 299 | static SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, |
| 302 | struct matrix_keypad *keypad) | 300 | matrix_keypad_suspend, matrix_keypad_resume); |
| 301 | |||
| 302 | static int __devinit matrix_keypad_init_gpio(struct platform_device *pdev, | ||
| 303 | struct matrix_keypad *keypad) | ||
| 303 | { | 304 | { |
| 304 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | 305 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; |
| 305 | int i, err = -EINVAL; | 306 | int i, err; |
| 306 | 307 | ||
| 307 | /* initialized strobe lines as outputs, activated */ | 308 | /* initialized strobe lines as outputs, activated */ |
| 308 | for (i = 0; i < pdata->num_col_gpios; i++) { | 309 | for (i = 0; i < pdata->num_col_gpios; i++) { |
| @@ -348,8 +349,7 @@ static int __devinit init_matrix_gpio(struct platform_device *pdev, | |||
| 348 | "matrix-keypad", keypad); | 349 | "matrix-keypad", keypad); |
| 349 | if (err) { | 350 | if (err) { |
| 350 | dev_err(&pdev->dev, | 351 | dev_err(&pdev->dev, |
| 351 | "Unable to acquire interrupt " | 352 | "Unable to acquire interrupt for GPIO line %i\n", |
| 352 | "for GPIO line %i\n", | ||
| 353 | pdata->row_gpios[i]); | 353 | pdata->row_gpios[i]); |
| 354 | goto err_free_irqs; | 354 | goto err_free_irqs; |
| 355 | } | 355 | } |
| @@ -375,14 +375,33 @@ err_free_cols: | |||
| 375 | return err; | 375 | return err; |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | static void matrix_keypad_free_gpio(struct matrix_keypad *keypad) | ||
| 379 | { | ||
| 380 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
| 381 | int i; | ||
| 382 | |||
| 383 | if (pdata->clustered_irq > 0) { | ||
| 384 | free_irq(pdata->clustered_irq, keypad); | ||
| 385 | } else { | ||
| 386 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 387 | free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); | ||
| 388 | } | ||
| 389 | |||
| 390 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 391 | gpio_free(pdata->row_gpios[i]); | ||
| 392 | |||
| 393 | for (i = 0; i < pdata->num_col_gpios; i++) | ||
| 394 | gpio_free(pdata->col_gpios[i]); | ||
| 395 | } | ||
| 396 | |||
| 378 | static int __devinit matrix_keypad_probe(struct platform_device *pdev) | 397 | static int __devinit matrix_keypad_probe(struct platform_device *pdev) |
| 379 | { | 398 | { |
| 380 | const struct matrix_keypad_platform_data *pdata; | 399 | const struct matrix_keypad_platform_data *pdata; |
| 381 | const struct matrix_keymap_data *keymap_data; | 400 | const struct matrix_keymap_data *keymap_data; |
| 382 | struct matrix_keypad *keypad; | 401 | struct matrix_keypad *keypad; |
| 383 | struct input_dev *input_dev; | 402 | struct input_dev *input_dev; |
| 384 | unsigned short *keycodes; | ||
| 385 | unsigned int row_shift; | 403 | unsigned int row_shift; |
| 404 | size_t keymap_size; | ||
| 386 | int err; | 405 | int err; |
| 387 | 406 | ||
| 388 | pdata = pdev->dev.platform_data; | 407 | pdata = pdev->dev.platform_data; |
| @@ -398,20 +417,18 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) | |||
| 398 | } | 417 | } |
| 399 | 418 | ||
| 400 | row_shift = get_count_order(pdata->num_col_gpios); | 419 | row_shift = get_count_order(pdata->num_col_gpios); |
| 401 | 420 | keymap_size = (pdata->num_row_gpios << row_shift) * | |
| 402 | keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL); | 421 | sizeof(keypad->keycodes[0]); |
| 403 | keycodes = kzalloc((pdata->num_row_gpios << row_shift) * | 422 | keypad = kzalloc(sizeof(struct matrix_keypad) + keymap_size, |
| 404 | sizeof(*keycodes), | 423 | GFP_KERNEL); |
| 405 | GFP_KERNEL); | ||
| 406 | input_dev = input_allocate_device(); | 424 | input_dev = input_allocate_device(); |
| 407 | if (!keypad || !keycodes || !input_dev) { | 425 | if (!keypad || !input_dev) { |
| 408 | err = -ENOMEM; | 426 | err = -ENOMEM; |
| 409 | goto err_free_mem; | 427 | goto err_free_mem; |
| 410 | } | 428 | } |
| 411 | 429 | ||
| 412 | keypad->input_dev = input_dev; | 430 | keypad->input_dev = input_dev; |
| 413 | keypad->pdata = pdata; | 431 | keypad->pdata = pdata; |
| 414 | keypad->keycodes = keycodes; | ||
| 415 | keypad->row_shift = row_shift; | 432 | keypad->row_shift = row_shift; |
| 416 | keypad->stopped = true; | 433 | keypad->stopped = true; |
| 417 | INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); | 434 | INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); |
| @@ -420,38 +437,38 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) | |||
| 420 | input_dev->name = pdev->name; | 437 | input_dev->name = pdev->name; |
| 421 | input_dev->id.bustype = BUS_HOST; | 438 | input_dev->id.bustype = BUS_HOST; |
| 422 | input_dev->dev.parent = &pdev->dev; | 439 | input_dev->dev.parent = &pdev->dev; |
| 423 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
| 424 | if (!pdata->no_autorepeat) | ||
| 425 | input_dev->evbit[0] |= BIT_MASK(EV_REP); | ||
| 426 | input_dev->open = matrix_keypad_start; | 440 | input_dev->open = matrix_keypad_start; |
| 427 | input_dev->close = matrix_keypad_stop; | 441 | input_dev->close = matrix_keypad_stop; |
| 428 | 442 | ||
| 429 | input_dev->keycode = keycodes; | 443 | err = matrix_keypad_build_keymap(keymap_data, NULL, |
| 430 | input_dev->keycodesize = sizeof(*keycodes); | 444 | pdata->num_row_gpios, |
| 431 | input_dev->keycodemax = pdata->num_row_gpios << row_shift; | 445 | pdata->num_col_gpios, |
| 432 | 446 | keypad->keycodes, input_dev); | |
| 433 | matrix_keypad_build_keymap(keymap_data, row_shift, | 447 | if (err) |
| 434 | input_dev->keycode, input_dev->keybit); | 448 | goto err_free_mem; |
| 435 | 449 | ||
| 450 | if (!pdata->no_autorepeat) | ||
| 451 | __set_bit(EV_REP, input_dev->evbit); | ||
| 436 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 452 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
| 437 | input_set_drvdata(input_dev, keypad); | 453 | input_set_drvdata(input_dev, keypad); |
| 438 | 454 | ||
| 439 | err = init_matrix_gpio(pdev, keypad); | 455 | err = matrix_keypad_init_gpio(pdev, keypad); |
| 440 | if (err) | 456 | if (err) |
| 441 | goto err_free_mem; | 457 | goto err_free_mem; |
| 442 | 458 | ||
| 443 | err = input_register_device(keypad->input_dev); | 459 | err = input_register_device(keypad->input_dev); |
| 444 | if (err) | 460 | if (err) |
| 445 | goto err_free_mem; | 461 | goto err_free_gpio; |
| 446 | 462 | ||
| 447 | device_init_wakeup(&pdev->dev, pdata->wakeup); | 463 | device_init_wakeup(&pdev->dev, pdata->wakeup); |
| 448 | platform_set_drvdata(pdev, keypad); | 464 | platform_set_drvdata(pdev, keypad); |
| 449 | 465 | ||
| 450 | return 0; | 466 | return 0; |
| 451 | 467 | ||
| 468 | err_free_gpio: | ||
| 469 | matrix_keypad_free_gpio(keypad); | ||
| 452 | err_free_mem: | 470 | err_free_mem: |
| 453 | input_free_device(input_dev); | 471 | input_free_device(input_dev); |
| 454 | kfree(keycodes); | ||
| 455 | kfree(keypad); | 472 | kfree(keypad); |
| 456 | return err; | 473 | return err; |
| 457 | } | 474 | } |
| @@ -459,29 +476,15 @@ err_free_mem: | |||
| 459 | static int __devexit matrix_keypad_remove(struct platform_device *pdev) | 476 | static int __devexit matrix_keypad_remove(struct platform_device *pdev) |
| 460 | { | 477 | { |
| 461 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | 478 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); |
| 462 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | ||
| 463 | int i; | ||
| 464 | 479 | ||
| 465 | device_init_wakeup(&pdev->dev, 0); | 480 | device_init_wakeup(&pdev->dev, 0); |
| 466 | 481 | ||
| 467 | if (pdata->clustered_irq > 0) { | 482 | matrix_keypad_free_gpio(keypad); |
| 468 | free_irq(pdata->clustered_irq, keypad); | ||
| 469 | } else { | ||
| 470 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 471 | free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad); | ||
| 472 | } | ||
| 473 | |||
| 474 | for (i = 0; i < pdata->num_row_gpios; i++) | ||
| 475 | gpio_free(pdata->row_gpios[i]); | ||
| 476 | |||
| 477 | for (i = 0; i < pdata->num_col_gpios; i++) | ||
| 478 | gpio_free(pdata->col_gpios[i]); | ||
| 479 | |||
| 480 | input_unregister_device(keypad->input_dev); | 483 | input_unregister_device(keypad->input_dev); |
| 481 | platform_set_drvdata(pdev, NULL); | ||
| 482 | kfree(keypad->keycodes); | ||
| 483 | kfree(keypad); | 484 | kfree(keypad); |
| 484 | 485 | ||
| 486 | platform_set_drvdata(pdev, NULL); | ||
| 487 | |||
| 485 | return 0; | 488 | return 0; |
| 486 | } | 489 | } |
| 487 | 490 | ||
| @@ -491,9 +494,7 @@ static struct platform_driver matrix_keypad_driver = { | |||
| 491 | .driver = { | 494 | .driver = { |
| 492 | .name = "matrix-keypad", | 495 | .name = "matrix-keypad", |
| 493 | .owner = THIS_MODULE, | 496 | .owner = THIS_MODULE, |
| 494 | #ifdef CONFIG_PM | ||
| 495 | .pm = &matrix_keypad_pm_ops, | 497 | .pm = &matrix_keypad_pm_ops, |
| 496 | #endif | ||
| 497 | }, | 498 | }, |
| 498 | }; | 499 | }; |
| 499 | module_platform_driver(matrix_keypad_driver); | 500 | module_platform_driver(matrix_keypad_driver); |
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index 48d1cab0aa1c..f971898ad591 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c | |||
| @@ -166,15 +166,4 @@ static struct serio_driver nkbd_drv = { | |||
| 166 | .disconnect = nkbd_disconnect, | 166 | .disconnect = nkbd_disconnect, |
| 167 | }; | 167 | }; |
| 168 | 168 | ||
| 169 | static int __init nkbd_init(void) | 169 | module_serio_driver(nkbd_drv); |
| 170 | { | ||
| 171 | return serio_register_driver(&nkbd_drv); | ||
| 172 | } | ||
| 173 | |||
| 174 | static void __exit nkbd_exit(void) | ||
| 175 | { | ||
| 176 | serio_unregister_driver(&nkbd_drv); | ||
| 177 | } | ||
| 178 | |||
| 179 | module_init(nkbd_init); | ||
| 180 | module_exit(nkbd_exit); | ||
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index 101e245944e7..4ea4341a68c5 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c | |||
| @@ -39,7 +39,8 @@ | |||
| 39 | #define SKE_KPRISA (0x1 << 2) | 39 | #define SKE_KPRISA (0x1 << 2) |
| 40 | 40 | ||
| 41 | #define SKE_KEYPAD_ROW_SHIFT 3 | 41 | #define SKE_KEYPAD_ROW_SHIFT 3 |
| 42 | #define SKE_KPD_KEYMAP_SIZE (8 * 8) | 42 | #define SKE_KPD_NUM_ROWS 8 |
| 43 | #define SKE_KPD_NUM_COLS 8 | ||
| 43 | 44 | ||
| 44 | /* keypad auto scan registers */ | 45 | /* keypad auto scan registers */ |
| 45 | #define SKE_ASR0 0x20 | 46 | #define SKE_ASR0 0x20 |
| @@ -63,7 +64,7 @@ struct ske_keypad { | |||
| 63 | void __iomem *reg_base; | 64 | void __iomem *reg_base; |
| 64 | struct input_dev *input; | 65 | struct input_dev *input; |
| 65 | const struct ske_keypad_platform_data *board; | 66 | const struct ske_keypad_platform_data *board; |
| 66 | unsigned short keymap[SKE_KPD_KEYMAP_SIZE]; | 67 | unsigned short keymap[SKE_KPD_NUM_ROWS * SKE_KPD_NUM_COLS]; |
| 67 | struct clk *clk; | 68 | struct clk *clk; |
| 68 | spinlock_t ske_keypad_lock; | 69 | spinlock_t ske_keypad_lock; |
| 69 | }; | 70 | }; |
| @@ -261,19 +262,18 @@ static int __init ske_keypad_probe(struct platform_device *pdev) | |||
| 261 | input->name = "ux500-ske-keypad"; | 262 | input->name = "ux500-ske-keypad"; |
| 262 | input->dev.parent = &pdev->dev; | 263 | input->dev.parent = &pdev->dev; |
| 263 | 264 | ||
| 264 | input->keycode = keypad->keymap; | 265 | error = matrix_keypad_build_keymap(plat->keymap_data, NULL, |
| 265 | input->keycodesize = sizeof(keypad->keymap[0]); | 266 | SKE_KPD_NUM_ROWS, SKE_KPD_NUM_COLS, |
| 266 | input->keycodemax = ARRAY_SIZE(keypad->keymap); | 267 | keypad->keymap, input); |
| 268 | if (error) { | ||
| 269 | dev_err(&pdev->dev, "Failed to build keymap\n"); | ||
| 270 | goto err_iounmap; | ||
| 271 | } | ||
| 267 | 272 | ||
| 268 | input_set_capability(input, EV_MSC, MSC_SCAN); | 273 | input_set_capability(input, EV_MSC, MSC_SCAN); |
| 269 | |||
| 270 | __set_bit(EV_KEY, input->evbit); | ||
| 271 | if (!plat->no_autorepeat) | 274 | if (!plat->no_autorepeat) |
| 272 | __set_bit(EV_REP, input->evbit); | 275 | __set_bit(EV_REP, input->evbit); |
| 273 | 276 | ||
| 274 | matrix_keypad_build_keymap(plat->keymap_data, SKE_KEYPAD_ROW_SHIFT, | ||
| 275 | input->keycode, input->keybit); | ||
| 276 | |||
| 277 | clk_enable(keypad->clk); | 277 | clk_enable(keypad->clk); |
| 278 | 278 | ||
| 279 | /* go through board initialization helpers */ | 279 | /* go through board initialization helpers */ |
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 6b630d9d3dff..a0222db4dc86 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
| @@ -61,6 +61,7 @@ struct omap_kp { | |||
| 61 | unsigned int cols; | 61 | unsigned int cols; |
| 62 | unsigned long delay; | 62 | unsigned long delay; |
| 63 | unsigned int debounce; | 63 | unsigned int debounce; |
| 64 | unsigned short keymap[]; | ||
| 64 | }; | 65 | }; |
| 65 | 66 | ||
| 66 | static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0); | 67 | static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0); |
| @@ -316,13 +317,6 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) | |||
| 316 | if (!cpu_is_omap24xx()) | 317 | if (!cpu_is_omap24xx()) |
| 317 | omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); | 318 | omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); |
| 318 | 319 | ||
| 319 | input_dev->keycode = &omap_kp[1]; | ||
| 320 | input_dev->keycodesize = sizeof(unsigned short); | ||
| 321 | input_dev->keycodemax = keycodemax; | ||
| 322 | |||
| 323 | if (pdata->rep) | ||
| 324 | __set_bit(EV_REP, input_dev->evbit); | ||
| 325 | |||
| 326 | if (pdata->delay) | 320 | if (pdata->delay) |
| 327 | omap_kp->delay = pdata->delay; | 321 | omap_kp->delay = pdata->delay; |
| 328 | 322 | ||
| @@ -371,9 +365,6 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) | |||
| 371 | goto err2; | 365 | goto err2; |
| 372 | 366 | ||
| 373 | /* setup input device */ | 367 | /* setup input device */ |
| 374 | __set_bit(EV_KEY, input_dev->evbit); | ||
| 375 | matrix_keypad_build_keymap(pdata->keymap_data, row_shift, | ||
| 376 | input_dev->keycode, input_dev->keybit); | ||
| 377 | input_dev->name = "omap-keypad"; | 368 | input_dev->name = "omap-keypad"; |
| 378 | input_dev->phys = "omap-keypad/input0"; | 369 | input_dev->phys = "omap-keypad/input0"; |
| 379 | input_dev->dev.parent = &pdev->dev; | 370 | input_dev->dev.parent = &pdev->dev; |
| @@ -383,6 +374,15 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) | |||
| 383 | input_dev->id.product = 0x0001; | 374 | input_dev->id.product = 0x0001; |
| 384 | input_dev->id.version = 0x0100; | 375 | input_dev->id.version = 0x0100; |
| 385 | 376 | ||
| 377 | if (pdata->rep) | ||
| 378 | __set_bit(EV_REP, input_dev->evbit); | ||
| 379 | |||
| 380 | ret = matrix_keypad_build_keymap(pdata->keymap_data, NULL, | ||
| 381 | pdata->rows, pdata->cols, | ||
| 382 | omap_kp->keymap, input_dev); | ||
| 383 | if (ret < 0) | ||
| 384 | goto err3; | ||
| 385 | |||
| 386 | ret = input_register_device(omap_kp->input); | 386 | ret = input_register_device(omap_kp->input); |
| 387 | if (ret < 0) { | 387 | if (ret < 0) { |
| 388 | printk(KERN_ERR "Unable to register omap-keypad input device\n"); | 388 | printk(KERN_ERR "Unable to register omap-keypad input device\n"); |
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index e809ac095a38..aed5f6999ce2 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c | |||
| @@ -68,19 +68,52 @@ | |||
| 68 | 68 | ||
| 69 | #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF | 69 | #define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF |
| 70 | 70 | ||
| 71 | enum { | ||
| 72 | KBD_REVISION_OMAP4 = 0, | ||
| 73 | KBD_REVISION_OMAP5, | ||
| 74 | }; | ||
| 75 | |||
| 71 | struct omap4_keypad { | 76 | struct omap4_keypad { |
| 72 | struct input_dev *input; | 77 | struct input_dev *input; |
| 73 | 78 | ||
| 74 | void __iomem *base; | 79 | void __iomem *base; |
| 75 | int irq; | 80 | unsigned int irq; |
| 76 | 81 | ||
| 77 | unsigned int rows; | 82 | unsigned int rows; |
| 78 | unsigned int cols; | 83 | unsigned int cols; |
| 84 | u32 reg_offset; | ||
| 85 | u32 irqreg_offset; | ||
| 79 | unsigned int row_shift; | 86 | unsigned int row_shift; |
| 80 | unsigned char key_state[8]; | 87 | unsigned char key_state[8]; |
| 81 | unsigned short keymap[]; | 88 | unsigned short keymap[]; |
| 82 | }; | 89 | }; |
| 83 | 90 | ||
| 91 | static int kbd_readl(struct omap4_keypad *keypad_data, u32 offset) | ||
| 92 | { | ||
| 93 | return __raw_readl(keypad_data->base + | ||
| 94 | keypad_data->reg_offset + offset); | ||
| 95 | } | ||
| 96 | |||
| 97 | static void kbd_writel(struct omap4_keypad *keypad_data, u32 offset, u32 value) | ||
| 98 | { | ||
| 99 | __raw_writel(value, | ||
| 100 | keypad_data->base + keypad_data->reg_offset + offset); | ||
| 101 | } | ||
| 102 | |||
| 103 | static int kbd_read_irqreg(struct omap4_keypad *keypad_data, u32 offset) | ||
| 104 | { | ||
| 105 | return __raw_readl(keypad_data->base + | ||
| 106 | keypad_data->irqreg_offset + offset); | ||
| 107 | } | ||
| 108 | |||
| 109 | static void kbd_write_irqreg(struct omap4_keypad *keypad_data, | ||
| 110 | u32 offset, u32 value) | ||
| 111 | { | ||
| 112 | __raw_writel(value, | ||
| 113 | keypad_data->base + keypad_data->irqreg_offset + offset); | ||
| 114 | } | ||
| 115 | |||
| 116 | |||
| 84 | /* Interrupt handler */ | 117 | /* Interrupt handler */ |
| 85 | static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) | 118 | static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) |
| 86 | { | 119 | { |
| @@ -91,12 +124,11 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) | |||
| 91 | u32 *new_state = (u32 *) key_state; | 124 | u32 *new_state = (u32 *) key_state; |
| 92 | 125 | ||
| 93 | /* Disable interrupts */ | 126 | /* Disable interrupts */ |
| 94 | __raw_writel(OMAP4_VAL_IRQDISABLE, | 127 | kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, |
| 95 | keypad_data->base + OMAP4_KBD_IRQENABLE); | 128 | OMAP4_VAL_IRQDISABLE); |
| 96 | 129 | ||
| 97 | *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0); | 130 | *new_state = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE31_0); |
| 98 | *(new_state + 1) = __raw_readl(keypad_data->base | 131 | *(new_state + 1) = kbd_readl(keypad_data, OMAP4_KBD_FULLCODE63_32); |
| 99 | + OMAP4_KBD_FULLCODE63_32); | ||
| 100 | 132 | ||
| 101 | for (row = 0; row < keypad_data->rows; row++) { | 133 | for (row = 0; row < keypad_data->rows; row++) { |
| 102 | changed = key_state[row] ^ keypad_data->key_state[row]; | 134 | changed = key_state[row] ^ keypad_data->key_state[row]; |
| @@ -121,12 +153,13 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id) | |||
| 121 | sizeof(keypad_data->key_state)); | 153 | sizeof(keypad_data->key_state)); |
| 122 | 154 | ||
| 123 | /* clear pending interrupts */ | 155 | /* clear pending interrupts */ |
| 124 | __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS), | 156 | kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, |
| 125 | keypad_data->base + OMAP4_KBD_IRQSTATUS); | 157 | kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)); |
| 126 | 158 | ||
| 127 | /* enable interrupts */ | 159 | /* enable interrupts */ |
| 128 | __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, | 160 | kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, |
| 129 | keypad_data->base + OMAP4_KBD_IRQENABLE); | 161 | OMAP4_DEF_IRQENABLE_EVENTEN | |
| 162 | OMAP4_DEF_IRQENABLE_LONGKEY); | ||
| 130 | 163 | ||
| 131 | return IRQ_HANDLED; | 164 | return IRQ_HANDLED; |
| 132 | } | 165 | } |
| @@ -139,16 +172,17 @@ static int omap4_keypad_open(struct input_dev *input) | |||
| 139 | 172 | ||
| 140 | disable_irq(keypad_data->irq); | 173 | disable_irq(keypad_data->irq); |
| 141 | 174 | ||
| 142 | __raw_writel(OMAP4_VAL_FUNCTIONALCFG, | 175 | kbd_writel(keypad_data, OMAP4_KBD_CTRL, |
| 143 | keypad_data->base + OMAP4_KBD_CTRL); | 176 | OMAP4_VAL_FUNCTIONALCFG); |
| 144 | __raw_writel(OMAP4_VAL_DEBOUNCINGTIME, | 177 | kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME, |
| 145 | keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME); | 178 | OMAP4_VAL_DEBOUNCINGTIME); |
| 146 | __raw_writel(OMAP4_VAL_IRQDISABLE, | 179 | kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, |
| 147 | keypad_data->base + OMAP4_KBD_IRQSTATUS); | 180 | OMAP4_VAL_IRQDISABLE); |
| 148 | __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY, | 181 | kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, |
| 149 | keypad_data->base + OMAP4_KBD_IRQENABLE); | 182 | OMAP4_DEF_IRQENABLE_EVENTEN | |
| 150 | __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA, | 183 | OMAP4_DEF_IRQENABLE_LONGKEY); |
| 151 | keypad_data->base + OMAP4_KBD_WAKEUPENABLE); | 184 | kbd_writel(keypad_data, OMAP4_KBD_WAKEUPENABLE, |
| 185 | OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA); | ||
| 152 | 186 | ||
| 153 | enable_irq(keypad_data->irq); | 187 | enable_irq(keypad_data->irq); |
| 154 | 188 | ||
| @@ -162,12 +196,12 @@ static void omap4_keypad_close(struct input_dev *input) | |||
| 162 | disable_irq(keypad_data->irq); | 196 | disable_irq(keypad_data->irq); |
| 163 | 197 | ||
| 164 | /* Disable interrupts */ | 198 | /* Disable interrupts */ |
| 165 | __raw_writel(OMAP4_VAL_IRQDISABLE, | 199 | kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, |
| 166 | keypad_data->base + OMAP4_KBD_IRQENABLE); | 200 | OMAP4_VAL_IRQDISABLE); |
| 167 | 201 | ||
| 168 | /* clear pending interrupts */ | 202 | /* clear pending interrupts */ |
| 169 | __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS), | 203 | kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, |
| 170 | keypad_data->base + OMAP4_KBD_IRQSTATUS); | 204 | kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)); |
| 171 | 205 | ||
| 172 | enable_irq(keypad_data->irq); | 206 | enable_irq(keypad_data->irq); |
| 173 | 207 | ||
| @@ -182,6 +216,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) | |||
| 182 | struct resource *res; | 216 | struct resource *res; |
| 183 | resource_size_t size; | 217 | resource_size_t size; |
| 184 | unsigned int row_shift, max_keys; | 218 | unsigned int row_shift, max_keys; |
| 219 | int rev; | ||
| 185 | int irq; | 220 | int irq; |
| 186 | int error; | 221 | int error; |
| 187 | 222 | ||
| @@ -241,11 +276,40 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) | |||
| 241 | keypad_data->rows = pdata->rows; | 276 | keypad_data->rows = pdata->rows; |
| 242 | keypad_data->cols = pdata->cols; | 277 | keypad_data->cols = pdata->cols; |
| 243 | 278 | ||
| 279 | /* | ||
| 280 | * Enable clocks for the keypad module so that we can read | ||
| 281 | * revision register. | ||
| 282 | */ | ||
| 283 | pm_runtime_enable(&pdev->dev); | ||
| 284 | error = pm_runtime_get_sync(&pdev->dev); | ||
| 285 | if (error) { | ||
| 286 | dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); | ||
| 287 | goto err_unmap; | ||
| 288 | } | ||
| 289 | rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION); | ||
| 290 | rev &= 0x03 << 30; | ||
| 291 | rev >>= 30; | ||
| 292 | switch (rev) { | ||
| 293 | case KBD_REVISION_OMAP4: | ||
| 294 | keypad_data->reg_offset = 0x00; | ||
| 295 | keypad_data->irqreg_offset = 0x00; | ||
| 296 | break; | ||
| 297 | case KBD_REVISION_OMAP5: | ||
| 298 | keypad_data->reg_offset = 0x10; | ||
| 299 | keypad_data->irqreg_offset = 0x0c; | ||
| 300 | break; | ||
| 301 | default: | ||
| 302 | dev_err(&pdev->dev, | ||
| 303 | "Keypad reports unsupported revision %d", rev); | ||
| 304 | error = -EINVAL; | ||
| 305 | goto err_pm_put_sync; | ||
| 306 | } | ||
| 307 | |||
| 244 | /* input device allocation */ | 308 | /* input device allocation */ |
| 245 | keypad_data->input = input_dev = input_allocate_device(); | 309 | keypad_data->input = input_dev = input_allocate_device(); |
| 246 | if (!input_dev) { | 310 | if (!input_dev) { |
| 247 | error = -ENOMEM; | 311 | error = -ENOMEM; |
| 248 | goto err_unmap; | 312 | goto err_pm_put_sync; |
| 249 | } | 313 | } |
| 250 | 314 | ||
| 251 | input_dev->name = pdev->name; | 315 | input_dev->name = pdev->name; |
| @@ -258,20 +322,19 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) | |||
| 258 | input_dev->open = omap4_keypad_open; | 322 | input_dev->open = omap4_keypad_open; |
| 259 | input_dev->close = omap4_keypad_close; | 323 | input_dev->close = omap4_keypad_close; |
| 260 | 324 | ||
| 261 | input_dev->keycode = keypad_data->keymap; | 325 | error = matrix_keypad_build_keymap(pdata->keymap_data, NULL, |
| 262 | input_dev->keycodesize = sizeof(keypad_data->keymap[0]); | 326 | pdata->rows, pdata->cols, |
| 263 | input_dev->keycodemax = max_keys; | 327 | keypad_data->keymap, input_dev); |
| 328 | if (error) { | ||
| 329 | dev_err(&pdev->dev, "failed to build keymap\n"); | ||
| 330 | goto err_free_input; | ||
| 331 | } | ||
| 264 | 332 | ||
| 265 | __set_bit(EV_KEY, input_dev->evbit); | ||
| 266 | __set_bit(EV_REP, input_dev->evbit); | 333 | __set_bit(EV_REP, input_dev->evbit); |
| 267 | |||
| 268 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 334 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
| 269 | 335 | ||
| 270 | input_set_drvdata(input_dev, keypad_data); | 336 | input_set_drvdata(input_dev, keypad_data); |
| 271 | 337 | ||
| 272 | matrix_keypad_build_keymap(pdata->keymap_data, row_shift, | ||
| 273 | input_dev->keycode, input_dev->keybit); | ||
| 274 | |||
| 275 | error = request_irq(keypad_data->irq, omap4_keypad_interrupt, | 338 | error = request_irq(keypad_data->irq, omap4_keypad_interrupt, |
| 276 | IRQF_TRIGGER_RISING, | 339 | IRQF_TRIGGER_RISING, |
| 277 | "omap4-keypad", keypad_data); | 340 | "omap4-keypad", keypad_data); |
| @@ -280,7 +343,7 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev) | |||
| 280 | goto err_free_input; | 343 | goto err_free_input; |
| 281 | } | 344 | } |
| 282 | 345 | ||
| 283 | pm_runtime_enable(&pdev->dev); | 346 | pm_runtime_put_sync(&pdev->dev); |
| 284 | 347 | ||
| 285 | error = input_register_device(keypad_data->input); | 348 | error = input_register_device(keypad_data->input); |
| 286 | if (error < 0) { | 349 | if (error < 0) { |
| @@ -296,6 +359,8 @@ err_pm_disable: | |||
| 296 | free_irq(keypad_data->irq, keypad_data); | 359 | free_irq(keypad_data->irq, keypad_data); |
| 297 | err_free_input: | 360 | err_free_input: |
| 298 | input_free_device(input_dev); | 361 | input_free_device(input_dev); |
| 362 | err_pm_put_sync: | ||
| 363 | pm_runtime_put_sync(&pdev->dev); | ||
| 299 | err_unmap: | 364 | err_unmap: |
| 300 | iounmap(keypad_data->base); | 365 | iounmap(keypad_data->base); |
| 301 | err_release_mem: | 366 | err_release_mem: |
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 01a1c9f8a383..52c34657d301 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c | |||
| @@ -626,21 +626,21 @@ static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) | |||
| 626 | kp->input->id.product = 0x0001; | 626 | kp->input->id.product = 0x0001; |
| 627 | kp->input->id.vendor = 0x0001; | 627 | kp->input->id.vendor = 0x0001; |
| 628 | 628 | ||
| 629 | kp->input->evbit[0] = BIT_MASK(EV_KEY); | ||
| 630 | |||
| 631 | if (pdata->rep) | ||
| 632 | __set_bit(EV_REP, kp->input->evbit); | ||
| 633 | |||
| 634 | kp->input->keycode = kp->keycodes; | ||
| 635 | kp->input->keycodemax = PM8XXX_MATRIX_MAX_SIZE; | ||
| 636 | kp->input->keycodesize = sizeof(kp->keycodes); | ||
| 637 | kp->input->open = pmic8xxx_kp_open; | 629 | kp->input->open = pmic8xxx_kp_open; |
| 638 | kp->input->close = pmic8xxx_kp_close; | 630 | kp->input->close = pmic8xxx_kp_close; |
| 639 | 631 | ||
| 640 | matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT, | 632 | rc = matrix_keypad_build_keymap(keymap_data, NULL, |
| 641 | kp->input->keycode, kp->input->keybit); | 633 | PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS, |
| 634 | kp->keycodes, kp->input); | ||
| 635 | if (rc) { | ||
| 636 | dev_err(&pdev->dev, "failed to build keymap\n"); | ||
| 637 | goto err_get_irq; | ||
| 638 | } | ||
| 642 | 639 | ||
| 640 | if (pdata->rep) | ||
| 641 | __set_bit(EV_REP, kp->input->evbit); | ||
| 643 | input_set_capability(kp->input, EV_MSC, MSC_SCAN); | 642 | input_set_capability(kp->input, EV_MSC, MSC_SCAN); |
| 643 | |||
| 644 | input_set_drvdata(kp->input, kp); | 644 | input_set_drvdata(kp->input, kp); |
| 645 | 645 | ||
| 646 | /* initialize keypad state */ | 646 | /* initialize keypad state */ |
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index 2391ae884fee..a061ba603a29 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c | |||
| @@ -454,23 +454,23 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) | |||
| 454 | input_dev->name = pdev->name; | 454 | input_dev->name = pdev->name; |
| 455 | input_dev->id.bustype = BUS_HOST; | 455 | input_dev->id.bustype = BUS_HOST; |
| 456 | input_dev->dev.parent = &pdev->dev; | 456 | input_dev->dev.parent = &pdev->dev; |
| 457 | input_set_drvdata(input_dev, keypad); | ||
| 458 | 457 | ||
| 459 | input_dev->open = samsung_keypad_open; | 458 | input_dev->open = samsung_keypad_open; |
| 460 | input_dev->close = samsung_keypad_close; | 459 | input_dev->close = samsung_keypad_close; |
| 461 | 460 | ||
| 462 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | 461 | error = matrix_keypad_build_keymap(keymap_data, NULL, |
| 463 | if (!pdata->no_autorepeat) | 462 | pdata->rows, pdata->cols, |
| 464 | input_dev->evbit[0] |= BIT_MASK(EV_REP); | 463 | keypad->keycodes, input_dev); |
| 464 | if (error) { | ||
| 465 | dev_err(&pdev->dev, "failed to build keymap\n"); | ||
| 466 | goto err_put_clk; | ||
| 467 | } | ||
| 465 | 468 | ||
| 466 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 469 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
| 470 | if (!pdata->no_autorepeat) | ||
| 471 | __set_bit(EV_REP, input_dev->evbit); | ||
| 467 | 472 | ||
| 468 | input_dev->keycode = keypad->keycodes; | 473 | input_set_drvdata(input_dev, keypad); |
| 469 | input_dev->keycodesize = sizeof(keypad->keycodes[0]); | ||
| 470 | input_dev->keycodemax = pdata->rows << row_shift; | ||
| 471 | |||
| 472 | matrix_keypad_build_keymap(keymap_data, row_shift, | ||
| 473 | input_dev->keycode, input_dev->keybit); | ||
| 474 | 474 | ||
| 475 | keypad->irq = platform_get_irq(pdev, 0); | 475 | keypad->irq = platform_get_irq(pdev, 0); |
| 476 | if (keypad->irq < 0) { | 476 | if (keypad->irq < 0) { |
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 3b6b528f02fd..6f287f7e1538 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
| 20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 22 | #include <linux/of.h> | ||
| 22 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 23 | #include <linux/pm_wakeup.h> | 24 | #include <linux/pm_wakeup.h> |
| 24 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| @@ -49,7 +50,9 @@ | |||
| 49 | #define KEY_VALUE 0x00FFFFFF | 50 | #define KEY_VALUE 0x00FFFFFF |
| 50 | #define ROW_MASK 0xF0 | 51 | #define ROW_MASK 0xF0 |
| 51 | #define COLUMN_MASK 0x0F | 52 | #define COLUMN_MASK 0x0F |
| 52 | #define ROW_SHIFT 4 | 53 | #define NUM_ROWS 16 |
| 54 | #define NUM_COLS 16 | ||
| 55 | |||
| 53 | #define KEY_MATRIX_SHIFT 6 | 56 | #define KEY_MATRIX_SHIFT 6 |
| 54 | 57 | ||
| 55 | struct spear_kbd { | 58 | struct spear_kbd { |
| @@ -60,7 +63,8 @@ struct spear_kbd { | |||
| 60 | unsigned int irq; | 63 | unsigned int irq; |
| 61 | unsigned int mode; | 64 | unsigned int mode; |
| 62 | unsigned short last_key; | 65 | unsigned short last_key; |
| 63 | unsigned short keycodes[256]; | 66 | unsigned short keycodes[NUM_ROWS * NUM_COLS]; |
| 67 | bool rep; | ||
| 64 | }; | 68 | }; |
| 65 | 69 | ||
| 66 | static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id) | 70 | static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id) |
| @@ -136,27 +140,49 @@ static void spear_kbd_close(struct input_dev *dev) | |||
| 136 | kbd->last_key = KEY_RESERVED; | 140 | kbd->last_key = KEY_RESERVED; |
| 137 | } | 141 | } |
| 138 | 142 | ||
| 139 | static int __devinit spear_kbd_probe(struct platform_device *pdev) | 143 | #ifdef CONFIG_OF |
| 144 | static int __devinit spear_kbd_parse_dt(struct platform_device *pdev, | ||
| 145 | struct spear_kbd *kbd) | ||
| 140 | { | 146 | { |
| 141 | const struct kbd_platform_data *pdata = pdev->dev.platform_data; | 147 | struct device_node *np = pdev->dev.of_node; |
| 142 | const struct matrix_keymap_data *keymap; | ||
| 143 | struct spear_kbd *kbd; | ||
| 144 | struct input_dev *input_dev; | ||
| 145 | struct resource *res; | ||
| 146 | int irq; | ||
| 147 | int error; | 148 | int error; |
| 149 | u32 val; | ||
| 148 | 150 | ||
| 149 | if (!pdata) { | 151 | if (!np) { |
| 150 | dev_err(&pdev->dev, "Invalid platform data\n"); | 152 | dev_err(&pdev->dev, "Missing DT data\n"); |
| 151 | return -EINVAL; | 153 | return -EINVAL; |
| 152 | } | 154 | } |
| 153 | 155 | ||
| 154 | keymap = pdata->keymap; | 156 | if (of_property_read_bool(np, "autorepeat")) |
| 155 | if (!keymap) { | 157 | kbd->rep = true; |
| 156 | dev_err(&pdev->dev, "no keymap defined\n"); | 158 | |
| 157 | return -EINVAL; | 159 | error = of_property_read_u32(np, "st,mode", &val); |
| 160 | if (error) { | ||
| 161 | dev_err(&pdev->dev, "DT: Invalid or missing mode\n"); | ||
| 162 | return error; | ||
| 158 | } | 163 | } |
| 159 | 164 | ||
| 165 | kbd->mode = val; | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | #else | ||
| 169 | static inline int spear_kbd_parse_dt(struct platform_device *pdev, | ||
| 170 | struct spear_kbd *kbd) | ||
| 171 | { | ||
| 172 | return -ENOSYS; | ||
| 173 | } | ||
| 174 | #endif | ||
| 175 | |||
| 176 | static int __devinit spear_kbd_probe(struct platform_device *pdev) | ||
| 177 | { | ||
| 178 | struct kbd_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
| 179 | const struct matrix_keymap_data *keymap = pdata ? pdata->keymap : NULL; | ||
| 180 | struct spear_kbd *kbd; | ||
| 181 | struct input_dev *input_dev; | ||
| 182 | struct resource *res; | ||
| 183 | int irq; | ||
| 184 | int error; | ||
| 185 | |||
| 160 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 186 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 161 | if (!res) { | 187 | if (!res) { |
| 162 | dev_err(&pdev->dev, "no keyboard resource defined\n"); | 188 | dev_err(&pdev->dev, "no keyboard resource defined\n"); |
| @@ -179,7 +205,15 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) | |||
| 179 | 205 | ||
| 180 | kbd->input = input_dev; | 206 | kbd->input = input_dev; |
| 181 | kbd->irq = irq; | 207 | kbd->irq = irq; |
| 182 | kbd->mode = pdata->mode; | 208 | |
| 209 | if (!pdata) { | ||
| 210 | error = spear_kbd_parse_dt(pdev, kbd); | ||
| 211 | if (error) | ||
| 212 | goto err_free_mem; | ||
| 213 | } else { | ||
| 214 | kbd->mode = pdata->mode; | ||
| 215 | kbd->rep = pdata->rep; | ||
| 216 | } | ||
| 183 | 217 | ||
| 184 | kbd->res = request_mem_region(res->start, resource_size(res), | 218 | kbd->res = request_mem_region(res->start, resource_size(res), |
| 185 | pdev->name); | 219 | pdev->name); |
| @@ -212,18 +246,17 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) | |||
| 212 | input_dev->open = spear_kbd_open; | 246 | input_dev->open = spear_kbd_open; |
| 213 | input_dev->close = spear_kbd_close; | 247 | input_dev->close = spear_kbd_close; |
| 214 | 248 | ||
| 215 | __set_bit(EV_KEY, input_dev->evbit); | 249 | error = matrix_keypad_build_keymap(keymap, NULL, NUM_ROWS, NUM_COLS, |
| 216 | if (pdata->rep) | 250 | kbd->keycodes, input_dev); |
| 251 | if (error) { | ||
| 252 | dev_err(&pdev->dev, "Failed to build keymap\n"); | ||
| 253 | goto err_put_clk; | ||
| 254 | } | ||
| 255 | |||
| 256 | if (kbd->rep) | ||
| 217 | __set_bit(EV_REP, input_dev->evbit); | 257 | __set_bit(EV_REP, input_dev->evbit); |
| 218 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 258 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
| 219 | 259 | ||
| 220 | input_dev->keycode = kbd->keycodes; | ||
| 221 | input_dev->keycodesize = sizeof(kbd->keycodes[0]); | ||
| 222 | input_dev->keycodemax = ARRAY_SIZE(kbd->keycodes); | ||
| 223 | |||
| 224 | matrix_keypad_build_keymap(keymap, ROW_SHIFT, | ||
| 225 | input_dev->keycode, input_dev->keybit); | ||
| 226 | |||
| 227 | input_set_drvdata(input_dev, kbd); | 260 | input_set_drvdata(input_dev, kbd); |
| 228 | 261 | ||
| 229 | error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd); | 262 | error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd); |
| @@ -317,6 +350,14 @@ static int spear_kbd_resume(struct device *dev) | |||
| 317 | 350 | ||
| 318 | static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume); | 351 | static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume); |
| 319 | 352 | ||
| 353 | #ifdef CONFIG_OF | ||
| 354 | static const struct of_device_id spear_kbd_id_table[] = { | ||
| 355 | { .compatible = "st,spear300-kbd" }, | ||
| 356 | {} | ||
| 357 | }; | ||
| 358 | MODULE_DEVICE_TABLE(of, spear_kbd_id_table); | ||
| 359 | #endif | ||
| 360 | |||
| 320 | static struct platform_driver spear_kbd_driver = { | 361 | static struct platform_driver spear_kbd_driver = { |
| 321 | .probe = spear_kbd_probe, | 362 | .probe = spear_kbd_probe, |
| 322 | .remove = __devexit_p(spear_kbd_remove), | 363 | .remove = __devexit_p(spear_kbd_remove), |
| @@ -324,6 +365,7 @@ static struct platform_driver spear_kbd_driver = { | |||
| 324 | .name = "keyboard", | 365 | .name = "keyboard", |
| 325 | .owner = THIS_MODULE, | 366 | .owner = THIS_MODULE, |
| 326 | .pm = &spear_kbd_pm_ops, | 367 | .pm = &spear_kbd_pm_ops, |
| 368 | .of_match_table = of_match_ptr(spear_kbd_id_table), | ||
| 327 | }, | 369 | }, |
| 328 | }; | 370 | }; |
| 329 | module_platform_driver(spear_kbd_driver); | 371 | module_platform_driver(spear_kbd_driver); |
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c index 9397cf9c625c..470a8778dec1 100644 --- a/drivers/input/keyboard/stmpe-keypad.c +++ b/drivers/input/keyboard/stmpe-keypad.c | |||
| @@ -289,19 +289,17 @@ static int __devinit stmpe_keypad_probe(struct platform_device *pdev) | |||
| 289 | input->id.bustype = BUS_I2C; | 289 | input->id.bustype = BUS_I2C; |
| 290 | input->dev.parent = &pdev->dev; | 290 | input->dev.parent = &pdev->dev; |
| 291 | 291 | ||
| 292 | input_set_capability(input, EV_MSC, MSC_SCAN); | 292 | ret = matrix_keypad_build_keymap(plat->keymap_data, NULL, |
| 293 | STMPE_KEYPAD_MAX_ROWS, | ||
| 294 | STMPE_KEYPAD_MAX_COLS, | ||
| 295 | keypad->keymap, input); | ||
| 296 | if (ret) | ||
| 297 | goto out_freeinput; | ||
| 293 | 298 | ||
| 294 | __set_bit(EV_KEY, input->evbit); | 299 | input_set_capability(input, EV_MSC, MSC_SCAN); |
| 295 | if (!plat->no_autorepeat) | 300 | if (!plat->no_autorepeat) |
| 296 | __set_bit(EV_REP, input->evbit); | 301 | __set_bit(EV_REP, input->evbit); |
| 297 | 302 | ||
| 298 | input->keycode = keypad->keymap; | ||
| 299 | input->keycodesize = sizeof(keypad->keymap[0]); | ||
| 300 | input->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
| 301 | |||
| 302 | matrix_keypad_build_keymap(plat->keymap_data, STMPE_KEYPAD_ROW_SHIFT, | ||
| 303 | input->keycode, input->keybit); | ||
| 304 | |||
| 305 | for (i = 0; i < plat->keymap_data->keymap_size; i++) { | 303 | for (i = 0; i < plat->keymap_data->keymap_size; i++) { |
| 306 | unsigned int key = plat->keymap_data->keymap[i]; | 304 | unsigned int key = plat->keymap_data->keymap[i]; |
| 307 | 305 | ||
diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c index 7437219370b1..cc612c5d5427 100644 --- a/drivers/input/keyboard/stowaway.c +++ b/drivers/input/keyboard/stowaway.c | |||
| @@ -170,15 +170,4 @@ static struct serio_driver skbd_drv = { | |||
| 170 | .disconnect = skbd_disconnect, | 170 | .disconnect = skbd_disconnect, |
| 171 | }; | 171 | }; |
| 172 | 172 | ||
| 173 | static int __init skbd_init(void) | 173 | module_serio_driver(skbd_drv); |
| 174 | { | ||
| 175 | return serio_register_driver(&skbd_drv); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void __exit skbd_exit(void) | ||
| 179 | { | ||
| 180 | serio_unregister_driver(&skbd_drv); | ||
| 181 | } | ||
| 182 | |||
| 183 | module_init(skbd_init); | ||
| 184 | module_exit(skbd_exit); | ||
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index a99a04b03ee4..5f836b1638c1 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c | |||
| @@ -369,19 +369,4 @@ static struct serio_driver sunkbd_drv = { | |||
| 369 | .disconnect = sunkbd_disconnect, | 369 | .disconnect = sunkbd_disconnect, |
| 370 | }; | 370 | }; |
| 371 | 371 | ||
| 372 | /* | 372 | module_serio_driver(sunkbd_drv); |
| 373 | * The functions for insering/removing us as a module. | ||
| 374 | */ | ||
| 375 | |||
| 376 | static int __init sunkbd_init(void) | ||
| 377 | { | ||
| 378 | return serio_register_driver(&sunkbd_drv); | ||
| 379 | } | ||
| 380 | |||
| 381 | static void __exit sunkbd_exit(void) | ||
| 382 | { | ||
| 383 | serio_unregister_driver(&sunkbd_drv); | ||
| 384 | } | ||
| 385 | |||
| 386 | module_init(sunkbd_init); | ||
| 387 | module_exit(sunkbd_exit); | ||
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c index 2dee3e4e7c6f..7d498e698508 100644 --- a/drivers/input/keyboard/tc3589x-keypad.c +++ b/drivers/input/keyboard/tc3589x-keypad.c | |||
| @@ -78,7 +78,7 @@ | |||
| 78 | * @input: pointer to input device object | 78 | * @input: pointer to input device object |
| 79 | * @board: keypad platform device | 79 | * @board: keypad platform device |
| 80 | * @krow: number of rows | 80 | * @krow: number of rows |
| 81 | * @kcol: number of coloumns | 81 | * @kcol: number of columns |
| 82 | * @keymap: matrix scan code table for keycodes | 82 | * @keymap: matrix scan code table for keycodes |
| 83 | * @keypad_stopped: holds keypad status | 83 | * @keypad_stopped: holds keypad status |
| 84 | */ | 84 | */ |
| @@ -96,21 +96,15 @@ static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad) | |||
| 96 | { | 96 | { |
| 97 | int ret; | 97 | int ret; |
| 98 | struct tc3589x *tc3589x = keypad->tc3589x; | 98 | struct tc3589x *tc3589x = keypad->tc3589x; |
| 99 | u8 settle_time = keypad->board->settle_time; | 99 | const struct tc3589x_keypad_platform_data *board = keypad->board; |
| 100 | u8 dbounce_period = keypad->board->debounce_period; | 100 | |
| 101 | u8 rows = keypad->board->krow & 0xf; /* mask out the nibble */ | 101 | /* validate platform configuration */ |
| 102 | u8 column = keypad->board->kcol & 0xf; /* mask out the nibble */ | 102 | if (board->kcol > TC3589x_MAX_KPCOL || board->krow > TC3589x_MAX_KPROW) |
| 103 | |||
| 104 | /* validate platform configurations */ | ||
| 105 | if (keypad->board->kcol > TC3589x_MAX_KPCOL || | ||
| 106 | keypad->board->krow > TC3589x_MAX_KPROW || | ||
| 107 | keypad->board->debounce_period > TC3589x_MAX_DEBOUNCE_SETTLE || | ||
| 108 | keypad->board->settle_time > TC3589x_MAX_DEBOUNCE_SETTLE) | ||
| 109 | return -EINVAL; | 103 | return -EINVAL; |
| 110 | 104 | ||
| 111 | /* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */ | 105 | /* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */ |
| 112 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE, | 106 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE, |
| 113 | (rows << KP_ROW_SHIFT) | column); | 107 | (board->krow << KP_ROW_SHIFT) | board->kcol); |
| 114 | if (ret < 0) | 108 | if (ret < 0) |
| 115 | return ret; | 109 | return ret; |
| 116 | 110 | ||
| @@ -124,12 +118,14 @@ static int tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad) | |||
| 124 | return ret; | 118 | return ret; |
| 125 | 119 | ||
| 126 | /* Configure settle time */ | 120 | /* Configure settle time */ |
| 127 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, settle_time); | 121 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, |
| 122 | board->settle_time); | ||
| 128 | if (ret < 0) | 123 | if (ret < 0) |
| 129 | return ret; | 124 | return ret; |
| 130 | 125 | ||
| 131 | /* Configure debounce time */ | 126 | /* Configure debounce time */ |
| 132 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, dbounce_period); | 127 | ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, |
| 128 | board->debounce_period); | ||
| 133 | if (ret < 0) | 129 | if (ret < 0) |
| 134 | return ret; | 130 | return ret; |
| 135 | 131 | ||
| @@ -337,23 +333,22 @@ static int __devinit tc3589x_keypad_probe(struct platform_device *pdev) | |||
| 337 | input->name = pdev->name; | 333 | input->name = pdev->name; |
| 338 | input->dev.parent = &pdev->dev; | 334 | input->dev.parent = &pdev->dev; |
| 339 | 335 | ||
| 340 | input->keycode = keypad->keymap; | ||
| 341 | input->keycodesize = sizeof(keypad->keymap[0]); | ||
| 342 | input->keycodemax = ARRAY_SIZE(keypad->keymap); | ||
| 343 | |||
| 344 | input->open = tc3589x_keypad_open; | 336 | input->open = tc3589x_keypad_open; |
| 345 | input->close = tc3589x_keypad_close; | 337 | input->close = tc3589x_keypad_close; |
| 346 | 338 | ||
| 347 | input_set_drvdata(input, keypad); | 339 | error = matrix_keypad_build_keymap(plat->keymap_data, NULL, |
| 340 | TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL, | ||
| 341 | keypad->keymap, input); | ||
| 342 | if (error) { | ||
| 343 | dev_err(&pdev->dev, "Failed to build keymap\n"); | ||
| 344 | goto err_free_mem; | ||
| 345 | } | ||
| 348 | 346 | ||
| 349 | input_set_capability(input, EV_MSC, MSC_SCAN); | 347 | input_set_capability(input, EV_MSC, MSC_SCAN); |
| 350 | |||
| 351 | __set_bit(EV_KEY, input->evbit); | ||
| 352 | if (!plat->no_autorepeat) | 348 | if (!plat->no_autorepeat) |
| 353 | __set_bit(EV_REP, input->evbit); | 349 | __set_bit(EV_REP, input->evbit); |
| 354 | 350 | ||
| 355 | matrix_keypad_build_keymap(plat->keymap_data, 0x3, | 351 | input_set_drvdata(input, keypad); |
| 356 | input->keycode, input->keybit); | ||
| 357 | 352 | ||
| 358 | error = request_threaded_irq(irq, NULL, | 353 | error = request_threaded_irq(irq, NULL, |
| 359 | tc3589x_keypad_irq, plat->irqtype, | 354 | tc3589x_keypad_irq, plat->irqtype, |
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 958ec107bfbc..5f87b28b3192 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c | |||
| @@ -342,21 +342,20 @@ static int __devinit tca8418_keypad_probe(struct i2c_client *client, | |||
| 342 | input->id.product = 0x001; | 342 | input->id.product = 0x001; |
| 343 | input->id.version = 0x0001; | 343 | input->id.version = 0x0001; |
| 344 | 344 | ||
| 345 | input->keycode = keypad_data->keymap; | 345 | error = matrix_keypad_build_keymap(pdata->keymap_data, NULL, |
| 346 | input->keycodesize = sizeof(keypad_data->keymap[0]); | 346 | pdata->rows, pdata->cols, |
| 347 | input->keycodemax = max_keys; | 347 | keypad_data->keymap, input); |
| 348 | if (error) { | ||
| 349 | dev_dbg(&client->dev, "Failed to build keymap\n"); | ||
| 350 | goto fail2; | ||
| 351 | } | ||
| 348 | 352 | ||
| 349 | __set_bit(EV_KEY, input->evbit); | ||
| 350 | if (pdata->rep) | 353 | if (pdata->rep) |
| 351 | __set_bit(EV_REP, input->evbit); | 354 | __set_bit(EV_REP, input->evbit); |
| 352 | |||
| 353 | input_set_capability(input, EV_MSC, MSC_SCAN); | 355 | input_set_capability(input, EV_MSC, MSC_SCAN); |
| 354 | 356 | ||
| 355 | input_set_drvdata(input, keypad_data); | 357 | input_set_drvdata(input, keypad_data); |
| 356 | 358 | ||
| 357 | matrix_keypad_build_keymap(pdata->keymap_data, row_shift, | ||
| 358 | input->keycode, input->keybit); | ||
| 359 | |||
| 360 | if (pdata->irq_is_gpio) | 359 | if (pdata->irq_is_gpio) |
| 361 | client->irq = gpio_to_irq(client->irq); | 360 | client->irq = gpio_to_irq(client->irq); |
| 362 | 361 | ||
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index fe4ac95ca6c8..4ffe64d53107 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c | |||
| @@ -619,8 +619,8 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, | |||
| 619 | } | 619 | } |
| 620 | 620 | ||
| 621 | #ifdef CONFIG_OF | 621 | #ifdef CONFIG_OF |
| 622 | static struct tegra_kbc_platform_data * __devinit | 622 | static struct tegra_kbc_platform_data * __devinit tegra_kbc_dt_parse_pdata( |
| 623 | tegra_kbc_dt_parse_pdata(struct platform_device *pdev) | 623 | struct platform_device *pdev) |
| 624 | { | 624 | { |
| 625 | struct tegra_kbc_platform_data *pdata; | 625 | struct tegra_kbc_platform_data *pdata; |
| 626 | struct device_node *np = pdev->dev.of_node; | 626 | struct device_node *np = pdev->dev.of_node; |
| @@ -660,10 +660,6 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev) | |||
| 660 | pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL; | 660 | pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL; |
| 661 | } | 661 | } |
| 662 | 662 | ||
| 663 | pdata->keymap_data = matrix_keyboard_of_fill_keymap(np, "linux,keymap"); | ||
| 664 | |||
| 665 | /* FIXME: Add handling of linux,fn-keymap here */ | ||
| 666 | |||
| 667 | return pdata; | 663 | return pdata; |
| 668 | } | 664 | } |
| 669 | #else | 665 | #else |
| @@ -674,10 +670,36 @@ static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( | |||
| 674 | } | 670 | } |
| 675 | #endif | 671 | #endif |
| 676 | 672 | ||
| 673 | static int __devinit tegra_kbd_setup_keymap(struct tegra_kbc *kbc) | ||
| 674 | { | ||
| 675 | const struct tegra_kbc_platform_data *pdata = kbc->pdata; | ||
| 676 | const struct matrix_keymap_data *keymap_data = pdata->keymap_data; | ||
| 677 | unsigned int keymap_rows = KBC_MAX_KEY; | ||
| 678 | int retval; | ||
| 679 | |||
| 680 | if (keymap_data && pdata->use_fn_map) | ||
| 681 | keymap_rows *= 2; | ||
| 682 | |||
| 683 | retval = matrix_keypad_build_keymap(keymap_data, NULL, | ||
| 684 | keymap_rows, KBC_MAX_COL, | ||
| 685 | kbc->keycode, kbc->idev); | ||
| 686 | if (retval == -ENOSYS || retval == -ENOENT) { | ||
| 687 | /* | ||
| 688 | * If there is no OF support in kernel or keymap | ||
| 689 | * property is missing, use default keymap. | ||
| 690 | */ | ||
| 691 | retval = matrix_keypad_build_keymap( | ||
| 692 | &tegra_kbc_default_keymap_data, NULL, | ||
| 693 | keymap_rows, KBC_MAX_COL, | ||
| 694 | kbc->keycode, kbc->idev); | ||
| 695 | } | ||
| 696 | |||
| 697 | return retval; | ||
| 698 | } | ||
| 699 | |||
| 677 | static int __devinit tegra_kbc_probe(struct platform_device *pdev) | 700 | static int __devinit tegra_kbc_probe(struct platform_device *pdev) |
| 678 | { | 701 | { |
| 679 | const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; | 702 | const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; |
| 680 | const struct matrix_keymap_data *keymap_data; | ||
| 681 | struct tegra_kbc *kbc; | 703 | struct tegra_kbc *kbc; |
| 682 | struct input_dev *input_dev; | 704 | struct input_dev *input_dev; |
| 683 | struct resource *res; | 705 | struct resource *res; |
| @@ -757,29 +779,26 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) | |||
| 757 | kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + pdata->repeat_cnt; | 779 | kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + pdata->repeat_cnt; |
| 758 | kbc->repoll_dly = DIV_ROUND_UP(kbc->repoll_dly, KBC_CYCLE_MS); | 780 | kbc->repoll_dly = DIV_ROUND_UP(kbc->repoll_dly, KBC_CYCLE_MS); |
| 759 | 781 | ||
| 782 | kbc->wakeup_key = pdata->wakeup_key; | ||
| 783 | kbc->use_fn_map = pdata->use_fn_map; | ||
| 784 | kbc->use_ghost_filter = pdata->use_ghost_filter; | ||
| 785 | |||
| 760 | input_dev->name = pdev->name; | 786 | input_dev->name = pdev->name; |
| 761 | input_dev->id.bustype = BUS_HOST; | 787 | input_dev->id.bustype = BUS_HOST; |
| 762 | input_dev->dev.parent = &pdev->dev; | 788 | input_dev->dev.parent = &pdev->dev; |
| 763 | input_dev->open = tegra_kbc_open; | 789 | input_dev->open = tegra_kbc_open; |
| 764 | input_dev->close = tegra_kbc_close; | 790 | input_dev->close = tegra_kbc_close; |
| 765 | 791 | ||
| 766 | input_set_drvdata(input_dev, kbc); | 792 | err = tegra_kbd_setup_keymap(kbc); |
| 793 | if (err) { | ||
| 794 | dev_err(&pdev->dev, "failed to setup keymap\n"); | ||
| 795 | goto err_put_clk; | ||
| 796 | } | ||
| 767 | 797 | ||
| 768 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 798 | __set_bit(EV_REP, input_dev->evbit); |
| 769 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | 799 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); |
| 770 | 800 | ||
| 771 | input_dev->keycode = kbc->keycode; | 801 | input_set_drvdata(input_dev, kbc); |
| 772 | input_dev->keycodesize = sizeof(kbc->keycode[0]); | ||
| 773 | input_dev->keycodemax = KBC_MAX_KEY; | ||
| 774 | if (pdata->use_fn_map) | ||
| 775 | input_dev->keycodemax *= 2; | ||
| 776 | |||
| 777 | kbc->use_fn_map = pdata->use_fn_map; | ||
| 778 | kbc->use_ghost_filter = pdata->use_ghost_filter; | ||
| 779 | keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; | ||
| 780 | matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, | ||
| 781 | input_dev->keycode, input_dev->keybit); | ||
| 782 | kbc->wakeup_key = pdata->wakeup_key; | ||
| 783 | 802 | ||
| 784 | err = request_irq(kbc->irq, tegra_kbc_isr, | 803 | err = request_irq(kbc->irq, tegra_kbc_isr, |
| 785 | IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc); | 804 | IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc); |
| @@ -799,9 +818,6 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) | |||
| 799 | platform_set_drvdata(pdev, kbc); | 818 | platform_set_drvdata(pdev, kbc); |
| 800 | device_init_wakeup(&pdev->dev, pdata->wakeup); | 819 | device_init_wakeup(&pdev->dev, pdata->wakeup); |
| 801 | 820 | ||
| 802 | if (!pdev->dev.platform_data) | ||
| 803 | matrix_keyboard_of_free_keymap(pdata->keymap_data); | ||
| 804 | |||
| 805 | return 0; | 821 | return 0; |
| 806 | 822 | ||
| 807 | err_free_irq: | 823 | err_free_irq: |
| @@ -816,10 +832,8 @@ err_free_mem: | |||
| 816 | input_free_device(input_dev); | 832 | input_free_device(input_dev); |
| 817 | kfree(kbc); | 833 | kfree(kbc); |
| 818 | err_free_pdata: | 834 | err_free_pdata: |
| 819 | if (!pdev->dev.platform_data) { | 835 | if (!pdev->dev.platform_data) |
| 820 | matrix_keyboard_of_free_keymap(pdata->keymap_data); | ||
| 821 | kfree(pdata); | 836 | kfree(pdata); |
| 822 | } | ||
| 823 | 837 | ||
| 824 | return err; | 838 | return err; |
| 825 | } | 839 | } |
diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index fb39c94b6fdd..a4a445fb7020 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c | |||
| @@ -247,15 +247,11 @@ static int __devinit keypad_probe(struct platform_device *pdev) | |||
| 247 | error = -ENOMEM; | 247 | error = -ENOMEM; |
| 248 | goto error_input; | 248 | goto error_input; |
| 249 | } | 249 | } |
| 250 | input_set_drvdata(kp->input_dev, kp); | ||
| 251 | 250 | ||
| 252 | kp->input_dev->name = pdev->name; | 251 | kp->input_dev->name = pdev->name; |
| 253 | kp->input_dev->dev.parent = &pdev->dev; | 252 | kp->input_dev->dev.parent = &pdev->dev; |
| 254 | kp->input_dev->open = keypad_start; | 253 | kp->input_dev->open = keypad_start; |
| 255 | kp->input_dev->close = keypad_stop; | 254 | kp->input_dev->close = keypad_stop; |
| 256 | kp->input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
| 257 | if (!pdata->no_autorepeat) | ||
| 258 | kp->input_dev->evbit[0] |= BIT_MASK(EV_REP); | ||
| 259 | 255 | ||
| 260 | clk_enable(kp->clk); | 256 | clk_enable(kp->clk); |
| 261 | rev = keypad_read(kp, rev); | 257 | rev = keypad_read(kp, rev); |
| @@ -264,15 +260,20 @@ static int __devinit keypad_probe(struct platform_device *pdev) | |||
| 264 | kp->input_dev->id.version = ((rev >> 16) & 0xfff); | 260 | kp->input_dev->id.version = ((rev >> 16) & 0xfff); |
| 265 | clk_disable(kp->clk); | 261 | clk_disable(kp->clk); |
| 266 | 262 | ||
| 267 | kp->input_dev->keycode = kp->keycodes; | 263 | error = matrix_keypad_build_keymap(keymap_data, NULL, |
| 268 | kp->input_dev->keycodesize = sizeof(kp->keycodes[0]); | 264 | kp->rows, kp->cols, |
| 269 | kp->input_dev->keycodemax = kp->rows << kp->row_shift; | 265 | kp->keycodes, kp->input_dev); |
| 270 | 266 | if (error) { | |
| 271 | matrix_keypad_build_keymap(keymap_data, kp->row_shift, kp->keycodes, | 267 | dev_err(dev, "Failed to build keymap\n"); |
| 272 | kp->input_dev->keybit); | 268 | goto error_reg; |
| 269 | } | ||
| 273 | 270 | ||
| 271 | if (!pdata->no_autorepeat) | ||
| 272 | kp->input_dev->evbit[0] |= BIT_MASK(EV_REP); | ||
| 274 | input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN); | 273 | input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN); |
| 275 | 274 | ||
| 275 | input_set_drvdata(kp->input_dev, kp); | ||
| 276 | |||
| 276 | error = input_register_device(kp->input_dev); | 277 | error = input_register_device(kp->input_dev); |
| 277 | if (error < 0) { | 278 | if (error < 0) { |
| 278 | dev_err(dev, "Could not register input device\n"); | 279 | dev_err(dev, "Could not register input device\n"); |
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 67bec14e8b96..a2c6f79aa101 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c | |||
| @@ -361,14 +361,6 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev) | |||
| 361 | kp->irq = platform_get_irq(pdev, 0); | 361 | kp->irq = platform_get_irq(pdev, 0); |
| 362 | 362 | ||
| 363 | /* setup input device */ | 363 | /* setup input device */ |
| 364 | __set_bit(EV_KEY, input->evbit); | ||
| 365 | |||
| 366 | /* Enable auto repeat feature of Linux input subsystem */ | ||
| 367 | if (pdata->rep) | ||
| 368 | __set_bit(EV_REP, input->evbit); | ||
| 369 | |||
| 370 | input_set_capability(input, EV_MSC, MSC_SCAN); | ||
| 371 | |||
| 372 | input->name = "TWL4030 Keypad"; | 364 | input->name = "TWL4030 Keypad"; |
| 373 | input->phys = "twl4030_keypad/input0"; | 365 | input->phys = "twl4030_keypad/input0"; |
| 374 | input->dev.parent = &pdev->dev; | 366 | input->dev.parent = &pdev->dev; |
| @@ -378,12 +370,19 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev) | |||
| 378 | input->id.product = 0x0001; | 370 | input->id.product = 0x0001; |
| 379 | input->id.version = 0x0003; | 371 | input->id.version = 0x0003; |
| 380 | 372 | ||
| 381 | input->keycode = kp->keymap; | 373 | error = matrix_keypad_build_keymap(keymap_data, NULL, |
| 382 | input->keycodesize = sizeof(kp->keymap[0]); | 374 | TWL4030_MAX_ROWS, |
| 383 | input->keycodemax = ARRAY_SIZE(kp->keymap); | 375 | 1 << TWL4030_ROW_SHIFT, |
| 376 | kp->keymap, input); | ||
| 377 | if (error) { | ||
| 378 | dev_err(kp->dbg_dev, "Failed to build keymap\n"); | ||
| 379 | goto err1; | ||
| 380 | } | ||
| 384 | 381 | ||
| 385 | matrix_keypad_build_keymap(keymap_data, TWL4030_ROW_SHIFT, | 382 | input_set_capability(input, EV_MSC, MSC_SCAN); |
| 386 | input->keycode, input->keybit); | 383 | /* Enable auto repeat feature of Linux input subsystem */ |
| 384 | if (pdata->rep) | ||
| 385 | __set_bit(EV_REP, input->evbit); | ||
| 387 | 386 | ||
| 388 | error = input_register_device(input); | 387 | error = input_register_device(input); |
| 389 | if (error) { | 388 | if (error) { |
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index 99bbb7e775ae..085ede4d972d 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c | |||
| @@ -42,7 +42,8 @@ | |||
| 42 | #define KGET_RAW(n) (((n) & KEY0R) >> 3) | 42 | #define KGET_RAW(n) (((n) & KEY0R) >> 3) |
| 43 | #define KGET_COLUMN(n) ((n) & KEY0C) | 43 | #define KGET_COLUMN(n) ((n) & KEY0C) |
| 44 | 44 | ||
| 45 | #define W90P910_MAX_KEY_NUM (8 * 8) | 45 | #define W90P910_NUM_ROWS 8 |
| 46 | #define W90P910_NUM_COLS 8 | ||
| 46 | #define W90P910_ROW_SHIFT 3 | 47 | #define W90P910_ROW_SHIFT 3 |
| 47 | 48 | ||
| 48 | struct w90p910_keypad { | 49 | struct w90p910_keypad { |
| @@ -51,7 +52,7 @@ struct w90p910_keypad { | |||
| 51 | struct input_dev *input_dev; | 52 | struct input_dev *input_dev; |
| 52 | void __iomem *mmio_base; | 53 | void __iomem *mmio_base; |
| 53 | int irq; | 54 | int irq; |
| 54 | unsigned short keymap[W90P910_MAX_KEY_NUM]; | 55 | unsigned short keymap[W90P910_NUM_ROWS * W90P910_NUM_COLS]; |
| 55 | }; | 56 | }; |
| 56 | 57 | ||
| 57 | static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, | 58 | static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad, |
| @@ -190,17 +191,13 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | |||
| 190 | input_dev->close = w90p910_keypad_close; | 191 | input_dev->close = w90p910_keypad_close; |
| 191 | input_dev->dev.parent = &pdev->dev; | 192 | input_dev->dev.parent = &pdev->dev; |
| 192 | 193 | ||
| 193 | input_dev->keycode = keypad->keymap; | 194 | error = matrix_keypad_build_keymap(keymap_data, NULL, |
| 194 | input_dev->keycodesize = sizeof(keypad->keymap[0]); | 195 | W90P910_NUM_ROWS, W90P910_NUM_COLS, |
| 195 | input_dev->keycodemax = ARRAY_SIZE(keypad->keymap); | 196 | keypad->keymap, input_dev); |
| 196 | 197 | if (error) { | |
| 197 | input_set_drvdata(input_dev, keypad); | 198 | dev_err(&pdev->dev, "failed to build keymap\n"); |
| 198 | 199 | goto failed_put_clk; | |
| 199 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 200 | } |
| 200 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
| 201 | |||
| 202 | matrix_keypad_build_keymap(keymap_data, W90P910_ROW_SHIFT, | ||
| 203 | input_dev->keycode, input_dev->keybit); | ||
| 204 | 201 | ||
| 205 | error = request_irq(keypad->irq, w90p910_keypad_irq_handler, | 202 | error = request_irq(keypad->irq, w90p910_keypad_irq_handler, |
| 206 | 0, pdev->name, keypad); | 203 | 0, pdev->name, keypad); |
| @@ -209,6 +206,10 @@ static int __devinit w90p910_keypad_probe(struct platform_device *pdev) | |||
| 209 | goto failed_put_clk; | 206 | goto failed_put_clk; |
| 210 | } | 207 | } |
| 211 | 208 | ||
| 209 | __set_bit(EV_REP, input_dev->evbit); | ||
| 210 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
| 211 | input_set_drvdata(input_dev, keypad); | ||
| 212 | |||
| 212 | /* Register the input device */ | 213 | /* Register the input device */ |
| 213 | error = input_register_device(input_dev); | 214 | error = input_register_device(input_dev); |
| 214 | if (error) { | 215 | if (error) { |
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index 37b01d777a4a..d050d9d0011b 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c | |||
| @@ -169,15 +169,4 @@ static struct serio_driver xtkbd_drv = { | |||
| 169 | .disconnect = xtkbd_disconnect, | 169 | .disconnect = xtkbd_disconnect, |
| 170 | }; | 170 | }; |
| 171 | 171 | ||
| 172 | static int __init xtkbd_init(void) | 172 | module_serio_driver(xtkbd_drv); |
| 173 | { | ||
| 174 | return serio_register_driver(&xtkbd_drv); | ||
| 175 | } | ||
| 176 | |||
| 177 | static void __exit xtkbd_exit(void) | ||
| 178 | { | ||
| 179 | serio_unregister_driver(&xtkbd_drv); | ||
| 180 | } | ||
| 181 | |||
| 182 | module_init(xtkbd_init); | ||
| 183 | module_exit(xtkbd_exit); | ||
diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c new file mode 100644 index 000000000000..443ad64b7f2a --- /dev/null +++ b/drivers/input/matrix-keymap.c | |||
| @@ -0,0 +1,163 @@ | |||
| 1 | /* | ||
| 2 | * Helpers for matrix keyboard bindings | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Google, Inc | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Olof Johansson <olof@lixom.net> | ||
| 8 | * | ||
| 9 | * This software is licensed under the terms of the GNU General Public | ||
| 10 | * License version 2, as published by the Free Software Foundation, and | ||
| 11 | * may be copied, distributed, and modified under those terms. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/device.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/types.h> | ||
| 23 | #include <linux/input.h> | ||
| 24 | #include <linux/of.h> | ||
| 25 | #include <linux/export.h> | ||
| 26 | #include <linux/input/matrix_keypad.h> | ||
| 27 | |||
| 28 | static bool matrix_keypad_map_key(struct input_dev *input_dev, | ||
| 29 | unsigned int rows, unsigned int cols, | ||
| 30 | unsigned int row_shift, unsigned int key) | ||
| 31 | { | ||
| 32 | unsigned short *keymap = input_dev->keycode; | ||
| 33 | unsigned int row = KEY_ROW(key); | ||
| 34 | unsigned int col = KEY_COL(key); | ||
| 35 | unsigned short code = KEY_VAL(key); | ||
| 36 | |||
| 37 | if (row >= rows || col >= cols) { | ||
| 38 | dev_err(input_dev->dev.parent, | ||
| 39 | "%s: invalid keymap entry 0x%x (row: %d, col: %d, rows: %d, cols: %d)\n", | ||
| 40 | __func__, key, row, col, rows, cols); | ||
| 41 | return false; | ||
| 42 | } | ||
| 43 | |||
| 44 | keymap[MATRIX_SCAN_CODE(row, col, row_shift)] = code; | ||
| 45 | __set_bit(code, input_dev->keybit); | ||
| 46 | |||
| 47 | return true; | ||
| 48 | } | ||
| 49 | |||
| 50 | #ifdef CONFIG_OF | ||
| 51 | static int matrix_keypad_parse_of_keymap(const char *propname, | ||
| 52 | unsigned int rows, unsigned int cols, | ||
| 53 | struct input_dev *input_dev) | ||
| 54 | { | ||
| 55 | struct device *dev = input_dev->dev.parent; | ||
| 56 | struct device_node *np = dev->of_node; | ||
| 57 | unsigned int row_shift = get_count_order(cols); | ||
| 58 | unsigned int max_keys = rows << row_shift; | ||
| 59 | unsigned int proplen, i, size; | ||
| 60 | const __be32 *prop; | ||
| 61 | |||
| 62 | if (!np) | ||
| 63 | return -ENOENT; | ||
| 64 | |||
| 65 | if (!propname) | ||
| 66 | propname = "linux,keymap"; | ||
| 67 | |||
| 68 | prop = of_get_property(np, propname, &proplen); | ||
| 69 | if (!prop) { | ||
| 70 | dev_err(dev, "OF: %s property not defined in %s\n", | ||
| 71 | propname, np->full_name); | ||
| 72 | return -ENOENT; | ||
| 73 | } | ||
| 74 | |||
| 75 | if (proplen % sizeof(u32)) { | ||
| 76 | dev_err(dev, "OF: Malformed keycode property %s in %s\n", | ||
| 77 | propname, np->full_name); | ||
| 78 | return -EINVAL; | ||
| 79 | } | ||
| 80 | |||
| 81 | size = proplen / sizeof(u32); | ||
| 82 | if (size > max_keys) { | ||
| 83 | dev_err(dev, "OF: %s size overflow\n", propname); | ||
| 84 | return -EINVAL; | ||
| 85 | } | ||
| 86 | |||
| 87 | for (i = 0; i < size; i++) { | ||
| 88 | unsigned int key = be32_to_cpup(prop + i); | ||
| 89 | |||
| 90 | if (!matrix_keypad_map_key(input_dev, rows, cols, | ||
| 91 | row_shift, key)) | ||
| 92 | return -EINVAL; | ||
| 93 | } | ||
| 94 | |||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | #else | ||
| 98 | static int matrix_keypad_parse_of_keymap(const char *propname, | ||
| 99 | unsigned int rows, unsigned int cols, | ||
| 100 | struct input_dev *input_dev) | ||
| 101 | { | ||
| 102 | return -ENOSYS; | ||
| 103 | } | ||
| 104 | #endif | ||
| 105 | |||
| 106 | /** | ||
| 107 | * matrix_keypad_build_keymap - convert platform keymap into matrix keymap | ||
| 108 | * @keymap_data: keymap supplied by the platform code | ||
| 109 | * @keymap_name: name of device tree property containing keymap (if device | ||
| 110 | * tree support is enabled). | ||
| 111 | * @rows: number of rows in target keymap array | ||
| 112 | * @cols: number of cols in target keymap array | ||
| 113 | * @keymap: expanded version of keymap that is suitable for use by | ||
| 114 | * matrix keyboard driver | ||
| 115 | * @input_dev: input devices for which we are setting up the keymap | ||
| 116 | * | ||
| 117 | * This function converts platform keymap (encoded with KEY() macro) into | ||
| 118 | * an array of keycodes that is suitable for using in a standard matrix | ||
| 119 | * keyboard driver that uses row and col as indices. | ||
| 120 | * | ||
| 121 | * If @keymap_data is not supplied and device tree support is enabled | ||
| 122 | * it will attempt load the keymap from property specified by @keymap_name | ||
| 123 | * argument (or "linux,keymap" if @keymap_name is %NULL). | ||
| 124 | * | ||
| 125 | * Callers are expected to set up input_dev->dev.parent before calling this | ||
| 126 | * function. | ||
| 127 | */ | ||
| 128 | int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, | ||
| 129 | const char *keymap_name, | ||
| 130 | unsigned int rows, unsigned int cols, | ||
| 131 | unsigned short *keymap, | ||
| 132 | struct input_dev *input_dev) | ||
| 133 | { | ||
| 134 | unsigned int row_shift = get_count_order(cols); | ||
| 135 | int i; | ||
| 136 | int error; | ||
| 137 | |||
| 138 | input_dev->keycode = keymap; | ||
| 139 | input_dev->keycodesize = sizeof(*keymap); | ||
| 140 | input_dev->keycodemax = rows << row_shift; | ||
| 141 | |||
| 142 | __set_bit(EV_KEY, input_dev->evbit); | ||
| 143 | |||
| 144 | if (keymap_data) { | ||
| 145 | for (i = 0; i < keymap_data->keymap_size; i++) { | ||
| 146 | unsigned int key = keymap_data->keymap[i]; | ||
| 147 | |||
| 148 | if (!matrix_keypad_map_key(input_dev, rows, cols, | ||
| 149 | row_shift, key)) | ||
| 150 | return -EINVAL; | ||
| 151 | } | ||
| 152 | } else { | ||
| 153 | error = matrix_keypad_parse_of_keymap(keymap_name, rows, cols, | ||
| 154 | input_dev); | ||
| 155 | if (error) | ||
| 156 | return error; | ||
| 157 | } | ||
| 158 | |||
| 159 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | EXPORT_SYMBOL(matrix_keypad_build_keymap); | ||
diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c index 06517e60e50c..a3735a01e9fd 100644 --- a/drivers/input/misc/cma3000_d0x.c +++ b/drivers/input/misc/cma3000_d0x.c | |||
| @@ -318,7 +318,7 @@ struct cma3000_accl_data *cma3000_init(struct device *dev, int irq, | |||
| 318 | mutex_init(&data->mutex); | 318 | mutex_init(&data->mutex); |
| 319 | 319 | ||
| 320 | data->mode = pdata->mode; | 320 | data->mode = pdata->mode; |
| 321 | if (data->mode < CMAMODE_DEFAULT || data->mode > CMAMODE_POFF) { | 321 | if (data->mode > CMAMODE_POFF) { |
| 322 | data->mode = CMAMODE_MOTDET; | 322 | data->mode = CMAMODE_MOTDET; |
| 323 | dev_warn(dev, | 323 | dev_warn(dev, |
| 324 | "Invalid mode specified, assuming Motion Detect\n"); | 324 | "Invalid mode specified, assuming Motion Detect\n"); |
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c index 5403c571b6a5..306f84c2d8fb 100644 --- a/drivers/input/misc/mpu3050.c +++ b/drivers/input/misc/mpu3050.c | |||
| @@ -367,7 +367,7 @@ static int __devinit mpu3050_probe(struct i2c_client *client, | |||
| 367 | 367 | ||
| 368 | error = request_threaded_irq(client->irq, | 368 | error = request_threaded_irq(client->irq, |
| 369 | NULL, mpu3050_interrupt_thread, | 369 | NULL, mpu3050_interrupt_thread, |
| 370 | IRQF_TRIGGER_RISING, | 370 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
| 371 | "mpu3050", sensor); | 371 | "mpu3050", sensor); |
| 372 | if (error) { | 372 | if (error) { |
| 373 | dev_err(&client->dev, | 373 | dev_err(&client->dev, |
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index 14e94f56cb7d..c34f6c0371c4 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | */ | 27 | */ |
| 28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 29 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
| 30 | #include <linux/of.h> | ||
| 30 | #include <linux/workqueue.h> | 31 | #include <linux/workqueue.h> |
| 31 | #include <linux/input.h> | 32 | #include <linux/input.h> |
| 32 | #include <linux/mfd/twl6040.h> | 33 | #include <linux/mfd/twl6040.h> |
| @@ -258,10 +259,13 @@ static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL); | |||
| 258 | static int __devinit twl6040_vibra_probe(struct platform_device *pdev) | 259 | static int __devinit twl6040_vibra_probe(struct platform_device *pdev) |
| 259 | { | 260 | { |
| 260 | struct twl6040_vibra_data *pdata = pdev->dev.platform_data; | 261 | struct twl6040_vibra_data *pdata = pdev->dev.platform_data; |
| 262 | struct device_node *node = pdev->dev.of_node; | ||
| 261 | struct vibra_info *info; | 263 | struct vibra_info *info; |
| 264 | int vddvibl_uV = 0; | ||
| 265 | int vddvibr_uV = 0; | ||
| 262 | int ret; | 266 | int ret; |
| 263 | 267 | ||
| 264 | if (!pdata) { | 268 | if (!pdata && !node) { |
| 265 | dev_err(&pdev->dev, "platform_data not available\n"); | 269 | dev_err(&pdev->dev, "platform_data not available\n"); |
| 266 | return -EINVAL; | 270 | return -EINVAL; |
| 267 | } | 271 | } |
| @@ -273,11 +277,26 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev) | |||
| 273 | } | 277 | } |
| 274 | 278 | ||
| 275 | info->dev = &pdev->dev; | 279 | info->dev = &pdev->dev; |
| 280 | |||
| 276 | info->twl6040 = dev_get_drvdata(pdev->dev.parent); | 281 | info->twl6040 = dev_get_drvdata(pdev->dev.parent); |
| 277 | info->vibldrv_res = pdata->vibldrv_res; | 282 | if (pdata) { |
| 278 | info->vibrdrv_res = pdata->vibrdrv_res; | 283 | info->vibldrv_res = pdata->vibldrv_res; |
| 279 | info->viblmotor_res = pdata->viblmotor_res; | 284 | info->vibrdrv_res = pdata->vibrdrv_res; |
| 280 | info->vibrmotor_res = pdata->vibrmotor_res; | 285 | info->viblmotor_res = pdata->viblmotor_res; |
| 286 | info->vibrmotor_res = pdata->vibrmotor_res; | ||
| 287 | vddvibl_uV = pdata->vddvibl_uV; | ||
| 288 | vddvibr_uV = pdata->vddvibr_uV; | ||
| 289 | } else { | ||
| 290 | of_property_read_u32(node, "vibldrv_res", &info->vibldrv_res); | ||
| 291 | of_property_read_u32(node, "vibrdrv_res", &info->vibrdrv_res); | ||
| 292 | of_property_read_u32(node, "viblmotor_res", | ||
| 293 | &info->viblmotor_res); | ||
| 294 | of_property_read_u32(node, "vibrmotor_res", | ||
| 295 | &info->vibrmotor_res); | ||
| 296 | of_property_read_u32(node, "vddvibl_uV", &vddvibl_uV); | ||
| 297 | of_property_read_u32(node, "vddvibr_uV", &vddvibr_uV); | ||
| 298 | } | ||
| 299 | |||
| 281 | if ((!info->vibldrv_res && !info->viblmotor_res) || | 300 | if ((!info->vibldrv_res && !info->viblmotor_res) || |
| 282 | (!info->vibrdrv_res && !info->vibrmotor_res)) { | 301 | (!info->vibrdrv_res && !info->vibrmotor_res)) { |
| 283 | dev_err(info->dev, "invalid vibra driver/motor resistance\n"); | 302 | dev_err(info->dev, "invalid vibra driver/motor resistance\n"); |
| @@ -339,10 +358,9 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev) | |||
| 339 | goto err_regulator; | 358 | goto err_regulator; |
| 340 | } | 359 | } |
| 341 | 360 | ||
| 342 | if (pdata->vddvibl_uV) { | 361 | if (vddvibl_uV) { |
| 343 | ret = regulator_set_voltage(info->supplies[0].consumer, | 362 | ret = regulator_set_voltage(info->supplies[0].consumer, |
| 344 | pdata->vddvibl_uV, | 363 | vddvibl_uV, vddvibl_uV); |
| 345 | pdata->vddvibl_uV); | ||
| 346 | if (ret) { | 364 | if (ret) { |
| 347 | dev_err(info->dev, "failed to set VDDVIBL volt %d\n", | 365 | dev_err(info->dev, "failed to set VDDVIBL volt %d\n", |
| 348 | ret); | 366 | ret); |
| @@ -350,10 +368,9 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev) | |||
| 350 | } | 368 | } |
| 351 | } | 369 | } |
| 352 | 370 | ||
| 353 | if (pdata->vddvibr_uV) { | 371 | if (vddvibr_uV) { |
| 354 | ret = regulator_set_voltage(info->supplies[1].consumer, | 372 | ret = regulator_set_voltage(info->supplies[1].consumer, |
| 355 | pdata->vddvibr_uV, | 373 | vddvibr_uV, vddvibr_uV); |
| 356 | pdata->vddvibr_uV); | ||
| 357 | if (ret) { | 374 | if (ret) { |
| 358 | dev_err(info->dev, "failed to set VDDVIBR volt %d\n", | 375 | dev_err(info->dev, "failed to set VDDVIBR volt %d\n", |
| 359 | ret); | 376 | ret); |
| @@ -401,6 +418,12 @@ static int __devexit twl6040_vibra_remove(struct platform_device *pdev) | |||
| 401 | return 0; | 418 | return 0; |
| 402 | } | 419 | } |
| 403 | 420 | ||
| 421 | static const struct of_device_id twl6040_vibra_of_match[] = { | ||
| 422 | {.compatible = "ti,twl6040-vibra", }, | ||
| 423 | { }, | ||
| 424 | }; | ||
| 425 | MODULE_DEVICE_TABLE(of, twl6040_vibra_of_match); | ||
| 426 | |||
| 404 | static struct platform_driver twl6040_vibra_driver = { | 427 | static struct platform_driver twl6040_vibra_driver = { |
| 405 | .probe = twl6040_vibra_probe, | 428 | .probe = twl6040_vibra_probe, |
| 406 | .remove = __devexit_p(twl6040_vibra_remove), | 429 | .remove = __devexit_p(twl6040_vibra_remove), |
| @@ -408,6 +431,7 @@ static struct platform_driver twl6040_vibra_driver = { | |||
| 408 | .name = "twl6040-vibra", | 431 | .name = "twl6040-vibra", |
| 409 | .owner = THIS_MODULE, | 432 | .owner = THIS_MODULE, |
| 410 | .pm = &twl6040_vibra_pm_ops, | 433 | .pm = &twl6040_vibra_pm_ops, |
| 434 | .of_match_table = twl6040_vibra_of_match, | ||
| 411 | }, | 435 | }, |
| 412 | }; | 436 | }; |
| 413 | module_platform_driver(twl6040_vibra_driver); | 437 | module_platform_driver(twl6040_vibra_driver); |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 9b8db821d5f0..cd6268cf7cd5 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
| @@ -339,4 +339,16 @@ config MOUSE_SYNAPTICS_USB | |||
| 339 | To compile this driver as a module, choose M here: the | 339 | To compile this driver as a module, choose M here: the |
| 340 | module will be called synaptics_usb. | 340 | module will be called synaptics_usb. |
| 341 | 341 | ||
| 342 | config MOUSE_NAVPOINT_PXA27x | ||
| 343 | tristate "Synaptics NavPoint (PXA27x SSP/SPI)" | ||
| 344 | depends on PXA27x && PXA_SSP | ||
| 345 | help | ||
| 346 | This driver adds support for the Synaptics NavPoint touchpad connected | ||
| 347 | to a PXA27x SSP port in SPI slave mode. The device emulates a mouse; | ||
| 348 | a tap or tap-and-a-half drag gesture emulates the left mouse button. | ||
| 349 | For example, use the xf86-input-evdev driver for an X pointing device. | ||
| 350 | |||
| 351 | To compile this driver as a module, choose M here: the | ||
| 352 | module will be called navpoint. | ||
| 353 | |||
| 342 | endif | 354 | endif |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 4718effeb8d9..46ba7556fd4f 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
| @@ -12,6 +12,7 @@ obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o | |||
| 12 | obj-$(CONFIG_MOUSE_INPORT) += inport.o | 12 | obj-$(CONFIG_MOUSE_INPORT) += inport.o |
| 13 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o | 13 | obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o |
| 14 | obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o | 14 | obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o |
| 15 | obj-$(CONFIG_MOUSE_NAVPOINT_PXA27x) += navpoint.o | ||
| 15 | obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o | 16 | obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o |
| 16 | obj-$(CONFIG_MOUSE_PS2) += psmouse.o | 17 | obj-$(CONFIG_MOUSE_PS2) += psmouse.o |
| 17 | obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o | 18 | obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 4c6a72d3d48c..4a1347e91bdc 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -553,10 +553,7 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) | |||
| 553 | 553 | ||
| 554 | alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); | 554 | alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); |
| 555 | 555 | ||
| 556 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 556 | input_mt_report_finger_count(dev, fingers); |
| 557 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); | ||
| 558 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); | ||
| 559 | input_report_key(dev, BTN_TOOL_QUADTAP, fingers == 4); | ||
| 560 | 557 | ||
| 561 | input_report_key(dev, BTN_LEFT, left); | 558 | input_report_key(dev, BTN_LEFT, left); |
| 562 | input_report_key(dev, BTN_RIGHT, right); | 559 | input_report_key(dev, BTN_RIGHT, right); |
| @@ -604,10 +601,54 @@ static void alps_process_packet_v3(struct psmouse *psmouse) | |||
| 604 | 601 | ||
| 605 | static void alps_process_packet_v4(struct psmouse *psmouse) | 602 | static void alps_process_packet_v4(struct psmouse *psmouse) |
| 606 | { | 603 | { |
| 604 | struct alps_data *priv = psmouse->private; | ||
| 607 | unsigned char *packet = psmouse->packet; | 605 | unsigned char *packet = psmouse->packet; |
| 608 | struct input_dev *dev = psmouse->dev; | 606 | struct input_dev *dev = psmouse->dev; |
| 607 | int offset; | ||
| 609 | int x, y, z; | 608 | int x, y, z; |
| 610 | int left, right; | 609 | int left, right; |
| 610 | int x1, y1, x2, y2; | ||
| 611 | int fingers = 0; | ||
| 612 | unsigned int x_bitmap, y_bitmap; | ||
| 613 | |||
| 614 | /* | ||
| 615 | * v4 has a 6-byte encoding for bitmap data, but this data is | ||
| 616 | * broken up between 3 normal packets. Use priv->multi_packet to | ||
| 617 | * track our position in the bitmap packet. | ||
| 618 | */ | ||
| 619 | if (packet[6] & 0x40) { | ||
| 620 | /* sync, reset position */ | ||
| 621 | priv->multi_packet = 0; | ||
| 622 | } | ||
| 623 | |||
| 624 | if (WARN_ON_ONCE(priv->multi_packet > 2)) | ||
| 625 | return; | ||
| 626 | |||
| 627 | offset = 2 * priv->multi_packet; | ||
| 628 | priv->multi_data[offset] = packet[6]; | ||
| 629 | priv->multi_data[offset + 1] = packet[7]; | ||
| 630 | |||
| 631 | if (++priv->multi_packet > 2) { | ||
| 632 | priv->multi_packet = 0; | ||
| 633 | |||
| 634 | x_bitmap = ((priv->multi_data[2] & 0x1f) << 10) | | ||
| 635 | ((priv->multi_data[3] & 0x60) << 3) | | ||
| 636 | ((priv->multi_data[0] & 0x3f) << 2) | | ||
| 637 | ((priv->multi_data[1] & 0x60) >> 5); | ||
| 638 | y_bitmap = ((priv->multi_data[5] & 0x01) << 10) | | ||
| 639 | ((priv->multi_data[3] & 0x1f) << 5) | | ||
| 640 | (priv->multi_data[1] & 0x1f); | ||
| 641 | |||
| 642 | fingers = alps_process_bitmap(x_bitmap, y_bitmap, | ||
| 643 | &x1, &y1, &x2, &y2); | ||
| 644 | |||
| 645 | /* Store MT data.*/ | ||
| 646 | priv->fingers = fingers; | ||
| 647 | priv->x1 = x1; | ||
| 648 | priv->x2 = x2; | ||
| 649 | priv->y1 = y1; | ||
| 650 | priv->y2 = y2; | ||
| 651 | } | ||
| 611 | 652 | ||
| 612 | left = packet[4] & 0x01; | 653 | left = packet[4] & 0x01; |
| 613 | right = packet[4] & 0x02; | 654 | right = packet[4] & 0x02; |
| @@ -617,21 +658,41 @@ static void alps_process_packet_v4(struct psmouse *psmouse) | |||
| 617 | y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); | 658 | y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f); |
| 618 | z = packet[5] & 0x7f; | 659 | z = packet[5] & 0x7f; |
| 619 | 660 | ||
| 661 | /* | ||
| 662 | * If there were no contacts in the bitmap, use ST | ||
| 663 | * points in MT reports. | ||
| 664 | * If there were two contacts or more, report MT data. | ||
| 665 | */ | ||
| 666 | if (priv->fingers < 2) { | ||
| 667 | x1 = x; | ||
| 668 | y1 = y; | ||
| 669 | fingers = z > 0 ? 1 : 0; | ||
| 670 | } else { | ||
| 671 | fingers = priv->fingers; | ||
| 672 | x1 = priv->x1; | ||
| 673 | x2 = priv->x2; | ||
| 674 | y1 = priv->y1; | ||
| 675 | y2 = priv->y2; | ||
| 676 | } | ||
| 677 | |||
| 620 | if (z >= 64) | 678 | if (z >= 64) |
| 621 | input_report_key(dev, BTN_TOUCH, 1); | 679 | input_report_key(dev, BTN_TOUCH, 1); |
| 622 | else | 680 | else |
| 623 | input_report_key(dev, BTN_TOUCH, 0); | 681 | input_report_key(dev, BTN_TOUCH, 0); |
| 624 | 682 | ||
| 683 | alps_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); | ||
| 684 | |||
| 685 | input_mt_report_finger_count(dev, fingers); | ||
| 686 | |||
| 687 | input_report_key(dev, BTN_LEFT, left); | ||
| 688 | input_report_key(dev, BTN_RIGHT, right); | ||
| 689 | |||
| 625 | if (z > 0) { | 690 | if (z > 0) { |
| 626 | input_report_abs(dev, ABS_X, x); | 691 | input_report_abs(dev, ABS_X, x); |
| 627 | input_report_abs(dev, ABS_Y, y); | 692 | input_report_abs(dev, ABS_Y, y); |
| 628 | } | 693 | } |
| 629 | input_report_abs(dev, ABS_PRESSURE, z); | 694 | input_report_abs(dev, ABS_PRESSURE, z); |
| 630 | 695 | ||
| 631 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); | ||
| 632 | input_report_key(dev, BTN_LEFT, left); | ||
| 633 | input_report_key(dev, BTN_RIGHT, right); | ||
| 634 | |||
| 635 | input_sync(dev); | 696 | input_sync(dev); |
| 636 | } | 697 | } |
| 637 | 698 | ||
| @@ -1557,6 +1618,7 @@ int alps_init(struct psmouse *psmouse) | |||
| 1557 | input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); | 1618 | input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); |
| 1558 | break; | 1619 | break; |
| 1559 | case ALPS_PROTO_V3: | 1620 | case ALPS_PROTO_V3: |
| 1621 | case ALPS_PROTO_V4: | ||
| 1560 | set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); | 1622 | set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); |
| 1561 | input_mt_init_slots(dev1, 2); | 1623 | input_mt_init_slots(dev1, 2); |
| 1562 | input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); | 1624 | input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); |
| @@ -1565,8 +1627,7 @@ int alps_init(struct psmouse *psmouse) | |||
| 1565 | set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); | 1627 | set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); |
| 1566 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); | 1628 | set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); |
| 1567 | set_bit(BTN_TOOL_QUADTAP, dev1->keybit); | 1629 | set_bit(BTN_TOOL_QUADTAP, dev1->keybit); |
| 1568 | /* fall through */ | 1630 | |
| 1569 | case ALPS_PROTO_V4: | ||
| 1570 | input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); | 1631 | input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); |
| 1571 | input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); | 1632 | input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); |
| 1572 | break; | 1633 | break; |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index a00a4ab92a0f..ae1ac354c778 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
| @@ -39,6 +39,8 @@ struct alps_data { | |||
| 39 | int prev_fin; /* Finger bit from previous packet */ | 39 | int prev_fin; /* Finger bit from previous packet */ |
| 40 | int multi_packet; /* Multi-packet data in progress */ | 40 | int multi_packet; /* Multi-packet data in progress */ |
| 41 | unsigned char multi_data[6]; /* Saved multi-packet data */ | 41 | unsigned char multi_data[6]; /* Saved multi-packet data */ |
| 42 | int x1, x2, y1, y2; /* Coordinates from last MT report */ | ||
| 43 | int fingers; /* Number of fingers from MT report */ | ||
| 42 | u8 quirks; | 44 | u8 quirks; |
| 43 | struct timer_list timer; | 45 | struct timer_list timer; |
| 44 | }; | 46 | }; |
diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c new file mode 100644 index 000000000000..c29ae7654d5e --- /dev/null +++ b/drivers/input/mouse/navpoint.c | |||
| @@ -0,0 +1,369 @@ | |||
| 1 | /* | ||
| 2 | * Synaptics NavPoint (PXA27x SSP/SPI) driver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Paul Parsons <lost.distance@yahoo.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 version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/init.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/clk.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/gpio.h> | ||
| 18 | #include <linux/input.h> | ||
| 19 | #include <linux/input/navpoint.h> | ||
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/mutex.h> | ||
| 22 | #include <linux/pxa2xx_ssp.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | |||
| 25 | /* | ||
| 26 | * Synaptics Modular Embedded Protocol: Module Packet Format. | ||
| 27 | * Module header byte 2:0 = Length (# bytes that follow) | ||
| 28 | * Module header byte 4:3 = Control | ||
| 29 | * Module header byte 7:5 = Module Address | ||
| 30 | */ | ||
| 31 | #define HEADER_LENGTH(byte) ((byte) & 0x07) | ||
| 32 | #define HEADER_CONTROL(byte) (((byte) >> 3) & 0x03) | ||
| 33 | #define HEADER_ADDRESS(byte) ((byte) >> 5) | ||
| 34 | |||
| 35 | struct navpoint { | ||
| 36 | struct ssp_device *ssp; | ||
| 37 | struct input_dev *input; | ||
| 38 | struct device *dev; | ||
| 39 | int gpio; | ||
| 40 | int index; | ||
| 41 | u8 data[1 + HEADER_LENGTH(0xff)]; | ||
| 42 | }; | ||
| 43 | |||
| 44 | /* | ||
| 45 | * Initialization values for SSCR0_x, SSCR1_x, SSSR_x. | ||
| 46 | */ | ||
| 47 | static const u32 sscr0 = 0 | ||
| 48 | | SSCR0_TUM /* TIM = 1; No TUR interrupts */ | ||
| 49 | | SSCR0_RIM /* RIM = 1; No ROR interrupts */ | ||
| 50 | | SSCR0_SSE /* SSE = 1; SSP enabled */ | ||
| 51 | | SSCR0_Motorola /* FRF = 0; Motorola SPI */ | ||
| 52 | | SSCR0_DataSize(16) /* DSS = 15; Data size = 16-bit */ | ||
| 53 | ; | ||
| 54 | static const u32 sscr1 = 0 | ||
| 55 | | SSCR1_SCFR /* SCFR = 1; SSPSCLK only during transfers */ | ||
| 56 | | SSCR1_SCLKDIR /* SCLKDIR = 1; Slave mode */ | ||
| 57 | | SSCR1_SFRMDIR /* SFRMDIR = 1; Slave mode */ | ||
| 58 | | SSCR1_RWOT /* RWOT = 1; Receive without transmit mode */ | ||
| 59 | | SSCR1_RxTresh(1) /* RFT = 0; Receive FIFO threshold = 1 */ | ||
| 60 | | SSCR1_SPH /* SPH = 1; SSPSCLK inactive 0.5 + 1 cycles */ | ||
| 61 | | SSCR1_RIE /* RIE = 1; Receive FIFO interrupt enabled */ | ||
| 62 | ; | ||
| 63 | static const u32 sssr = 0 | ||
| 64 | | SSSR_BCE /* BCE = 1; Clear BCE */ | ||
| 65 | | SSSR_TUR /* TUR = 1; Clear TUR */ | ||
| 66 | | SSSR_EOC /* EOC = 1; Clear EOC */ | ||
| 67 | | SSSR_TINT /* TINT = 1; Clear TINT */ | ||
| 68 | | SSSR_PINT /* PINT = 1; Clear PINT */ | ||
| 69 | | SSSR_ROR /* ROR = 1; Clear ROR */ | ||
| 70 | ; | ||
| 71 | |||
| 72 | /* | ||
| 73 | * MEP Query $22: Touchpad Coordinate Range Query is not supported by | ||
| 74 | * the NavPoint module, so sampled values provide the default limits. | ||
| 75 | */ | ||
| 76 | #define NAVPOINT_X_MIN 1278 | ||
| 77 | #define NAVPOINT_X_MAX 5340 | ||
| 78 | #define NAVPOINT_Y_MIN 1572 | ||
| 79 | #define NAVPOINT_Y_MAX 4396 | ||
| 80 | #define NAVPOINT_PRESSURE_MIN 0 | ||
| 81 | #define NAVPOINT_PRESSURE_MAX 255 | ||
| 82 | |||
| 83 | static void navpoint_packet(struct navpoint *navpoint) | ||
| 84 | { | ||
| 85 | int finger; | ||
| 86 | int gesture; | ||
| 87 | int x, y, z; | ||
| 88 | |||
| 89 | switch (navpoint->data[0]) { | ||
| 90 | case 0xff: /* Garbage (packet?) between reset and Hello packet */ | ||
| 91 | case 0x00: /* Module 0, NULL packet */ | ||
| 92 | break; | ||
| 93 | |||
| 94 | case 0x0e: /* Module 0, Absolute packet */ | ||
| 95 | finger = (navpoint->data[1] & 0x01); | ||
| 96 | gesture = (navpoint->data[1] & 0x02); | ||
| 97 | x = ((navpoint->data[2] & 0x1f) << 8) | navpoint->data[3]; | ||
| 98 | y = ((navpoint->data[4] & 0x1f) << 8) | navpoint->data[5]; | ||
| 99 | z = navpoint->data[6]; | ||
| 100 | input_report_key(navpoint->input, BTN_TOUCH, finger); | ||
| 101 | input_report_abs(navpoint->input, ABS_X, x); | ||
| 102 | input_report_abs(navpoint->input, ABS_Y, y); | ||
| 103 | input_report_abs(navpoint->input, ABS_PRESSURE, z); | ||
| 104 | input_report_key(navpoint->input, BTN_TOOL_FINGER, finger); | ||
| 105 | input_report_key(navpoint->input, BTN_LEFT, gesture); | ||
| 106 | input_sync(navpoint->input); | ||
| 107 | break; | ||
| 108 | |||
| 109 | case 0x19: /* Module 0, Hello packet */ | ||
| 110 | if ((navpoint->data[1] & 0xf0) == 0x10) | ||
| 111 | break; | ||
| 112 | /* FALLTHROUGH */ | ||
| 113 | default: | ||
| 114 | dev_warn(navpoint->dev, | ||
| 115 | "spurious packet: data=0x%02x,0x%02x,...\n", | ||
| 116 | navpoint->data[0], navpoint->data[1]); | ||
| 117 | break; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | static irqreturn_t navpoint_irq(int irq, void *dev_id) | ||
| 122 | { | ||
| 123 | struct navpoint *navpoint = dev_id; | ||
| 124 | struct ssp_device *ssp = navpoint->ssp; | ||
| 125 | irqreturn_t ret = IRQ_NONE; | ||
| 126 | u32 status; | ||
| 127 | |||
| 128 | status = pxa_ssp_read_reg(ssp, SSSR); | ||
| 129 | if (status & sssr) { | ||
| 130 | dev_warn(navpoint->dev, | ||
| 131 | "unexpected interrupt: status=0x%08x\n", status); | ||
| 132 | pxa_ssp_write_reg(ssp, SSSR, (status & sssr)); | ||
| 133 | ret = IRQ_HANDLED; | ||
| 134 | } | ||
| 135 | |||
| 136 | while (status & SSSR_RNE) { | ||
| 137 | u32 data; | ||
| 138 | |||
| 139 | data = pxa_ssp_read_reg(ssp, SSDR); | ||
| 140 | navpoint->data[navpoint->index + 0] = (data >> 8); | ||
| 141 | navpoint->data[navpoint->index + 1] = data; | ||
| 142 | navpoint->index += 2; | ||
| 143 | if (HEADER_LENGTH(navpoint->data[0]) < navpoint->index) { | ||
| 144 | navpoint_packet(navpoint); | ||
| 145 | navpoint->index = 0; | ||
| 146 | } | ||
| 147 | status = pxa_ssp_read_reg(ssp, SSSR); | ||
| 148 | ret = IRQ_HANDLED; | ||
| 149 | } | ||
| 150 | |||
| 151 | return ret; | ||
| 152 | } | ||
| 153 | |||
| 154 | static void navpoint_up(struct navpoint *navpoint) | ||
| 155 | { | ||
| 156 | struct ssp_device *ssp = navpoint->ssp; | ||
| 157 | int timeout; | ||
| 158 | |||
| 159 | clk_prepare_enable(ssp->clk); | ||
| 160 | |||
| 161 | pxa_ssp_write_reg(ssp, SSCR1, sscr1); | ||
| 162 | pxa_ssp_write_reg(ssp, SSSR, sssr); | ||
| 163 | pxa_ssp_write_reg(ssp, SSTO, 0); | ||
| 164 | pxa_ssp_write_reg(ssp, SSCR0, sscr0); /* SSCR0_SSE written last */ | ||
| 165 | |||
| 166 | /* Wait until SSP port is ready for slave clock operations */ | ||
| 167 | for (timeout = 100; timeout != 0; --timeout) { | ||
| 168 | if (!(pxa_ssp_read_reg(ssp, SSSR) & SSSR_CSS)) | ||
| 169 | break; | ||
| 170 | msleep(1); | ||
| 171 | } | ||
| 172 | |||
| 173 | if (timeout == 0) | ||
| 174 | dev_err(navpoint->dev, | ||
| 175 | "timeout waiting for SSSR[CSS] to clear\n"); | ||
| 176 | |||
| 177 | if (gpio_is_valid(navpoint->gpio)) | ||
| 178 | gpio_set_value(navpoint->gpio, 1); | ||
| 179 | } | ||
| 180 | |||
| 181 | static void navpoint_down(struct navpoint *navpoint) | ||
| 182 | { | ||
| 183 | struct ssp_device *ssp = navpoint->ssp; | ||
| 184 | |||
| 185 | if (gpio_is_valid(navpoint->gpio)) | ||
| 186 | gpio_set_value(navpoint->gpio, 0); | ||
| 187 | |||
| 188 | pxa_ssp_write_reg(ssp, SSCR0, 0); | ||
| 189 | |||
| 190 | clk_disable_unprepare(ssp->clk); | ||
| 191 | } | ||
| 192 | |||
| 193 | static int navpoint_open(struct input_dev *input) | ||
| 194 | { | ||
| 195 | struct navpoint *navpoint = input_get_drvdata(input); | ||
| 196 | |||
| 197 | navpoint_up(navpoint); | ||
| 198 | |||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | |||
| 202 | static void navpoint_close(struct input_dev *input) | ||
| 203 | { | ||
| 204 | struct navpoint *navpoint = input_get_drvdata(input); | ||
| 205 | |||
| 206 | navpoint_down(navpoint); | ||
| 207 | } | ||
| 208 | |||
| 209 | static int __devinit navpoint_probe(struct platform_device *pdev) | ||
| 210 | { | ||
| 211 | const struct navpoint_platform_data *pdata = | ||
| 212 | dev_get_platdata(&pdev->dev); | ||
| 213 | struct ssp_device *ssp; | ||
| 214 | struct input_dev *input; | ||
| 215 | struct navpoint *navpoint; | ||
| 216 | int error; | ||
| 217 | |||
| 218 | if (!pdata) { | ||
| 219 | dev_err(&pdev->dev, "no platform data\n"); | ||
| 220 | return -EINVAL; | ||
| 221 | } | ||
| 222 | |||
| 223 | if (gpio_is_valid(pdata->gpio)) { | ||
| 224 | error = gpio_request_one(pdata->gpio, GPIOF_OUT_INIT_LOW, | ||
| 225 | "SYNAPTICS_ON"); | ||
| 226 | if (error) | ||
| 227 | return error; | ||
| 228 | } | ||
| 229 | |||
| 230 | ssp = pxa_ssp_request(pdata->port, pdev->name); | ||
| 231 | if (!ssp) { | ||
| 232 | error = -ENODEV; | ||
| 233 | goto err_free_gpio; | ||
| 234 | } | ||
| 235 | |||
| 236 | /* HaRET does not disable devices before jumping into Linux */ | ||
| 237 | if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) { | ||
| 238 | pxa_ssp_write_reg(ssp, SSCR0, 0); | ||
| 239 | dev_warn(&pdev->dev, "ssp%d already enabled\n", pdata->port); | ||
| 240 | } | ||
| 241 | |||
| 242 | navpoint = kzalloc(sizeof(*navpoint), GFP_KERNEL); | ||
| 243 | input = input_allocate_device(); | ||
| 244 | if (!navpoint || !input) { | ||
| 245 | error = -ENOMEM; | ||
| 246 | goto err_free_mem; | ||
| 247 | } | ||
| 248 | |||
| 249 | navpoint->ssp = ssp; | ||
| 250 | navpoint->input = input; | ||
| 251 | navpoint->dev = &pdev->dev; | ||
| 252 | navpoint->gpio = pdata->gpio; | ||
| 253 | |||
| 254 | input->name = pdev->name; | ||
| 255 | input->dev.parent = &pdev->dev; | ||
| 256 | |||
| 257 | __set_bit(EV_KEY, input->evbit); | ||
| 258 | __set_bit(EV_ABS, input->evbit); | ||
| 259 | __set_bit(BTN_LEFT, input->keybit); | ||
| 260 | __set_bit(BTN_TOUCH, input->keybit); | ||
| 261 | __set_bit(BTN_TOOL_FINGER, input->keybit); | ||
| 262 | |||
| 263 | input_set_abs_params(input, ABS_X, | ||
| 264 | NAVPOINT_X_MIN, NAVPOINT_X_MAX, 0, 0); | ||
| 265 | input_set_abs_params(input, ABS_Y, | ||
| 266 | NAVPOINT_Y_MIN, NAVPOINT_Y_MAX, 0, 0); | ||
| 267 | input_set_abs_params(input, ABS_PRESSURE, | ||
| 268 | NAVPOINT_PRESSURE_MIN, NAVPOINT_PRESSURE_MAX, | ||
| 269 | 0, 0); | ||
| 270 | |||
| 271 | input->open = navpoint_open; | ||
| 272 | input->close = navpoint_close; | ||
| 273 | |||
| 274 | input_set_drvdata(input, navpoint); | ||
| 275 | |||
| 276 | error = request_irq(ssp->irq, navpoint_irq, 0, pdev->name, navpoint); | ||
| 277 | if (error) | ||
| 278 | goto err_free_mem; | ||
| 279 | |||
| 280 | error = input_register_device(input); | ||
| 281 | if (error) | ||
| 282 | goto err_free_irq; | ||
| 283 | |||
| 284 | platform_set_drvdata(pdev, navpoint); | ||
| 285 | dev_dbg(&pdev->dev, "ssp%d, irq %d\n", pdata->port, ssp->irq); | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | |||
| 289 | err_free_irq: | ||
| 290 | free_irq(ssp->irq, &pdev->dev); | ||
| 291 | err_free_mem: | ||
| 292 | input_free_device(input); | ||
| 293 | kfree(navpoint); | ||
| 294 | pxa_ssp_free(ssp); | ||
| 295 | err_free_gpio: | ||
| 296 | if (gpio_is_valid(pdata->gpio)) | ||
| 297 | gpio_free(pdata->gpio); | ||
| 298 | |||
| 299 | return error; | ||
| 300 | } | ||
| 301 | |||
| 302 | static int __devexit navpoint_remove(struct platform_device *pdev) | ||
| 303 | { | ||
| 304 | const struct navpoint_platform_data *pdata = | ||
| 305 | dev_get_platdata(&pdev->dev); | ||
| 306 | struct navpoint *navpoint = platform_get_drvdata(pdev); | ||
| 307 | struct ssp_device *ssp = navpoint->ssp; | ||
| 308 | |||
| 309 | free_irq(ssp->irq, navpoint); | ||
| 310 | |||
| 311 | input_unregister_device(navpoint->input); | ||
| 312 | kfree(navpoint); | ||
| 313 | |||
| 314 | pxa_ssp_free(ssp); | ||
| 315 | |||
| 316 | if (gpio_is_valid(pdata->gpio)) | ||
| 317 | gpio_free(pdata->gpio); | ||
| 318 | |||
| 319 | return 0; | ||
| 320 | } | ||
| 321 | |||
| 322 | #ifdef CONFIG_PM_SLEEP | ||
| 323 | static int navpoint_suspend(struct device *dev) | ||
| 324 | { | ||
| 325 | struct platform_device *pdev = to_platform_device(dev); | ||
| 326 | struct navpoint *navpoint = platform_get_drvdata(pdev); | ||
| 327 | struct input_dev *input = navpoint->input; | ||
| 328 | |||
| 329 | mutex_lock(&input->mutex); | ||
| 330 | if (input->users) | ||
| 331 | navpoint_down(navpoint); | ||
| 332 | mutex_unlock(&input->mutex); | ||
| 333 | |||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | static int navpoint_resume(struct device *dev) | ||
| 338 | { | ||
| 339 | struct platform_device *pdev = to_platform_device(dev); | ||
| 340 | struct navpoint *navpoint = platform_get_drvdata(pdev); | ||
| 341 | struct input_dev *input = navpoint->input; | ||
| 342 | |||
| 343 | mutex_lock(&input->mutex); | ||
| 344 | if (input->users) | ||
| 345 | navpoint_up(navpoint); | ||
| 346 | mutex_unlock(&input->mutex); | ||
| 347 | |||
| 348 | return 0; | ||
| 349 | } | ||
| 350 | #endif | ||
| 351 | |||
| 352 | static SIMPLE_DEV_PM_OPS(navpoint_pm_ops, navpoint_suspend, navpoint_resume); | ||
| 353 | |||
| 354 | static struct platform_driver navpoint_driver = { | ||
| 355 | .probe = navpoint_probe, | ||
| 356 | .remove = __devexit_p(navpoint_remove), | ||
| 357 | .driver = { | ||
| 358 | .name = "navpoint", | ||
| 359 | .owner = THIS_MODULE, | ||
| 360 | .pm = &navpoint_pm_ops, | ||
| 361 | }, | ||
| 362 | }; | ||
| 363 | |||
| 364 | module_platform_driver(navpoint_driver); | ||
| 365 | |||
| 366 | MODULE_AUTHOR("Paul Parsons <lost.distance@yahoo.com>"); | ||
| 367 | MODULE_DESCRIPTION("Synaptics NavPoint (PXA27x SSP/SPI) driver"); | ||
| 368 | MODULE_LICENSE("GPL"); | ||
| 369 | MODULE_ALIAS("platform:navpoint"); | ||
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 661a0ca3b3d6..3f5649f19082 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c | |||
| @@ -41,7 +41,7 @@ | |||
| 41 | #define GET_ABS_Y(packet) ((packet[2] << 2) | (packet[3] & 0x03)) | 41 | #define GET_ABS_Y(packet) ((packet[2] << 2) | (packet[3] & 0x03)) |
| 42 | 42 | ||
| 43 | /** Driver version. */ | 43 | /** Driver version. */ |
| 44 | static const char fsp_drv_ver[] = "1.0.0-K"; | 44 | static const char fsp_drv_ver[] = "1.1.0-K"; |
| 45 | 45 | ||
| 46 | /* | 46 | /* |
| 47 | * Make sure that the value being sent to FSP will not conflict with | 47 | * Make sure that the value being sent to FSP will not conflict with |
| @@ -303,6 +303,27 @@ static int fsp_get_revision(struct psmouse *psmouse, int *rev) | |||
| 303 | return 0; | 303 | return 0; |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | static int fsp_get_sn(struct psmouse *psmouse, int *sn) | ||
| 307 | { | ||
| 308 | int v0, v1, v2; | ||
| 309 | int rc = -EIO; | ||
| 310 | |||
| 311 | /* production number since Cx is available at: 0x0b40 ~ 0x0b42 */ | ||
| 312 | if (fsp_page_reg_write(psmouse, FSP_PAGE_0B)) | ||
| 313 | goto out; | ||
| 314 | if (fsp_reg_read(psmouse, FSP_REG_SN0, &v0)) | ||
| 315 | goto out; | ||
| 316 | if (fsp_reg_read(psmouse, FSP_REG_SN1, &v1)) | ||
| 317 | goto out; | ||
| 318 | if (fsp_reg_read(psmouse, FSP_REG_SN2, &v2)) | ||
| 319 | goto out; | ||
| 320 | *sn = (v0 << 16) | (v1 << 8) | v2; | ||
| 321 | rc = 0; | ||
| 322 | out: | ||
| 323 | fsp_page_reg_write(psmouse, FSP_PAGE_DEFAULT); | ||
| 324 | return rc; | ||
| 325 | } | ||
| 326 | |||
| 306 | static int fsp_get_buttons(struct psmouse *psmouse, int *btn) | 327 | static int fsp_get_buttons(struct psmouse *psmouse, int *btn) |
| 307 | { | 328 | { |
| 308 | static const int buttons[] = { | 329 | static const int buttons[] = { |
| @@ -1000,16 +1021,21 @@ static int fsp_reconnect(struct psmouse *psmouse) | |||
| 1000 | int fsp_init(struct psmouse *psmouse) | 1021 | int fsp_init(struct psmouse *psmouse) |
| 1001 | { | 1022 | { |
| 1002 | struct fsp_data *priv; | 1023 | struct fsp_data *priv; |
| 1003 | int ver, rev; | 1024 | int ver, rev, sn = 0; |
| 1004 | int error; | 1025 | int error; |
| 1005 | 1026 | ||
| 1006 | if (fsp_get_version(psmouse, &ver) || | 1027 | if (fsp_get_version(psmouse, &ver) || |
| 1007 | fsp_get_revision(psmouse, &rev)) { | 1028 | fsp_get_revision(psmouse, &rev)) { |
| 1008 | return -ENODEV; | 1029 | return -ENODEV; |
| 1009 | } | 1030 | } |
| 1031 | if (ver >= FSP_VER_STL3888_C0) { | ||
| 1032 | /* firmware information is only available since C0 */ | ||
| 1033 | fsp_get_sn(psmouse, &sn); | ||
| 1034 | } | ||
| 1010 | 1035 | ||
| 1011 | psmouse_info(psmouse, "Finger Sensing Pad, hw: %d.%d.%d, sw: %s\n", | 1036 | psmouse_info(psmouse, |
| 1012 | ver >> 4, ver & 0x0F, rev, fsp_drv_ver); | 1037 | "Finger Sensing Pad, hw: %d.%d.%d, sn: %x, sw: %s\n", |
| 1038 | ver >> 4, ver & 0x0F, rev, sn, fsp_drv_ver); | ||
| 1013 | 1039 | ||
| 1014 | psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); | 1040 | psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); |
| 1015 | if (!priv) | 1041 | if (!priv) |
diff --git a/drivers/input/mouse/sentelic.h b/drivers/input/mouse/sentelic.h index 334de19e5ddb..aa697ece405b 100644 --- a/drivers/input/mouse/sentelic.h +++ b/drivers/input/mouse/sentelic.h | |||
| @@ -65,6 +65,14 @@ | |||
| 65 | #define FSP_BIT_SWC1_GST_GRP1 BIT(6) | 65 | #define FSP_BIT_SWC1_GST_GRP1 BIT(6) |
| 66 | #define FSP_BIT_SWC1_BX_COMPAT BIT(7) | 66 | #define FSP_BIT_SWC1_BX_COMPAT BIT(7) |
| 67 | 67 | ||
| 68 | #define FSP_PAGE_0B (0x0b) | ||
| 69 | #define FSP_PAGE_82 (0x82) | ||
| 70 | #define FSP_PAGE_DEFAULT FSP_PAGE_82 | ||
| 71 | |||
| 72 | #define FSP_REG_SN0 (0x40) | ||
| 73 | #define FSP_REG_SN1 (0x41) | ||
| 74 | #define FSP_REG_SN2 (0x42) | ||
| 75 | |||
| 68 | /* Finger-sensing Pad packet formating related definitions */ | 76 | /* Finger-sensing Pad packet formating related definitions */ |
| 69 | 77 | ||
| 70 | /* absolute packet type */ | 78 | /* absolute packet type */ |
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c index 17ff137b9bd5..d5928fd0c914 100644 --- a/drivers/input/mouse/sermouse.c +++ b/drivers/input/mouse/sermouse.c | |||
| @@ -355,15 +355,4 @@ static struct serio_driver sermouse_drv = { | |||
| 355 | .disconnect = sermouse_disconnect, | 355 | .disconnect = sermouse_disconnect, |
| 356 | }; | 356 | }; |
| 357 | 357 | ||
| 358 | static int __init sermouse_init(void) | 358 | module_serio_driver(sermouse_drv); |
| 359 | { | ||
| 360 | return serio_register_driver(&sermouse_drv); | ||
| 361 | } | ||
| 362 | |||
| 363 | static void __exit sermouse_exit(void) | ||
| 364 | { | ||
| 365 | serio_unregister_driver(&sermouse_drv); | ||
| 366 | } | ||
| 367 | |||
| 368 | module_init(sermouse_init); | ||
| 369 | module_exit(sermouse_exit); | ||
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index a4b14a41cbf4..c703d53be3a0 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
| @@ -45,16 +45,6 @@ | |||
| 45 | #define YMIN_NOMINAL 1408 | 45 | #define YMIN_NOMINAL 1408 |
| 46 | #define YMAX_NOMINAL 4448 | 46 | #define YMAX_NOMINAL 4448 |
| 47 | 47 | ||
| 48 | /* | ||
| 49 | * Synaptics touchpads report the y coordinate from bottom to top, which is | ||
| 50 | * opposite from what userspace expects. | ||
| 51 | * This function is used to invert y before reporting. | ||
| 52 | */ | ||
| 53 | static int synaptics_invert_y(int y) | ||
| 54 | { | ||
| 55 | return YMAX_NOMINAL + YMIN_NOMINAL - y; | ||
| 56 | } | ||
| 57 | |||
| 58 | 48 | ||
| 59 | /***************************************************************************** | 49 | /***************************************************************************** |
| 60 | * Stuff we need even when we do not want native Synaptics support | 50 | * Stuff we need even when we do not want native Synaptics support |
| @@ -112,6 +102,16 @@ void synaptics_reset(struct psmouse *psmouse) | |||
| 112 | ****************************************************************************/ | 102 | ****************************************************************************/ |
| 113 | 103 | ||
| 114 | /* | 104 | /* |
| 105 | * Synaptics touchpads report the y coordinate from bottom to top, which is | ||
| 106 | * opposite from what userspace expects. | ||
| 107 | * This function is used to invert y before reporting. | ||
| 108 | */ | ||
| 109 | static int synaptics_invert_y(int y) | ||
| 110 | { | ||
| 111 | return YMAX_NOMINAL + YMIN_NOMINAL - y; | ||
| 112 | } | ||
| 113 | |||
| 114 | /* | ||
| 115 | * Send a command to the synpatics touchpad by special commands | 115 | * Send a command to the synpatics touchpad by special commands |
| 116 | */ | 116 | */ |
| 117 | static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param) | 117 | static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c, unsigned char *param) |
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index eb9a3cfbeefa..e900d465aaf6 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c | |||
| @@ -548,16 +548,4 @@ static struct serio_driver vsxxxaa_drv = { | |||
| 548 | .disconnect = vsxxxaa_disconnect, | 548 | .disconnect = vsxxxaa_disconnect, |
| 549 | }; | 549 | }; |
| 550 | 550 | ||
| 551 | static int __init vsxxxaa_init(void) | 551 | module_serio_driver(vsxxxaa_drv); |
| 552 | { | ||
| 553 | return serio_register_driver(&vsxxxaa_drv); | ||
| 554 | } | ||
| 555 | |||
| 556 | static void __exit vsxxxaa_exit(void) | ||
| 557 | { | ||
| 558 | serio_unregister_driver(&vsxxxaa_drv); | ||
| 559 | } | ||
| 560 | |||
| 561 | module_init(vsxxxaa_init); | ||
| 562 | module_exit(vsxxxaa_exit); | ||
| 563 | |||
diff --git a/drivers/input/of_keymap.c b/drivers/input/of_keymap.c deleted file mode 100644 index 061493d57682..000000000000 --- a/drivers/input/of_keymap.c +++ /dev/null | |||
| @@ -1,87 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Helpers for open firmware matrix keyboard bindings | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Google, Inc | ||
| 5 | * | ||
| 6 | * Author: | ||
| 7 | * Olof Johansson <olof@lixom.net> | ||
| 8 | * | ||
| 9 | * This software is licensed under the terms of the GNU General Public | ||
| 10 | * License version 2, as published by the Free Software Foundation, and | ||
| 11 | * may be copied, distributed, and modified under those terms. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | * | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/types.h> | ||
| 22 | #include <linux/input.h> | ||
| 23 | #include <linux/of.h> | ||
| 24 | #include <linux/input/matrix_keypad.h> | ||
| 25 | #include <linux/export.h> | ||
| 26 | #include <linux/gfp.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | |||
| 29 | struct matrix_keymap_data * | ||
| 30 | matrix_keyboard_of_fill_keymap(struct device_node *np, | ||
| 31 | const char *propname) | ||
| 32 | { | ||
| 33 | struct matrix_keymap_data *kd; | ||
| 34 | u32 *keymap; | ||
| 35 | int proplen, i; | ||
| 36 | const __be32 *prop; | ||
| 37 | |||
| 38 | if (!np) | ||
| 39 | return NULL; | ||
| 40 | |||
| 41 | if (!propname) | ||
| 42 | propname = "linux,keymap"; | ||
| 43 | |||
| 44 | prop = of_get_property(np, propname, &proplen); | ||
| 45 | if (!prop) | ||
| 46 | return NULL; | ||
| 47 | |||
| 48 | if (proplen % sizeof(u32)) { | ||
| 49 | pr_warn("Malformed keymap property %s in %s\n", | ||
| 50 | propname, np->full_name); | ||
| 51 | return NULL; | ||
| 52 | } | ||
| 53 | |||
| 54 | kd = kzalloc(sizeof(*kd), GFP_KERNEL); | ||
| 55 | if (!kd) | ||
| 56 | return NULL; | ||
| 57 | |||
| 58 | kd->keymap = keymap = kzalloc(proplen, GFP_KERNEL); | ||
| 59 | if (!kd->keymap) { | ||
| 60 | kfree(kd); | ||
| 61 | return NULL; | ||
| 62 | } | ||
| 63 | |||
| 64 | kd->keymap_size = proplen / sizeof(u32); | ||
| 65 | |||
| 66 | for (i = 0; i < kd->keymap_size; i++) { | ||
| 67 | u32 tmp = be32_to_cpup(prop + i); | ||
| 68 | int key_code, row, col; | ||
| 69 | |||
| 70 | row = (tmp >> 24) & 0xff; | ||
| 71 | col = (tmp >> 16) & 0xff; | ||
| 72 | key_code = tmp & 0xffff; | ||
| 73 | keymap[i] = KEY(row, col, key_code); | ||
| 74 | } | ||
| 75 | |||
| 76 | return kd; | ||
| 77 | } | ||
| 78 | EXPORT_SYMBOL_GPL(matrix_keyboard_of_fill_keymap); | ||
| 79 | |||
| 80 | void matrix_keyboard_of_free_keymap(const struct matrix_keymap_data *kd) | ||
| 81 | { | ||
| 82 | if (kd) { | ||
| 83 | kfree(kd->keymap); | ||
| 84 | kfree(kd); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | EXPORT_SYMBOL_GPL(matrix_keyboard_of_free_keymap); | ||
diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c index 43494742541c..0c42497aaaf4 100644 --- a/drivers/input/serio/pcips2.c +++ b/drivers/input/serio/pcips2.c | |||
| @@ -206,6 +206,7 @@ static const struct pci_device_id pcips2_ids[] = { | |||
| 206 | }, | 206 | }, |
| 207 | { 0, } | 207 | { 0, } |
| 208 | }; | 208 | }; |
| 209 | MODULE_DEVICE_TABLE(pci, pcips2_ids); | ||
| 209 | 210 | ||
| 210 | static struct pci_driver pcips2_driver = { | 211 | static struct pci_driver pcips2_driver = { |
| 211 | .name = "pcips2", | 212 | .name = "pcips2", |
| @@ -214,20 +215,8 @@ static struct pci_driver pcips2_driver = { | |||
| 214 | .remove = __devexit_p(pcips2_remove), | 215 | .remove = __devexit_p(pcips2_remove), |
| 215 | }; | 216 | }; |
| 216 | 217 | ||
| 217 | static int __init pcips2_init(void) | 218 | module_pci_driver(pcips2_driver); |
| 218 | { | ||
| 219 | return pci_register_driver(&pcips2_driver); | ||
| 220 | } | ||
| 221 | |||
| 222 | static void __exit pcips2_exit(void) | ||
| 223 | { | ||
| 224 | pci_unregister_driver(&pcips2_driver); | ||
| 225 | } | ||
| 226 | |||
| 227 | module_init(pcips2_init); | ||
| 228 | module_exit(pcips2_exit); | ||
| 229 | 219 | ||
| 230 | MODULE_LICENSE("GPL"); | 220 | MODULE_LICENSE("GPL"); |
| 231 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); | 221 | MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); |
| 232 | MODULE_DESCRIPTION("PCI PS/2 keyboard/mouse driver"); | 222 | MODULE_DESCRIPTION("PCI PS/2 keyboard/mouse driver"); |
| 233 | MODULE_DEVICE_TABLE(pci, pcips2_ids); | ||
diff --git a/drivers/input/serio/ps2mult.c b/drivers/input/serio/ps2mult.c index 15aa81c9f1fb..a76fb64f03db 100644 --- a/drivers/input/serio/ps2mult.c +++ b/drivers/input/serio/ps2mult.c | |||
| @@ -304,15 +304,4 @@ static struct serio_driver ps2mult_drv = { | |||
| 304 | .reconnect = ps2mult_reconnect, | 304 | .reconnect = ps2mult_reconnect, |
| 305 | }; | 305 | }; |
| 306 | 306 | ||
| 307 | static int __init ps2mult_init(void) | 307 | module_serio_driver(ps2mult_drv); |
| 308 | { | ||
| 309 | return serio_register_driver(&ps2mult_drv); | ||
| 310 | } | ||
| 311 | |||
| 312 | static void __exit ps2mult_exit(void) | ||
| 313 | { | ||
| 314 | serio_unregister_driver(&ps2mult_drv); | ||
| 315 | } | ||
| 316 | |||
| 317 | module_init(ps2mult_init); | ||
| 318 | module_exit(ps2mult_exit); | ||
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 4494233d331a..59df2e7317a3 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c | |||
| @@ -165,31 +165,38 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, | |||
| 165 | struct serio_raw *serio_raw = client->serio_raw; | 165 | struct serio_raw *serio_raw = client->serio_raw; |
| 166 | char uninitialized_var(c); | 166 | char uninitialized_var(c); |
| 167 | ssize_t read = 0; | 167 | ssize_t read = 0; |
| 168 | int retval; | 168 | int error; |
| 169 | 169 | ||
| 170 | if (serio_raw->dead) | 170 | for (;;) { |
| 171 | return -ENODEV; | 171 | if (serio_raw->dead) |
| 172 | return -ENODEV; | ||
| 172 | 173 | ||
| 173 | if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK)) | 174 | if (serio_raw->head == serio_raw->tail && |
| 174 | return -EAGAIN; | 175 | (file->f_flags & O_NONBLOCK)) |
| 176 | return -EAGAIN; | ||
| 175 | 177 | ||
| 176 | retval = wait_event_interruptible(serio_raw->wait, | 178 | if (count == 0) |
| 177 | serio_raw->head != serio_raw->tail || serio_raw->dead); | 179 | break; |
| 178 | if (retval) | ||
| 179 | return retval; | ||
| 180 | 180 | ||
| 181 | if (serio_raw->dead) | 181 | while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { |
| 182 | return -ENODEV; | 182 | if (put_user(c, buffer++)) |
| 183 | return -EFAULT; | ||
| 184 | read++; | ||
| 185 | } | ||
| 183 | 186 | ||
| 184 | while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { | 187 | if (read) |
| 185 | if (put_user(c, buffer++)) { | ||
| 186 | retval = -EFAULT; | ||
| 187 | break; | 188 | break; |
| 189 | |||
| 190 | if (!(file->f_flags & O_NONBLOCK)) { | ||
| 191 | error = wait_event_interruptible(serio_raw->wait, | ||
| 192 | serio_raw->head != serio_raw->tail || | ||
| 193 | serio_raw->dead); | ||
| 194 | if (error) | ||
| 195 | return error; | ||
| 188 | } | 196 | } |
| 189 | read++; | ||
| 190 | } | 197 | } |
| 191 | 198 | ||
| 192 | return read ?: retval; | 199 | return read; |
| 193 | } | 200 | } |
| 194 | 201 | ||
| 195 | static ssize_t serio_raw_write(struct file *file, const char __user *buffer, | 202 | static ssize_t serio_raw_write(struct file *file, const char __user *buffer, |
| @@ -197,8 +204,7 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, | |||
| 197 | { | 204 | { |
| 198 | struct serio_raw_client *client = file->private_data; | 205 | struct serio_raw_client *client = file->private_data; |
| 199 | struct serio_raw *serio_raw = client->serio_raw; | 206 | struct serio_raw *serio_raw = client->serio_raw; |
| 200 | ssize_t written = 0; | 207 | int retval = 0; |
| 201 | int retval; | ||
| 202 | unsigned char c; | 208 | unsigned char c; |
| 203 | 209 | ||
| 204 | retval = mutex_lock_interruptible(&serio_raw_mutex); | 210 | retval = mutex_lock_interruptible(&serio_raw_mutex); |
| @@ -218,16 +224,20 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, | |||
| 218 | retval = -EFAULT; | 224 | retval = -EFAULT; |
| 219 | goto out; | 225 | goto out; |
| 220 | } | 226 | } |
| 227 | |||
| 221 | if (serio_write(serio_raw->serio, c)) { | 228 | if (serio_write(serio_raw->serio, c)) { |
| 222 | retval = -EIO; | 229 | /* Either signal error or partial write */ |
| 230 | if (retval == 0) | ||
| 231 | retval = -EIO; | ||
| 223 | goto out; | 232 | goto out; |
| 224 | } | 233 | } |
| 225 | written++; | 234 | |
| 235 | retval++; | ||
| 226 | } | 236 | } |
| 227 | 237 | ||
| 228 | out: | 238 | out: |
| 229 | mutex_unlock(&serio_raw_mutex); | 239 | mutex_unlock(&serio_raw_mutex); |
| 230 | return written ?: retval; | 240 | return retval; |
| 231 | } | 241 | } |
| 232 | 242 | ||
| 233 | static unsigned int serio_raw_poll(struct file *file, poll_table *wait) | 243 | static unsigned int serio_raw_poll(struct file *file, poll_table *wait) |
| @@ -432,15 +442,4 @@ static struct serio_driver serio_raw_drv = { | |||
| 432 | .manual_bind = true, | 442 | .manual_bind = true, |
| 433 | }; | 443 | }; |
| 434 | 444 | ||
| 435 | static int __init serio_raw_init(void) | 445 | module_serio_driver(serio_raw_drv); |
| 436 | { | ||
| 437 | return serio_register_driver(&serio_raw_drv); | ||
| 438 | } | ||
| 439 | |||
| 440 | static void __exit serio_raw_exit(void) | ||
| 441 | { | ||
| 442 | serio_unregister_driver(&serio_raw_drv); | ||
| 443 | } | ||
| 444 | |||
| 445 | module_init(serio_raw_init); | ||
| 446 | module_exit(serio_raw_exit); | ||
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index d96d4c2a76a9..1e983bec7d86 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c | |||
| @@ -73,7 +73,8 @@ struct xps2data { | |||
| 73 | spinlock_t lock; | 73 | spinlock_t lock; |
| 74 | void __iomem *base_address; /* virt. address of control registers */ | 74 | void __iomem *base_address; /* virt. address of control registers */ |
| 75 | unsigned int flags; | 75 | unsigned int flags; |
| 76 | struct serio serio; /* serio */ | 76 | struct serio *serio; /* serio */ |
| 77 | struct device *dev; | ||
| 77 | }; | 78 | }; |
| 78 | 79 | ||
| 79 | /************************************/ | 80 | /************************************/ |
| @@ -119,7 +120,7 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id) | |||
| 119 | 120 | ||
| 120 | /* Check which interrupt is active */ | 121 | /* Check which interrupt is active */ |
| 121 | if (intr_sr & XPS2_IPIXR_RX_OVF) | 122 | if (intr_sr & XPS2_IPIXR_RX_OVF) |
| 122 | dev_warn(drvdata->serio.dev.parent, "receive overrun error\n"); | 123 | dev_warn(drvdata->dev, "receive overrun error\n"); |
| 123 | 124 | ||
| 124 | if (intr_sr & XPS2_IPIXR_RX_ERR) | 125 | if (intr_sr & XPS2_IPIXR_RX_ERR) |
| 125 | drvdata->flags |= SERIO_PARITY; | 126 | drvdata->flags |= SERIO_PARITY; |
| @@ -132,10 +133,10 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id) | |||
| 132 | 133 | ||
| 133 | /* Error, if a byte is not received */ | 134 | /* Error, if a byte is not received */ |
| 134 | if (status) { | 135 | if (status) { |
| 135 | dev_err(drvdata->serio.dev.parent, | 136 | dev_err(drvdata->dev, |
| 136 | "wrong rcvd byte count (%d)\n", status); | 137 | "wrong rcvd byte count (%d)\n", status); |
| 137 | } else { | 138 | } else { |
| 138 | serio_interrupt(&drvdata->serio, c, drvdata->flags); | 139 | serio_interrupt(drvdata->serio, c, drvdata->flags); |
| 139 | drvdata->flags = 0; | 140 | drvdata->flags = 0; |
| 140 | } | 141 | } |
| 141 | } | 142 | } |
| @@ -193,7 +194,7 @@ static int sxps2_open(struct serio *pserio) | |||
| 193 | error = request_irq(drvdata->irq, &xps2_interrupt, 0, | 194 | error = request_irq(drvdata->irq, &xps2_interrupt, 0, |
| 194 | DRIVER_NAME, drvdata); | 195 | DRIVER_NAME, drvdata); |
| 195 | if (error) { | 196 | if (error) { |
| 196 | dev_err(drvdata->serio.dev.parent, | 197 | dev_err(drvdata->dev, |
| 197 | "Couldn't allocate interrupt %d\n", drvdata->irq); | 198 | "Couldn't allocate interrupt %d\n", drvdata->irq); |
| 198 | return error; | 199 | return error; |
| 199 | } | 200 | } |
| @@ -259,15 +260,16 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev) | |||
| 259 | } | 260 | } |
| 260 | 261 | ||
| 261 | drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL); | 262 | drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL); |
| 262 | if (!drvdata) { | 263 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); |
| 263 | dev_err(dev, "Couldn't allocate device private record\n"); | 264 | if (!drvdata || !serio) { |
| 264 | return -ENOMEM; | 265 | error = -ENOMEM; |
| 266 | goto failed1; | ||
| 265 | } | 267 | } |
| 266 | 268 | ||
| 267 | dev_set_drvdata(dev, drvdata); | ||
| 268 | |||
| 269 | spin_lock_init(&drvdata->lock); | 269 | spin_lock_init(&drvdata->lock); |
| 270 | drvdata->irq = r_irq.start; | 270 | drvdata->irq = r_irq.start; |
| 271 | drvdata->serio = serio; | ||
| 272 | drvdata->dev = dev; | ||
| 271 | 273 | ||
| 272 | phys_addr = r_mem.start; | 274 | phys_addr = r_mem.start; |
| 273 | remap_size = resource_size(&r_mem); | 275 | remap_size = resource_size(&r_mem); |
| @@ -298,7 +300,6 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev) | |||
| 298 | (unsigned long long)phys_addr, drvdata->base_address, | 300 | (unsigned long long)phys_addr, drvdata->base_address, |
| 299 | drvdata->irq); | 301 | drvdata->irq); |
| 300 | 302 | ||
| 301 | serio = &drvdata->serio; | ||
| 302 | serio->id.type = SERIO_8042; | 303 | serio->id.type = SERIO_8042; |
| 303 | serio->write = sxps2_write; | 304 | serio->write = sxps2_write; |
| 304 | serio->open = sxps2_open; | 305 | serio->open = sxps2_open; |
| @@ -312,13 +313,14 @@ static int __devinit xps2_of_probe(struct platform_device *ofdev) | |||
| 312 | 313 | ||
| 313 | serio_register_port(serio); | 314 | serio_register_port(serio); |
| 314 | 315 | ||
| 316 | platform_set_drvdata(ofdev, drvdata); | ||
| 315 | return 0; /* success */ | 317 | return 0; /* success */ |
| 316 | 318 | ||
| 317 | failed2: | 319 | failed2: |
| 318 | release_mem_region(phys_addr, remap_size); | 320 | release_mem_region(phys_addr, remap_size); |
| 319 | failed1: | 321 | failed1: |
| 322 | kfree(serio); | ||
| 320 | kfree(drvdata); | 323 | kfree(drvdata); |
| 321 | dev_set_drvdata(dev, NULL); | ||
| 322 | 324 | ||
| 323 | return error; | 325 | return error; |
| 324 | } | 326 | } |
| @@ -333,22 +335,21 @@ failed1: | |||
| 333 | */ | 335 | */ |
| 334 | static int __devexit xps2_of_remove(struct platform_device *of_dev) | 336 | static int __devexit xps2_of_remove(struct platform_device *of_dev) |
| 335 | { | 337 | { |
| 336 | struct device *dev = &of_dev->dev; | 338 | struct xps2data *drvdata = platform_get_drvdata(of_dev); |
| 337 | struct xps2data *drvdata = dev_get_drvdata(dev); | ||
| 338 | struct resource r_mem; /* IO mem resources */ | 339 | struct resource r_mem; /* IO mem resources */ |
| 339 | 340 | ||
| 340 | serio_unregister_port(&drvdata->serio); | 341 | serio_unregister_port(drvdata->serio); |
| 341 | iounmap(drvdata->base_address); | 342 | iounmap(drvdata->base_address); |
| 342 | 343 | ||
| 343 | /* Get iospace of the device */ | 344 | /* Get iospace of the device */ |
| 344 | if (of_address_to_resource(of_dev->dev.of_node, 0, &r_mem)) | 345 | if (of_address_to_resource(of_dev->dev.of_node, 0, &r_mem)) |
| 345 | dev_err(dev, "invalid address\n"); | 346 | dev_err(drvdata->dev, "invalid address\n"); |
| 346 | else | 347 | else |
| 347 | release_mem_region(r_mem.start, resource_size(&r_mem)); | 348 | release_mem_region(r_mem.start, resource_size(&r_mem)); |
| 348 | 349 | ||
| 349 | kfree(drvdata); | 350 | kfree(drvdata); |
| 350 | 351 | ||
| 351 | dev_set_drvdata(dev, NULL); | 352 | platform_set_drvdata(of_dev, NULL); |
| 352 | 353 | ||
| 353 | return 0; | 354 | return 0; |
| 354 | } | 355 | } |
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 755a39e4c9e9..ee83c3904ee8 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c | |||
| @@ -1862,7 +1862,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
| 1862 | if (i == ARRAY_SIZE(speeds)) { | 1862 | if (i == ARRAY_SIZE(speeds)) { |
| 1863 | dev_info(&intf->dev, | 1863 | dev_info(&intf->dev, |
| 1864 | "Aiptek tried all speeds, no sane response\n"); | 1864 | "Aiptek tried all speeds, no sane response\n"); |
| 1865 | goto fail2; | 1865 | goto fail3; |
| 1866 | } | 1866 | } |
| 1867 | 1867 | ||
| 1868 | /* Associate this driver's struct with the usb interface. | 1868 | /* Associate this driver's struct with the usb interface. |
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index b4842d0e61dd..b79d45198d82 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
| @@ -135,6 +135,6 @@ extern const struct usb_device_id wacom_ids[]; | |||
| 135 | 135 | ||
| 136 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); | 136 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); |
| 137 | void wacom_setup_device_quirks(struct wacom_features *features); | 137 | void wacom_setup_device_quirks(struct wacom_features *features); |
| 138 | void wacom_setup_input_capabilities(struct input_dev *input_dev, | 138 | int wacom_setup_input_capabilities(struct input_dev *input_dev, |
| 139 | struct wacom_wac *wacom_wac); | 139 | struct wacom_wac *wacom_wac); |
| 140 | #endif | 140 | #endif |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 79a0509882d4..cad5602d3ce4 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #define HID_USAGE_Y_TILT 0x3e | 28 | #define HID_USAGE_Y_TILT 0x3e |
| 29 | #define HID_USAGE_FINGER 0x22 | 29 | #define HID_USAGE_FINGER 0x22 |
| 30 | #define HID_USAGE_STYLUS 0x20 | 30 | #define HID_USAGE_STYLUS 0x20 |
| 31 | #define HID_USAGE_CONTACTMAX 0x55 | ||
| 31 | #define HID_COLLECTION 0xa1 | 32 | #define HID_COLLECTION 0xa1 |
| 32 | #define HID_COLLECTION_LOGICAL 0x02 | 33 | #define HID_COLLECTION_LOGICAL 0x02 |
| 33 | #define HID_COLLECTION_END 0xc0 | 34 | #define HID_COLLECTION_END 0xc0 |
| @@ -204,6 +205,27 @@ static int wacom_parse_logical_collection(unsigned char *report, | |||
| 204 | return length; | 205 | return length; |
| 205 | } | 206 | } |
| 206 | 207 | ||
| 208 | static void wacom_retrieve_report_data(struct usb_interface *intf, | ||
| 209 | struct wacom_features *features) | ||
| 210 | { | ||
| 211 | int result = 0; | ||
| 212 | unsigned char *rep_data; | ||
| 213 | |||
| 214 | rep_data = kmalloc(2, GFP_KERNEL); | ||
| 215 | if (rep_data) { | ||
| 216 | |||
| 217 | rep_data[0] = 12; | ||
| 218 | result = wacom_get_report(intf, WAC_HID_FEATURE_REPORT, | ||
| 219 | rep_data[0], &rep_data, 2, | ||
| 220 | WAC_MSG_RETRIES); | ||
| 221 | |||
| 222 | if (result >= 0 && rep_data[1] > 2) | ||
| 223 | features->touch_max = rep_data[1]; | ||
| 224 | |||
| 225 | kfree(rep_data); | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 207 | /* | 229 | /* |
| 208 | * Interface Descriptor of wacom devices can be incomplete and | 230 | * Interface Descriptor of wacom devices can be incomplete and |
| 209 | * inconsistent so wacom_features table is used to store stylus | 231 | * inconsistent so wacom_features table is used to store stylus |
| @@ -236,6 +258,9 @@ static int wacom_parse_logical_collection(unsigned char *report, | |||
| 236 | * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical | 258 | * 3rd gen Bamboo Touch no longer define a Digitizer-Finger Pysical |
| 237 | * Collection. Instead they define a Logical Collection with a single | 259 | * Collection. Instead they define a Logical Collection with a single |
| 238 | * Logical Maximum for both X and Y. | 260 | * Logical Maximum for both X and Y. |
| 261 | * | ||
| 262 | * Intuos5 touch interface does not contain useful data. We deal with | ||
| 263 | * this after returning from this function. | ||
| 239 | */ | 264 | */ |
| 240 | static int wacom_parse_hid(struct usb_interface *intf, | 265 | static int wacom_parse_hid(struct usb_interface *intf, |
| 241 | struct hid_descriptor *hid_desc, | 266 | struct hid_descriptor *hid_desc, |
| @@ -295,6 +320,10 @@ static int wacom_parse_hid(struct usb_interface *intf, | |||
| 295 | /* need to reset back */ | 320 | /* need to reset back */ |
| 296 | features->pktlen = WACOM_PKGLEN_TPC2FG; | 321 | features->pktlen = WACOM_PKGLEN_TPC2FG; |
| 297 | } | 322 | } |
| 323 | |||
| 324 | if (features->type == MTSCREEN) | ||
| 325 | features->pktlen = WACOM_PKGLEN_MTOUCH; | ||
| 326 | |||
| 298 | if (features->type == BAMBOO_PT) { | 327 | if (features->type == BAMBOO_PT) { |
| 299 | /* need to reset back */ | 328 | /* need to reset back */ |
| 300 | features->pktlen = WACOM_PKGLEN_BBTOUCH; | 329 | features->pktlen = WACOM_PKGLEN_BBTOUCH; |
| @@ -327,18 +356,15 @@ static int wacom_parse_hid(struct usb_interface *intf, | |||
| 327 | case HID_USAGE_Y: | 356 | case HID_USAGE_Y: |
| 328 | if (usage == WCM_DESKTOP) { | 357 | if (usage == WCM_DESKTOP) { |
| 329 | if (finger) { | 358 | if (finger) { |
| 330 | features->device_type = BTN_TOOL_FINGER; | 359 | int type = features->type; |
| 331 | if (features->type == TABLETPC2FG) { | 360 | |
| 332 | /* need to reset back */ | 361 | if (type == TABLETPC2FG || type == MTSCREEN) { |
| 333 | features->pktlen = WACOM_PKGLEN_TPC2FG; | ||
| 334 | features->y_max = | 362 | features->y_max = |
| 335 | get_unaligned_le16(&report[i + 3]); | 363 | get_unaligned_le16(&report[i + 3]); |
| 336 | features->y_phy = | 364 | features->y_phy = |
| 337 | get_unaligned_le16(&report[i + 6]); | 365 | get_unaligned_le16(&report[i + 6]); |
| 338 | i += 7; | 366 | i += 7; |
| 339 | } else if (features->type == BAMBOO_PT) { | 367 | } else if (type == BAMBOO_PT) { |
| 340 | /* need to reset back */ | ||
| 341 | features->pktlen = WACOM_PKGLEN_BBTOUCH; | ||
| 342 | features->y_phy = | 368 | features->y_phy = |
| 343 | get_unaligned_le16(&report[i + 3]); | 369 | get_unaligned_le16(&report[i + 3]); |
| 344 | features->y_max = | 370 | features->y_max = |
| @@ -352,10 +378,6 @@ static int wacom_parse_hid(struct usb_interface *intf, | |||
| 352 | i += 4; | 378 | i += 4; |
| 353 | } | 379 | } |
| 354 | } else if (pen) { | 380 | } else if (pen) { |
| 355 | /* penabled only accepts exact bytes of data */ | ||
| 356 | if (features->type == TABLETPC2FG) | ||
| 357 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; | ||
| 358 | features->device_type = BTN_TOOL_PEN; | ||
| 359 | features->y_max = | 381 | features->y_max = |
| 360 | get_unaligned_le16(&report[i + 3]); | 382 | get_unaligned_le16(&report[i + 3]); |
| 361 | i += 4; | 383 | i += 4; |
| @@ -377,6 +399,11 @@ static int wacom_parse_hid(struct usb_interface *intf, | |||
| 377 | pen = 1; | 399 | pen = 1; |
| 378 | i++; | 400 | i++; |
| 379 | break; | 401 | break; |
| 402 | |||
| 403 | case HID_USAGE_CONTACTMAX: | ||
| 404 | wacom_retrieve_report_data(intf, features); | ||
| 405 | i++; | ||
| 406 | break; | ||
| 380 | } | 407 | } |
| 381 | break; | 408 | break; |
| 382 | 409 | ||
| @@ -413,22 +440,29 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat | |||
| 413 | if (!rep_data) | 440 | if (!rep_data) |
| 414 | return error; | 441 | return error; |
| 415 | 442 | ||
| 416 | /* ask to report tablet data if it is MT Tablet PC or | 443 | /* ask to report Wacom data */ |
| 417 | * not a Tablet PC */ | 444 | if (features->device_type == BTN_TOOL_FINGER) { |
| 418 | if (features->type == TABLETPC2FG) { | 445 | /* if it is an MT Tablet PC touch */ |
| 419 | do { | 446 | if (features->type == TABLETPC2FG || |
| 420 | rep_data[0] = 3; | 447 | features->type == MTSCREEN) { |
| 421 | rep_data[1] = 4; | 448 | do { |
| 422 | rep_data[2] = 0; | 449 | rep_data[0] = 3; |
| 423 | rep_data[3] = 0; | 450 | rep_data[1] = 4; |
| 424 | report_id = 3; | 451 | rep_data[2] = 0; |
| 425 | error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, | 452 | rep_data[3] = 0; |
| 426 | report_id, rep_data, 4, 1); | 453 | report_id = 3; |
| 427 | if (error >= 0) | 454 | error = wacom_set_report(intf, |
| 428 | error = wacom_get_report(intf, | 455 | WAC_HID_FEATURE_REPORT, |
| 429 | WAC_HID_FEATURE_REPORT, | 456 | report_id, |
| 430 | report_id, rep_data, 4, 1); | 457 | rep_data, 4, 1); |
| 431 | } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); | 458 | if (error >= 0) |
| 459 | error = wacom_get_report(intf, | ||
| 460 | WAC_HID_FEATURE_REPORT, | ||
| 461 | report_id, | ||
| 462 | rep_data, 4, 1); | ||
| 463 | } while ((error < 0 || rep_data[1] != 4) && | ||
| 464 | limit++ < WAC_MSG_RETRIES); | ||
| 465 | } | ||
| 432 | } else if (features->type != TABLETPC && | 466 | } else if (features->type != TABLETPC && |
| 433 | features->type != WIRELESS && | 467 | features->type != WIRELESS && |
| 434 | features->device_type == BTN_TOOL_PEN) { | 468 | features->device_type == BTN_TOOL_PEN) { |
| @@ -450,7 +484,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat | |||
| 450 | } | 484 | } |
| 451 | 485 | ||
| 452 | static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, | 486 | static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, |
| 453 | struct wacom_features *features) | 487 | struct wacom_features *features) |
| 454 | { | 488 | { |
| 455 | int error = 0; | 489 | int error = 0; |
| 456 | struct usb_host_interface *interface = intf->cur_altsetting; | 490 | struct usb_host_interface *interface = intf->cur_altsetting; |
| @@ -478,16 +512,21 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, | |||
| 478 | } | 512 | } |
| 479 | } | 513 | } |
| 480 | 514 | ||
| 481 | /* only Tablet PCs and Bamboo P&T need to retrieve the info */ | 515 | /* only devices that support touch need to retrieve the info */ |
| 482 | if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && | 516 | if (features->type != TABLETPC && |
| 483 | (features->type != BAMBOO_PT)) | 517 | features->type != TABLETPC2FG && |
| 518 | features->type != BAMBOO_PT && | ||
| 519 | features->type != MTSCREEN) { | ||
| 484 | goto out; | 520 | goto out; |
| 521 | } | ||
| 485 | 522 | ||
| 486 | if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { | 523 | error = usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc); |
| 487 | if (usb_get_extra_descriptor(&interface->endpoint[0], | 524 | if (error) { |
| 488 | HID_DEVICET_REPORT, &hid_desc)) { | 525 | error = usb_get_extra_descriptor(&interface->endpoint[0], |
| 489 | printk("wacom: can not retrieve extra class descriptor\n"); | 526 | HID_DEVICET_REPORT, &hid_desc); |
| 490 | error = 1; | 527 | if (error) { |
| 528 | dev_err(&intf->dev, | ||
| 529 | "can not retrieve extra class descriptor\n"); | ||
| 491 | goto out; | 530 | goto out; |
| 492 | } | 531 | } |
| 493 | } | 532 | } |
| @@ -577,23 +616,39 @@ static void wacom_remove_shared_data(struct wacom_wac *wacom) | |||
| 577 | static int wacom_led_control(struct wacom *wacom) | 616 | static int wacom_led_control(struct wacom *wacom) |
| 578 | { | 617 | { |
| 579 | unsigned char *buf; | 618 | unsigned char *buf; |
| 580 | int retval, led = 0; | 619 | int retval; |
| 581 | 620 | ||
| 582 | buf = kzalloc(9, GFP_KERNEL); | 621 | buf = kzalloc(9, GFP_KERNEL); |
| 583 | if (!buf) | 622 | if (!buf) |
| 584 | return -ENOMEM; | 623 | return -ENOMEM; |
| 585 | 624 | ||
| 586 | if (wacom->wacom_wac.features.type == WACOM_21UX2 || | 625 | if (wacom->wacom_wac.features.type >= INTUOS5S && |
| 587 | wacom->wacom_wac.features.type == WACOM_24HD) | 626 | wacom->wacom_wac.features.type <= INTUOS5L) { |
| 588 | led = (wacom->led.select[1] << 4) | 0x40; | 627 | /* |
| 589 | 628 | * Touch Ring and crop mark LED luminance may take on | |
| 590 | led |= wacom->led.select[0] | 0x4; | 629 | * one of four values: |
| 591 | 630 | * 0 = Low; 1 = Medium; 2 = High; 3 = Off | |
| 592 | buf[0] = WAC_CMD_LED_CONTROL; | 631 | */ |
| 593 | buf[1] = led; | 632 | int ring_led = wacom->led.select[0] & 0x03; |
| 594 | buf[2] = wacom->led.llv; | 633 | int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03; |
| 595 | buf[3] = wacom->led.hlv; | 634 | int crop_lum = 0; |
| 596 | buf[4] = wacom->led.img_lum; | 635 | |
| 636 | buf[0] = WAC_CMD_LED_CONTROL; | ||
| 637 | buf[1] = (crop_lum << 4) | (ring_lum << 2) | (ring_led); | ||
| 638 | } | ||
| 639 | else { | ||
| 640 | int led = wacom->led.select[0] | 0x4; | ||
| 641 | |||
| 642 | if (wacom->wacom_wac.features.type == WACOM_21UX2 || | ||
| 643 | wacom->wacom_wac.features.type == WACOM_24HD) | ||
| 644 | led |= (wacom->led.select[1] << 4) | 0x40; | ||
| 645 | |||
| 646 | buf[0] = WAC_CMD_LED_CONTROL; | ||
| 647 | buf[1] = led; | ||
| 648 | buf[2] = wacom->led.llv; | ||
| 649 | buf[3] = wacom->led.hlv; | ||
| 650 | buf[4] = wacom->led.img_lum; | ||
| 651 | } | ||
| 597 | 652 | ||
| 598 | retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL, | 653 | retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL, |
| 599 | buf, 9, WAC_CMD_RETRIES); | 654 | buf, 9, WAC_CMD_RETRIES); |
| @@ -786,6 +841,17 @@ static struct attribute_group intuos4_led_attr_group = { | |||
| 786 | .attrs = intuos4_led_attrs, | 841 | .attrs = intuos4_led_attrs, |
| 787 | }; | 842 | }; |
| 788 | 843 | ||
| 844 | static struct attribute *intuos5_led_attrs[] = { | ||
| 845 | &dev_attr_status0_luminance.attr, | ||
| 846 | &dev_attr_status_led0_select.attr, | ||
| 847 | NULL | ||
| 848 | }; | ||
| 849 | |||
| 850 | static struct attribute_group intuos5_led_attr_group = { | ||
| 851 | .name = "wacom_led", | ||
| 852 | .attrs = intuos5_led_attrs, | ||
| 853 | }; | ||
| 854 | |||
| 789 | static int wacom_initialize_leds(struct wacom *wacom) | 855 | static int wacom_initialize_leds(struct wacom *wacom) |
| 790 | { | 856 | { |
| 791 | int error; | 857 | int error; |
| @@ -815,6 +881,19 @@ static int wacom_initialize_leds(struct wacom *wacom) | |||
| 815 | &cintiq_led_attr_group); | 881 | &cintiq_led_attr_group); |
| 816 | break; | 882 | break; |
| 817 | 883 | ||
| 884 | case INTUOS5S: | ||
| 885 | case INTUOS5: | ||
| 886 | case INTUOS5L: | ||
| 887 | wacom->led.select[0] = 0; | ||
| 888 | wacom->led.select[1] = 0; | ||
| 889 | wacom->led.llv = 32; | ||
| 890 | wacom->led.hlv = 0; | ||
| 891 | wacom->led.img_lum = 0; | ||
| 892 | |||
| 893 | error = sysfs_create_group(&wacom->intf->dev.kobj, | ||
| 894 | &intuos5_led_attr_group); | ||
| 895 | break; | ||
| 896 | |||
| 818 | default: | 897 | default: |
| 819 | return 0; | 898 | return 0; |
| 820 | } | 899 | } |
| @@ -843,6 +922,13 @@ static void wacom_destroy_leds(struct wacom *wacom) | |||
| 843 | sysfs_remove_group(&wacom->intf->dev.kobj, | 922 | sysfs_remove_group(&wacom->intf->dev.kobj, |
| 844 | &cintiq_led_attr_group); | 923 | &cintiq_led_attr_group); |
| 845 | break; | 924 | break; |
| 925 | |||
| 926 | case INTUOS5S: | ||
| 927 | case INTUOS5: | ||
| 928 | case INTUOS5L: | ||
| 929 | sysfs_remove_group(&wacom->intf->dev.kobj, | ||
| 930 | &intuos5_led_attr_group); | ||
| 931 | break; | ||
| 846 | } | 932 | } |
| 847 | } | 933 | } |
| 848 | 934 | ||
| @@ -904,8 +990,10 @@ static int wacom_register_input(struct wacom *wacom) | |||
| 904 | int error; | 990 | int error; |
| 905 | 991 | ||
| 906 | input_dev = input_allocate_device(); | 992 | input_dev = input_allocate_device(); |
| 907 | if (!input_dev) | 993 | if (!input_dev) { |
| 908 | return -ENOMEM; | 994 | error = -ENOMEM; |
| 995 | goto fail1; | ||
| 996 | } | ||
| 909 | 997 | ||
| 910 | input_dev->name = wacom_wac->name; | 998 | input_dev->name = wacom_wac->name; |
| 911 | input_dev->dev.parent = &intf->dev; | 999 | input_dev->dev.parent = &intf->dev; |
| @@ -915,14 +1003,20 @@ static int wacom_register_input(struct wacom *wacom) | |||
| 915 | input_set_drvdata(input_dev, wacom); | 1003 | input_set_drvdata(input_dev, wacom); |
| 916 | 1004 | ||
| 917 | wacom_wac->input = input_dev; | 1005 | wacom_wac->input = input_dev; |
| 918 | wacom_setup_input_capabilities(input_dev, wacom_wac); | 1006 | error = wacom_setup_input_capabilities(input_dev, wacom_wac); |
| 1007 | if (error) | ||
| 1008 | goto fail1; | ||
| 919 | 1009 | ||
| 920 | error = input_register_device(input_dev); | 1010 | error = input_register_device(input_dev); |
| 921 | if (error) { | 1011 | if (error) |
| 922 | input_free_device(input_dev); | 1012 | goto fail2; |
| 923 | wacom_wac->input = NULL; | ||
| 924 | } | ||
| 925 | 1013 | ||
| 1014 | return 0; | ||
| 1015 | |||
| 1016 | fail2: | ||
| 1017 | input_free_device(input_dev); | ||
| 1018 | wacom_wac->input = NULL; | ||
| 1019 | fail1: | ||
| 926 | return error; | 1020 | return error; |
| 927 | } | 1021 | } |
| 928 | 1022 | ||
| @@ -941,22 +1035,22 @@ static void wacom_wireless_work(struct work_struct *work) | |||
| 941 | wacom = usb_get_intfdata(usbdev->config->interface[1]); | 1035 | wacom = usb_get_intfdata(usbdev->config->interface[1]); |
| 942 | if (wacom->wacom_wac.input) | 1036 | if (wacom->wacom_wac.input) |
| 943 | input_unregister_device(wacom->wacom_wac.input); | 1037 | input_unregister_device(wacom->wacom_wac.input); |
| 944 | wacom->wacom_wac.input = 0; | 1038 | wacom->wacom_wac.input = NULL; |
| 945 | 1039 | ||
| 946 | /* Touch interface */ | 1040 | /* Touch interface */ |
| 947 | wacom = usb_get_intfdata(usbdev->config->interface[2]); | 1041 | wacom = usb_get_intfdata(usbdev->config->interface[2]); |
| 948 | if (wacom->wacom_wac.input) | 1042 | if (wacom->wacom_wac.input) |
| 949 | input_unregister_device(wacom->wacom_wac.input); | 1043 | input_unregister_device(wacom->wacom_wac.input); |
| 950 | wacom->wacom_wac.input = 0; | 1044 | wacom->wacom_wac.input = NULL; |
| 951 | 1045 | ||
| 952 | if (wacom_wac->pid == 0) { | 1046 | if (wacom_wac->pid == 0) { |
| 953 | printk(KERN_INFO "wacom: wireless tablet disconnected\n"); | 1047 | dev_info(&wacom->intf->dev, "wireless tablet disconnected\n"); |
| 954 | } else { | 1048 | } else { |
| 955 | const struct usb_device_id *id = wacom_ids; | 1049 | const struct usb_device_id *id = wacom_ids; |
| 956 | 1050 | ||
| 957 | printk(KERN_INFO | 1051 | dev_info(&wacom->intf->dev, |
| 958 | "wacom: wireless tablet connected with PID %x\n", | 1052 | "wireless tablet connected with PID %x\n", |
| 959 | wacom_wac->pid); | 1053 | wacom_wac->pid); |
| 960 | 1054 | ||
| 961 | while (id->match_flags) { | 1055 | while (id->match_flags) { |
| 962 | if (id->idVendor == USB_VENDOR_ID_WACOM && | 1056 | if (id->idVendor == USB_VENDOR_ID_WACOM && |
| @@ -966,8 +1060,8 @@ static void wacom_wireless_work(struct work_struct *work) | |||
| 966 | } | 1060 | } |
| 967 | 1061 | ||
| 968 | if (!id->match_flags) { | 1062 | if (!id->match_flags) { |
| 969 | printk(KERN_INFO | 1063 | dev_info(&wacom->intf->dev, |
| 970 | "wacom: ignorning unknown PID.\n"); | 1064 | "ignoring unknown PID.\n"); |
| 971 | return; | 1065 | return; |
| 972 | } | 1066 | } |
| 973 | 1067 | ||
| @@ -1038,11 +1132,33 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 1038 | 1132 | ||
| 1039 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | 1133 | endpoint = &intf->cur_altsetting->endpoint[0].desc; |
| 1040 | 1134 | ||
| 1041 | /* Retrieve the physical and logical size for OEM devices */ | 1135 | /* Retrieve the physical and logical size for touch devices */ |
| 1042 | error = wacom_retrieve_hid_descriptor(intf, features); | 1136 | error = wacom_retrieve_hid_descriptor(intf, features); |
| 1043 | if (error) | 1137 | if (error) |
| 1044 | goto fail3; | 1138 | goto fail3; |
| 1045 | 1139 | ||
| 1140 | /* | ||
| 1141 | * Intuos5 has no useful data about its touch interface in its | ||
| 1142 | * HID descriptor. If this is the touch interface (wMaxPacketSize | ||
| 1143 | * of WACOM_PKGLEN_BBTOUCH3), override the table values. | ||
| 1144 | */ | ||
| 1145 | if (features->type >= INTUOS5S && features->type <= INTUOS5L) { | ||
| 1146 | if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) { | ||
| 1147 | features->device_type = BTN_TOOL_FINGER; | ||
| 1148 | features->pktlen = WACOM_PKGLEN_BBTOUCH3; | ||
| 1149 | |||
| 1150 | features->x_phy = | ||
| 1151 | (features->x_max * 100) / features->x_resolution; | ||
| 1152 | features->y_phy = | ||
| 1153 | (features->y_max * 100) / features->y_resolution; | ||
| 1154 | |||
| 1155 | features->x_max = 4096; | ||
| 1156 | features->y_max = 4096; | ||
| 1157 | } else { | ||
| 1158 | features->device_type = BTN_TOOL_PEN; | ||
| 1159 | } | ||
| 1160 | } | ||
| 1161 | |||
| 1046 | wacom_setup_device_quirks(features); | 1162 | wacom_setup_device_quirks(features); |
| 1047 | 1163 | ||
| 1048 | strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); | 1164 | strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index b327790e9a0c..004bc1bb1544 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
| @@ -61,7 +61,8 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom) | |||
| 61 | break; | 61 | break; |
| 62 | 62 | ||
| 63 | default: | 63 | default: |
| 64 | printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]); | 64 | dev_dbg(input->dev.parent, |
| 65 | "%s: received unknown report #%d\n", __func__, data[0]); | ||
| 65 | return 0; | 66 | return 0; |
| 66 | } | 67 | } |
| 67 | 68 | ||
| @@ -76,8 +77,8 @@ static int wacom_pl_irq(struct wacom_wac *wacom) | |||
| 76 | int prox, pressure; | 77 | int prox, pressure; |
| 77 | 78 | ||
| 78 | if (data[0] != WACOM_REPORT_PENABLED) { | 79 | if (data[0] != WACOM_REPORT_PENABLED) { |
| 79 | dev_dbg(&input->dev, | 80 | dev_dbg(input->dev.parent, |
| 80 | "wacom_pl_irq: received unknown report #%d\n", data[0]); | 81 | "%s: received unknown report #%d\n", __func__, data[0]); |
| 81 | return 0; | 82 | return 0; |
| 82 | } | 83 | } |
| 83 | 84 | ||
| @@ -147,7 +148,8 @@ static int wacom_ptu_irq(struct wacom_wac *wacom) | |||
| 147 | struct input_dev *input = wacom->input; | 148 | struct input_dev *input = wacom->input; |
| 148 | 149 | ||
| 149 | if (data[0] != WACOM_REPORT_PENABLED) { | 150 | if (data[0] != WACOM_REPORT_PENABLED) { |
| 150 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); | 151 | dev_dbg(input->dev.parent, |
| 152 | "%s: received unknown report #%d\n", __func__, data[0]); | ||
| 151 | return 0; | 153 | return 0; |
| 152 | } | 154 | } |
| 153 | 155 | ||
| @@ -176,7 +178,8 @@ static int wacom_dtu_irq(struct wacom_wac *wacom) | |||
| 176 | struct input_dev *input = wacom->input; | 178 | struct input_dev *input = wacom->input; |
| 177 | int prox = data[1] & 0x20, pressure; | 179 | int prox = data[1] & 0x20, pressure; |
| 178 | 180 | ||
| 179 | dev_dbg(&input->dev, "wacom_dtu_irq: received report #%d\n", data[0]); | 181 | dev_dbg(input->dev.parent, |
| 182 | "%s: received report #%d", __func__, data[0]); | ||
| 180 | 183 | ||
| 181 | if (prox) { | 184 | if (prox) { |
| 182 | /* Going into proximity select tool */ | 185 | /* Going into proximity select tool */ |
| @@ -212,9 +215,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) | |||
| 212 | int retval = 0; | 215 | int retval = 0; |
| 213 | 216 | ||
| 214 | if (data[0] != WACOM_REPORT_PENABLED) { | 217 | if (data[0] != WACOM_REPORT_PENABLED) { |
| 215 | dev_dbg(&input->dev, | 218 | dev_dbg(input->dev.parent, |
| 216 | "wacom_graphire_irq: received unknown report #%d\n", | 219 | "%s: received unknown report #%d\n", __func__, data[0]); |
| 217 | data[0]); | ||
| 218 | goto exit; | 220 | goto exit; |
| 219 | } | 221 | } |
| 220 | 222 | ||
| @@ -324,6 +326,9 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) | |||
| 324 | 326 | ||
| 325 | /* Enter report */ | 327 | /* Enter report */ |
| 326 | if ((data[1] & 0xfc) == 0xc0) { | 328 | if ((data[1] & 0xfc) == 0xc0) { |
| 329 | if (features->type >= INTUOS5S && features->type <= INTUOS5L) | ||
| 330 | wacom->shared->stylus_in_proximity = true; | ||
| 331 | |||
| 327 | /* serial number of the tool */ | 332 | /* serial number of the tool */ |
| 328 | wacom->serial[idx] = ((data[3] & 0x0f) << 28) + | 333 | wacom->serial[idx] = ((data[3] & 0x0f) << 28) + |
| 329 | (data[4] << 20) + (data[5] << 12) + | 334 | (data[4] << 20) + (data[5] << 12) + |
| @@ -409,6 +414,9 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) | |||
| 409 | 414 | ||
| 410 | /* Exit report */ | 415 | /* Exit report */ |
| 411 | if ((data[1] & 0xfe) == 0x80) { | 416 | if ((data[1] & 0xfe) == 0x80) { |
| 417 | if (features->type >= INTUOS5S && features->type <= INTUOS5L) | ||
| 418 | wacom->shared->stylus_in_proximity = false; | ||
| 419 | |||
| 412 | /* | 420 | /* |
| 413 | * Reset all states otherwise we lose the initial states | 421 | * Reset all states otherwise we lose the initial states |
| 414 | * when in-prox next time | 422 | * when in-prox next time |
| @@ -455,6 +463,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom) | |||
| 455 | if ((data[1] & 0xb8) == 0xa0) { | 463 | if ((data[1] & 0xb8) == 0xa0) { |
| 456 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | 464 | t = (data[6] << 2) | ((data[7] >> 6) & 3); |
| 457 | if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || | 465 | if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || |
| 466 | (features->type >= INTUOS5S && features->type <= INTUOS5L) || | ||
| 458 | features->type == WACOM_21UX2 || features->type == WACOM_24HD) { | 467 | features->type == WACOM_21UX2 || features->type == WACOM_24HD) { |
| 459 | t = (t << 1) | (data[1] & 1); | 468 | t = (t << 1) | (data[1] & 1); |
| 460 | } | 469 | } |
| @@ -485,11 +494,13 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
| 485 | unsigned int t; | 494 | unsigned int t; |
| 486 | int idx = 0, result; | 495 | int idx = 0, result; |
| 487 | 496 | ||
| 488 | if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_INTUOSREAD | 497 | if (data[0] != WACOM_REPORT_PENABLED && |
| 489 | && data[0] != WACOM_REPORT_INTUOSWRITE && data[0] != WACOM_REPORT_INTUOSPAD) { | 498 | data[0] != WACOM_REPORT_INTUOSREAD && |
| 490 | dev_dbg(&input->dev, | 499 | data[0] != WACOM_REPORT_INTUOSWRITE && |
| 491 | "wacom_intuos_irq: received unknown report #%d\n", | 500 | data[0] != WACOM_REPORT_INTUOSPAD && |
| 492 | data[0]); | 501 | data[0] != WACOM_REPORT_INTUOS5PAD) { |
| 502 | dev_dbg(input->dev.parent, | ||
| 503 | "%s: received unknown report #%d\n", __func__, data[0]); | ||
| 493 | return 0; | 504 | return 0; |
| 494 | } | 505 | } |
| 495 | 506 | ||
| @@ -498,7 +509,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
| 498 | idx = data[1] & 0x01; | 509 | idx = data[1] & 0x01; |
| 499 | 510 | ||
| 500 | /* pad packets. Works as a second tool and is always in prox */ | 511 | /* pad packets. Works as a second tool and is always in prox */ |
| 501 | if (data[0] == WACOM_REPORT_INTUOSPAD) { | 512 | if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) { |
| 502 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { | 513 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { |
| 503 | input_report_key(input, BTN_0, (data[2] & 0x01)); | 514 | input_report_key(input, BTN_0, (data[2] & 0x01)); |
| 504 | input_report_key(input, BTN_1, (data[3] & 0x01)); | 515 | input_report_key(input, BTN_1, (data[3] & 0x01)); |
| @@ -574,6 +585,34 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
| 574 | input_report_key(input, wacom->tool[1], 0); | 585 | input_report_key(input, wacom->tool[1], 0); |
| 575 | input_report_abs(input, ABS_MISC, 0); | 586 | input_report_abs(input, ABS_MISC, 0); |
| 576 | } | 587 | } |
| 588 | } else if (features->type >= INTUOS5S && features->type <= INTUOS5L) { | ||
| 589 | int i; | ||
| 590 | |||
| 591 | /* Touch ring mode switch has no capacitive sensor */ | ||
| 592 | input_report_key(input, BTN_0, (data[3] & 0x01)); | ||
| 593 | |||
| 594 | /* | ||
| 595 | * ExpressKeys on Intuos5 have a capacitive sensor in | ||
| 596 | * addition to the mechanical switch. Switch data is | ||
| 597 | * stored in data[4], capacitive data in data[5]. | ||
| 598 | */ | ||
| 599 | for (i = 0; i < 8; i++) | ||
| 600 | input_report_key(input, BTN_1 + i, data[4] & (1 << i)); | ||
| 601 | |||
| 602 | if (data[2] & 0x80) { | ||
| 603 | input_report_abs(input, ABS_WHEEL, (data[2] & 0x7f)); | ||
| 604 | } else { | ||
| 605 | /* Out of proximity, clear wheel value. */ | ||
| 606 | input_report_abs(input, ABS_WHEEL, 0); | ||
| 607 | } | ||
| 608 | |||
| 609 | if (data[2] | (data[3] & 0x01) | data[4]) { | ||
| 610 | input_report_key(input, wacom->tool[1], 1); | ||
| 611 | input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); | ||
| 612 | } else { | ||
| 613 | input_report_key(input, wacom->tool[1], 0); | ||
| 614 | input_report_abs(input, ABS_MISC, 0); | ||
| 615 | } | ||
| 577 | } else { | 616 | } else { |
| 578 | if (features->type == WACOM_21UX2) { | 617 | if (features->type == WACOM_21UX2) { |
| 579 | input_report_key(input, BTN_0, (data[5] & 0x01)); | 618 | input_report_key(input, BTN_0, (data[5] & 0x01)); |
| @@ -637,7 +676,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
| 637 | (features->type == INTUOS3 || | 676 | (features->type == INTUOS3 || |
| 638 | features->type == INTUOS3S || | 677 | features->type == INTUOS3S || |
| 639 | features->type == INTUOS4 || | 678 | features->type == INTUOS4 || |
| 640 | features->type == INTUOS4S)) { | 679 | features->type == INTUOS4S || |
| 680 | features->type == INTUOS5 || | ||
| 681 | features->type == INTUOS5S)) { | ||
| 641 | 682 | ||
| 642 | return 0; | 683 | return 0; |
| 643 | } | 684 | } |
| @@ -690,7 +731,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
| 690 | 731 | ||
| 691 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { | 732 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { |
| 692 | /* I4 mouse */ | 733 | /* I4 mouse */ |
| 693 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { | 734 | if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || |
| 735 | (features->type >= INTUOS5S && features->type <= INTUOS5L)) { | ||
| 694 | input_report_key(input, BTN_LEFT, data[6] & 0x01); | 736 | input_report_key(input, BTN_LEFT, data[6] & 0x01); |
| 695 | input_report_key(input, BTN_MIDDLE, data[6] & 0x02); | 737 | input_report_key(input, BTN_MIDDLE, data[6] & 0x02); |
| 696 | input_report_key(input, BTN_RIGHT, data[6] & 0x04); | 738 | input_report_key(input, BTN_RIGHT, data[6] & 0x04); |
| @@ -717,7 +759,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
| 717 | } | 759 | } |
| 718 | } | 760 | } |
| 719 | } else if ((features->type < INTUOS3S || features->type == INTUOS3L || | 761 | } else if ((features->type < INTUOS3S || features->type == INTUOS3L || |
| 720 | features->type == INTUOS4L) && | 762 | features->type == INTUOS4L || features->type == INTUOS5L) && |
| 721 | wacom->tool[idx] == BTN_TOOL_LENS) { | 763 | wacom->tool[idx] == BTN_TOOL_LENS) { |
| 722 | /* Lens cursor packets */ | 764 | /* Lens cursor packets */ |
| 723 | input_report_key(input, BTN_LEFT, data[8] & 0x01); | 765 | input_report_key(input, BTN_LEFT, data[8] & 0x01); |
| @@ -734,6 +776,72 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
| 734 | return 1; | 776 | return 1; |
| 735 | } | 777 | } |
| 736 | 778 | ||
| 779 | static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid) | ||
| 780 | { | ||
| 781 | int touch_max = wacom->features.touch_max; | ||
| 782 | int i; | ||
| 783 | |||
| 784 | if (!wacom->slots) | ||
| 785 | return -1; | ||
| 786 | |||
| 787 | for (i = 0; i < touch_max; ++i) { | ||
| 788 | if (wacom->slots[i] == contactid) | ||
| 789 | return i; | ||
| 790 | } | ||
| 791 | for (i = 0; i < touch_max; ++i) { | ||
| 792 | if (wacom->slots[i] == -1) | ||
| 793 | return i; | ||
| 794 | } | ||
| 795 | return -1; | ||
| 796 | } | ||
| 797 | |||
| 798 | static int wacom_mt_touch(struct wacom_wac *wacom) | ||
| 799 | { | ||
| 800 | struct input_dev *input = wacom->input; | ||
| 801 | char *data = wacom->data; | ||
| 802 | int i; | ||
| 803 | int current_num_contacts = data[2]; | ||
| 804 | int contacts_to_send = 0; | ||
| 805 | |||
| 806 | /* | ||
| 807 | * First packet resets the counter since only the first | ||
| 808 | * packet in series will have non-zero current_num_contacts. | ||
| 809 | */ | ||
| 810 | if (current_num_contacts) | ||
| 811 | wacom->num_contacts_left = current_num_contacts; | ||
| 812 | |||
| 813 | /* There are at most 5 contacts per packet */ | ||
| 814 | contacts_to_send = min(5, wacom->num_contacts_left); | ||
| 815 | |||
| 816 | for (i = 0; i < contacts_to_send; i++) { | ||
| 817 | int offset = (WACOM_BYTES_PER_MT_PACKET * i) + 3; | ||
| 818 | bool touch = data[offset] & 0x1; | ||
| 819 | int id = le16_to_cpup((__le16 *)&data[offset + 1]); | ||
| 820 | int slot = find_slot_from_contactid(wacom, id); | ||
| 821 | |||
| 822 | if (slot < 0) | ||
| 823 | continue; | ||
| 824 | |||
| 825 | input_mt_slot(input, slot); | ||
| 826 | input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); | ||
| 827 | if (touch) { | ||
| 828 | int x = le16_to_cpup((__le16 *)&data[offset + 7]); | ||
| 829 | int y = le16_to_cpup((__le16 *)&data[offset + 9]); | ||
| 830 | input_report_abs(input, ABS_MT_POSITION_X, x); | ||
| 831 | input_report_abs(input, ABS_MT_POSITION_Y, y); | ||
| 832 | } | ||
| 833 | wacom->slots[slot] = touch ? id : -1; | ||
| 834 | } | ||
| 835 | |||
| 836 | input_mt_report_pointer_emulation(input, true); | ||
| 837 | |||
| 838 | wacom->num_contacts_left -= contacts_to_send; | ||
| 839 | if (wacom->num_contacts_left < 0) | ||
| 840 | wacom->num_contacts_left = 0; | ||
| 841 | |||
| 842 | return 1; | ||
| 843 | } | ||
| 844 | |||
| 737 | static int wacom_tpc_mt_touch(struct wacom_wac *wacom) | 845 | static int wacom_tpc_mt_touch(struct wacom_wac *wacom) |
| 738 | { | 846 | { |
| 739 | struct input_dev *input = wacom->input; | 847 | struct input_dev *input = wacom->input; |
| @@ -772,6 +880,9 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) | |||
| 772 | bool prox; | 880 | bool prox; |
| 773 | int x = 0, y = 0; | 881 | int x = 0, y = 0; |
| 774 | 882 | ||
| 883 | if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG) | ||
| 884 | return 0; | ||
| 885 | |||
| 775 | if (!wacom->shared->stylus_in_proximity) { | 886 | if (!wacom->shared->stylus_in_proximity) { |
| 776 | if (len == WACOM_PKGLEN_TPC1FG) { | 887 | if (len == WACOM_PKGLEN_TPC1FG) { |
| 777 | prox = data[0] & 0x01; | 888 | prox = data[0] & 0x01; |
| @@ -835,15 +946,15 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
| 835 | { | 946 | { |
| 836 | char *data = wacom->data; | 947 | char *data = wacom->data; |
| 837 | 948 | ||
| 838 | dev_dbg(&wacom->input->dev, "wacom_tpc_irq: received report #%d\n", | 949 | dev_dbg(wacom->input->dev.parent, |
| 839 | data[0]); | 950 | "%s: received report #%d\n", __func__, data[0]); |
| 840 | 951 | ||
| 841 | switch (len) { | 952 | switch (len) { |
| 842 | case WACOM_PKGLEN_TPC1FG: | 953 | case WACOM_PKGLEN_TPC1FG: |
| 843 | return wacom_tpc_single_touch(wacom, len); | 954 | return wacom_tpc_single_touch(wacom, len); |
| 844 | 955 | ||
| 845 | case WACOM_PKGLEN_TPC2FG: | 956 | case WACOM_PKGLEN_TPC2FG: |
| 846 | return wacom_tpc_mt_touch(wacom); | 957 | return wacom_tpc_mt_touch(wacom); |
| 847 | 958 | ||
| 848 | default: | 959 | default: |
| 849 | switch (data[0]) { | 960 | switch (data[0]) { |
| @@ -852,6 +963,9 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
| 852 | case WACOM_REPORT_TPCST: | 963 | case WACOM_REPORT_TPCST: |
| 853 | return wacom_tpc_single_touch(wacom, len); | 964 | return wacom_tpc_single_touch(wacom, len); |
| 854 | 965 | ||
| 966 | case WACOM_REPORT_TPCMT: | ||
| 967 | return wacom_mt_touch(wacom); | ||
| 968 | |||
| 855 | case WACOM_REPORT_PENABLED: | 969 | case WACOM_REPORT_PENABLED: |
| 856 | return wacom_tpc_pen(wacom); | 970 | return wacom_tpc_pen(wacom); |
| 857 | } | 971 | } |
| @@ -1120,8 +1234,18 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | |||
| 1120 | sync = wacom_intuos_irq(wacom_wac); | 1234 | sync = wacom_intuos_irq(wacom_wac); |
| 1121 | break; | 1235 | break; |
| 1122 | 1236 | ||
| 1237 | case INTUOS5S: | ||
| 1238 | case INTUOS5: | ||
| 1239 | case INTUOS5L: | ||
| 1240 | if (len == WACOM_PKGLEN_BBTOUCH3) | ||
| 1241 | sync = wacom_bpt3_touch(wacom_wac); | ||
| 1242 | else | ||
| 1243 | sync = wacom_intuos_irq(wacom_wac); | ||
| 1244 | break; | ||
| 1245 | |||
| 1123 | case TABLETPC: | 1246 | case TABLETPC: |
| 1124 | case TABLETPC2FG: | 1247 | case TABLETPC2FG: |
| 1248 | case MTSCREEN: | ||
| 1125 | sync = wacom_tpc_irq(wacom_wac, len); | 1249 | sync = wacom_tpc_irq(wacom_wac, len); |
| 1126 | break; | 1250 | break; |
| 1127 | 1251 | ||
| @@ -1194,7 +1318,9 @@ void wacom_setup_device_quirks(struct wacom_features *features) | |||
| 1194 | 1318 | ||
| 1195 | /* these device have multiple inputs */ | 1319 | /* these device have multiple inputs */ |
| 1196 | if (features->type == TABLETPC || features->type == TABLETPC2FG || | 1320 | if (features->type == TABLETPC || features->type == TABLETPC2FG || |
| 1197 | features->type == BAMBOO_PT || features->type == WIRELESS) | 1321 | features->type == BAMBOO_PT || features->type == WIRELESS || |
| 1322 | (features->type >= INTUOS5S && features->type <= INTUOS5L) || | ||
| 1323 | features->type == MTSCREEN) | ||
| 1198 | features->quirks |= WACOM_QUIRK_MULTI_INPUT; | 1324 | features->quirks |= WACOM_QUIRK_MULTI_INPUT; |
| 1199 | 1325 | ||
| 1200 | /* quirk for bamboo touch with 2 low res touches */ | 1326 | /* quirk for bamboo touch with 2 low res touches */ |
| @@ -1225,8 +1351,8 @@ static unsigned int wacom_calculate_touch_res(unsigned int logical_max, | |||
| 1225 | return (logical_max * 100) / physical_max; | 1351 | return (logical_max * 100) / physical_max; |
| 1226 | } | 1352 | } |
| 1227 | 1353 | ||
| 1228 | void wacom_setup_input_capabilities(struct input_dev *input_dev, | 1354 | int wacom_setup_input_capabilities(struct input_dev *input_dev, |
| 1229 | struct wacom_wac *wacom_wac) | 1355 | struct wacom_wac *wacom_wac) |
| 1230 | { | 1356 | { |
| 1231 | struct wacom_features *features = &wacom_wac->features; | 1357 | struct wacom_features *features = &wacom_wac->features; |
| 1232 | int i; | 1358 | int i; |
| @@ -1361,6 +1487,50 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 1361 | wacom_setup_intuos(wacom_wac); | 1487 | wacom_setup_intuos(wacom_wac); |
| 1362 | break; | 1488 | break; |
| 1363 | 1489 | ||
| 1490 | case INTUOS5: | ||
| 1491 | case INTUOS5L: | ||
| 1492 | if (features->device_type == BTN_TOOL_PEN) { | ||
| 1493 | __set_bit(BTN_7, input_dev->keybit); | ||
| 1494 | __set_bit(BTN_8, input_dev->keybit); | ||
| 1495 | } | ||
| 1496 | /* fall through */ | ||
| 1497 | |||
| 1498 | case INTUOS5S: | ||
| 1499 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||
| 1500 | |||
| 1501 | if (features->device_type == BTN_TOOL_PEN) { | ||
| 1502 | for (i = 0; i < 7; i++) | ||
| 1503 | __set_bit(BTN_0 + i, input_dev->keybit); | ||
| 1504 | |||
| 1505 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, | ||
| 1506 | features->distance_max, | ||
| 1507 | 0, 0); | ||
| 1508 | |||
| 1509 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | ||
| 1510 | |||
| 1511 | wacom_setup_intuos(wacom_wac); | ||
| 1512 | } else if (features->device_type == BTN_TOOL_FINGER) { | ||
| 1513 | __clear_bit(ABS_MISC, input_dev->absbit); | ||
| 1514 | |||
| 1515 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
| 1516 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
| 1517 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | ||
| 1518 | __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); | ||
| 1519 | |||
| 1520 | input_mt_init_slots(input_dev, features->touch_max); | ||
| 1521 | |||
| 1522 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | ||
| 1523 | 0, 255, 0, 0); | ||
| 1524 | |||
| 1525 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
| 1526 | 0, features->x_max, | ||
| 1527 | features->x_fuzz, 0); | ||
| 1528 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
| 1529 | 0, features->y_max, | ||
| 1530 | features->y_fuzz, 0); | ||
| 1531 | } | ||
| 1532 | break; | ||
| 1533 | |||
| 1364 | case INTUOS4: | 1534 | case INTUOS4: |
| 1365 | case INTUOS4L: | 1535 | case INTUOS4L: |
| 1366 | __set_bit(BTN_7, input_dev->keybit); | 1536 | __set_bit(BTN_7, input_dev->keybit); |
| @@ -1378,9 +1548,19 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 1378 | break; | 1548 | break; |
| 1379 | 1549 | ||
| 1380 | case TABLETPC2FG: | 1550 | case TABLETPC2FG: |
| 1551 | case MTSCREEN: | ||
| 1381 | if (features->device_type == BTN_TOOL_FINGER) { | 1552 | if (features->device_type == BTN_TOOL_FINGER) { |
| 1382 | 1553 | ||
| 1383 | input_mt_init_slots(input_dev, 2); | 1554 | wacom_wac->slots = kmalloc(features->touch_max * |
| 1555 | sizeof(int), | ||
| 1556 | GFP_KERNEL); | ||
| 1557 | if (!wacom_wac->slots) | ||
| 1558 | return -ENOMEM; | ||
| 1559 | |||
| 1560 | for (i = 0; i < features->touch_max; i++) | ||
| 1561 | wacom_wac->slots[i] = -1; | ||
| 1562 | |||
| 1563 | input_mt_init_slots(input_dev, features->touch_max); | ||
| 1384 | input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, | 1564 | input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, |
| 1385 | 0, MT_TOOL_MAX, 0, 0); | 1565 | 0, MT_TOOL_MAX, 0, 0); |
| 1386 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | 1566 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, |
| @@ -1435,6 +1615,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 1435 | 1615 | ||
| 1436 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | 1616 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); |
| 1437 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | 1617 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); |
| 1618 | input_mt_init_slots(input_dev, features->touch_max); | ||
| 1438 | 1619 | ||
| 1439 | if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { | 1620 | if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { |
| 1440 | __set_bit(BTN_TOOL_TRIPLETAP, | 1621 | __set_bit(BTN_TOOL_TRIPLETAP, |
| @@ -1442,13 +1623,9 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 1442 | __set_bit(BTN_TOOL_QUADTAP, | 1623 | __set_bit(BTN_TOOL_QUADTAP, |
| 1443 | input_dev->keybit); | 1624 | input_dev->keybit); |
| 1444 | 1625 | ||
| 1445 | input_mt_init_slots(input_dev, 16); | ||
| 1446 | |||
| 1447 | input_set_abs_params(input_dev, | 1626 | input_set_abs_params(input_dev, |
| 1448 | ABS_MT_TOUCH_MAJOR, | 1627 | ABS_MT_TOUCH_MAJOR, |
| 1449 | 0, 255, 0, 0); | 1628 | 0, 255, 0, 0); |
| 1450 | } else { | ||
| 1451 | input_mt_init_slots(input_dev, 2); | ||
| 1452 | } | 1629 | } |
| 1453 | 1630 | ||
| 1454 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | 1631 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, |
| @@ -1468,6 +1645,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 1468 | } | 1645 | } |
| 1469 | break; | 1646 | break; |
| 1470 | } | 1647 | } |
| 1648 | return 0; | ||
| 1471 | } | 1649 | } |
| 1472 | 1650 | ||
| 1473 | static const struct wacom_features wacom_features_0x00 = | 1651 | static const struct wacom_features wacom_features_0x00 = |
| @@ -1635,6 +1813,24 @@ static const struct wacom_features wacom_features_0xBB = | |||
| 1635 | static const struct wacom_features wacom_features_0xBC = | 1813 | static const struct wacom_features wacom_features_0xBC = |
| 1636 | { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 25400, 2047, | 1814 | { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 25400, 2047, |
| 1637 | 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | 1815 | 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; |
| 1816 | static const struct wacom_features wacom_features_0x26 = | ||
| 1817 | { "Wacom Intuos5 touch S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, | ||
| 1818 | 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, | ||
| 1819 | .touch_max = 16 }; | ||
| 1820 | static const struct wacom_features wacom_features_0x27 = | ||
| 1821 | { "Wacom Intuos5 touch M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, | ||
| 1822 | 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, | ||
| 1823 | .touch_max = 16 }; | ||
| 1824 | static const struct wacom_features wacom_features_0x28 = | ||
| 1825 | { "Wacom Intuos5 touch L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, | ||
| 1826 | 63, INTUOS5L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, | ||
| 1827 | .touch_max = 16 }; | ||
| 1828 | static const struct wacom_features wacom_features_0x29 = | ||
| 1829 | { "Wacom Intuos5 S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, | ||
| 1830 | 63, INTUOS5S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
| 1831 | static const struct wacom_features wacom_features_0x2A = | ||
| 1832 | { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, | ||
| 1833 | 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | ||
| 1638 | static const struct wacom_features wacom_features_0xF4 = | 1834 | static const struct wacom_features wacom_features_0xF4 = |
| 1639 | { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, | 1835 | { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, |
| 1640 | 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | 1836 | 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; |
| @@ -1676,13 +1872,19 @@ static const struct wacom_features wacom_features_0x9F = | |||
| 1676 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1872 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 1677 | static const struct wacom_features wacom_features_0xE2 = | 1873 | static const struct wacom_features wacom_features_0xE2 = |
| 1678 | { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, | 1874 | { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, |
| 1679 | 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1875 | 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1876 | .touch_max = 2 }; | ||
| 1680 | static const struct wacom_features wacom_features_0xE3 = | 1877 | static const struct wacom_features wacom_features_0xE3 = |
| 1681 | { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, | 1878 | { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, |
| 1682 | 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1879 | 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1880 | .touch_max = 2 }; | ||
| 1881 | static const struct wacom_features wacom_features_0xE5 = | ||
| 1882 | { "Wacom ISDv4 E5", WACOM_PKGLEN_MTOUCH, 26202, 16325, 255, | ||
| 1883 | 0, MTSCREEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
| 1683 | static const struct wacom_features wacom_features_0xE6 = | 1884 | static const struct wacom_features wacom_features_0xE6 = |
| 1684 | { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, | 1885 | { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, |
| 1685 | 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1886 | 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1887 | .touch_max = 2 }; | ||
| 1686 | static const struct wacom_features wacom_features_0xEC = | 1888 | static const struct wacom_features wacom_features_0xEC = |
| 1687 | { "Wacom ISDv4 EC", WACOM_PKGLEN_GRAPHIRE, 25710, 14500, 255, | 1889 | { "Wacom ISDv4 EC", WACOM_PKGLEN_GRAPHIRE, 25710, 14500, 255, |
| 1688 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1890 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| @@ -1691,19 +1893,22 @@ static const struct wacom_features wacom_features_0x47 = | |||
| 1691 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1893 | 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 1692 | static const struct wacom_features wacom_features_0x84 = | 1894 | static const struct wacom_features wacom_features_0x84 = |
| 1693 | { "Wacom Wireless Receiver", WACOM_PKGLEN_WIRELESS, 0, 0, 0, | 1895 | { "Wacom Wireless Receiver", WACOM_PKGLEN_WIRELESS, 0, 0, 0, |
| 1694 | 0, WIRELESS, 0, 0 }; | 1896 | 0, WIRELESS, 0, 0, .touch_max = 16 }; |
| 1695 | static const struct wacom_features wacom_features_0xD0 = | 1897 | static const struct wacom_features wacom_features_0xD0 = |
| 1696 | { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1898 | { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
| 1697 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1899 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1900 | .touch_max = 2 }; | ||
| 1698 | static const struct wacom_features wacom_features_0xD1 = | 1901 | static const struct wacom_features wacom_features_0xD1 = |
| 1699 | { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1902 | { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
| 1700 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1903 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1904 | .touch_max = 2 }; | ||
| 1701 | static const struct wacom_features wacom_features_0xD2 = | 1905 | static const struct wacom_features wacom_features_0xD2 = |
| 1702 | { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1906 | { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
| 1703 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1907 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 1704 | static const struct wacom_features wacom_features_0xD3 = | 1908 | static const struct wacom_features wacom_features_0xD3 = |
| 1705 | { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, | 1909 | { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, |
| 1706 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1910 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1911 | .touch_max = 2 }; | ||
| 1707 | static const struct wacom_features wacom_features_0xD4 = | 1912 | static const struct wacom_features wacom_features_0xD4 = |
| 1708 | { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1913 | { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
| 1709 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1914 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| @@ -1712,28 +1917,35 @@ static const struct wacom_features wacom_features_0xD5 = | |||
| 1712 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1917 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 1713 | static const struct wacom_features wacom_features_0xD6 = | 1918 | static const struct wacom_features wacom_features_0xD6 = |
| 1714 | { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1919 | { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
| 1715 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1920 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1921 | .touch_max = 2 }; | ||
| 1716 | static const struct wacom_features wacom_features_0xD7 = | 1922 | static const struct wacom_features wacom_features_0xD7 = |
| 1717 | { "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1923 | { "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
| 1718 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1924 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1925 | .touch_max = 2 }; | ||
| 1719 | static const struct wacom_features wacom_features_0xD8 = | 1926 | static const struct wacom_features wacom_features_0xD8 = |
| 1720 | { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, | 1927 | { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, |
| 1721 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1928 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1929 | .touch_max = 2 }; | ||
| 1722 | static const struct wacom_features wacom_features_0xDA = | 1930 | static const struct wacom_features wacom_features_0xDA = |
| 1723 | { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, | 1931 | { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, |
| 1724 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1932 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1933 | .touch_max = 2 }; | ||
| 1725 | static struct wacom_features wacom_features_0xDB = | 1934 | static struct wacom_features wacom_features_0xDB = |
| 1726 | { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, | 1935 | { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, |
| 1727 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1936 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1937 | .touch_max = 2 }; | ||
| 1728 | static const struct wacom_features wacom_features_0xDD = | 1938 | static const struct wacom_features wacom_features_0xDD = |
| 1729 | { "Wacom Bamboo Connect", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023, | 1939 | { "Wacom Bamboo Connect", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023, |
| 1730 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1940 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 1731 | static const struct wacom_features wacom_features_0xDE = | 1941 | static const struct wacom_features wacom_features_0xDE = |
| 1732 | { "Wacom Bamboo 16FG 4x5", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023, | 1942 | { "Wacom Bamboo 16FG 4x5", WACOM_PKGLEN_BBPEN, 14720, 9200, 1023, |
| 1733 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1943 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1944 | .touch_max = 16 }; | ||
| 1734 | static const struct wacom_features wacom_features_0xDF = | 1945 | static const struct wacom_features wacom_features_0xDF = |
| 1735 | { "Wacom Bamboo 16FG 6x8", WACOM_PKGLEN_BBPEN, 21648, 13700, 1023, | 1946 | { "Wacom Bamboo 16FG 6x8", WACOM_PKGLEN_BBPEN, 21648, 13700, 1023, |
| 1736 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1947 | 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 1948 | .touch_max = 16 }; | ||
| 1737 | static const struct wacom_features wacom_features_0x6004 = | 1949 | static const struct wacom_features wacom_features_0x6004 = |
| 1738 | { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, | 1950 | { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, |
| 1739 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 1951 | 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| @@ -1807,6 +2019,11 @@ const struct usb_device_id wacom_ids[] = { | |||
| 1807 | { USB_DEVICE_WACOM(0xBA) }, | 2019 | { USB_DEVICE_WACOM(0xBA) }, |
| 1808 | { USB_DEVICE_WACOM(0xBB) }, | 2020 | { USB_DEVICE_WACOM(0xBB) }, |
| 1809 | { USB_DEVICE_WACOM(0xBC) }, | 2021 | { USB_DEVICE_WACOM(0xBC) }, |
| 2022 | { USB_DEVICE_WACOM(0x26) }, | ||
| 2023 | { USB_DEVICE_WACOM(0x27) }, | ||
| 2024 | { USB_DEVICE_WACOM(0x28) }, | ||
| 2025 | { USB_DEVICE_WACOM(0x29) }, | ||
| 2026 | { USB_DEVICE_WACOM(0x2A) }, | ||
| 1810 | { USB_DEVICE_WACOM(0x3F) }, | 2027 | { USB_DEVICE_WACOM(0x3F) }, |
| 1811 | { USB_DEVICE_WACOM(0xC5) }, | 2028 | { USB_DEVICE_WACOM(0xC5) }, |
| 1812 | { USB_DEVICE_WACOM(0xC6) }, | 2029 | { USB_DEVICE_WACOM(0xC6) }, |
| @@ -1842,6 +2059,7 @@ const struct usb_device_id wacom_ids[] = { | |||
| 1842 | { USB_DEVICE_WACOM(0x9F) }, | 2059 | { USB_DEVICE_WACOM(0x9F) }, |
| 1843 | { USB_DEVICE_WACOM(0xE2) }, | 2060 | { USB_DEVICE_WACOM(0xE2) }, |
| 1844 | { USB_DEVICE_WACOM(0xE3) }, | 2061 | { USB_DEVICE_WACOM(0xE3) }, |
| 2062 | { USB_DEVICE_WACOM(0xE5) }, | ||
| 1845 | { USB_DEVICE_WACOM(0xE6) }, | 2063 | { USB_DEVICE_WACOM(0xE6) }, |
| 1846 | { USB_DEVICE_WACOM(0xEC) }, | 2064 | { USB_DEVICE_WACOM(0xEC) }, |
| 1847 | { USB_DEVICE_WACOM(0x47) }, | 2065 | { USB_DEVICE_WACOM(0x47) }, |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index ba5a334e54d6..78fbd3f42009 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
| @@ -25,6 +25,10 @@ | |||
| 25 | #define WACOM_PKGLEN_BBTOUCH3 64 | 25 | #define WACOM_PKGLEN_BBTOUCH3 64 |
| 26 | #define WACOM_PKGLEN_BBPEN 10 | 26 | #define WACOM_PKGLEN_BBPEN 10 |
| 27 | #define WACOM_PKGLEN_WIRELESS 32 | 27 | #define WACOM_PKGLEN_WIRELESS 32 |
| 28 | #define WACOM_PKGLEN_MTOUCH 62 | ||
| 29 | |||
| 30 | /* wacom data size per MT contact */ | ||
| 31 | #define WACOM_BYTES_PER_MT_PACKET 11 | ||
| 28 | 32 | ||
| 29 | /* device IDs */ | 33 | /* device IDs */ |
| 30 | #define STYLUS_DEVICE_ID 0x02 | 34 | #define STYLUS_DEVICE_ID 0x02 |
| @@ -38,8 +42,10 @@ | |||
| 38 | #define WACOM_REPORT_INTUOSREAD 5 | 42 | #define WACOM_REPORT_INTUOSREAD 5 |
| 39 | #define WACOM_REPORT_INTUOSWRITE 6 | 43 | #define WACOM_REPORT_INTUOSWRITE 6 |
| 40 | #define WACOM_REPORT_INTUOSPAD 12 | 44 | #define WACOM_REPORT_INTUOSPAD 12 |
| 45 | #define WACOM_REPORT_INTUOS5PAD 3 | ||
| 41 | #define WACOM_REPORT_TPC1FG 6 | 46 | #define WACOM_REPORT_TPC1FG 6 |
| 42 | #define WACOM_REPORT_TPC2FG 13 | 47 | #define WACOM_REPORT_TPC2FG 13 |
| 48 | #define WACOM_REPORT_TPCMT 13 | ||
| 43 | #define WACOM_REPORT_TPCHID 15 | 49 | #define WACOM_REPORT_TPCHID 15 |
| 44 | #define WACOM_REPORT_TPCST 16 | 50 | #define WACOM_REPORT_TPCST 16 |
| 45 | 51 | ||
| @@ -65,6 +71,9 @@ enum { | |||
| 65 | INTUOS4S, | 71 | INTUOS4S, |
| 66 | INTUOS4, | 72 | INTUOS4, |
| 67 | INTUOS4L, | 73 | INTUOS4L, |
| 74 | INTUOS5S, | ||
| 75 | INTUOS5, | ||
| 76 | INTUOS5L, | ||
| 68 | WACOM_24HD, | 77 | WACOM_24HD, |
| 69 | WACOM_21UX2, | 78 | WACOM_21UX2, |
| 70 | CINTIQ, | 79 | CINTIQ, |
| @@ -72,6 +81,7 @@ enum { | |||
| 72 | WACOM_MO, | 81 | WACOM_MO, |
| 73 | TABLETPC, | 82 | TABLETPC, |
| 74 | TABLETPC2FG, | 83 | TABLETPC2FG, |
| 84 | MTSCREEN, | ||
| 75 | MAX_TYPE | 85 | MAX_TYPE |
| 76 | }; | 86 | }; |
| 77 | 87 | ||
| @@ -95,6 +105,7 @@ struct wacom_features { | |||
| 95 | int pressure_fuzz; | 105 | int pressure_fuzz; |
| 96 | int distance_fuzz; | 106 | int distance_fuzz; |
| 97 | unsigned quirks; | 107 | unsigned quirks; |
| 108 | unsigned touch_max; | ||
| 98 | }; | 109 | }; |
| 99 | 110 | ||
| 100 | struct wacom_shared { | 111 | struct wacom_shared { |
| @@ -113,6 +124,8 @@ struct wacom_wac { | |||
| 113 | struct input_dev *input; | 124 | struct input_dev *input; |
| 114 | int pid; | 125 | int pid; |
| 115 | int battery_capacity; | 126 | int battery_capacity; |
| 127 | int num_contacts_left; | ||
| 128 | int *slots; | ||
| 116 | }; | 129 | }; |
| 117 | 130 | ||
| 118 | #endif | 131 | #endif |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 75838d7710ce..98d263504eea 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -187,6 +187,23 @@ config TOUCHSCREEN_DA9034 | |||
| 187 | Say Y here to enable the support for the touchscreen found | 187 | Say Y here to enable the support for the touchscreen found |
| 188 | on Dialog Semiconductor DA9034 PMIC. | 188 | on Dialog Semiconductor DA9034 PMIC. |
| 189 | 189 | ||
| 190 | If unsure, say N. | ||
| 191 | |||
| 192 | To compile this driver as a module, choose M here: the | ||
| 193 | module will be called da9034-ts. | ||
| 194 | |||
| 195 | config TOUCHSCREEN_DA9052 | ||
| 196 | tristate "Dialog DA9052/DA9053 TSI" | ||
| 197 | depends on PMIC_DA9052 | ||
| 198 | help | ||
| 199 | Say Y here to support the touchscreen found on Dialog Semiconductor | ||
| 200 | DA9052-BC and DA9053-AA/Bx PMICs. | ||
| 201 | |||
| 202 | If unsure, say N. | ||
| 203 | |||
| 204 | To compile this driver as a module, choose M here: the | ||
| 205 | module will be called da9052_tsi. | ||
| 206 | |||
| 190 | config TOUCHSCREEN_DYNAPRO | 207 | config TOUCHSCREEN_DYNAPRO |
| 191 | tristate "Dynapro serial touchscreen" | 208 | tristate "Dynapro serial touchscreen" |
| 192 | select SERIO | 209 | select SERIO |
| @@ -306,6 +323,18 @@ config TOUCHSCREEN_WACOM_W8001 | |||
| 306 | To compile this driver as a module, choose M here: the | 323 | To compile this driver as a module, choose M here: the |
| 307 | module will be called wacom_w8001. | 324 | module will be called wacom_w8001. |
| 308 | 325 | ||
| 326 | config TOUCHSCREEN_WACOM_I2C | ||
| 327 | tristate "Wacom Tablet support (I2C)" | ||
| 328 | depends on I2C | ||
| 329 | help | ||
| 330 | Say Y here if you want to use the I2C version of the Wacom | ||
| 331 | Pen Tablet. | ||
| 332 | |||
| 333 | If unsure, say N. | ||
| 334 | |||
| 335 | To compile this driver as a module, choose M here: the module | ||
| 336 | will be called wacom_i2c. | ||
| 337 | |||
| 309 | config TOUCHSCREEN_LPC32XX | 338 | config TOUCHSCREEN_LPC32XX |
| 310 | tristate "LPC32XX touchscreen controller" | 339 | tristate "LPC32XX touchscreen controller" |
| 311 | depends on ARCH_LPC32XX | 340 | depends on ARCH_LPC32XX |
| @@ -635,6 +664,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
| 635 | - Zytronic controllers | 664 | - Zytronic controllers |
| 636 | - Elo TouchSystems 2700 IntelliTouch | 665 | - Elo TouchSystems 2700 IntelliTouch |
| 637 | - EasyTouch USB Touch Controller from Data Modul | 666 | - EasyTouch USB Touch Controller from Data Modul |
| 667 | - e2i (Mimo monitors) | ||
| 638 | 668 | ||
| 639 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 669 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
| 640 | a usage description and the required user-space stuff. | 670 | a usage description and the required user-space stuff. |
| @@ -721,7 +751,7 @@ config TOUCHSCREEN_USB_ELO | |||
| 721 | 751 | ||
| 722 | config TOUCHSCREEN_USB_E2I | 752 | config TOUCHSCREEN_USB_E2I |
| 723 | default y | 753 | default y |
| 724 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" | 754 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" if EXPERT |
| 725 | depends on TOUCHSCREEN_USB_COMPOSITE | 755 | depends on TOUCHSCREEN_USB_COMPOSITE |
| 726 | 756 | ||
| 727 | config TOUCHSCREEN_USB_ZYTRONIC | 757 | config TOUCHSCREEN_USB_ZYTRONIC |
| @@ -744,7 +774,7 @@ config TOUCHSCREEN_USB_EASYTOUCH | |||
| 744 | bool "EasyTouch USB Touch controller device support" if EMBEDDED | 774 | bool "EasyTouch USB Touch controller device support" if EMBEDDED |
| 745 | depends on TOUCHSCREEN_USB_COMPOSITE | 775 | depends on TOUCHSCREEN_USB_COMPOSITE |
| 746 | help | 776 | help |
| 747 | Say Y here if you have a EasyTouch USB Touch controller device support. | 777 | Say Y here if you have an EasyTouch USB Touch controller. |
| 748 | If unsure, say N. | 778 | If unsure, say N. |
| 749 | 779 | ||
| 750 | config TOUCHSCREEN_TOUCHIT213 | 780 | config TOUCHSCREEN_TOUCHIT213 |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 3d5cf8cbf89c..eb8bfe1c1a46 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o | |||
| 22 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o | 22 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o |
| 23 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o | 23 | obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o |
| 24 | obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o | 24 | obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o |
| 25 | obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o | ||
| 25 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o | 26 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o |
| 26 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o | 27 | obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o |
| 27 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 28 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
| @@ -59,6 +60,7 @@ obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o | |||
| 59 | obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o | 60 | obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o |
| 60 | obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o | 61 | obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o |
| 61 | obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o | 62 | obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o |
| 63 | obj-$(CONFIG_TOUCHSCREEN_WACOM_I2C) += wacom_i2c.o | ||
| 62 | obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o | 64 | obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o |
| 63 | obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o | 65 | obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o |
| 64 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o | 66 | wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o |
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 19d4ea65ea01..42e645062c20 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
| @@ -236,7 +236,6 @@ struct mxt_object { | |||
| 236 | struct mxt_message { | 236 | struct mxt_message { |
| 237 | u8 reportid; | 237 | u8 reportid; |
| 238 | u8 message[7]; | 238 | u8 message[7]; |
| 239 | u8 checksum; | ||
| 240 | }; | 239 | }; |
| 241 | 240 | ||
| 242 | struct mxt_finger { | 241 | struct mxt_finger { |
| @@ -326,17 +325,12 @@ static bool mxt_object_writable(unsigned int type) | |||
| 326 | } | 325 | } |
| 327 | 326 | ||
| 328 | static void mxt_dump_message(struct device *dev, | 327 | static void mxt_dump_message(struct device *dev, |
| 329 | struct mxt_message *message) | 328 | struct mxt_message *message) |
| 330 | { | 329 | { |
| 331 | dev_dbg(dev, "reportid:\t0x%x\n", message->reportid); | 330 | dev_dbg(dev, "reportid: %u\tmessage: %02x %02x %02x %02x %02x %02x %02x\n", |
| 332 | dev_dbg(dev, "message1:\t0x%x\n", message->message[0]); | 331 | message->reportid, message->message[0], message->message[1], |
| 333 | dev_dbg(dev, "message2:\t0x%x\n", message->message[1]); | 332 | message->message[2], message->message[3], message->message[4], |
| 334 | dev_dbg(dev, "message3:\t0x%x\n", message->message[2]); | 333 | message->message[5], message->message[6]); |
| 335 | dev_dbg(dev, "message4:\t0x%x\n", message->message[3]); | ||
| 336 | dev_dbg(dev, "message5:\t0x%x\n", message->message[4]); | ||
| 337 | dev_dbg(dev, "message6:\t0x%x\n", message->message[5]); | ||
| 338 | dev_dbg(dev, "message7:\t0x%x\n", message->message[6]); | ||
| 339 | dev_dbg(dev, "checksum:\t0x%x\n", message->checksum); | ||
| 340 | } | 334 | } |
| 341 | 335 | ||
| 342 | static int mxt_check_bootloader(struct i2c_client *client, | 336 | static int mxt_check_bootloader(struct i2c_client *client, |
| @@ -506,7 +500,7 @@ static int mxt_write_object(struct mxt_data *data, | |||
| 506 | u16 reg; | 500 | u16 reg; |
| 507 | 501 | ||
| 508 | object = mxt_get_object(data, type); | 502 | object = mxt_get_object(data, type); |
| 509 | if (!object) | 503 | if (!object || offset >= object->size + 1) |
| 510 | return -EINVAL; | 504 | return -EINVAL; |
| 511 | 505 | ||
| 512 | reg = object->start_address; | 506 | reg = object->start_address; |
| @@ -1049,8 +1043,8 @@ static ssize_t mxt_update_fw_store(struct device *dev, | |||
| 1049 | return count; | 1043 | return count; |
| 1050 | } | 1044 | } |
| 1051 | 1045 | ||
| 1052 | static DEVICE_ATTR(object, 0444, mxt_object_show, NULL); | 1046 | static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); |
| 1053 | static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store); | 1047 | static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store); |
| 1054 | 1048 | ||
| 1055 | static struct attribute *mxt_attrs[] = { | 1049 | static struct attribute *mxt_attrs[] = { |
| 1056 | &dev_attr_object.attr, | 1050 | &dev_attr_object.attr, |
| @@ -1201,7 +1195,7 @@ static int __devexit mxt_remove(struct i2c_client *client) | |||
| 1201 | return 0; | 1195 | return 0; |
| 1202 | } | 1196 | } |
| 1203 | 1197 | ||
| 1204 | #ifdef CONFIG_PM | 1198 | #ifdef CONFIG_PM_SLEEP |
| 1205 | static int mxt_suspend(struct device *dev) | 1199 | static int mxt_suspend(struct device *dev) |
| 1206 | { | 1200 | { |
| 1207 | struct i2c_client *client = to_i2c_client(dev); | 1201 | struct i2c_client *client = to_i2c_client(dev); |
| @@ -1239,13 +1233,10 @@ static int mxt_resume(struct device *dev) | |||
| 1239 | 1233 | ||
| 1240 | return 0; | 1234 | return 0; |
| 1241 | } | 1235 | } |
| 1242 | |||
| 1243 | static const struct dev_pm_ops mxt_pm_ops = { | ||
| 1244 | .suspend = mxt_suspend, | ||
| 1245 | .resume = mxt_resume, | ||
| 1246 | }; | ||
| 1247 | #endif | 1236 | #endif |
| 1248 | 1237 | ||
| 1238 | static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); | ||
| 1239 | |||
| 1249 | static const struct i2c_device_id mxt_id[] = { | 1240 | static const struct i2c_device_id mxt_id[] = { |
| 1250 | { "qt602240_ts", 0 }, | 1241 | { "qt602240_ts", 0 }, |
| 1251 | { "atmel_mxt_ts", 0 }, | 1242 | { "atmel_mxt_ts", 0 }, |
| @@ -1258,9 +1249,7 @@ static struct i2c_driver mxt_driver = { | |||
| 1258 | .driver = { | 1249 | .driver = { |
| 1259 | .name = "atmel_mxt_ts", | 1250 | .name = "atmel_mxt_ts", |
| 1260 | .owner = THIS_MODULE, | 1251 | .owner = THIS_MODULE, |
| 1261 | #ifdef CONFIG_PM | ||
| 1262 | .pm = &mxt_pm_ops, | 1252 | .pm = &mxt_pm_ops, |
| 1263 | #endif | ||
| 1264 | }, | 1253 | }, |
| 1265 | .probe = mxt_probe, | 1254 | .probe = mxt_probe, |
| 1266 | .remove = __devexit_p(mxt_remove), | 1255 | .remove = __devexit_p(mxt_remove), |
diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c new file mode 100644 index 000000000000..e8df341090c0 --- /dev/null +++ b/drivers/input/touchscreen/da9052_tsi.c | |||
| @@ -0,0 +1,370 @@ | |||
| 1 | /* | ||
| 2 | * TSI driver for Dialog DA9052 | ||
| 3 | * | ||
| 4 | * Copyright(c) 2012 Dialog Semiconductor Ltd. | ||
| 5 | * | ||
| 6 | * Author: David Dajun Chen <dchen@diasemi.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/input.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | |||
| 20 | #include <linux/mfd/da9052/reg.h> | ||
| 21 | #include <linux/mfd/da9052/da9052.h> | ||
| 22 | |||
| 23 | #define TSI_PEN_DOWN_STATUS 0x40 | ||
| 24 | |||
| 25 | struct da9052_tsi { | ||
| 26 | struct da9052 *da9052; | ||
| 27 | struct input_dev *dev; | ||
| 28 | struct delayed_work ts_pen_work; | ||
| 29 | struct mutex mutex; | ||
| 30 | unsigned int irq_pendwn; | ||
| 31 | unsigned int irq_datardy; | ||
| 32 | bool stopped; | ||
| 33 | bool adc_on; | ||
| 34 | }; | ||
| 35 | |||
| 36 | static void da9052_ts_adc_toggle(struct da9052_tsi *tsi, bool on) | ||
| 37 | { | ||
| 38 | da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 0, on); | ||
| 39 | tsi->adc_on = on; | ||
| 40 | } | ||
| 41 | |||
| 42 | static irqreturn_t da9052_ts_pendwn_irq(int irq, void *data) | ||
| 43 | { | ||
| 44 | struct da9052_tsi *tsi = data; | ||
| 45 | |||
| 46 | if (!tsi->stopped) { | ||
| 47 | /* Mask PEN_DOWN event and unmask TSI_READY event */ | ||
| 48 | disable_irq_nosync(tsi->irq_pendwn); | ||
| 49 | enable_irq(tsi->irq_datardy); | ||
| 50 | |||
| 51 | da9052_ts_adc_toggle(tsi, true); | ||
| 52 | |||
| 53 | schedule_delayed_work(&tsi->ts_pen_work, HZ / 50); | ||
| 54 | } | ||
| 55 | |||
| 56 | return IRQ_HANDLED; | ||
| 57 | } | ||
| 58 | |||
| 59 | static void da9052_ts_read(struct da9052_tsi *tsi) | ||
| 60 | { | ||
| 61 | struct input_dev *input = tsi->dev; | ||
| 62 | int ret; | ||
| 63 | u16 x, y, z; | ||
| 64 | u8 v; | ||
| 65 | |||
| 66 | ret = da9052_reg_read(tsi->da9052, DA9052_TSI_X_MSB_REG); | ||
| 67 | if (ret < 0) | ||
| 68 | return; | ||
| 69 | |||
| 70 | x = (u16) ret; | ||
| 71 | |||
| 72 | ret = da9052_reg_read(tsi->da9052, DA9052_TSI_Y_MSB_REG); | ||
| 73 | if (ret < 0) | ||
| 74 | return; | ||
| 75 | |||
| 76 | y = (u16) ret; | ||
| 77 | |||
| 78 | ret = da9052_reg_read(tsi->da9052, DA9052_TSI_Z_MSB_REG); | ||
| 79 | if (ret < 0) | ||
| 80 | return; | ||
| 81 | |||
| 82 | z = (u16) ret; | ||
| 83 | |||
| 84 | ret = da9052_reg_read(tsi->da9052, DA9052_TSI_LSB_REG); | ||
| 85 | if (ret < 0) | ||
| 86 | return; | ||
| 87 | |||
| 88 | v = (u8) ret; | ||
| 89 | |||
| 90 | x = ((x << 2) & 0x3fc) | (v & 0x3); | ||
| 91 | y = ((y << 2) & 0x3fc) | ((v & 0xc) >> 2); | ||
| 92 | z = ((z << 2) & 0x3fc) | ((v & 0x30) >> 4); | ||
| 93 | |||
| 94 | input_report_key(input, BTN_TOUCH, 1); | ||
| 95 | input_report_abs(input, ABS_X, x); | ||
| 96 | input_report_abs(input, ABS_Y, y); | ||
| 97 | input_report_abs(input, ABS_PRESSURE, z); | ||
| 98 | input_sync(input); | ||
| 99 | } | ||
| 100 | |||
| 101 | static irqreturn_t da9052_ts_datardy_irq(int irq, void *data) | ||
| 102 | { | ||
| 103 | struct da9052_tsi *tsi = data; | ||
| 104 | |||
| 105 | da9052_ts_read(tsi); | ||
| 106 | |||
| 107 | return IRQ_HANDLED; | ||
| 108 | } | ||
| 109 | |||
| 110 | static void da9052_ts_pen_work(struct work_struct *work) | ||
| 111 | { | ||
| 112 | struct da9052_tsi *tsi = container_of(work, struct da9052_tsi, | ||
| 113 | ts_pen_work.work); | ||
| 114 | if (!tsi->stopped) { | ||
| 115 | int ret = da9052_reg_read(tsi->da9052, DA9052_TSI_LSB_REG); | ||
| 116 | if (ret < 0 || (ret & TSI_PEN_DOWN_STATUS)) { | ||
| 117 | /* Pen is still DOWN (or read error) */ | ||
| 118 | schedule_delayed_work(&tsi->ts_pen_work, HZ / 50); | ||
| 119 | } else { | ||
| 120 | struct input_dev *input = tsi->dev; | ||
| 121 | |||
| 122 | /* Pen UP */ | ||
| 123 | da9052_ts_adc_toggle(tsi, false); | ||
| 124 | |||
| 125 | /* Report Pen UP */ | ||
| 126 | input_report_key(input, BTN_TOUCH, 0); | ||
| 127 | input_report_abs(input, ABS_PRESSURE, 0); | ||
| 128 | input_sync(input); | ||
| 129 | |||
| 130 | /* | ||
| 131 | * FIXME: Fixes the unhandled irq issue when quick | ||
| 132 | * pen down and pen up events occurs | ||
| 133 | */ | ||
| 134 | ret = da9052_reg_update(tsi->da9052, | ||
| 135 | DA9052_EVENT_B_REG, 0xC0, 0xC0); | ||
| 136 | if (ret < 0) | ||
| 137 | return; | ||
| 138 | |||
| 139 | /* Mask TSI_READY event and unmask PEN_DOWN event */ | ||
| 140 | disable_irq(tsi->irq_datardy); | ||
| 141 | enable_irq(tsi->irq_pendwn); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | static int __devinit da9052_ts_configure_gpio(struct da9052 *da9052) | ||
| 147 | { | ||
| 148 | int error; | ||
| 149 | |||
| 150 | error = da9052_reg_update(da9052, DA9052_GPIO_2_3_REG, 0x30, 0); | ||
| 151 | if (error < 0) | ||
| 152 | return error; | ||
| 153 | |||
| 154 | error = da9052_reg_update(da9052, DA9052_GPIO_4_5_REG, 0x33, 0); | ||
| 155 | if (error < 0) | ||
| 156 | return error; | ||
| 157 | |||
| 158 | error = da9052_reg_update(da9052, DA9052_GPIO_6_7_REG, 0x33, 0); | ||
| 159 | if (error < 0) | ||
| 160 | return error; | ||
| 161 | |||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int __devinit da9052_configure_tsi(struct da9052_tsi *tsi) | ||
| 166 | { | ||
| 167 | int error; | ||
| 168 | |||
| 169 | error = da9052_ts_configure_gpio(tsi->da9052); | ||
| 170 | if (error) | ||
| 171 | return error; | ||
| 172 | |||
| 173 | /* Measure TSI sample every 1ms */ | ||
| 174 | error = da9052_reg_update(tsi->da9052, DA9052_ADC_CONT_REG, | ||
| 175 | 1 << 6, 1 << 6); | ||
| 176 | if (error < 0) | ||
| 177 | return error; | ||
| 178 | |||
| 179 | /* TSI_DELAY: 3 slots, TSI_SKIP: 0 slots, TSI_MODE: XYZP */ | ||
| 180 | error = da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 0xFC, 0xC0); | ||
| 181 | if (error < 0) | ||
| 182 | return error; | ||
| 183 | |||
| 184 | /* Supply TSIRef through LD09 */ | ||
| 185 | error = da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x59); | ||
| 186 | if (error < 0) | ||
| 187 | return error; | ||
| 188 | |||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int da9052_ts_input_open(struct input_dev *input_dev) | ||
| 193 | { | ||
| 194 | struct da9052_tsi *tsi = input_get_drvdata(input_dev); | ||
| 195 | |||
| 196 | tsi->stopped = false; | ||
| 197 | mb(); | ||
| 198 | |||
| 199 | /* Unmask PEN_DOWN event */ | ||
| 200 | enable_irq(tsi->irq_pendwn); | ||
| 201 | |||
| 202 | /* Enable Pen Detect Circuit */ | ||
| 203 | return da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, | ||
| 204 | 1 << 1, 1 << 1); | ||
| 205 | } | ||
| 206 | |||
| 207 | static void da9052_ts_input_close(struct input_dev *input_dev) | ||
| 208 | { | ||
| 209 | struct da9052_tsi *tsi = input_get_drvdata(input_dev); | ||
| 210 | |||
| 211 | tsi->stopped = true; | ||
| 212 | mb(); | ||
| 213 | disable_irq(tsi->irq_pendwn); | ||
| 214 | cancel_delayed_work_sync(&tsi->ts_pen_work); | ||
| 215 | |||
| 216 | if (tsi->adc_on) { | ||
| 217 | disable_irq(tsi->irq_datardy); | ||
| 218 | da9052_ts_adc_toggle(tsi, false); | ||
| 219 | |||
| 220 | /* | ||
| 221 | * If ADC was on that means that pendwn IRQ was disabled | ||
| 222 | * twice and we need to enable it to keep enable/disable | ||
| 223 | * counter balanced. IRQ is still off though. | ||
| 224 | */ | ||
| 225 | enable_irq(tsi->irq_pendwn); | ||
| 226 | } | ||
| 227 | |||
| 228 | /* Disable Pen Detect Circuit */ | ||
| 229 | da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 1, 0); | ||
| 230 | } | ||
| 231 | |||
| 232 | static int __devinit da9052_ts_probe(struct platform_device *pdev) | ||
| 233 | { | ||
| 234 | struct da9052 *da9052; | ||
| 235 | struct da9052_tsi *tsi; | ||
| 236 | struct input_dev *input_dev; | ||
| 237 | int irq_pendwn; | ||
| 238 | int irq_datardy; | ||
| 239 | int error; | ||
| 240 | |||
| 241 | da9052 = dev_get_drvdata(pdev->dev.parent); | ||
| 242 | if (!da9052) | ||
| 243 | return -EINVAL; | ||
| 244 | |||
| 245 | irq_pendwn = platform_get_irq_byname(pdev, "PENDWN"); | ||
| 246 | irq_datardy = platform_get_irq_byname(pdev, "TSIRDY"); | ||
| 247 | if (irq_pendwn < 0 || irq_datardy < 0) { | ||
| 248 | dev_err(da9052->dev, "Unable to determine device interrupts\n"); | ||
| 249 | return -ENXIO; | ||
| 250 | } | ||
| 251 | |||
| 252 | tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL); | ||
| 253 | input_dev = input_allocate_device(); | ||
| 254 | if (!tsi || !input_dev) { | ||
| 255 | error = -ENOMEM; | ||
| 256 | goto err_free_mem; | ||
| 257 | } | ||
| 258 | |||
| 259 | tsi->da9052 = da9052; | ||
| 260 | tsi->dev = input_dev; | ||
| 261 | tsi->irq_pendwn = da9052->irq_base + irq_pendwn; | ||
| 262 | tsi->irq_datardy = da9052->irq_base + irq_datardy; | ||
| 263 | tsi->stopped = true; | ||
| 264 | INIT_DELAYED_WORK(&tsi->ts_pen_work, da9052_ts_pen_work); | ||
| 265 | |||
| 266 | input_dev->id.version = 0x0101; | ||
| 267 | input_dev->id.vendor = 0x15B6; | ||
| 268 | input_dev->id.product = 0x9052; | ||
| 269 | input_dev->name = "Dialog DA9052 TouchScreen Driver"; | ||
| 270 | input_dev->dev.parent = &pdev->dev; | ||
| 271 | input_dev->open = da9052_ts_input_open; | ||
| 272 | input_dev->close = da9052_ts_input_close; | ||
| 273 | |||
| 274 | __set_bit(EV_ABS, input_dev->evbit); | ||
| 275 | __set_bit(EV_KEY, input_dev->evbit); | ||
| 276 | __set_bit(BTN_TOUCH, input_dev->keybit); | ||
| 277 | |||
| 278 | input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0); | ||
| 279 | input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0); | ||
| 280 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1023, 0, 0); | ||
| 281 | |||
| 282 | input_set_drvdata(input_dev, tsi); | ||
| 283 | |||
| 284 | /* Disable Pen Detect Circuit */ | ||
| 285 | da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 1, 0); | ||
| 286 | |||
| 287 | /* Disable ADC */ | ||
| 288 | da9052_ts_adc_toggle(tsi, false); | ||
| 289 | |||
| 290 | error = request_threaded_irq(tsi->irq_pendwn, | ||
| 291 | NULL, da9052_ts_pendwn_irq, | ||
| 292 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
| 293 | "PENDWN", tsi); | ||
| 294 | if (error) { | ||
| 295 | dev_err(tsi->da9052->dev, | ||
| 296 | "Failed to register PENDWN IRQ %d, error = %d\n", | ||
| 297 | tsi->irq_pendwn, error); | ||
| 298 | goto err_free_mem; | ||
| 299 | } | ||
| 300 | |||
| 301 | error = request_threaded_irq(tsi->irq_datardy, | ||
| 302 | NULL, da9052_ts_datardy_irq, | ||
| 303 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
| 304 | "TSIRDY", tsi); | ||
| 305 | if (error) { | ||
| 306 | dev_err(tsi->da9052->dev, | ||
| 307 | "Failed to register TSIRDY IRQ %d, error = %d\n", | ||
| 308 | tsi->irq_datardy, error); | ||
| 309 | goto err_free_pendwn_irq; | ||
| 310 | } | ||
| 311 | |||
| 312 | /* Mask PEN_DOWN and TSI_READY events */ | ||
| 313 | disable_irq(tsi->irq_pendwn); | ||
| 314 | disable_irq(tsi->irq_datardy); | ||
| 315 | |||
| 316 | error = da9052_configure_tsi(tsi); | ||
| 317 | if (error) | ||
| 318 | goto err_free_datardy_irq; | ||
| 319 | |||
| 320 | error = input_register_device(tsi->dev); | ||
| 321 | if (error) | ||
| 322 | goto err_free_datardy_irq; | ||
| 323 | |||
| 324 | platform_set_drvdata(pdev, tsi); | ||
| 325 | |||
| 326 | return 0; | ||
| 327 | |||
| 328 | err_free_datardy_irq: | ||
| 329 | free_irq(tsi->irq_datardy, tsi); | ||
| 330 | err_free_pendwn_irq: | ||
| 331 | free_irq(tsi->irq_pendwn, tsi); | ||
| 332 | err_free_mem: | ||
| 333 | kfree(tsi); | ||
| 334 | input_free_device(input_dev); | ||
| 335 | |||
| 336 | return error; | ||
| 337 | } | ||
| 338 | |||
| 339 | static int __devexit da9052_ts_remove(struct platform_device *pdev) | ||
| 340 | { | ||
| 341 | struct da9052_tsi *tsi = platform_get_drvdata(pdev); | ||
| 342 | |||
| 343 | da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x19); | ||
| 344 | |||
| 345 | free_irq(tsi->irq_pendwn, tsi); | ||
| 346 | free_irq(tsi->irq_datardy, tsi); | ||
| 347 | |||
| 348 | input_unregister_device(tsi->dev); | ||
| 349 | kfree(tsi); | ||
| 350 | |||
| 351 | platform_set_drvdata(pdev, NULL); | ||
| 352 | |||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | |||
| 356 | static struct platform_driver da9052_tsi_driver = { | ||
| 357 | .probe = da9052_ts_probe, | ||
| 358 | .remove = __devexit_p(da9052_ts_remove), | ||
| 359 | .driver = { | ||
| 360 | .name = "da9052-tsi", | ||
| 361 | .owner = THIS_MODULE, | ||
| 362 | }, | ||
| 363 | }; | ||
| 364 | |||
| 365 | module_platform_driver(da9052_tsi_driver); | ||
| 366 | |||
| 367 | MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9052"); | ||
| 368 | MODULE_AUTHOR("Anthony Olech <Anthony.Olech@diasemi.com>"); | ||
| 369 | MODULE_LICENSE("GPL"); | ||
| 370 | MODULE_ALIAS("platform:da9052-tsi"); | ||
diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c index 455353908bdf..1809677a6513 100644 --- a/drivers/input/touchscreen/dynapro.c +++ b/drivers/input/touchscreen/dynapro.c | |||
| @@ -188,19 +188,4 @@ static struct serio_driver dynapro_drv = { | |||
| 188 | .disconnect = dynapro_disconnect, | 188 | .disconnect = dynapro_disconnect, |
| 189 | }; | 189 | }; |
| 190 | 190 | ||
| 191 | /* | 191 | module_serio_driver(dynapro_drv); |
| 192 | * The functions for inserting/removing us as a module. | ||
| 193 | */ | ||
| 194 | |||
| 195 | static int __init dynapro_init(void) | ||
| 196 | { | ||
| 197 | return serio_register_driver(&dynapro_drv); | ||
| 198 | } | ||
| 199 | |||
| 200 | static void __exit dynapro_exit(void) | ||
| 201 | { | ||
| 202 | serio_unregister_driver(&dynapro_drv); | ||
| 203 | } | ||
| 204 | |||
| 205 | module_init(dynapro_init); | ||
| 206 | module_exit(dynapro_exit); | ||
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 486d31ba9c09..957423d1471d 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c | |||
| @@ -405,19 +405,4 @@ static struct serio_driver elo_drv = { | |||
| 405 | .disconnect = elo_disconnect, | 405 | .disconnect = elo_disconnect, |
| 406 | }; | 406 | }; |
| 407 | 407 | ||
| 408 | /* | 408 | module_serio_driver(elo_drv); |
| 409 | * The functions for inserting/removing us as a module. | ||
| 410 | */ | ||
| 411 | |||
| 412 | static int __init elo_init(void) | ||
| 413 | { | ||
| 414 | return serio_register_driver(&elo_drv); | ||
| 415 | } | ||
| 416 | |||
| 417 | static void __exit elo_exit(void) | ||
| 418 | { | ||
| 419 | serio_unregister_driver(&elo_drv); | ||
| 420 | } | ||
| 421 | |||
| 422 | module_init(elo_init); | ||
| 423 | module_exit(elo_exit); | ||
diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c index 80b21800355f..10794ddbdf58 100644 --- a/drivers/input/touchscreen/fujitsu_ts.c +++ b/drivers/input/touchscreen/fujitsu_ts.c | |||
| @@ -175,15 +175,4 @@ static struct serio_driver fujitsu_drv = { | |||
| 175 | .disconnect = fujitsu_disconnect, | 175 | .disconnect = fujitsu_disconnect, |
| 176 | }; | 176 | }; |
| 177 | 177 | ||
| 178 | static int __init fujitsu_init(void) | 178 | module_serio_driver(fujitsu_drv); |
| 179 | { | ||
| 180 | return serio_register_driver(&fujitsu_drv); | ||
| 181 | } | ||
| 182 | |||
| 183 | static void __exit fujitsu_exit(void) | ||
| 184 | { | ||
| 185 | serio_unregister_driver(&fujitsu_drv); | ||
| 186 | } | ||
| 187 | |||
| 188 | module_init(fujitsu_init); | ||
| 189 | module_exit(fujitsu_exit); | ||
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index a54f90e02ab6..41c71766bf18 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c | |||
| @@ -186,19 +186,4 @@ static struct serio_driver gunze_drv = { | |||
| 186 | .disconnect = gunze_disconnect, | 186 | .disconnect = gunze_disconnect, |
| 187 | }; | 187 | }; |
| 188 | 188 | ||
| 189 | /* | 189 | module_serio_driver(gunze_drv); |
| 190 | * The functions for inserting/removing us as a module. | ||
| 191 | */ | ||
| 192 | |||
| 193 | static int __init gunze_init(void) | ||
| 194 | { | ||
| 195 | return serio_register_driver(&gunze_drv); | ||
| 196 | } | ||
| 197 | |||
| 198 | static void __exit gunze_exit(void) | ||
| 199 | { | ||
| 200 | serio_unregister_driver(&gunze_drv); | ||
| 201 | } | ||
| 202 | |||
| 203 | module_init(gunze_init); | ||
| 204 | module_exit(gunze_exit); | ||
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index 6107e563e681..b9e8686a6f1c 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
| @@ -476,19 +476,4 @@ static struct serio_driver h3600ts_drv = { | |||
| 476 | .disconnect = h3600ts_disconnect, | 476 | .disconnect = h3600ts_disconnect, |
| 477 | }; | 477 | }; |
| 478 | 478 | ||
| 479 | /* | 479 | module_serio_driver(h3600ts_drv); |
| 480 | * The functions for inserting/removing us as a module. | ||
| 481 | */ | ||
| 482 | |||
| 483 | static int __init h3600ts_init(void) | ||
| 484 | { | ||
| 485 | return serio_register_driver(&h3600ts_drv); | ||
| 486 | } | ||
| 487 | |||
| 488 | static void __exit h3600ts_exit(void) | ||
| 489 | { | ||
| 490 | serio_unregister_driver(&h3600ts_drv); | ||
| 491 | } | ||
| 492 | |||
| 493 | module_init(h3600ts_init); | ||
| 494 | module_exit(h3600ts_exit); | ||
diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c index 2da6cc31bb21..0cc47ea98acf 100644 --- a/drivers/input/touchscreen/hampshire.c +++ b/drivers/input/touchscreen/hampshire.c | |||
| @@ -187,19 +187,4 @@ static struct serio_driver hampshire_drv = { | |||
| 187 | .disconnect = hampshire_disconnect, | 187 | .disconnect = hampshire_disconnect, |
| 188 | }; | 188 | }; |
| 189 | 189 | ||
| 190 | /* | 190 | module_serio_driver(hampshire_drv); |
| 191 | * The functions for inserting/removing us as a module. | ||
| 192 | */ | ||
| 193 | |||
| 194 | static int __init hampshire_init(void) | ||
| 195 | { | ||
| 196 | return serio_register_driver(&hampshire_drv); | ||
| 197 | } | ||
| 198 | |||
| 199 | static void __exit hampshire_exit(void) | ||
| 200 | { | ||
| 201 | serio_unregister_driver(&hampshire_drv); | ||
| 202 | } | ||
| 203 | |||
| 204 | module_init(hampshire_init); | ||
| 205 | module_exit(hampshire_exit); | ||
diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c index 192ade0a0fb9..a29c99c32245 100644 --- a/drivers/input/touchscreen/inexio.c +++ b/drivers/input/touchscreen/inexio.c | |||
| @@ -189,19 +189,4 @@ static struct serio_driver inexio_drv = { | |||
| 189 | .disconnect = inexio_disconnect, | 189 | .disconnect = inexio_disconnect, |
| 190 | }; | 190 | }; |
| 191 | 191 | ||
| 192 | /* | 192 | module_serio_driver(inexio_drv); |
| 193 | * The functions for inserting/removing us as a module. | ||
| 194 | */ | ||
| 195 | |||
| 196 | static int __init inexio_init(void) | ||
| 197 | { | ||
| 198 | return serio_register_driver(&inexio_drv); | ||
| 199 | } | ||
| 200 | |||
| 201 | static void __exit inexio_exit(void) | ||
| 202 | { | ||
| 203 | serio_unregister_driver(&inexio_drv); | ||
| 204 | } | ||
| 205 | |||
| 206 | module_init(inexio_init); | ||
| 207 | module_exit(inexio_exit); | ||
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c index afcd0691ec67..4c2b8ed3bf16 100644 --- a/drivers/input/touchscreen/lpc32xx_ts.c +++ b/drivers/input/touchscreen/lpc32xx_ts.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
| 23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
| 24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | #include <linux/of.h> | ||
| 25 | 26 | ||
| 26 | /* | 27 | /* |
| 27 | * Touchscreen controller register offsets | 28 | * Touchscreen controller register offsets |
| @@ -383,6 +384,14 @@ static const struct dev_pm_ops lpc32xx_ts_pm_ops = { | |||
| 383 | #define LPC32XX_TS_PM_OPS NULL | 384 | #define LPC32XX_TS_PM_OPS NULL |
| 384 | #endif | 385 | #endif |
| 385 | 386 | ||
| 387 | #ifdef CONFIG_OF | ||
| 388 | static struct of_device_id lpc32xx_tsc_of_match[] = { | ||
| 389 | { .compatible = "nxp,lpc3220-tsc", }, | ||
| 390 | { }, | ||
| 391 | }; | ||
| 392 | MODULE_DEVICE_TABLE(of, lpc32xx_tsc_of_match); | ||
| 393 | #endif | ||
| 394 | |||
| 386 | static struct platform_driver lpc32xx_ts_driver = { | 395 | static struct platform_driver lpc32xx_ts_driver = { |
| 387 | .probe = lpc32xx_ts_probe, | 396 | .probe = lpc32xx_ts_probe, |
| 388 | .remove = __devexit_p(lpc32xx_ts_remove), | 397 | .remove = __devexit_p(lpc32xx_ts_remove), |
| @@ -390,6 +399,7 @@ static struct platform_driver lpc32xx_ts_driver = { | |||
| 390 | .name = MOD_NAME, | 399 | .name = MOD_NAME, |
| 391 | .owner = THIS_MODULE, | 400 | .owner = THIS_MODULE, |
| 392 | .pm = LPC32XX_TS_PM_OPS, | 401 | .pm = LPC32XX_TS_PM_OPS, |
| 402 | .of_match_table = of_match_ptr(lpc32xx_tsc_of_match), | ||
| 393 | }, | 403 | }, |
| 394 | }; | 404 | }; |
| 395 | module_platform_driver(lpc32xx_ts_driver); | 405 | module_platform_driver(lpc32xx_ts_driver); |
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index 9077228418b7..eb66b7c37c2f 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c | |||
| @@ -202,19 +202,4 @@ static struct serio_driver mtouch_drv = { | |||
| 202 | .disconnect = mtouch_disconnect, | 202 | .disconnect = mtouch_disconnect, |
| 203 | }; | 203 | }; |
| 204 | 204 | ||
| 205 | /* | 205 | module_serio_driver(mtouch_drv); |
| 206 | * The functions for inserting/removing us as a module. | ||
| 207 | */ | ||
| 208 | |||
| 209 | static int __init mtouch_init(void) | ||
| 210 | { | ||
| 211 | return serio_register_driver(&mtouch_drv); | ||
| 212 | } | ||
| 213 | |||
| 214 | static void __exit mtouch_exit(void) | ||
| 215 | { | ||
| 216 | serio_unregister_driver(&mtouch_drv); | ||
| 217 | } | ||
| 218 | |||
| 219 | module_init(mtouch_init); | ||
| 220 | module_exit(mtouch_exit); | ||
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c index 4c012fb2b01e..4ccde45b9da2 100644 --- a/drivers/input/touchscreen/penmount.c +++ b/drivers/input/touchscreen/penmount.c | |||
| @@ -317,19 +317,4 @@ static struct serio_driver pm_drv = { | |||
| 317 | .disconnect = pm_disconnect, | 317 | .disconnect = pm_disconnect, |
| 318 | }; | 318 | }; |
| 319 | 319 | ||
| 320 | /* | 320 | module_serio_driver(pm_drv); |
| 321 | * The functions for inserting/removing us as a module. | ||
| 322 | */ | ||
| 323 | |||
| 324 | static int __init pm_init(void) | ||
| 325 | { | ||
| 326 | return serio_register_driver(&pm_drv); | ||
| 327 | } | ||
| 328 | |||
| 329 | static void __exit pm_exit(void) | ||
| 330 | { | ||
| 331 | serio_unregister_driver(&pm_drv); | ||
| 332 | } | ||
| 333 | |||
| 334 | module_init(pm_init); | ||
| 335 | module_exit(pm_exit); | ||
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index cbbf71b22696..6cb68a1981bf 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c | |||
| @@ -218,7 +218,7 @@ static int __devexit st1232_ts_remove(struct i2c_client *client) | |||
| 218 | return 0; | 218 | return 0; |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | #ifdef CONFIG_PM | 221 | #ifdef CONFIG_PM_SLEEP |
| 222 | static int st1232_ts_suspend(struct device *dev) | 222 | static int st1232_ts_suspend(struct device *dev) |
| 223 | { | 223 | { |
| 224 | struct i2c_client *client = to_i2c_client(dev); | 224 | struct i2c_client *client = to_i2c_client(dev); |
| @@ -243,18 +243,25 @@ static int st1232_ts_resume(struct device *dev) | |||
| 243 | return 0; | 243 | return 0; |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | static const struct dev_pm_ops st1232_ts_pm_ops = { | ||
| 247 | .suspend = st1232_ts_suspend, | ||
| 248 | .resume = st1232_ts_resume, | ||
| 249 | }; | ||
| 250 | #endif | 246 | #endif |
| 251 | 247 | ||
| 248 | static SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops, | ||
| 249 | st1232_ts_suspend, st1232_ts_resume); | ||
| 250 | |||
| 252 | static const struct i2c_device_id st1232_ts_id[] = { | 251 | static const struct i2c_device_id st1232_ts_id[] = { |
| 253 | { ST1232_TS_NAME, 0 }, | 252 | { ST1232_TS_NAME, 0 }, |
| 254 | { } | 253 | { } |
| 255 | }; | 254 | }; |
| 256 | MODULE_DEVICE_TABLE(i2c, st1232_ts_id); | 255 | MODULE_DEVICE_TABLE(i2c, st1232_ts_id); |
| 257 | 256 | ||
| 257 | #ifdef CONFIG_OF | ||
| 258 | static const struct of_device_id st1232_ts_dt_ids[] __devinitconst = { | ||
| 259 | { .compatible = "sitronix,st1232", }, | ||
| 260 | { } | ||
| 261 | }; | ||
| 262 | MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); | ||
| 263 | #endif | ||
| 264 | |||
| 258 | static struct i2c_driver st1232_ts_driver = { | 265 | static struct i2c_driver st1232_ts_driver = { |
| 259 | .probe = st1232_ts_probe, | 266 | .probe = st1232_ts_probe, |
| 260 | .remove = __devexit_p(st1232_ts_remove), | 267 | .remove = __devexit_p(st1232_ts_remove), |
| @@ -262,9 +269,8 @@ static struct i2c_driver st1232_ts_driver = { | |||
| 262 | .driver = { | 269 | .driver = { |
| 263 | .name = ST1232_TS_NAME, | 270 | .name = ST1232_TS_NAME, |
| 264 | .owner = THIS_MODULE, | 271 | .owner = THIS_MODULE, |
| 265 | #ifdef CONFIG_PM | 272 | .of_match_table = of_match_ptr(st1232_ts_dt_ids), |
| 266 | .pm = &st1232_ts_pm_ops, | 273 | .pm = &st1232_ts_pm_ops, |
| 267 | #endif | ||
| 268 | }, | 274 | }, |
| 269 | }; | 275 | }; |
| 270 | 276 | ||
diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c index d1297ba19daf..5f29e5b8e1c1 100644 --- a/drivers/input/touchscreen/touchit213.c +++ b/drivers/input/touchscreen/touchit213.c | |||
| @@ -216,19 +216,4 @@ static struct serio_driver touchit213_drv = { | |||
| 216 | .disconnect = touchit213_disconnect, | 216 | .disconnect = touchit213_disconnect, |
| 217 | }; | 217 | }; |
| 218 | 218 | ||
| 219 | /* | 219 | module_serio_driver(touchit213_drv); |
| 220 | * The functions for inserting/removing us as a module. | ||
| 221 | */ | ||
| 222 | |||
| 223 | static int __init touchit213_init(void) | ||
| 224 | { | ||
| 225 | return serio_register_driver(&touchit213_drv); | ||
| 226 | } | ||
| 227 | |||
| 228 | static void __exit touchit213_exit(void) | ||
| 229 | { | ||
| 230 | serio_unregister_driver(&touchit213_drv); | ||
| 231 | } | ||
| 232 | |||
| 233 | module_init(touchit213_init); | ||
| 234 | module_exit(touchit213_exit); | ||
diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c index 3a5c142c2a78..8a2887daf194 100644 --- a/drivers/input/touchscreen/touchright.c +++ b/drivers/input/touchscreen/touchright.c | |||
| @@ -176,19 +176,4 @@ static struct serio_driver tr_drv = { | |||
| 176 | .disconnect = tr_disconnect, | 176 | .disconnect = tr_disconnect, |
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | /* | 179 | module_serio_driver(tr_drv); |
| 180 | * The functions for inserting/removing us as a module. | ||
| 181 | */ | ||
| 182 | |||
| 183 | static int __init tr_init(void) | ||
| 184 | { | ||
| 185 | return serio_register_driver(&tr_drv); | ||
| 186 | } | ||
| 187 | |||
| 188 | static void __exit tr_exit(void) | ||
| 189 | { | ||
| 190 | serio_unregister_driver(&tr_drv); | ||
| 191 | } | ||
| 192 | |||
| 193 | module_init(tr_init); | ||
| 194 | module_exit(tr_exit); | ||
diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c index 763a656a59f8..588cdcb839dd 100644 --- a/drivers/input/touchscreen/touchwin.c +++ b/drivers/input/touchscreen/touchwin.c | |||
| @@ -183,19 +183,4 @@ static struct serio_driver tw_drv = { | |||
| 183 | .disconnect = tw_disconnect, | 183 | .disconnect = tw_disconnect, |
| 184 | }; | 184 | }; |
| 185 | 185 | ||
| 186 | /* | 186 | module_serio_driver(tw_drv); |
| 187 | * The functions for inserting/removing us as a module. | ||
| 188 | */ | ||
| 189 | |||
| 190 | static int __init tw_init(void) | ||
| 191 | { | ||
| 192 | return serio_register_driver(&tw_drv); | ||
| 193 | } | ||
| 194 | |||
| 195 | static void __exit tw_exit(void) | ||
| 196 | { | ||
| 197 | serio_unregister_driver(&tw_drv); | ||
| 198 | } | ||
| 199 | |||
| 200 | module_init(tw_init); | ||
| 201 | module_exit(tw_exit); | ||
diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 29d5ed4dd31c..63209aaa55f0 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c | |||
| @@ -167,17 +167,7 @@ static struct serio_driver tsc_drv = { | |||
| 167 | .disconnect = tsc_disconnect, | 167 | .disconnect = tsc_disconnect, |
| 168 | }; | 168 | }; |
| 169 | 169 | ||
| 170 | static int __init tsc_ser_init(void) | 170 | module_serio_driver(tsc_drv); |
| 171 | { | ||
| 172 | return serio_register_driver(&tsc_drv); | ||
| 173 | } | ||
| 174 | module_init(tsc_ser_init); | ||
| 175 | |||
| 176 | static void __exit tsc_exit(void) | ||
| 177 | { | ||
| 178 | serio_unregister_driver(&tsc_drv); | ||
| 179 | } | ||
| 180 | module_exit(tsc_exit); | ||
| 181 | 171 | ||
| 182 | MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>"); | 172 | MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>"); |
| 183 | MODULE_DESCRIPTION(DRIVER_DESC); | 173 | MODULE_DESCRIPTION(DRIVER_DESC); |
diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c new file mode 100644 index 000000000000..35572575d34a --- /dev/null +++ b/drivers/input/touchscreen/wacom_i2c.c | |||
| @@ -0,0 +1,282 @@ | |||
| 1 | /* | ||
| 2 | * Wacom Penabled Driver for I2C | ||
| 3 | * | ||
| 4 | * Copyright (c) 2011 Tatsunosuke Tobita, Wacom. | ||
| 5 | * <tobita.tatsunosuke@wacom.co.jp> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it | ||
| 8 | * and/or modify it under the terms of the GNU General | ||
| 9 | * Public License as published by the Free Software | ||
| 10 | * Foundation; either version of 2 of the License, | ||
| 11 | * or (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/input.h> | ||
| 16 | #include <linux/i2c.h> | ||
| 17 | #include <linux/slab.h> | ||
| 18 | #include <linux/irq.h> | ||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/gpio.h> | ||
| 21 | #include <asm/unaligned.h> | ||
| 22 | |||
| 23 | #define WACOM_CMD_QUERY0 0x04 | ||
| 24 | #define WACOM_CMD_QUERY1 0x00 | ||
| 25 | #define WACOM_CMD_QUERY2 0x33 | ||
| 26 | #define WACOM_CMD_QUERY3 0x02 | ||
| 27 | #define WACOM_CMD_THROW0 0x05 | ||
| 28 | #define WACOM_CMD_THROW1 0x00 | ||
| 29 | #define WACOM_QUERY_SIZE 19 | ||
| 30 | #define WACOM_RETRY_CNT 100 | ||
| 31 | |||
| 32 | struct wacom_features { | ||
| 33 | int x_max; | ||
| 34 | int y_max; | ||
| 35 | int pressure_max; | ||
| 36 | char fw_version; | ||
| 37 | }; | ||
| 38 | |||
| 39 | struct wacom_i2c { | ||
| 40 | struct i2c_client *client; | ||
| 41 | struct input_dev *input; | ||
| 42 | u8 data[WACOM_QUERY_SIZE]; | ||
| 43 | }; | ||
| 44 | |||
| 45 | static int wacom_query_device(struct i2c_client *client, | ||
| 46 | struct wacom_features *features) | ||
| 47 | { | ||
| 48 | int ret; | ||
| 49 | u8 cmd1[] = { WACOM_CMD_QUERY0, WACOM_CMD_QUERY1, | ||
| 50 | WACOM_CMD_QUERY2, WACOM_CMD_QUERY3 }; | ||
| 51 | u8 cmd2[] = { WACOM_CMD_THROW0, WACOM_CMD_THROW1 }; | ||
| 52 | u8 data[WACOM_QUERY_SIZE]; | ||
| 53 | struct i2c_msg msgs[] = { | ||
| 54 | { | ||
| 55 | .addr = client->addr, | ||
| 56 | .flags = 0, | ||
| 57 | .len = sizeof(cmd1), | ||
| 58 | .buf = cmd1, | ||
| 59 | }, | ||
| 60 | { | ||
| 61 | .addr = client->addr, | ||
| 62 | .flags = 0, | ||
| 63 | .len = sizeof(cmd2), | ||
| 64 | .buf = cmd2, | ||
| 65 | }, | ||
| 66 | { | ||
| 67 | .addr = client->addr, | ||
| 68 | .flags = I2C_M_RD, | ||
| 69 | .len = sizeof(data), | ||
| 70 | .buf = data, | ||
| 71 | }, | ||
| 72 | }; | ||
| 73 | |||
| 74 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
| 75 | if (ret < 0) | ||
| 76 | return ret; | ||
| 77 | if (ret != ARRAY_SIZE(msgs)) | ||
| 78 | return -EIO; | ||
| 79 | |||
| 80 | features->x_max = get_unaligned_le16(&data[3]); | ||
| 81 | features->y_max = get_unaligned_le16(&data[5]); | ||
| 82 | features->pressure_max = get_unaligned_le16(&data[11]); | ||
| 83 | features->fw_version = get_unaligned_le16(&data[13]); | ||
| 84 | |||
| 85 | dev_dbg(&client->dev, | ||
| 86 | "x_max:%d, y_max:%d, pressure:%d, fw:%d\n", | ||
| 87 | features->x_max, features->y_max, | ||
| 88 | features->pressure_max, features->fw_version); | ||
| 89 | |||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | static irqreturn_t wacom_i2c_irq(int irq, void *dev_id) | ||
| 94 | { | ||
| 95 | struct wacom_i2c *wac_i2c = dev_id; | ||
| 96 | struct input_dev *input = wac_i2c->input; | ||
| 97 | u8 *data = wac_i2c->data; | ||
| 98 | unsigned int x, y, pressure; | ||
| 99 | unsigned char tsw, f1, f2, ers; | ||
| 100 | int error; | ||
| 101 | |||
| 102 | error = i2c_master_recv(wac_i2c->client, | ||
| 103 | wac_i2c->data, sizeof(wac_i2c->data)); | ||
| 104 | if (error < 0) | ||
| 105 | goto out; | ||
| 106 | |||
| 107 | tsw = data[3] & 0x01; | ||
| 108 | ers = data[3] & 0x04; | ||
| 109 | f1 = data[3] & 0x02; | ||
| 110 | f2 = data[3] & 0x10; | ||
| 111 | x = le16_to_cpup((__le16 *)&data[4]); | ||
| 112 | y = le16_to_cpup((__le16 *)&data[6]); | ||
| 113 | pressure = le16_to_cpup((__le16 *)&data[8]); | ||
| 114 | |||
| 115 | input_report_key(input, BTN_TOUCH, tsw || ers); | ||
| 116 | input_report_key(input, BTN_TOOL_PEN, tsw); | ||
| 117 | input_report_key(input, BTN_TOOL_RUBBER, ers); | ||
| 118 | input_report_key(input, BTN_STYLUS, f1); | ||
| 119 | input_report_key(input, BTN_STYLUS2, f2); | ||
| 120 | input_report_abs(input, ABS_X, x); | ||
| 121 | input_report_abs(input, ABS_Y, y); | ||
| 122 | input_report_abs(input, ABS_PRESSURE, pressure); | ||
| 123 | input_sync(input); | ||
| 124 | |||
| 125 | out: | ||
| 126 | return IRQ_HANDLED; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int wacom_i2c_open(struct input_dev *dev) | ||
| 130 | { | ||
| 131 | struct wacom_i2c *wac_i2c = input_get_drvdata(dev); | ||
| 132 | struct i2c_client *client = wac_i2c->client; | ||
| 133 | |||
| 134 | enable_irq(client->irq); | ||
| 135 | |||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static void wacom_i2c_close(struct input_dev *dev) | ||
| 140 | { | ||
| 141 | struct wacom_i2c *wac_i2c = input_get_drvdata(dev); | ||
| 142 | struct i2c_client *client = wac_i2c->client; | ||
| 143 | |||
| 144 | disable_irq(client->irq); | ||
| 145 | } | ||
| 146 | |||
| 147 | static int __devinit wacom_i2c_probe(struct i2c_client *client, | ||
| 148 | const struct i2c_device_id *id) | ||
| 149 | { | ||
| 150 | struct wacom_i2c *wac_i2c; | ||
| 151 | struct input_dev *input; | ||
| 152 | struct wacom_features features; | ||
| 153 | int error; | ||
| 154 | |||
| 155 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
| 156 | dev_err(&client->dev, "i2c_check_functionality error\n"); | ||
| 157 | return -EIO; | ||
| 158 | } | ||
| 159 | |||
| 160 | error = wacom_query_device(client, &features); | ||
| 161 | if (error) | ||
| 162 | return error; | ||
| 163 | |||
| 164 | wac_i2c = kzalloc(sizeof(*wac_i2c), GFP_KERNEL); | ||
| 165 | input = input_allocate_device(); | ||
| 166 | if (!wac_i2c || !input) { | ||
| 167 | error = -ENOMEM; | ||
| 168 | goto err_free_mem; | ||
| 169 | } | ||
| 170 | |||
| 171 | wac_i2c->client = client; | ||
| 172 | wac_i2c->input = input; | ||
| 173 | |||
| 174 | input->name = "Wacom I2C Digitizer"; | ||
| 175 | input->id.bustype = BUS_I2C; | ||
| 176 | input->id.vendor = 0x56a; | ||
| 177 | input->id.version = features.fw_version; | ||
| 178 | input->dev.parent = &client->dev; | ||
| 179 | input->open = wacom_i2c_open; | ||
| 180 | input->close = wacom_i2c_close; | ||
| 181 | |||
| 182 | input->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 183 | |||
| 184 | __set_bit(BTN_TOOL_PEN, input->keybit); | ||
| 185 | __set_bit(BTN_TOOL_RUBBER, input->keybit); | ||
| 186 | __set_bit(BTN_STYLUS, input->keybit); | ||
| 187 | __set_bit(BTN_STYLUS2, input->keybit); | ||
| 188 | __set_bit(BTN_TOUCH, input->keybit); | ||
| 189 | |||
| 190 | input_set_abs_params(input, ABS_X, 0, features.x_max, 0, 0); | ||
| 191 | input_set_abs_params(input, ABS_Y, 0, features.y_max, 0, 0); | ||
| 192 | input_set_abs_params(input, ABS_PRESSURE, | ||
| 193 | 0, features.pressure_max, 0, 0); | ||
| 194 | |||
| 195 | input_set_drvdata(input, wac_i2c); | ||
| 196 | |||
| 197 | error = request_threaded_irq(client->irq, NULL, wacom_i2c_irq, | ||
| 198 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
| 199 | "wacom_i2c", wac_i2c); | ||
| 200 | if (error) { | ||
| 201 | dev_err(&client->dev, | ||
| 202 | "Failed to enable IRQ, error: %d\n", error); | ||
| 203 | goto err_free_mem; | ||
| 204 | } | ||
| 205 | |||
| 206 | /* Disable the IRQ, we'll enable it in wac_i2c_open() */ | ||
| 207 | disable_irq(client->irq); | ||
| 208 | |||
| 209 | error = input_register_device(wac_i2c->input); | ||
| 210 | if (error) { | ||
| 211 | dev_err(&client->dev, | ||
| 212 | "Failed to register input device, error: %d\n", error); | ||
| 213 | goto err_free_irq; | ||
| 214 | } | ||
| 215 | |||
| 216 | i2c_set_clientdata(client, wac_i2c); | ||
| 217 | return 0; | ||
| 218 | |||
| 219 | err_free_irq: | ||
| 220 | free_irq(client->irq, wac_i2c); | ||
| 221 | err_free_mem: | ||
| 222 | input_free_device(input); | ||
| 223 | kfree(wac_i2c); | ||
| 224 | |||
| 225 | return error; | ||
| 226 | } | ||
| 227 | |||
| 228 | static int __devexit wacom_i2c_remove(struct i2c_client *client) | ||
| 229 | { | ||
| 230 | struct wacom_i2c *wac_i2c = i2c_get_clientdata(client); | ||
| 231 | |||
| 232 | free_irq(client->irq, wac_i2c); | ||
| 233 | input_unregister_device(wac_i2c->input); | ||
| 234 | kfree(wac_i2c); | ||
| 235 | |||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | |||
| 239 | #ifdef CONFIG_PM_SLEEP | ||
| 240 | static int wacom_i2c_suspend(struct device *dev) | ||
| 241 | { | ||
| 242 | struct i2c_client *client = to_i2c_client(dev); | ||
| 243 | |||
| 244 | disable_irq(client->irq); | ||
| 245 | |||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | |||
| 249 | static int wacom_i2c_resume(struct device *dev) | ||
| 250 | { | ||
| 251 | struct i2c_client *client = to_i2c_client(dev); | ||
| 252 | |||
| 253 | enable_irq(client->irq); | ||
| 254 | |||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | #endif | ||
| 258 | |||
| 259 | static SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume); | ||
| 260 | |||
| 261 | static const struct i2c_device_id wacom_i2c_id[] = { | ||
| 262 | { "WAC_I2C_EMR", 0 }, | ||
| 263 | { }, | ||
| 264 | }; | ||
| 265 | MODULE_DEVICE_TABLE(i2c, wacom_i2c_id); | ||
| 266 | |||
| 267 | static struct i2c_driver wacom_i2c_driver = { | ||
| 268 | .driver = { | ||
| 269 | .name = "wacom_i2c", | ||
| 270 | .owner = THIS_MODULE, | ||
| 271 | .pm = &wacom_i2c_pm, | ||
| 272 | }, | ||
| 273 | |||
| 274 | .probe = wacom_i2c_probe, | ||
| 275 | .remove = __devexit_p(wacom_i2c_remove), | ||
| 276 | .id_table = wacom_i2c_id, | ||
| 277 | }; | ||
| 278 | module_i2c_driver(wacom_i2c_driver); | ||
| 279 | |||
| 280 | MODULE_AUTHOR("Tatsunosuke Tobita <tobita.tatsunosuke@wacom.co.jp>"); | ||
| 281 | MODULE_DESCRIPTION("WACOM EMR I2C Driver"); | ||
| 282 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 1569a3934ab2..8f9ad2f893b8 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c | |||
| @@ -594,15 +594,4 @@ static struct serio_driver w8001_drv = { | |||
| 594 | .disconnect = w8001_disconnect, | 594 | .disconnect = w8001_disconnect, |
| 595 | }; | 595 | }; |
| 596 | 596 | ||
| 597 | static int __init w8001_init(void) | 597 | module_serio_driver(w8001_drv); |
| 598 | { | ||
| 599 | return serio_register_driver(&w8001_drv); | ||
| 600 | } | ||
| 601 | |||
| 602 | static void __exit w8001_exit(void) | ||
| 603 | { | ||
| 604 | serio_unregister_driver(&w8001_drv); | ||
| 605 | } | ||
| 606 | |||
| 607 | module_init(w8001_init); | ||
| 608 | module_exit(w8001_exit); | ||
