aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86
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
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')
-rw-r--r--drivers/platform/x86/Kconfig1
-rw-r--r--drivers/platform/x86/panasonic-laptop.c172
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 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);