diff options
Diffstat (limited to 'drivers/misc/fujitsu-laptop.c')
-rw-r--r-- | drivers/misc/fujitsu-laptop.c | 135 |
1 files changed, 77 insertions, 58 deletions
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index 3e56203e4947..d2cf0bfe3163 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; |
@@ -224,7 +226,7 @@ static int set_lcd_level_alt(int level) | |||
224 | 226 | ||
225 | static int get_lcd_level(void) | 227 | static int get_lcd_level(void) |
226 | { | 228 | { |
227 | unsigned long state = 0; | 229 | unsigned long long state = 0; |
228 | acpi_status status = AE_OK; | 230 | acpi_status status = AE_OK; |
229 | 231 | ||
230 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n"); | 232 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLL\n"); |
@@ -246,7 +248,7 @@ static int get_lcd_level(void) | |||
246 | 248 | ||
247 | static int get_max_brightness(void) | 249 | static int get_max_brightness(void) |
248 | { | 250 | { |
249 | unsigned long state = 0; | 251 | unsigned long long state = 0; |
250 | acpi_status status = AE_OK; | 252 | acpi_status status = AE_OK; |
251 | 253 | ||
252 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n"); | 254 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get max lcd level via RBLL\n"); |
@@ -263,7 +265,7 @@ static int get_max_brightness(void) | |||
263 | 265 | ||
264 | static int get_lcd_level_alt(void) | 266 | static int get_lcd_level_alt(void) |
265 | { | 267 | { |
266 | unsigned long state = 0; | 268 | unsigned long long state = 0; |
267 | acpi_status status = AE_OK; | 269 | acpi_status status = AE_OK; |
268 | 270 | ||
269 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLS\n"); | 271 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLS\n"); |
@@ -384,7 +386,7 @@ static ssize_t store_lcd_level(struct device *dev, | |||
384 | 386 | ||
385 | static int get_irb(void) | 387 | static int get_irb(void) |
386 | { | 388 | { |
387 | unsigned long state = 0; | 389 | unsigned long long state = 0; |
388 | acpi_status status = AE_OK; | 390 | acpi_status status = AE_OK; |
389 | 391 | ||
390 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "Get irb\n"); | 392 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "Get irb\n"); |
@@ -430,7 +432,7 @@ static struct platform_driver fujitsupf_driver = { | |||
430 | } | 432 | } |
431 | }; | 433 | }; |
432 | 434 | ||
433 | static int dmi_check_cb_s6410(const struct dmi_system_id *id) | 435 | static 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 | |||
459 | static 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 | |||
467 | static 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 | ||
458 | static struct dmi_system_id __initdata fujitsu_dmi_table[] = { | 476 | static 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 | ||
@@ -490,7 +508,7 @@ static int acpi_fujitsu_add(struct acpi_device *device) | |||
490 | fujitsu->acpi_handle = device->handle; | 508 | fujitsu->acpi_handle = device->handle; |
491 | sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME); | 509 | sprintf(acpi_device_name(device), "%s", ACPI_FUJITSU_DEVICE_NAME); |
492 | sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); | 510 | sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); |
493 | acpi_driver_data(device) = fujitsu; | 511 | device->driver_data = fujitsu; |
494 | 512 | ||
495 | status = acpi_install_notify_handler(device->handle, | 513 | status = acpi_install_notify_handler(device->handle, |
496 | ACPI_DEVICE_NOTIFY, | 514 | ACPI_DEVICE_NOTIFY, |
@@ -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 { |
@@ -703,7 +718,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) | |||
703 | sprintf(acpi_device_name(device), "%s", | 718 | sprintf(acpi_device_name(device), "%s", |
704 | ACPI_FUJITSU_HOTKEY_DEVICE_NAME); | 719 | ACPI_FUJITSU_HOTKEY_DEVICE_NAME); |
705 | sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); | 720 | sprintf(acpi_device_class(device), "%s", ACPI_FUJITSU_CLASS); |
706 | acpi_driver_data(device) = fujitsu_hotkey; | 721 | device->driver_data = fujitsu_hotkey; |
707 | 722 | ||
708 | status = acpi_install_notify_handler(device->handle, | 723 | status = acpi_install_notify_handler(device->handle, |
709 | ACPI_DEVICE_NOTIFY, | 724 | ACPI_DEVICE_NOTIFY, |
@@ -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"); | |||
1076 | MODULE_VERSION(FUJITSU_DRIVER_VERSION); | 1096 | MODULE_VERSION(FUJITSU_DRIVER_VERSION); |
1077 | MODULE_LICENSE("GPL"); | 1097 | MODULE_LICENSE("GPL"); |
1078 | 1098 | ||
1079 | MODULE_ALIAS | 1099 | MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); |
1080 | ("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); | 1100 | MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); |
1081 | MODULE_ALIAS | ||
1082 | ("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); | ||
1083 | 1101 | ||
1084 | static struct pnp_device_id pnp_ids[] = { | 1102 | static 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 | |||
1090 | MODULE_DEVICE_TABLE(pnp, pnp_ids); | 1109 | MODULE_DEVICE_TABLE(pnp, pnp_ids); |