aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/fujitsu-laptop.c
diff options
context:
space:
mode:
authorJonathan Woithe <jwoithe@physics.adelaide.edu.au>2008-10-09 00:14:40 -0400
committerLen Brown <len.brown@intel.com>2008-10-10 16:25:49 -0400
commit0e6a66e9cf231140d2e49064d48162728edb7746 (patch)
treea838717e4646157201d61c1f00e5109f0228265d /drivers/misc/fujitsu-laptop.c
parent3fa8749e584b55f1180411ab1b51117190bac1e5 (diff)
fujitsu-laptop: better handling of P8010 hotkey
This patch (mostly from Peter Gruber) improves the handling of the hotkeys for P8010 laptops by passing more accurate input events back to userspace. This is needed because the P8010 labels these buttons quite differently to earlier laptops. As part of this, a P8010-specific DMI callback check has been implemented. Finally there's some minor whitespace cleanups from running the source through Lindent. Signed-off-by: Peter Gruber <nokos@gmx.net> Signed-off-by: Jonathan Woithe <jwoithe@physics.adelaide.edu.au> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/misc/fujitsu-laptop.c')
-rw-r--r--drivers/misc/fujitsu-laptop.c123
1 files changed, 71 insertions, 52 deletions
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
index 3e56203e4947..f861db072777 100644
--- a/drivers/misc/fujitsu-laptop.c
+++ b/drivers/misc/fujitsu-laptop.c
@@ -44,8 +44,9 @@
44 * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are 44 * Hotkeys present on certain Fujitsu laptops (eg: the S6xxx series) are
45 * also supported by this driver. 45 * also supported by this driver.
46 * 46 *
47 * This driver has been tested on a Fujitsu Lifebook S6410 and S7020. It 47 * This driver has been tested on a Fujitsu Lifebook S6410, S7020 and
48 * should work on most P-series and S-series Lifebooks, but YMMV. 48 * P8010. It should work on most P-series and S-series Lifebooks, but
49 * YMMV.
49 * 50 *
50 * The module parameter use_alt_lcd_levels switches between different ACPI 51 * The module parameter use_alt_lcd_levels switches between different ACPI
51 * brightness controls which are used by different Fujitsu laptops. In most 52 * brightness controls which are used by different Fujitsu laptops. In most
@@ -65,7 +66,7 @@
65#include <linux/video_output.h> 66#include <linux/video_output.h>
66#include <linux/platform_device.h> 67#include <linux/platform_device.h>
67 68
68#define FUJITSU_DRIVER_VERSION "0.4.2" 69#define FUJITSU_DRIVER_VERSION "0.4.3"
69 70
70#define FUJITSU_LCD_N_LEVELS 8 71#define FUJITSU_LCD_N_LEVELS 8
71 72
@@ -83,10 +84,10 @@
83#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 84#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87
84 85
85/* Hotkey details */ 86/* Hotkey details */
86#define LOCK_KEY 0x410 /* codes for the keys in the GIRB register */ 87#define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */
87#define DISPLAY_KEY 0x411 /* keys are mapped to KEY_SCREENLOCK (the key with the key symbol) */ 88#define KEY2_CODE 0x411
88#define ENERGY_KEY 0x412 /* KEY_MEDIA (the key with the laptop symbol, KEY_EMAIL (E key)) */ 89#define KEY3_CODE 0x412
89#define REST_KEY 0x413 /* KEY_SUSPEND (R key) */ 90#define KEY4_CODE 0x413
90 91
91#define MAX_HOTKEY_RINGBUFFER_SIZE 100 92#define MAX_HOTKEY_RINGBUFFER_SIZE 100
92#define RINGBUFFERSIZE 40 93#define RINGBUFFERSIZE 40
@@ -123,6 +124,7 @@ struct fujitsu_t {
123 char phys[32]; 124 char phys[32];
124 struct backlight_device *bl_device; 125 struct backlight_device *bl_device;
125 struct platform_device *pf_device; 126 struct platform_device *pf_device;
127 int keycode1, keycode2, keycode3, keycode4;
126 128
127 unsigned int max_brightness; 129 unsigned int max_brightness;
128 unsigned int brightness_changed; 130 unsigned int brightness_changed;
@@ -430,7 +432,7 @@ static struct platform_driver fujitsupf_driver = {
430 } 432 }
431}; 433};
432 434
433static int dmi_check_cb_s6410(const struct dmi_system_id *id) 435static void dmi_check_cb_common(const struct dmi_system_id *id)
434{ 436{
435 acpi_handle handle; 437 acpi_handle handle;
436 int have_blnf; 438 int have_blnf;
@@ -452,24 +454,40 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id)
452 "auto-detecting disable_adjust\n"); 454 "auto-detecting disable_adjust\n");
453 disable_brightness_adjust = have_blnf ? 0 : 1; 455 disable_brightness_adjust = have_blnf ? 0 : 1;
454 } 456 }
457}
458
459static int dmi_check_cb_s6410(const struct dmi_system_id *id)
460{
461 dmi_check_cb_common(id);
462 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */
463 fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */
464 return 0;
465}
466
467static int dmi_check_cb_p8010(const struct dmi_system_id *id)
468{
469 dmi_check_cb_common(id);
470 fujitsu->keycode1 = KEY_HELP; /* "Support" */
471 fujitsu->keycode3 = KEY_SWITCHVIDEOMODE; /* "Presentation" */
472 fujitsu->keycode4 = KEY_WWW; /* "Internet" */
455 return 0; 473 return 0;
456} 474}
457 475
458static struct dmi_system_id __initdata fujitsu_dmi_table[] = { 476static struct dmi_system_id __initdata fujitsu_dmi_table[] = {
459 { 477 {
460 .ident = "Fujitsu Siemens", 478 .ident = "Fujitsu Siemens S6410",
461 .matches = { 479 .matches = {
462 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), 480 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
463 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"), 481 DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"),
464 }, 482 },
465 .callback = dmi_check_cb_s6410}, 483 .callback = dmi_check_cb_s6410},
466 { 484 {
467 .ident = "FUJITSU LifeBook P8010", 485 .ident = "Fujitsu LifeBook P8010",
468 .matches = { 486 .matches = {
469 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), 487 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
470 DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"), 488 DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P8010"),
471 }, 489 },
472 .callback = dmi_check_cb_s6410}, 490 .callback = dmi_check_cb_p8010},
473 {} 491 {}
474}; 492};
475 493
@@ -547,7 +565,6 @@ static int acpi_fujitsu_add(struct acpi_device *device)
547 } 565 }
548 566
549 /* do config (detect defaults) */ 567 /* do config (detect defaults) */
550 dmi_check_system(fujitsu_dmi_table);
551 use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0; 568 use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0;
552 disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0; 569 disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0;
553 disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0; 570 disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0;
@@ -623,17 +640,17 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
623 keycode = 0; 640 keycode = 0;
624 if (disable_brightness_keys != 1) { 641 if (disable_brightness_keys != 1) {
625 if (oldb == 0) { 642 if (oldb == 0) {
626 acpi_bus_generate_proc_event(fujitsu-> 643 acpi_bus_generate_proc_event
627 dev, 644 (fujitsu->dev,
628 ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 645 ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
629 0); 646 0);
630 keycode = KEY_BRIGHTNESSDOWN; 647 keycode = KEY_BRIGHTNESSDOWN;
631 } else if (oldb == 648 } else if (oldb ==
632 (fujitsu->max_brightness) - 1) { 649 (fujitsu->max_brightness) - 1) {
633 acpi_bus_generate_proc_event(fujitsu-> 650 acpi_bus_generate_proc_event
634 dev, 651 (fujitsu->dev,
635 ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 652 ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
636 0); 653 0);
637 keycode = KEY_BRIGHTNESSUP; 654 keycode = KEY_BRIGHTNESSUP;
638 } 655 }
639 } 656 }
@@ -646,8 +663,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
646 } 663 }
647 if (disable_brightness_keys != 1) { 664 if (disable_brightness_keys != 1) {
648 acpi_bus_generate_proc_event(fujitsu->dev, 665 acpi_bus_generate_proc_event(fujitsu->dev,
649 ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 666 ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0);
650 0);
651 keycode = KEY_BRIGHTNESSUP; 667 keycode = KEY_BRIGHTNESSUP;
652 } 668 }
653 } else if (oldb > newb) { 669 } else if (oldb > newb) {
@@ -659,8 +675,7 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
659 } 675 }
660 if (disable_brightness_keys != 1) { 676 if (disable_brightness_keys != 1) {
661 acpi_bus_generate_proc_event(fujitsu->dev, 677 acpi_bus_generate_proc_event(fujitsu->dev,
662 ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 678 ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0);
663 0);
664 keycode = KEY_BRIGHTNESSDOWN; 679 keycode = KEY_BRIGHTNESSDOWN;
665 } 680 }
666 } else { 681 } else {
@@ -742,10 +757,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
742 input->id.product = 0x06; 757 input->id.product = 0x06;
743 input->dev.parent = &device->dev; 758 input->dev.parent = &device->dev;
744 input->evbit[0] = BIT(EV_KEY); 759 input->evbit[0] = BIT(EV_KEY);
745 set_bit(KEY_SCREENLOCK, input->keybit); 760 set_bit(fujitsu->keycode1, input->keybit);
746 set_bit(KEY_MEDIA, input->keybit); 761 set_bit(fujitsu->keycode2, input->keybit);
747 set_bit(KEY_EMAIL, input->keybit); 762 set_bit(fujitsu->keycode3, input->keybit);
748 set_bit(KEY_SUSPEND, input->keybit); 763 set_bit(fujitsu->keycode4, input->keybit);
749 set_bit(KEY_UNKNOWN, input->keybit); 764 set_bit(KEY_UNKNOWN, input->keybit);
750 765
751 error = input_register_device(input); 766 error = input_register_device(input);
@@ -833,24 +848,24 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
833 irb); 848 irb);
834 849
835 switch (irb & 0x4ff) { 850 switch (irb & 0x4ff) {
836 case LOCK_KEY: 851 case KEY1_CODE:
837 keycode = KEY_SCREENLOCK; 852 keycode = fujitsu->keycode1;
838 break; 853 break;
839 case DISPLAY_KEY: 854 case KEY2_CODE:
840 keycode = KEY_MEDIA; 855 keycode = fujitsu->keycode2;
841 break; 856 break;
842 case ENERGY_KEY: 857 case KEY3_CODE:
843 keycode = KEY_EMAIL; 858 keycode = fujitsu->keycode3;
844 break; 859 break;
845 case REST_KEY: 860 case KEY4_CODE:
846 keycode = KEY_SUSPEND; 861 keycode = fujitsu->keycode4;
847 break; 862 break;
848 case 0: 863 case 0:
849 keycode = 0; 864 keycode = 0;
850 break; 865 break;
851 default: 866 default:
852 vdbg_printk(FUJLAPTOP_DBG_WARN, 867 vdbg_printk(FUJLAPTOP_DBG_WARN,
853 "Unknown GIRB result [%x]\n", irb); 868 "Unknown GIRB result [%x]\n", irb);
854 keycode = -1; 869 keycode = -1;
855 break; 870 break;
856 } 871 }
@@ -859,12 +874,12 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
859 "Push keycode into ringbuffer [%d]\n", 874 "Push keycode into ringbuffer [%d]\n",
860 keycode); 875 keycode);
861 status = kfifo_put(fujitsu_hotkey->fifo, 876 status = kfifo_put(fujitsu_hotkey->fifo,
862 (unsigned char *)&keycode, 877 (unsigned char *)&keycode,
863 sizeof(keycode)); 878 sizeof(keycode));
864 if (status != sizeof(keycode)) { 879 if (status != sizeof(keycode)) {
865 vdbg_printk(FUJLAPTOP_DBG_WARN, 880 vdbg_printk(FUJLAPTOP_DBG_WARN,
866 "Could not push keycode [0x%x]\n", 881 "Could not push keycode [0x%x]\n",
867 keycode); 882 keycode);
868 } else { 883 } else {
869 input_report_key(input, keycode, 1); 884 input_report_key(input, keycode, 1);
870 input_sync(input); 885 input_sync(input);
@@ -879,8 +894,8 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
879 input_report_key(input, keycode_r, 0); 894 input_report_key(input, keycode_r, 0);
880 input_sync(input); 895 input_sync(input);
881 vdbg_printk(FUJLAPTOP_DBG_TRACE, 896 vdbg_printk(FUJLAPTOP_DBG_TRACE,
882 "Pop keycode from ringbuffer [%d]\n", 897 "Pop keycode from ringbuffer [%d]\n",
883 keycode_r); 898 keycode_r);
884 } 899 }
885 } 900 }
886 } 901 }
@@ -943,6 +958,11 @@ static int __init fujitsu_init(void)
943 if (!fujitsu) 958 if (!fujitsu)
944 return -ENOMEM; 959 return -ENOMEM;
945 memset(fujitsu, 0, sizeof(struct fujitsu_t)); 960 memset(fujitsu, 0, sizeof(struct fujitsu_t));
961 fujitsu->keycode1 = KEY_PROG1;
962 fujitsu->keycode2 = KEY_PROG2;
963 fujitsu->keycode3 = KEY_PROG3;
964 fujitsu->keycode4 = KEY_PROG4;
965 dmi_check_system(fujitsu_dmi_table);
946 966
947 result = acpi_bus_register_driver(&acpi_fujitsu_driver); 967 result = acpi_bus_register_driver(&acpi_fujitsu_driver);
948 if (result < 0) { 968 if (result < 0) {
@@ -1076,15 +1096,14 @@ MODULE_DESCRIPTION("Fujitsu laptop extras support");
1076MODULE_VERSION(FUJITSU_DRIVER_VERSION); 1096MODULE_VERSION(FUJITSU_DRIVER_VERSION);
1077MODULE_LICENSE("GPL"); 1097MODULE_LICENSE("GPL");
1078 1098
1079MODULE_ALIAS 1099MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
1080 ("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); 1100MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
1081MODULE_ALIAS
1082 ("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
1083 1101
1084static struct pnp_device_id pnp_ids[] = { 1102static struct pnp_device_id pnp_ids[] = {
1085 { .id = "FUJ02bf" }, 1103 {.id = "FUJ02bf"},
1086 { .id = "FUJ02B1" }, 1104 {.id = "FUJ02B1"},
1087 { .id = "FUJ02E3" }, 1105 {.id = "FUJ02E3"},
1088 { .id = "" } 1106 {.id = ""}
1089}; 1107};
1108
1090MODULE_DEVICE_TABLE(pnp, pnp_ids); 1109MODULE_DEVICE_TABLE(pnp, pnp_ids);