diff options
| -rw-r--r-- | drivers/misc/fujitsu-laptop.c | 305 |
1 files changed, 272 insertions, 33 deletions
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index a7dd3e9fb79d..9c407ab9ba2b 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | /* | 3 | /* |
| 4 | Copyright (C) 2007,2008 Jonathan Woithe <jwoithe@physics.adelaide.edu.au> | 4 | Copyright (C) 2007,2008 Jonathan Woithe <jwoithe@physics.adelaide.edu.au> |
| 5 | Copyright (C) 2008 Peter Gruber <nokos@gmx.net> | 5 | Copyright (C) 2008 Peter Gruber <nokos@gmx.net> |
| 6 | Copyright (C) 2008 Tony Vroon <tony@linx.net> | ||
| 6 | Based on earlier work: | 7 | Based on earlier work: |
| 7 | Copyright (C) 2003 Shane Spencer <shane@bogomip.com> | 8 | Copyright (C) 2003 Shane Spencer <shane@bogomip.com> |
| 8 | Adrian Yee <brewt-fujitsu@brewt.org> | 9 | Adrian Yee <brewt-fujitsu@brewt.org> |
| @@ -65,8 +66,11 @@ | |||
| 65 | #include <linux/kfifo.h> | 66 | #include <linux/kfifo.h> |
| 66 | #include <linux/video_output.h> | 67 | #include <linux/video_output.h> |
| 67 | #include <linux/platform_device.h> | 68 | #include <linux/platform_device.h> |
| 69 | #ifdef CONFIG_LEDS_CLASS | ||
| 70 | #include <linux/leds.h> | ||
| 71 | #endif | ||
| 68 | 72 | ||
| 69 | #define FUJITSU_DRIVER_VERSION "0.4.3" | 73 | #define FUJITSU_DRIVER_VERSION "0.5.0" |
| 70 | 74 | ||
| 71 | #define FUJITSU_LCD_N_LEVELS 8 | 75 | #define FUJITSU_LCD_N_LEVELS 8 |
| 72 | 76 | ||
| @@ -83,6 +87,24 @@ | |||
| 83 | #define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86 | 87 | #define ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS 0x86 |
| 84 | #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 | 88 | #define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS 0x87 |
| 85 | 89 | ||
| 90 | /* FUNC interface - command values */ | ||
| 91 | #define FUNC_RFKILL 0x1000 | ||
| 92 | #define FUNC_LEDS 0x1001 | ||
| 93 | #define FUNC_BUTTONS 0x1002 | ||
| 94 | #define FUNC_BACKLIGHT 0x1004 | ||
| 95 | |||
| 96 | /* FUNC interface - responses */ | ||
| 97 | #define UNSUPPORTED_CMD 0x80000000 | ||
| 98 | |||
| 99 | #ifdef CONFIG_LEDS_CLASS | ||
| 100 | /* FUNC interface - LED control */ | ||
| 101 | #define FUNC_LED_OFF 0x1 | ||
| 102 | #define FUNC_LED_ON 0x30001 | ||
| 103 | #define KEYBOARD_LAMPS 0x100 | ||
| 104 | #define LOGOLAMP_POWERON 0x2000 | ||
| 105 | #define LOGOLAMP_ALWAYS 0x4000 | ||
| 106 | #endif | ||
| 107 | |||
| 86 | /* Hotkey details */ | 108 | /* Hotkey details */ |
| 87 | #define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */ | 109 | #define KEY1_CODE 0x410 /* codes for the keys in the GIRB register */ |
| 88 | #define KEY2_CODE 0x411 | 110 | #define KEY2_CODE 0x411 |
| @@ -145,8 +167,9 @@ struct fujitsu_hotkey_t { | |||
| 145 | struct platform_device *pf_device; | 167 | struct platform_device *pf_device; |
| 146 | struct kfifo *fifo; | 168 | struct kfifo *fifo; |
| 147 | spinlock_t fifo_lock; | 169 | spinlock_t fifo_lock; |
| 148 | 170 | int rfkill_state; | |
| 149 | unsigned int irb; /* info about the pressed buttons */ | 171 | int logolamp_registered; |
| 172 | int kblamps_registered; | ||
| 150 | }; | 173 | }; |
| 151 | 174 | ||
| 152 | static struct fujitsu_hotkey_t *fujitsu_hotkey; | 175 | static struct fujitsu_hotkey_t *fujitsu_hotkey; |
| @@ -154,12 +177,139 @@ static struct fujitsu_hotkey_t *fujitsu_hotkey; | |||
| 154 | static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, | 177 | static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, |
| 155 | void *data); | 178 | void *data); |
| 156 | 179 | ||
| 180 | #ifdef CONFIG_LEDS_CLASS | ||
| 181 | static enum led_brightness logolamp_get(struct led_classdev *cdev); | ||
| 182 | static void logolamp_set(struct led_classdev *cdev, | ||
| 183 | enum led_brightness brightness); | ||
| 184 | |||
| 185 | struct led_classdev logolamp_led = { | ||
| 186 | .name = "fujitsu::logolamp", | ||
| 187 | .brightness_get = logolamp_get, | ||
| 188 | .brightness_set = logolamp_set | ||
| 189 | }; | ||
| 190 | |||
| 191 | static enum led_brightness kblamps_get(struct led_classdev *cdev); | ||
| 192 | static void kblamps_set(struct led_classdev *cdev, | ||
| 193 | enum led_brightness brightness); | ||
| 194 | |||
| 195 | struct led_classdev kblamps_led = { | ||
| 196 | .name = "fujitsu::kblamps", | ||
| 197 | .brightness_get = kblamps_get, | ||
| 198 | .brightness_set = kblamps_set | ||
| 199 | }; | ||
| 200 | #endif | ||
| 201 | |||
| 157 | #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG | 202 | #ifdef CONFIG_FUJITSU_LAPTOP_DEBUG |
| 158 | static u32 dbg_level = 0x03; | 203 | static u32 dbg_level = 0x03; |
| 159 | #endif | 204 | #endif |
| 160 | 205 | ||
| 161 | static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data); | 206 | static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data); |
| 162 | 207 | ||
| 208 | /* Fujitsu ACPI interface function */ | ||
| 209 | |||
| 210 | static int call_fext_func(int cmd, int arg0, int arg1, int arg2) | ||
| 211 | { | ||
| 212 | acpi_status status = AE_OK; | ||
| 213 | union acpi_object params[4] = { | ||
| 214 | { .type = ACPI_TYPE_INTEGER }, | ||
| 215 | { .type = ACPI_TYPE_INTEGER }, | ||
| 216 | { .type = ACPI_TYPE_INTEGER }, | ||
| 217 | { .type = ACPI_TYPE_INTEGER } | ||
| 218 | }; | ||
| 219 | struct acpi_object_list arg_list = { 4, ¶ms[0] }; | ||
| 220 | struct acpi_buffer output; | ||
| 221 | union acpi_object out_obj; | ||
| 222 | acpi_handle handle = NULL; | ||
| 223 | |||
| 224 | status = acpi_get_handle(fujitsu_hotkey->acpi_handle, "FUNC", &handle); | ||
| 225 | if (ACPI_FAILURE(status)) { | ||
| 226 | vdbg_printk(FUJLAPTOP_DBG_ERROR, | ||
| 227 | "FUNC interface is not present\n"); | ||
| 228 | return -ENODEV; | ||
| 229 | } | ||
| 230 | |||
| 231 | params[0].integer.value = cmd; | ||
| 232 | params[1].integer.value = arg0; | ||
| 233 | params[2].integer.value = arg1; | ||
| 234 | params[3].integer.value = arg2; | ||
| 235 | |||
| 236 | output.length = sizeof(out_obj); | ||
| 237 | output.pointer = &out_obj; | ||
| 238 | |||
| 239 | status = acpi_evaluate_object(handle, NULL, &arg_list, &output); | ||
| 240 | if (ACPI_FAILURE(status)) { | ||
| 241 | vdbg_printk(FUJLAPTOP_DBG_WARN, | ||
| 242 | "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) call failed\n", | ||
| 243 | cmd, arg0, arg1, arg2); | ||
| 244 | return -ENODEV; | ||
| 245 | } | ||
| 246 | |||
| 247 | if (out_obj.type != ACPI_TYPE_INTEGER) { | ||
| 248 | vdbg_printk(FUJLAPTOP_DBG_WARN, | ||
| 249 | "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) did not " | ||
| 250 | "return an integer\n", | ||
| 251 | cmd, arg0, arg1, arg2); | ||
| 252 | return -ENODEV; | ||
| 253 | } | ||
| 254 | |||
| 255 | vdbg_printk(FUJLAPTOP_DBG_TRACE, | ||
| 256 | "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n", | ||
| 257 | cmd, arg0, arg1, arg2, (int)out_obj.integer.value); | ||
| 258 | return out_obj.integer.value; | ||
| 259 | } | ||
| 260 | |||
| 261 | #ifdef CONFIG_LEDS_CLASS | ||
| 262 | /* LED class callbacks */ | ||
| 263 | |||
| 264 | static void logolamp_set(struct led_classdev *cdev, | ||
| 265 | enum led_brightness brightness) | ||
| 266 | { | ||
| 267 | if (brightness >= LED_FULL) { | ||
| 268 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON); | ||
| 269 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_ON); | ||
| 270 | } else if (brightness >= LED_HALF) { | ||
| 271 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON); | ||
| 272 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_OFF); | ||
| 273 | } else { | ||
| 274 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_OFF); | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | static void kblamps_set(struct led_classdev *cdev, | ||
| 279 | enum led_brightness brightness) | ||
| 280 | { | ||
| 281 | if (brightness >= LED_FULL) | ||
| 282 | call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_ON); | ||
| 283 | else | ||
| 284 | call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF); | ||
| 285 | } | ||
| 286 | |||
| 287 | static enum led_brightness logolamp_get(struct led_classdev *cdev) | ||
| 288 | { | ||
| 289 | enum led_brightness brightness = LED_OFF; | ||
| 290 | int poweron, always; | ||
| 291 | |||
| 292 | poweron = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0); | ||
| 293 | if (poweron == FUNC_LED_ON) { | ||
| 294 | brightness = LED_HALF; | ||
| 295 | always = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0); | ||
| 296 | if (always == FUNC_LED_ON) | ||
| 297 | brightness = LED_FULL; | ||
| 298 | } | ||
| 299 | return brightness; | ||
| 300 | } | ||
| 301 | |||
| 302 | static enum led_brightness kblamps_get(struct led_classdev *cdev) | ||
| 303 | { | ||
| 304 | enum led_brightness brightness = LED_OFF; | ||
| 305 | |||
| 306 | if (call_fext_func(FUNC_LEDS, 0x2, KEYBOARD_LAMPS, 0x0) == FUNC_LED_ON) | ||
| 307 | brightness = LED_FULL; | ||
| 308 | |||
| 309 | return brightness; | ||
| 310 | } | ||
| 311 | #endif | ||
| 312 | |||
| 163 | /* Hardware access for LCD brightness control */ | 313 | /* Hardware access for LCD brightness control */ |
| 164 | 314 | ||
| 165 | static int set_lcd_level(int level) | 315 | static int set_lcd_level(int level) |
| @@ -297,10 +447,25 @@ static int bl_get_brightness(struct backlight_device *b) | |||
| 297 | 447 | ||
| 298 | static int bl_update_status(struct backlight_device *b) | 448 | static int bl_update_status(struct backlight_device *b) |
| 299 | { | 449 | { |
| 450 | int ret; | ||
| 451 | if (b->props.power == 4) | ||
| 452 | ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x3); | ||
| 453 | else | ||
| 454 | ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x0); | ||
| 455 | if (ret != 0) | ||
| 456 | vdbg_printk(FUJLAPTOP_DBG_ERROR, | ||
| 457 | "Unable to adjust backlight power, error code %i\n", | ||
| 458 | ret); | ||
| 459 | |||
| 300 | if (use_alt_lcd_levels) | 460 | if (use_alt_lcd_levels) |
| 301 | return set_lcd_level_alt(b->props.brightness); | 461 | ret = set_lcd_level_alt(b->props.brightness); |
| 302 | else | 462 | else |
| 303 | return set_lcd_level(b->props.brightness); | 463 | ret = set_lcd_level(b->props.brightness); |
| 464 | if (ret != 0) | ||
| 465 | vdbg_printk(FUJLAPTOP_DBG_ERROR, | ||
| 466 | "Unable to adjust LCD brightness, error code %i\n", | ||
| 467 | ret); | ||
| 468 | return ret; | ||
| 304 | } | 469 | } |
| 305 | 470 | ||
| 306 | static struct backlight_ops fujitsubl_ops = { | 471 | static struct backlight_ops fujitsubl_ops = { |
| @@ -382,42 +547,64 @@ static ssize_t store_lcd_level(struct device *dev, | |||
| 382 | return count; | 547 | return count; |
| 383 | } | 548 | } |
| 384 | 549 | ||
| 385 | /* Hardware access for hotkey device */ | 550 | static ssize_t |
| 386 | 551 | ignore_store(struct device *dev, | |
| 387 | static int get_irb(void) | 552 | struct device_attribute *attr, const char *buf, size_t count) |
| 388 | { | 553 | { |
| 389 | unsigned long long state = 0; | 554 | return count; |
| 390 | acpi_status status = AE_OK; | 555 | } |
| 391 | |||
| 392 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "Get irb\n"); | ||
| 393 | |||
| 394 | status = | ||
| 395 | acpi_evaluate_integer(fujitsu_hotkey->acpi_handle, "GIRB", NULL, | ||
| 396 | &state); | ||
| 397 | if (status < 0) | ||
| 398 | return status; | ||
| 399 | 556 | ||
| 400 | fujitsu_hotkey->irb = state; | 557 | static ssize_t |
| 558 | show_lid_state(struct device *dev, | ||
| 559 | struct device_attribute *attr, char *buf) | ||
| 560 | { | ||
| 561 | if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD) | ||
| 562 | return sprintf(buf, "unknown\n"); | ||
| 563 | if (fujitsu_hotkey->rfkill_state & 0x100) | ||
| 564 | return sprintf(buf, "open\n"); | ||
| 565 | else | ||
| 566 | return sprintf(buf, "closed\n"); | ||
| 567 | } | ||
| 401 | 568 | ||
| 402 | return fujitsu_hotkey->irb; | 569 | static ssize_t |
| 570 | show_dock_state(struct device *dev, | ||
| 571 | struct device_attribute *attr, char *buf) | ||
| 572 | { | ||
| 573 | if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD) | ||
| 574 | return sprintf(buf, "unknown\n"); | ||
| 575 | if (fujitsu_hotkey->rfkill_state & 0x200) | ||
| 576 | return sprintf(buf, "docked\n"); | ||
| 577 | else | ||
| 578 | return sprintf(buf, "undocked\n"); | ||
| 403 | } | 579 | } |
| 404 | 580 | ||
| 405 | static ssize_t | 581 | static ssize_t |
| 406 | ignore_store(struct device *dev, | 582 | show_radios_state(struct device *dev, |
| 407 | struct device_attribute *attr, const char *buf, size_t count) | 583 | struct device_attribute *attr, char *buf) |
| 408 | { | 584 | { |
| 409 | return count; | 585 | if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD) |
| 586 | return sprintf(buf, "unknown\n"); | ||
| 587 | if (fujitsu_hotkey->rfkill_state & 0x20) | ||
| 588 | return sprintf(buf, "on\n"); | ||
| 589 | else | ||
| 590 | return sprintf(buf, "killed\n"); | ||
| 410 | } | 591 | } |
| 411 | 592 | ||
| 412 | static DEVICE_ATTR(max_brightness, 0444, show_max_brightness, ignore_store); | 593 | static DEVICE_ATTR(max_brightness, 0444, show_max_brightness, ignore_store); |
| 413 | static DEVICE_ATTR(brightness_changed, 0444, show_brightness_changed, | 594 | static DEVICE_ATTR(brightness_changed, 0444, show_brightness_changed, |
| 414 | ignore_store); | 595 | ignore_store); |
| 415 | static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); | 596 | static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); |
| 597 | static DEVICE_ATTR(lid, 0444, show_lid_state, ignore_store); | ||
| 598 | static DEVICE_ATTR(dock, 0444, show_dock_state, ignore_store); | ||
| 599 | static DEVICE_ATTR(radios, 0444, show_radios_state, ignore_store); | ||
| 416 | 600 | ||
| 417 | static struct attribute *fujitsupf_attributes[] = { | 601 | static struct attribute *fujitsupf_attributes[] = { |
| 418 | &dev_attr_brightness_changed.attr, | 602 | &dev_attr_brightness_changed.attr, |
| 419 | &dev_attr_max_brightness.attr, | 603 | &dev_attr_max_brightness.attr, |
| 420 | &dev_attr_lcd_level.attr, | 604 | &dev_attr_lcd_level.attr, |
| 605 | &dev_attr_lid.attr, | ||
| 606 | &dev_attr_dock.attr, | ||
| 607 | &dev_attr_radios.attr, | ||
| 421 | NULL | 608 | NULL |
| 422 | }; | 609 | }; |
| 423 | 610 | ||
| @@ -771,7 +958,8 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) | |||
| 771 | input->id.bustype = BUS_HOST; | 958 | input->id.bustype = BUS_HOST; |
| 772 | input->id.product = 0x06; | 959 | input->id.product = 0x06; |
| 773 | input->dev.parent = &device->dev; | 960 | input->dev.parent = &device->dev; |
| 774 | input->evbit[0] = BIT(EV_KEY); | 961 | |
| 962 | set_bit(EV_KEY, input->evbit); | ||
| 775 | set_bit(fujitsu->keycode1, input->keybit); | 963 | set_bit(fujitsu->keycode1, input->keybit); |
| 776 | set_bit(fujitsu->keycode2, input->keybit); | 964 | set_bit(fujitsu->keycode2, input->keybit); |
| 777 | set_bit(fujitsu->keycode3, input->keybit); | 965 | set_bit(fujitsu->keycode3, input->keybit); |
| @@ -803,10 +991,44 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) | |||
| 803 | printk(KERN_ERR "_INI Method failed\n"); | 991 | printk(KERN_ERR "_INI Method failed\n"); |
| 804 | } | 992 | } |
| 805 | 993 | ||
| 806 | i = 0; /* Discard hotkey ringbuffer */ | 994 | i = 0; |
| 807 | while (get_irb() != 0 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) ; | 995 | while (call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0 |
| 996 | && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) | ||
| 997 | ; /* No action, result is discarded */ | ||
| 808 | vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i); | 998 | vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i); |
| 809 | 999 | ||
| 1000 | fujitsu_hotkey->rfkill_state = | ||
| 1001 | call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0); | ||
| 1002 | |||
| 1003 | /* Suspect this is a keymap of the application panel, print it */ | ||
| 1004 | printk(KERN_INFO "fujitsu-laptop: BTNI: [0x%x]\n", | ||
| 1005 | call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0)); | ||
| 1006 | |||
| 1007 | #ifdef CONFIG_LEDS_CLASS | ||
| 1008 | if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) { | ||
| 1009 | result = led_classdev_register(&fujitsu->pf_device->dev, | ||
| 1010 | &logolamp_led); | ||
| 1011 | if (result == 0) { | ||
| 1012 | fujitsu_hotkey->logolamp_registered = 1; | ||
| 1013 | } else { | ||
| 1014 | printk(KERN_ERR "fujitsu-laptop: Could not register " | ||
| 1015 | "LED handler for logo lamp, error %i\n", result); | ||
| 1016 | } | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) && | ||
| 1020 | (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) { | ||
| 1021 | result = led_classdev_register(&fujitsu->pf_device->dev, | ||
| 1022 | &kblamps_led); | ||
| 1023 | if (result == 0) { | ||
| 1024 | fujitsu_hotkey->kblamps_registered = 1; | ||
| 1025 | } else { | ||
| 1026 | printk(KERN_ERR "fujitsu-laptop: Could not register " | ||
| 1027 | "LED handler for keyboard lamps, error %i\n", result); | ||
| 1028 | } | ||
| 1029 | } | ||
| 1030 | #endif | ||
| 1031 | |||
| 810 | return result; | 1032 | return result; |
| 811 | 1033 | ||
| 812 | end: | 1034 | end: |
| @@ -852,16 +1074,15 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, | |||
| 852 | 1074 | ||
| 853 | input = fujitsu_hotkey->input; | 1075 | input = fujitsu_hotkey->input; |
| 854 | 1076 | ||
| 855 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "Hotkey event\n"); | 1077 | fujitsu_hotkey->rfkill_state = |
| 1078 | call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0); | ||
| 856 | 1079 | ||
| 857 | switch (event) { | 1080 | switch (event) { |
| 858 | case ACPI_FUJITSU_NOTIFY_CODE1: | 1081 | case ACPI_FUJITSU_NOTIFY_CODE1: |
| 859 | i = 0; | 1082 | i = 0; |
| 860 | while ((irb = get_irb()) != 0 | 1083 | while ((irb = |
| 861 | && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) { | 1084 | call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0 |
| 862 | vdbg_printk(FUJLAPTOP_DBG_TRACE, "GIRB result [%x]\n", | 1085 | && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) { |
| 863 | irb); | ||
| 864 | |||
| 865 | switch (irb & 0x4ff) { | 1086 | switch (irb & 0x4ff) { |
| 866 | case KEY1_CODE: | 1087 | case KEY1_CODE: |
| 867 | keycode = fujitsu->keycode1; | 1088 | keycode = fujitsu->keycode1; |
| @@ -1035,6 +1256,15 @@ static int __init fujitsu_init(void) | |||
| 1035 | goto fail_hotkey1; | 1256 | goto fail_hotkey1; |
| 1036 | } | 1257 | } |
| 1037 | 1258 | ||
| 1259 | /* Sync backlight power status (needs FUJ02E3 device, hence deferred) */ | ||
| 1260 | |||
| 1261 | if (!acpi_video_backlight_support()) { | ||
| 1262 | if (call_fext_func(FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3) | ||
| 1263 | fujitsu->bl_device->props.power = 4; | ||
| 1264 | else | ||
| 1265 | fujitsu->bl_device->props.power = 0; | ||
| 1266 | } | ||
| 1267 | |||
| 1038 | printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION | 1268 | printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION |
| 1039 | " successfully loaded.\n"); | 1269 | " successfully loaded.\n"); |
| 1040 | 1270 | ||
| @@ -1074,6 +1304,14 @@ fail_acpi: | |||
| 1074 | 1304 | ||
| 1075 | static void __exit fujitsu_cleanup(void) | 1305 | static void __exit fujitsu_cleanup(void) |
| 1076 | { | 1306 | { |
| 1307 | #ifdef CONFIG_LEDS_CLASS | ||
| 1308 | if (fujitsu_hotkey->logolamp_registered != 0) | ||
| 1309 | led_classdev_unregister(&logolamp_led); | ||
| 1310 | |||
| 1311 | if (fujitsu_hotkey->kblamps_registered != 0) | ||
| 1312 | led_classdev_unregister(&kblamps_led); | ||
| 1313 | #endif | ||
| 1314 | |||
| 1077 | sysfs_remove_group(&fujitsu->pf_device->dev.kobj, | 1315 | sysfs_remove_group(&fujitsu->pf_device->dev.kobj, |
| 1078 | &fujitsupf_attribute_group); | 1316 | &fujitsupf_attribute_group); |
| 1079 | platform_device_unregister(fujitsu->pf_device); | 1317 | platform_device_unregister(fujitsu->pf_device); |
| @@ -1108,12 +1346,13 @@ module_param_named(debug, dbg_level, uint, 0644); | |||
| 1108 | MODULE_PARM_DESC(debug, "Sets debug level bit-mask"); | 1346 | MODULE_PARM_DESC(debug, "Sets debug level bit-mask"); |
| 1109 | #endif | 1347 | #endif |
| 1110 | 1348 | ||
| 1111 | MODULE_AUTHOR("Jonathan Woithe, Peter Gruber"); | 1349 | MODULE_AUTHOR("Jonathan Woithe, Peter Gruber, Tony Vroon"); |
| 1112 | MODULE_DESCRIPTION("Fujitsu laptop extras support"); | 1350 | MODULE_DESCRIPTION("Fujitsu laptop extras support"); |
| 1113 | MODULE_VERSION(FUJITSU_DRIVER_VERSION); | 1351 | MODULE_VERSION(FUJITSU_DRIVER_VERSION); |
| 1114 | MODULE_LICENSE("GPL"); | 1352 | MODULE_LICENSE("GPL"); |
| 1115 | 1353 | ||
| 1116 | MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); | 1354 | MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); |
| 1355 | MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1E6:*:cvrS6420:*"); | ||
| 1117 | MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); | 1356 | MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); |
| 1118 | 1357 | ||
| 1119 | static struct pnp_device_id pnp_ids[] = { | 1358 | static struct pnp_device_id pnp_ids[] = { |
