diff options
Diffstat (limited to 'drivers/platform/x86/panasonic-laptop.c')
-rw-r--r-- | drivers/platform/x86/panasonic-laptop.c | 194 |
1 files changed, 73 insertions, 121 deletions
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index ec01c3d8fc5a..cc1e0ba104d7 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 { |
@@ -267,7 +267,7 @@ static inline int acpi_pcc_get_sqty(struct acpi_device *device) | |||
267 | } | 267 | } |
268 | } | 268 | } |
269 | 269 | ||
270 | static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf) | 270 | static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc) |
271 | { | 271 | { |
272 | acpi_status status; | 272 | acpi_status status; |
273 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 273 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
@@ -285,6 +285,7 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf) | |||
285 | hkey = buffer.pointer; | 285 | hkey = buffer.pointer; |
286 | if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) { | 286 | if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) { |
287 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n")); | 287 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n")); |
288 | status = AE_ERROR; | ||
288 | goto end; | 289 | goto end; |
289 | } | 290 | } |
290 | 291 | ||
@@ -298,12 +299,12 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf) | |||
298 | for (i = 0; i < hkey->package.count; i++) { | 299 | for (i = 0; i < hkey->package.count; i++) { |
299 | union acpi_object *element = &(hkey->package.elements[i]); | 300 | union acpi_object *element = &(hkey->package.elements[i]); |
300 | if (likely(element->type == ACPI_TYPE_INTEGER)) { | 301 | if (likely(element->type == ACPI_TYPE_INTEGER)) { |
301 | sinf[i] = element->integer.value; | 302 | pcc->sinf[i] = element->integer.value; |
302 | } else | 303 | } else |
303 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 304 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
304 | "Invalid HKEY.SINF data\n")); | 305 | "Invalid HKEY.SINF data\n")); |
305 | } | 306 | } |
306 | sinf[hkey->package.count] = -1; | 307 | pcc->sinf[hkey->package.count] = -1; |
307 | 308 | ||
308 | end: | 309 | end: |
309 | kfree(buffer.pointer); | 310 | kfree(buffer.pointer); |
@@ -321,7 +322,7 @@ static int bl_get(struct backlight_device *bd) | |||
321 | { | 322 | { |
322 | struct pcc_acpi *pcc = bl_get_data(bd); | 323 | struct pcc_acpi *pcc = bl_get_data(bd); |
323 | 324 | ||
324 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | 325 | if (!acpi_pcc_retrieve_biosdata(pcc)) |
325 | return -EIO; | 326 | return -EIO; |
326 | 327 | ||
327 | return pcc->sinf[SINF_AC_CUR_BRIGHT]; | 328 | return pcc->sinf[SINF_AC_CUR_BRIGHT]; |
@@ -333,7 +334,7 @@ static int bl_set_status(struct backlight_device *bd) | |||
333 | int bright = bd->props.brightness; | 334 | int bright = bd->props.brightness; |
334 | int rc; | 335 | int rc; |
335 | 336 | ||
336 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | 337 | if (!acpi_pcc_retrieve_biosdata(pcc)) |
337 | return -EIO; | 338 | return -EIO; |
338 | 339 | ||
339 | if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT]) | 340 | if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT]) |
@@ -367,7 +368,7 @@ static ssize_t show_numbatt(struct device *dev, struct device_attribute *attr, | |||
367 | struct acpi_device *acpi = to_acpi_device(dev); | 368 | struct acpi_device *acpi = to_acpi_device(dev); |
368 | struct pcc_acpi *pcc = acpi_driver_data(acpi); | 369 | struct pcc_acpi *pcc = acpi_driver_data(acpi); |
369 | 370 | ||
370 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | 371 | if (!acpi_pcc_retrieve_biosdata(pcc)) |
371 | return -EIO; | 372 | return -EIO; |
372 | 373 | ||
373 | return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]); | 374 | return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]); |
@@ -379,7 +380,7 @@ static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr, | |||
379 | struct acpi_device *acpi = to_acpi_device(dev); | 380 | struct acpi_device *acpi = to_acpi_device(dev); |
380 | struct pcc_acpi *pcc = acpi_driver_data(acpi); | 381 | struct pcc_acpi *pcc = acpi_driver_data(acpi); |
381 | 382 | ||
382 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | 383 | if (!acpi_pcc_retrieve_biosdata(pcc)) |
383 | return -EIO; | 384 | return -EIO; |
384 | 385 | ||
385 | return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_LCD_TYPE]); | 386 | return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_LCD_TYPE]); |
@@ -391,7 +392,7 @@ static ssize_t show_mute(struct device *dev, struct device_attribute *attr, | |||
391 | struct acpi_device *acpi = to_acpi_device(dev); | 392 | struct acpi_device *acpi = to_acpi_device(dev); |
392 | struct pcc_acpi *pcc = acpi_driver_data(acpi); | 393 | struct pcc_acpi *pcc = acpi_driver_data(acpi); |
393 | 394 | ||
394 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | 395 | if (!acpi_pcc_retrieve_biosdata(pcc)) |
395 | return -EIO; | 396 | return -EIO; |
396 | 397 | ||
397 | return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_MUTE]); | 398 | return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_MUTE]); |
@@ -403,7 +404,7 @@ static ssize_t show_sticky(struct device *dev, struct device_attribute *attr, | |||
403 | struct acpi_device *acpi = to_acpi_device(dev); | 404 | struct acpi_device *acpi = to_acpi_device(dev); |
404 | struct pcc_acpi *pcc = acpi_driver_data(acpi); | 405 | struct pcc_acpi *pcc = acpi_driver_data(acpi); |
405 | 406 | ||
406 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) | 407 | if (!acpi_pcc_retrieve_biosdata(pcc)) |
407 | return -EIO; | 408 | return -EIO; |
408 | 409 | ||
409 | return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_STICKY_KEY]); | 410 | return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_STICKY_KEY]); |
@@ -446,56 +447,10 @@ static struct attribute_group pcc_attr_group = { | |||
446 | 447 | ||
447 | /* hotkey input device driver */ | 448 | /* hotkey input device driver */ |
448 | 449 | ||
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) | 450 | static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) |
495 | { | 451 | { |
496 | struct input_dev *hotk_input_dev = pcc->input_dev; | 452 | struct input_dev *hotk_input_dev = pcc->input_dev; |
497 | int rc; | 453 | int rc; |
498 | int key_code, hkey_num; | ||
499 | unsigned long long result; | 454 | unsigned long long result; |
500 | 455 | ||
501 | rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY, | 456 | rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY, |
@@ -508,25 +463,10 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) | |||
508 | 463 | ||
509 | acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result); | 464 | acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result); |
510 | 465 | ||
511 | hkey_num = result & 0xf; | 466 | if (!sparse_keymap_report_event(hotk_input_dev, |
512 | 467 | result & 0xf, result & 0x80, false)) | |
513 | if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) { | ||
514 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 468 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
515 | "hotkey number out of range: %d\n", | 469 | "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 | } | 470 | } |
531 | 471 | ||
532 | static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) | 472 | static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) |
@@ -545,40 +485,55 @@ static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event) | |||
545 | 485 | ||
546 | static int acpi_pcc_init_input(struct pcc_acpi *pcc) | 486 | static int acpi_pcc_init_input(struct pcc_acpi *pcc) |
547 | { | 487 | { |
548 | int i, rc; | 488 | struct input_dev *input_dev; |
489 | int error; | ||
549 | 490 | ||
550 | pcc->input_dev = input_allocate_device(); | 491 | input_dev = input_allocate_device(); |
551 | if (!pcc->input_dev) { | 492 | if (!input_dev) { |
552 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 493 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
553 | "Couldn't allocate input device for hotkey")); | 494 | "Couldn't allocate input device for hotkey")); |
554 | return -ENOMEM; | 495 | return -ENOMEM; |
555 | } | 496 | } |
556 | 497 | ||
557 | pcc->input_dev->evbit[0] = BIT(EV_KEY); | 498 | input_dev->name = ACPI_PCC_DRIVER_NAME; |
558 | 499 | input_dev->phys = ACPI_PCC_INPUT_PHYS; | |
559 | pcc->input_dev->name = ACPI_PCC_DRIVER_NAME; | 500 | input_dev->id.bustype = BUS_HOST; |
560 | pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS; | 501 | input_dev->id.vendor = 0x0001; |
561 | pcc->input_dev->id.bustype = BUS_HOST; | 502 | input_dev->id.product = 0x0001; |
562 | pcc->input_dev->id.vendor = 0x0001; | 503 | 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 | 504 | ||
568 | /* load initial keymap */ | 505 | error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL); |
569 | memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap)); | 506 | if (error) { |
507 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | ||
508 | "Unable to setup input device keymap\n")); | ||
509 | goto err_free_dev; | ||
510 | } | ||
570 | 511 | ||
571 | for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) | 512 | error = input_register_device(input_dev); |
572 | __set_bit(pcc->keymap[i], pcc->input_dev->keybit); | 513 | if (error) { |
573 | __clear_bit(KEY_RESERVED, pcc->input_dev->keybit); | 514 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
515 | "Unable to register input device\n")); | ||
516 | goto err_free_keymap; | ||
517 | } | ||
574 | 518 | ||
575 | input_set_drvdata(pcc->input_dev, pcc); | 519 | pcc->input_dev = input_dev; |
520 | return 0; | ||
576 | 521 | ||
577 | rc = input_register_device(pcc->input_dev); | 522 | err_free_keymap: |
578 | if (rc < 0) | 523 | sparse_keymap_free(input_dev); |
579 | input_free_device(pcc->input_dev); | 524 | err_free_dev: |
525 | input_free_device(input_dev); | ||
526 | return error; | ||
527 | } | ||
580 | 528 | ||
581 | return rc; | 529 | static void acpi_pcc_destroy_input(struct pcc_acpi *pcc) |
530 | { | ||
531 | sparse_keymap_free(pcc->input_dev); | ||
532 | input_unregister_device(pcc->input_dev); | ||
533 | /* | ||
534 | * No need to input_free_device() since core input API refcounts | ||
535 | * and free()s the device. | ||
536 | */ | ||
582 | } | 537 | } |
583 | 538 | ||
584 | /* kernel module interface */ | 539 | /* kernel module interface */ |
@@ -636,12 +591,13 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) | |||
636 | if (result) { | 591 | if (result) { |
637 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 592 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
638 | "Error installing keyinput handler\n")); | 593 | "Error installing keyinput handler\n")); |
639 | goto out_hotkey; | 594 | goto out_sinf; |
640 | } | 595 | } |
641 | 596 | ||
642 | if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) { | 597 | if (!acpi_pcc_retrieve_biosdata(pcc)) { |
643 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 598 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
644 | "Couldn't retrieve BIOS data\n")); | 599 | "Couldn't retrieve BIOS data\n")); |
600 | result = -EIO; | ||
645 | goto out_input; | 601 | goto out_input; |
646 | } | 602 | } |
647 | /* initialize backlight */ | 603 | /* initialize backlight */ |
@@ -651,7 +607,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) | |||
651 | &pcc_backlight_ops, &props); | 607 | &pcc_backlight_ops, &props); |
652 | if (IS_ERR(pcc->backlight)) { | 608 | if (IS_ERR(pcc->backlight)) { |
653 | result = PTR_ERR(pcc->backlight); | 609 | result = PTR_ERR(pcc->backlight); |
654 | goto out_sinf; | 610 | goto out_input; |
655 | } | 611 | } |
656 | 612 | ||
657 | /* read the initial brightness setting from the hardware */ | 613 | /* read the initial brightness setting from the hardware */ |
@@ -669,12 +625,10 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device) | |||
669 | 625 | ||
670 | out_backlight: | 626 | out_backlight: |
671 | backlight_device_unregister(pcc->backlight); | 627 | backlight_device_unregister(pcc->backlight); |
628 | out_input: | ||
629 | acpi_pcc_destroy_input(pcc); | ||
672 | out_sinf: | 630 | out_sinf: |
673 | kfree(pcc->sinf); | 631 | 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: | 632 | out_hotkey: |
679 | kfree(pcc); | 633 | kfree(pcc); |
680 | 634 | ||
@@ -709,9 +663,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type) | |||
709 | 663 | ||
710 | backlight_device_unregister(pcc->backlight); | 664 | backlight_device_unregister(pcc->backlight); |
711 | 665 | ||
712 | input_unregister_device(pcc->input_dev); | 666 | acpi_pcc_destroy_input(pcc); |
713 | /* no need to input_free_device() since core input API refcount and | ||
714 | * free()s the device */ | ||
715 | 667 | ||
716 | kfree(pcc->sinf); | 668 | kfree(pcc->sinf); |
717 | kfree(pcc); | 669 | kfree(pcc); |