diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-08-05 01:30:02 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2010-10-21 09:36:42 -0400 |
commit | 1a765cac9a241380511a3b1dd4edf74a41cbfdf9 (patch) | |
tree | 8750624e54e162082abb379170bf54197d99d2b7 /drivers/platform/x86 | |
parent | 97490f1cf82cccf2e088aafffb0517802f0ee336 (diff) |
panasonic-laptop - switch to using sparse keymap library
nstead of implementing its own version of keymap hanlding switch over to
using sparse keymap library.
Cc: Harald Welte <laforge@gnumonks.org>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r-- | drivers/platform/x86/Kconfig | 1 | ||||
-rw-r--r-- | drivers/platform/x86/panasonic-laptop.c | 172 |
2 files changed, 62 insertions, 111 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 0b11b41a85f9..c0446d67cf7a 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -171,6 +171,7 @@ config PANASONIC_LAPTOP | |||
171 | tristate "Panasonic Laptop Extras" | 171 | tristate "Panasonic Laptop Extras" |
172 | depends on INPUT && ACPI | 172 | depends on INPUT && ACPI |
173 | depends on BACKLIGHT_CLASS_DEVICE | 173 | depends on BACKLIGHT_CLASS_DEVICE |
174 | select INPUT_SPARSEKMAP | ||
174 | ---help--- | 175 | ---help--- |
175 | This driver adds support for access to backlight control and hotkeys | 176 | This driver adds support for access to backlight control and hotkeys |
176 | on Panasonic Let's Note laptops. | 177 | on Panasonic Let's Note laptops. |
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index ec01c3d8fc5a..b3b9e0458ae1 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c | |||
@@ -128,6 +128,7 @@ | |||
128 | #include <acpi/acpi_bus.h> | 128 | #include <acpi/acpi_bus.h> |
129 | #include <acpi/acpi_drivers.h> | 129 | #include <acpi/acpi_drivers.h> |
130 | #include <linux/input.h> | 130 | #include <linux/input.h> |
131 | #include <linux/input/sparse-keymap.h> | ||
131 | 132 | ||
132 | 133 | ||
133 | #ifndef ACPI_HOTKEY_COMPONENT | 134 | #ifndef ACPI_HOTKEY_COMPONENT |
@@ -200,30 +201,29 @@ static struct acpi_driver acpi_pcc_driver = { | |||
200 | }, | 201 | }, |
201 | }; | 202 | }; |
202 | 203 | ||
203 | #define KEYMAP_SIZE 11 | 204 | static const struct key_entry panasonic_keymap[] = { |
204 | static const unsigned int initial_keymap[KEYMAP_SIZE] = { | 205 | { KE_KEY, 0, { KEY_RESERVED } }, |
205 | /* 0 */ KEY_RESERVED, | 206 | { KE_KEY, 1, { KEY_BRIGHTNESSDOWN } }, |
206 | /* 1 */ KEY_BRIGHTNESSDOWN, | 207 | { KE_KEY, 2, { KEY_BRIGHTNESSUP } }, |
207 | /* 2 */ KEY_BRIGHTNESSUP, | 208 | { KE_KEY, 3, { KEY_DISPLAYTOGGLE } }, |
208 | /* 3 */ KEY_DISPLAYTOGGLE, | 209 | { KE_KEY, 4, { KEY_MUTE } }, |
209 | /* 4 */ KEY_MUTE, | 210 | { KE_KEY, 5, { KEY_VOLUMEDOWN } }, |
210 | /* 5 */ KEY_VOLUMEDOWN, | 211 | { KE_KEY, 6, { KEY_VOLUMEUP } }, |
211 | /* 6 */ KEY_VOLUMEUP, | 212 | { KE_KEY, 7, { KEY_SLEEP } }, |
212 | /* 7 */ KEY_SLEEP, | 213 | { KE_KEY, 8, { KEY_PROG1 } }, /* Change CPU boost */ |
213 | /* 8 */ KEY_PROG1, /* Change CPU boost */ | 214 | { KE_KEY, 9, { KEY_BATTERY } }, |
214 | /* 9 */ KEY_BATTERY, | 215 | { KE_KEY, 10, { KEY_SUSPEND } }, |
215 | /* 10 */ KEY_SUSPEND, | 216 | { KE_END, 0 } |
216 | }; | 217 | }; |
217 | 218 | ||
218 | struct pcc_acpi { | 219 | struct pcc_acpi { |
219 | acpi_handle handle; | 220 | acpi_handle handle; |
220 | unsigned long num_sifr; | 221 | unsigned long num_sifr; |
221 | int sticky_mode; | 222 | int sticky_mode; |
222 | u32 *sinf; | 223 | u32 *sinf; |
223 | struct acpi_device *device; | 224 | struct acpi_device *device; |
224 | struct input_dev *input_dev; | 225 | struct input_dev *input_dev; |
225 | struct backlight_device *backlight; | 226 | struct backlight_device *backlight; |
226 | unsigned int keymap[KEYMAP_SIZE]; | ||
227 | }; | 227 | }; |
228 | 228 | ||
229 | struct pcc_keyinput { | 229 | struct pcc_keyinput { |
@@ -446,56 +446,10 @@ static struct attribute_group pcc_attr_group = { | |||
446 | 446 | ||
447 | /* hotkey input device driver */ | 447 | /* hotkey input device driver */ |
448 | 448 | ||
449 | static int pcc_getkeycode(struct input_dev *dev, | ||
450 | unsigned int scancode, unsigned int *keycode) | ||
451 | { | ||
452 | struct pcc_acpi *pcc = input_get_drvdata(dev); | ||
453 | |||
454 | if (scancode >= ARRAY_SIZE(pcc->keymap)) | ||
455 | return -EINVAL; | ||
456 | |||
457 | *keycode = pcc->keymap[scancode]; | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static int keymap_get_by_keycode(struct pcc_acpi *pcc, unsigned int keycode) | ||
463 | { | ||
464 | int i; | ||
465 | |||
466 | for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) { | ||
467 | if (pcc->keymap[i] == keycode) | ||
468 | return i+1; | ||
469 | } | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static int pcc_setkeycode(struct input_dev *dev, | ||
475 | unsigned int scancode, unsigned int keycode) | ||
476 | { | ||
477 | struct pcc_acpi *pcc = input_get_drvdata(dev); | ||
478 | int oldkeycode; | ||
479 | |||
480 | if (scancode >= ARRAY_SIZE(pcc->keymap)) | ||
481 | return -EINVAL; | ||
482 | |||
483 | oldkeycode = pcc->keymap[scancode]; | ||
484 | pcc->keymap[scancode] = keycode; | ||
485 | |||
486 | set_bit(keycode, dev->keybit); | ||
487 | |||
488 | if (!keymap_get_by_keycode(pcc, oldkeycode)) | ||
489 | clear_bit(oldkeycode, dev->keybit); | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) | 449 | static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) |
495 | { | 450 | { |
496 | struct input_dev *hotk_input_dev = pcc->input_dev; | 451 | struct input_dev *hotk_input_dev = pcc->input_dev; |
497 | int rc; | 452 | int rc; |
498 | int key_code, hkey_num; | ||
499 | unsigned long long result; | 453 | unsigned long long result; |
500 | 454 | ||
501 | rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY, | 455 | rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY, |
@@ -508,25 +462,10 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) | |||
508 | 462 | ||
509 | acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result); | 463 | acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result); |
510 | 464 | ||
511 | hkey_num = result & 0xf; | 465 | if (!sparse_keymap_report_event(hotk_input_dev, |
512 | 466 | result & 0xf, result & 0x80, false)) | |
513 | if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) { | ||
514 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 467 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
515 | "hotkey number out of range: %d\n", | 468 | "Unknown hotkey event: %d\n", result)); |
516 | hkey_num)); | ||
517 | return; | ||
518 | } | ||
519 | |||
520 | key_code = pcc->keymap[hkey_num]; | ||
521 | |||
522 | if (key_code != KEY_RESERVED) { | ||
523 | int pushed = (result & 0x80) ? TRUE : FALSE; | ||
524 | |||
525 | input_report_key(hotk_input_dev, key_code, pushed); | ||
526 | input_sync(hotk_input_dev); | ||
527 | } | ||
528 | |||
529 | return; | ||
530 | } | 469 | } |
531 | 470 | ||
532 | static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) | 471 | static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) |
@@ -545,40 +484,55 @@ static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) | |||
545 | 484 | ||
546 | static int acpi_pcc_init_input(struct pcc_acpi *pcc) | 485 | static int acpi_pcc_init_input(struct pcc_acpi *pcc) |
547 | { | 486 | { |
548 | int i, rc; | 487 | struct input_dev *input_dev; |
488 | int error; | ||
549 | 489 | ||
550 | pcc->input_dev = input_allocate_device(); | 490 | input_dev = input_allocate_device(); |
551 | if (!pcc->input_dev) { | 491 | if (!input_dev) { |
552 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 492 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
553 | "Couldn't allocate input device for hotkey")); | 493 | "Couldn't allocate input device for hotkey")); |
554 | return -ENOMEM; | 494 | return -ENOMEM; |
555 | } | 495 | } |
556 | 496 | ||
557 | pcc->input_dev->evbit[0] = BIT(EV_KEY); | 497 | input_dev->name = ACPI_PCC_DRIVER_NAME; |
558 | 498 | input_dev->phys = ACPI_PCC_INPUT_PHYS; | |
559 | pcc->input_dev->name = ACPI_PCC_DRIVER_NAME; | 499 | input_dev->id.bustype = BUS_HOST; |
560 | pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS; | 500 | input_dev->id.vendor = 0x0001; |
561 | pcc->input_dev->id.bustype = BUS_HOST; | 501 | input_dev->id.product = 0x0001; |
562 | pcc->input_dev->id.vendor = 0x0001; | 502 | input_dev->id.version = 0x0100; |
563 | pcc->input_dev->id.product = 0x0001; | ||
564 | pcc->input_dev->id.version = 0x0100; | ||
565 | pcc->input_dev->getkeycode = pcc_getkeycode; | ||
566 | pcc->input_dev->setkeycode = pcc_setkeycode; | ||
567 | 503 | ||
568 | /* load initial keymap */ | 504 | error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL); |
569 | memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap)); | 505 | if (error) { |
506 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
507 | "Unable to setup input device keymap\n")); | ||
508 | goto err_free_dev; | ||
509 | } | ||
570 | 510 | ||
571 | for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) | 511 | error = input_register_device(input_dev); |
572 | __set_bit(pcc->keymap[i], pcc->input_dev->keybit); | 512 | if (error) { |
573 | __clear_bit(KEY_RESERVED, pcc->input_dev->keybit); | 513 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
514 | "Unable to register input device\n")); | ||
515 | goto err_free_keymap; | ||
516 | } | ||
574 | 517 | ||
575 | input_set_drvdata(pcc->input_dev, pcc); | 518 | pcc->input_dev = input_dev; |
519 | return 0; | ||
576 | 520 | ||
577 | rc = input_register_device(pcc->input_dev); | 521 | err_free_keymap: |
578 | if (rc < 0) | 522 | sparse_keymap_free(input_dev); |
579 | input_free_device(pcc->input_dev); | 523 | err_free_dev: |
524 | input_free_device(input_dev); | ||
525 | return error; | ||
526 | } | ||
580 | 527 | ||
581 | return rc; | 528 | static void acpi_pcc_destroy_input(struct pcc_acpi *pcc) |
529 | { | ||
530 | sparse_keymap_free(pcc->input_dev); | ||
531 | input_unregister_device(pcc->input_dev); | ||
532 | /* | ||
533 | * No need to input_free_device() since core input API refcounts | ||
534 | * and free()s the device. | ||
535 | */ | ||
582 | } | 536 | } |
583 | 537 | ||
584 | /* kernel module interface */ | 538 | /* kernel module interface */ |
@@ -636,7 +590,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) | |||
636 | if (result) { | 590 | if (result) { |
637 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 591 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
638 | "Error installing keyinput handler\n")); | 592 | "Error installing keyinput handler\n")); |
639 | goto out_hotkey; | 593 | goto out_sinf; |
640 | } | 594 | } |
641 | 595 | ||
642 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) { | 596 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) { |
@@ -651,7 +605,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) | |||
651 | &pcc_backlight_ops, &props); | 605 | &pcc_backlight_ops, &props); |
652 | if (IS_ERR(pcc->backlight)) { | 606 | if (IS_ERR(pcc->backlight)) { |
653 | result = PTR_ERR(pcc->backlight); | 607 | result = PTR_ERR(pcc->backlight); |
654 | goto out_sinf; | 608 | goto out_input; |
655 | } | 609 | } |
656 | 610 | ||
657 | /* read the initial brightness setting from the hardware */ | 611 | /* read the initial brightness setting from the hardware */ |
@@ -669,12 +623,10 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) | |||
669 | 623 | ||
670 | out_backlight: | 624 | out_backlight: |
671 | backlight_device_unregister(pcc->backlight); | 625 | backlight_device_unregister(pcc->backlight); |
626 | out_input: | ||
627 | acpi_pcc_destroy_input(pcc); | ||
672 | out_sinf: | 628 | out_sinf: |
673 | kfree(pcc->sinf); | 629 | kfree(pcc->sinf); |
674 | out_input: | ||
675 | input_unregister_device(pcc->input_dev); | ||
676 | /* no need to input_free_device() since core input API refcount and | ||
677 | * free()s the device */ | ||
678 | out_hotkey: | 630 | out_hotkey: |
679 | kfree(pcc); | 631 | kfree(pcc); |
680 | 632 | ||
@@ -709,9 +661,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type) | |||
709 | 661 | ||
710 | backlight_device_unregister(pcc->backlight); | 662 | backlight_device_unregister(pcc->backlight); |
711 | 663 | ||
712 | input_unregister_device(pcc->input_dev); | 664 | acpi_pcc_destroy_input(pcc); |
713 | /* no need to input_free_device() since core input API refcount and | ||
714 | * free()s the device */ | ||
715 | 665 | ||
716 | kfree(pcc->sinf); | 666 | kfree(pcc->sinf); |
717 | kfree(pcc); | 667 | kfree(pcc); |