aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/panasonic-laptop.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2010-08-05 01:30:02 -0400
committerMatthew Garrett <mjg@redhat.com>2010-10-21 09:36:42 -0400
commit1a765cac9a241380511a3b1dd4edf74a41cbfdf9 (patch)
tree8750624e54e162082abb379170bf54197d99d2b7 /drivers/platform/x86/panasonic-laptop.c
parent97490f1cf82cccf2e088aafffb0517802f0ee336 (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/panasonic-laptop.c')
-rw-r--r--drivers/platform/x86/panasonic-laptop.c172
1 files changed, 61 insertions, 111 deletions
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 204static const struct key_entry panasonic_keymap[] = {
204static 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
218struct pcc_acpi { 219struct 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
229struct pcc_keyinput { 229struct 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
449static 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
462static 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
474static 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
494static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) 449static 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
532static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) 471static 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
546static int acpi_pcc_init_input(struct pcc_acpi *pcc) 485static 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; 528static 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
670out_backlight: 624out_backlight:
671 backlight_device_unregister(pcc->backlight); 625 backlight_device_unregister(pcc->backlight);
626out_input:
627 acpi_pcc_destroy_input(pcc);
672out_sinf: 628out_sinf:
673 kfree(pcc->sinf); 629 kfree(pcc->sinf);
674out_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 */
678out_hotkey: 630out_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);