aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/fujitsu-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/fujitsu-laptop.c')
-rw-r--r--drivers/misc/fujitsu-laptop.c419
1 files changed, 293 insertions, 126 deletions
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
index a7dd3e9fb79d..65dc41540c62 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
@@ -133,7 +155,6 @@ struct fujitsu_t {
133 155
134static struct fujitsu_t *fujitsu; 156static struct fujitsu_t *fujitsu;
135static int use_alt_lcd_levels = -1; 157static int use_alt_lcd_levels = -1;
136static int disable_brightness_keys = -1;
137static int disable_brightness_adjust = -1; 158static int disable_brightness_adjust = -1;
138 159
139/* Device used to access other hotkeys on the laptop */ 160/* Device used to access other hotkeys on the laptop */
@@ -145,8 +166,9 @@ struct fujitsu_hotkey_t {
145 struct platform_device *pf_device; 166 struct platform_device *pf_device;
146 struct kfifo *fifo; 167 struct kfifo *fifo;
147 spinlock_t fifo_lock; 168 spinlock_t fifo_lock;
148 169 int rfkill_state;
149 unsigned int irb; /* info about the pressed buttons */ 170 int logolamp_registered;
171 int kblamps_registered;
150}; 172};
151 173
152static struct fujitsu_hotkey_t *fujitsu_hotkey; 174static struct fujitsu_hotkey_t *fujitsu_hotkey;
@@ -154,12 +176,139 @@ static struct fujitsu_hotkey_t *fujitsu_hotkey;
154static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event, 176static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
155 void *data); 177 void *data);
156 178
179#ifdef CONFIG_LEDS_CLASS
180static enum led_brightness logolamp_get(struct led_classdev *cdev);
181static void logolamp_set(struct led_classdev *cdev,
182 enum led_brightness brightness);
183
184struct led_classdev logolamp_led = {
185 .name = "fujitsu::logolamp",
186 .brightness_get = logolamp_get,
187 .brightness_set = logolamp_set
188};
189
190static enum led_brightness kblamps_get(struct led_classdev *cdev);
191static void kblamps_set(struct led_classdev *cdev,
192 enum led_brightness brightness);
193
194struct led_classdev kblamps_led = {
195 .name = "fujitsu::kblamps",
196 .brightness_get = kblamps_get,
197 .brightness_set = kblamps_set
198};
199#endif
200
157#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 201#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
158static u32 dbg_level = 0x03; 202static u32 dbg_level = 0x03;
159#endif 203#endif
160 204
161static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data); 205static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data);
162 206
207/* Fujitsu ACPI interface function */
208
209static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
210{
211 acpi_status status = AE_OK;
212 union acpi_object params[4] = {
213 { .type = ACPI_TYPE_INTEGER },
214 { .type = ACPI_TYPE_INTEGER },
215 { .type = ACPI_TYPE_INTEGER },
216 { .type = ACPI_TYPE_INTEGER }
217 };
218 struct acpi_object_list arg_list = { 4, &params[0] };
219 struct acpi_buffer output;
220 union acpi_object out_obj;
221 acpi_handle handle = NULL;
222
223 status = acpi_get_handle(fujitsu_hotkey->acpi_handle, "FUNC", &handle);
224 if (ACPI_FAILURE(status)) {
225 vdbg_printk(FUJLAPTOP_DBG_ERROR,
226 "FUNC interface is not present\n");
227 return -ENODEV;
228 }
229
230 params[0].integer.value = cmd;
231 params[1].integer.value = arg0;
232 params[2].integer.value = arg1;
233 params[3].integer.value = arg2;
234
235 output.length = sizeof(out_obj);
236 output.pointer = &out_obj;
237
238 status = acpi_evaluate_object(handle, NULL, &arg_list, &output);
239 if (ACPI_FAILURE(status)) {
240 vdbg_printk(FUJLAPTOP_DBG_WARN,
241 "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) call failed\n",
242 cmd, arg0, arg1, arg2);
243 return -ENODEV;
244 }
245
246 if (out_obj.type != ACPI_TYPE_INTEGER) {
247 vdbg_printk(FUJLAPTOP_DBG_WARN,
248 "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) did not "
249 "return an integer\n",
250 cmd, arg0, arg1, arg2);
251 return -ENODEV;
252 }
253
254 vdbg_printk(FUJLAPTOP_DBG_TRACE,
255 "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n",
256 cmd, arg0, arg1, arg2, (int)out_obj.integer.value);
257 return out_obj.integer.value;
258}
259
260#ifdef CONFIG_LEDS_CLASS
261/* LED class callbacks */
262
263static void logolamp_set(struct led_classdev *cdev,
264 enum led_brightness brightness)
265{
266 if (brightness >= LED_FULL) {
267 call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON);
268 call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_ON);
269 } else if (brightness >= LED_HALF) {
270 call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON);
271 call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_OFF);
272 } else {
273 call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_OFF);
274 }
275}
276
277static void kblamps_set(struct led_classdev *cdev,
278 enum led_brightness brightness)
279{
280 if (brightness >= LED_FULL)
281 call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_ON);
282 else
283 call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF);
284}
285
286static enum led_brightness logolamp_get(struct led_classdev *cdev)
287{
288 enum led_brightness brightness = LED_OFF;
289 int poweron, always;
290
291 poweron = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_POWERON, 0x0);
292 if (poweron == FUNC_LED_ON) {
293 brightness = LED_HALF;
294 always = call_fext_func(FUNC_LEDS, 0x2, LOGOLAMP_ALWAYS, 0x0);
295 if (always == FUNC_LED_ON)
296 brightness = LED_FULL;
297 }
298 return brightness;
299}
300
301static enum led_brightness kblamps_get(struct led_classdev *cdev)
302{
303 enum led_brightness brightness = LED_OFF;
304
305 if (call_fext_func(FUNC_LEDS, 0x2, KEYBOARD_LAMPS, 0x0) == FUNC_LED_ON)
306 brightness = LED_FULL;
307
308 return brightness;
309}
310#endif
311
163/* Hardware access for LCD brightness control */ 312/* Hardware access for LCD brightness control */
164 313
165static int set_lcd_level(int level) 314static int set_lcd_level(int level)
@@ -263,44 +412,34 @@ static int get_max_brightness(void)
263 return fujitsu->max_brightness; 412 return fujitsu->max_brightness;
264} 413}
265 414
266static int get_lcd_level_alt(void)
267{
268 unsigned long long state = 0;
269 acpi_status status = AE_OK;
270
271 vdbg_printk(FUJLAPTOP_DBG_TRACE, "get lcd level via GBLS\n");
272
273 status =
274 acpi_evaluate_integer(fujitsu->acpi_handle, "GBLS", NULL, &state);
275 if (status < 0)
276 return status;
277
278 fujitsu->brightness_level = state & 0x0fffffff;
279
280 if (state & 0x80000000)
281 fujitsu->brightness_changed = 1;
282 else
283 fujitsu->brightness_changed = 0;
284
285 return fujitsu->brightness_level;
286}
287
288/* Backlight device stuff */ 415/* Backlight device stuff */
289 416
290static int bl_get_brightness(struct backlight_device *b) 417static int bl_get_brightness(struct backlight_device *b)
291{ 418{
292 if (use_alt_lcd_levels) 419 return get_lcd_level();
293 return get_lcd_level_alt();
294 else
295 return get_lcd_level();
296} 420}
297 421
298static int bl_update_status(struct backlight_device *b) 422static int bl_update_status(struct backlight_device *b)
299{ 423{
424 int ret;
425 if (b->props.power == 4)
426 ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x3);
427 else
428 ret = call_fext_func(FUNC_BACKLIGHT, 0x1, 0x4, 0x0);
429 if (ret != 0)
430 vdbg_printk(FUJLAPTOP_DBG_ERROR,
431 "Unable to adjust backlight power, error code %i\n",
432 ret);
433
300 if (use_alt_lcd_levels) 434 if (use_alt_lcd_levels)
301 return set_lcd_level_alt(b->props.brightness); 435 ret = set_lcd_level_alt(b->props.brightness);
302 else 436 else
303 return set_lcd_level(b->props.brightness); 437 ret = set_lcd_level(b->props.brightness);
438 if (ret != 0)
439 vdbg_printk(FUJLAPTOP_DBG_ERROR,
440 "Unable to adjust LCD brightness, error code %i\n",
441 ret);
442 return ret;
304} 443}
305 444
306static struct backlight_ops fujitsubl_ops = { 445static struct backlight_ops fujitsubl_ops = {
@@ -344,10 +483,7 @@ static ssize_t show_lcd_level(struct device *dev,
344 483
345 int ret; 484 int ret;
346 485
347 if (use_alt_lcd_levels) 486 ret = get_lcd_level();
348 ret = get_lcd_level_alt();
349 else
350 ret = get_lcd_level();
351 if (ret < 0) 487 if (ret < 0)
352 return ret; 488 return ret;
353 489
@@ -372,52 +508,71 @@ static ssize_t store_lcd_level(struct device *dev,
372 if (ret < 0) 508 if (ret < 0)
373 return ret; 509 return ret;
374 510
375 if (use_alt_lcd_levels) 511 ret = get_lcd_level();
376 ret = get_lcd_level_alt();
377 else
378 ret = get_lcd_level();
379 if (ret < 0) 512 if (ret < 0)
380 return ret; 513 return ret;
381 514
382 return count; 515 return count;
383} 516}
384 517
385/* Hardware access for hotkey device */ 518static ssize_t
386 519ignore_store(struct device *dev,
387static int get_irb(void) 520 struct device_attribute *attr, const char *buf, size_t count)
388{ 521{
389 unsigned long long state = 0; 522 return count;
390 acpi_status status = AE_OK; 523}
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 524
400 fujitsu_hotkey->irb = state; 525static ssize_t
526show_lid_state(struct device *dev,
527 struct device_attribute *attr, char *buf)
528{
529 if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
530 return sprintf(buf, "unknown\n");
531 if (fujitsu_hotkey->rfkill_state & 0x100)
532 return sprintf(buf, "open\n");
533 else
534 return sprintf(buf, "closed\n");
535}
401 536
402 return fujitsu_hotkey->irb; 537static ssize_t
538show_dock_state(struct device *dev,
539 struct device_attribute *attr, char *buf)
540{
541 if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
542 return sprintf(buf, "unknown\n");
543 if (fujitsu_hotkey->rfkill_state & 0x200)
544 return sprintf(buf, "docked\n");
545 else
546 return sprintf(buf, "undocked\n");
403} 547}
404 548
405static ssize_t 549static ssize_t
406ignore_store(struct device *dev, 550show_radios_state(struct device *dev,
407 struct device_attribute *attr, const char *buf, size_t count) 551 struct device_attribute *attr, char *buf)
408{ 552{
409 return count; 553 if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
554 return sprintf(buf, "unknown\n");
555 if (fujitsu_hotkey->rfkill_state & 0x20)
556 return sprintf(buf, "on\n");
557 else
558 return sprintf(buf, "killed\n");
410} 559}
411 560
412static DEVICE_ATTR(max_brightness, 0444, show_max_brightness, ignore_store); 561static DEVICE_ATTR(max_brightness, 0444, show_max_brightness, ignore_store);
413static DEVICE_ATTR(brightness_changed, 0444, show_brightness_changed, 562static DEVICE_ATTR(brightness_changed, 0444, show_brightness_changed,
414 ignore_store); 563 ignore_store);
415static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); 564static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
565static DEVICE_ATTR(lid, 0444, show_lid_state, ignore_store);
566static DEVICE_ATTR(dock, 0444, show_dock_state, ignore_store);
567static DEVICE_ATTR(radios, 0444, show_radios_state, ignore_store);
416 568
417static struct attribute *fujitsupf_attributes[] = { 569static struct attribute *fujitsupf_attributes[] = {
418 &dev_attr_brightness_changed.attr, 570 &dev_attr_brightness_changed.attr,
419 &dev_attr_max_brightness.attr, 571 &dev_attr_max_brightness.attr,
420 &dev_attr_lcd_level.attr, 572 &dev_attr_lcd_level.attr,
573 &dev_attr_lid.attr,
574 &dev_attr_dock.attr,
575 &dev_attr_radios.attr,
421 NULL 576 NULL
422}; 577};
423 578
@@ -435,24 +590,16 @@ static struct platform_driver fujitsupf_driver = {
435static void dmi_check_cb_common(const struct dmi_system_id *id) 590static void dmi_check_cb_common(const struct dmi_system_id *id)
436{ 591{
437 acpi_handle handle; 592 acpi_handle handle;
438 int have_blnf;
439 printk(KERN_INFO "fujitsu-laptop: Identified laptop model '%s'.\n", 593 printk(KERN_INFO "fujitsu-laptop: Identified laptop model '%s'.\n",
440 id->ident); 594 id->ident);
441 have_blnf = ACPI_SUCCESS
442 (acpi_get_handle(NULL, "\\_SB.PCI0.GFX0.LCD.BLNF", &handle));
443 if (use_alt_lcd_levels == -1) { 595 if (use_alt_lcd_levels == -1) {
444 vdbg_printk(FUJLAPTOP_DBG_TRACE, "auto-detecting usealt\n"); 596 if (ACPI_SUCCESS(acpi_get_handle(NULL,
445 use_alt_lcd_levels = 1; 597 "\\_SB.PCI0.LPCB.FJEX.SBL2", &handle)))
446 } 598 use_alt_lcd_levels = 1;
447 if (disable_brightness_keys == -1) { 599 else
448 vdbg_printk(FUJLAPTOP_DBG_TRACE, 600 use_alt_lcd_levels = 0;
449 "auto-detecting disable_keys\n"); 601 vdbg_printk(FUJLAPTOP_DBG_TRACE, "auto-detected usealt as "
450 disable_brightness_keys = have_blnf ? 1 : 0; 602 "%i\n", use_alt_lcd_levels);
451 }
452 if (disable_brightness_adjust == -1) {
453 vdbg_printk(FUJLAPTOP_DBG_TRACE,
454 "auto-detecting disable_adjust\n");
455 disable_brightness_adjust = have_blnf ? 0 : 1;
456 } 603 }
457} 604}
458 605
@@ -581,19 +728,14 @@ static int acpi_fujitsu_add(struct acpi_device *device)
581 728
582 /* do config (detect defaults) */ 729 /* do config (detect defaults) */
583 use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0; 730 use_alt_lcd_levels = use_alt_lcd_levels == 1 ? 1 : 0;
584 disable_brightness_keys = disable_brightness_keys == 1 ? 1 : 0;
585 disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0; 731 disable_brightness_adjust = disable_brightness_adjust == 1 ? 1 : 0;
586 vdbg_printk(FUJLAPTOP_DBG_INFO, 732 vdbg_printk(FUJLAPTOP_DBG_INFO,
587 "config: [alt interface: %d], [key disable: %d], [adjust disable: %d]\n", 733 "config: [alt interface: %d], [adjust disable: %d]\n",
588 use_alt_lcd_levels, disable_brightness_keys, 734 use_alt_lcd_levels, disable_brightness_adjust);
589 disable_brightness_adjust);
590 735
591 if (get_max_brightness() <= 0) 736 if (get_max_brightness() <= 0)
592 fujitsu->max_brightness = FUJITSU_LCD_N_LEVELS; 737 fujitsu->max_brightness = FUJITSU_LCD_N_LEVELS;
593 if (use_alt_lcd_levels) 738 get_lcd_level();
594 get_lcd_level_alt();
595 else
596 get_lcd_level();
597 739
598 return result; 740 return result;
599 741
@@ -644,43 +786,23 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
644 case ACPI_FUJITSU_NOTIFY_CODE1: 786 case ACPI_FUJITSU_NOTIFY_CODE1:
645 keycode = 0; 787 keycode = 0;
646 oldb = fujitsu->brightness_level; 788 oldb = fujitsu->brightness_level;
647 get_lcd_level(); /* the alt version always yields changed */ 789 get_lcd_level();
648 newb = fujitsu->brightness_level; 790 newb = fujitsu->brightness_level;
649 791
650 vdbg_printk(FUJLAPTOP_DBG_TRACE, 792 vdbg_printk(FUJLAPTOP_DBG_TRACE,
651 "brightness button event [%i -> %i (%i)]\n", 793 "brightness button event [%i -> %i (%i)]\n",
652 oldb, newb, fujitsu->brightness_changed); 794 oldb, newb, fujitsu->brightness_changed);
653 795
654 if (oldb == newb && fujitsu->brightness_changed) { 796 if (oldb < newb) {
655 keycode = 0;
656 if (disable_brightness_keys != 1) {
657 if (oldb == 0) {
658 acpi_bus_generate_proc_event
659 (fujitsu->dev,
660 ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS,
661 0);
662 keycode = KEY_BRIGHTNESSDOWN;
663 } else if (oldb ==
664 (fujitsu->max_brightness) - 1) {
665 acpi_bus_generate_proc_event
666 (fujitsu->dev,
667 ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS,
668 0);
669 keycode = KEY_BRIGHTNESSUP;
670 }
671 }
672 } else if (oldb < newb) {
673 if (disable_brightness_adjust != 1) { 797 if (disable_brightness_adjust != 1) {
674 if (use_alt_lcd_levels) 798 if (use_alt_lcd_levels)
675 set_lcd_level_alt(newb); 799 set_lcd_level_alt(newb);
676 else 800 else
677 set_lcd_level(newb); 801 set_lcd_level(newb);
678 } 802 }
679 if (disable_brightness_keys != 1) { 803 acpi_bus_generate_proc_event(fujitsu->dev,
680 acpi_bus_generate_proc_event(fujitsu->dev, 804 ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0);
681 ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0); 805 keycode = KEY_BRIGHTNESSUP;
682 keycode = KEY_BRIGHTNESSUP;
683 }
684 } else if (oldb > newb) { 806 } else if (oldb > newb) {
685 if (disable_brightness_adjust != 1) { 807 if (disable_brightness_adjust != 1) {
686 if (use_alt_lcd_levels) 808 if (use_alt_lcd_levels)
@@ -688,13 +810,9 @@ static void acpi_fujitsu_notify(acpi_handle handle, u32 event, void *data)
688 else 810 else
689 set_lcd_level(newb); 811 set_lcd_level(newb);
690 } 812 }
691 if (disable_brightness_keys != 1) { 813 acpi_bus_generate_proc_event(fujitsu->dev,
692 acpi_bus_generate_proc_event(fujitsu->dev, 814 ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0);
693 ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0); 815 keycode = KEY_BRIGHTNESSDOWN;
694 keycode = KEY_BRIGHTNESSDOWN;
695 }
696 } else {
697 keycode = KEY_UNKNOWN;
698 } 816 }
699 break; 817 break;
700 default: 818 default:
@@ -771,7 +889,8 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
771 input->id.bustype = BUS_HOST; 889 input->id.bustype = BUS_HOST;
772 input->id.product = 0x06; 890 input->id.product = 0x06;
773 input->dev.parent = &device->dev; 891 input->dev.parent = &device->dev;
774 input->evbit[0] = BIT(EV_KEY); 892
893 set_bit(EV_KEY, input->evbit);
775 set_bit(fujitsu->keycode1, input->keybit); 894 set_bit(fujitsu->keycode1, input->keybit);
776 set_bit(fujitsu->keycode2, input->keybit); 895 set_bit(fujitsu->keycode2, input->keybit);
777 set_bit(fujitsu->keycode3, input->keybit); 896 set_bit(fujitsu->keycode3, input->keybit);
@@ -803,10 +922,44 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
803 printk(KERN_ERR "_INI Method failed\n"); 922 printk(KERN_ERR "_INI Method failed\n");
804 } 923 }
805 924
806 i = 0; /* Discard hotkey ringbuffer */ 925 i = 0;
807 while (get_irb() != 0 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) ; 926 while (call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0) != 0
927 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE)
928 ; /* No action, result is discarded */
808 vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i); 929 vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i);
809 930
931 fujitsu_hotkey->rfkill_state =
932 call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
933
934 /* Suspect this is a keymap of the application panel, print it */
935 printk(KERN_INFO "fujitsu-laptop: BTNI: [0x%x]\n",
936 call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0));
937
938 #ifdef CONFIG_LEDS_CLASS
939 if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) {
940 result = led_classdev_register(&fujitsu->pf_device->dev,
941 &logolamp_led);
942 if (result == 0) {
943 fujitsu_hotkey->logolamp_registered = 1;
944 } else {
945 printk(KERN_ERR "fujitsu-laptop: Could not register "
946 "LED handler for logo lamp, error %i\n", result);
947 }
948 }
949
950 if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & KEYBOARD_LAMPS) &&
951 (call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0) == 0x0)) {
952 result = led_classdev_register(&fujitsu->pf_device->dev,
953 &kblamps_led);
954 if (result == 0) {
955 fujitsu_hotkey->kblamps_registered = 1;
956 } else {
957 printk(KERN_ERR "fujitsu-laptop: Could not register "
958 "LED handler for keyboard lamps, error %i\n", result);
959 }
960 }
961 #endif
962
810 return result; 963 return result;
811 964
812end: 965end:
@@ -852,16 +1005,15 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
852 1005
853 input = fujitsu_hotkey->input; 1006 input = fujitsu_hotkey->input;
854 1007
855 vdbg_printk(FUJLAPTOP_DBG_TRACE, "Hotkey event\n"); 1008 fujitsu_hotkey->rfkill_state =
1009 call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
856 1010
857 switch (event) { 1011 switch (event) {
858 case ACPI_FUJITSU_NOTIFY_CODE1: 1012 case ACPI_FUJITSU_NOTIFY_CODE1:
859 i = 0; 1013 i = 0;
860 while ((irb = get_irb()) != 0 1014 while ((irb =
861 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) { 1015 call_fext_func(FUNC_BUTTONS, 0x1, 0x0, 0x0)) != 0
862 vdbg_printk(FUJLAPTOP_DBG_TRACE, "GIRB result [%x]\n", 1016 && (i++) < MAX_HOTKEY_RINGBUFFER_SIZE) {
863 irb);
864
865 switch (irb & 0x4ff) { 1017 switch (irb & 0x4ff) {
866 case KEY1_CODE: 1018 case KEY1_CODE:
867 keycode = fujitsu->keycode1; 1019 keycode = fujitsu->keycode1;
@@ -1035,6 +1187,15 @@ static int __init fujitsu_init(void)
1035 goto fail_hotkey1; 1187 goto fail_hotkey1;
1036 } 1188 }
1037 1189
1190 /* Sync backlight power status (needs FUJ02E3 device, hence deferred) */
1191
1192 if (!acpi_video_backlight_support()) {
1193 if (call_fext_func(FUNC_BACKLIGHT, 0x2, 0x4, 0x0) == 3)
1194 fujitsu->bl_device->props.power = 4;
1195 else
1196 fujitsu->bl_device->props.power = 0;
1197 }
1198
1038 printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION 1199 printk(KERN_INFO "fujitsu-laptop: driver " FUJITSU_DRIVER_VERSION
1039 " successfully loaded.\n"); 1200 " successfully loaded.\n");
1040 1201
@@ -1074,6 +1235,14 @@ fail_acpi:
1074 1235
1075static void __exit fujitsu_cleanup(void) 1236static void __exit fujitsu_cleanup(void)
1076{ 1237{
1238 #ifdef CONFIG_LEDS_CLASS
1239 if (fujitsu_hotkey->logolamp_registered != 0)
1240 led_classdev_unregister(&logolamp_led);
1241
1242 if (fujitsu_hotkey->kblamps_registered != 0)
1243 led_classdev_unregister(&kblamps_led);
1244 #endif
1245
1077 sysfs_remove_group(&fujitsu->pf_device->dev.kobj, 1246 sysfs_remove_group(&fujitsu->pf_device->dev.kobj,
1078 &fujitsupf_attribute_group); 1247 &fujitsupf_attribute_group);
1079 platform_device_unregister(fujitsu->pf_device); 1248 platform_device_unregister(fujitsu->pf_device);
@@ -1098,9 +1267,6 @@ module_exit(fujitsu_cleanup);
1098module_param(use_alt_lcd_levels, uint, 0644); 1267module_param(use_alt_lcd_levels, uint, 0644);
1099MODULE_PARM_DESC(use_alt_lcd_levels, 1268MODULE_PARM_DESC(use_alt_lcd_levels,
1100 "Use alternative interface for lcd_levels (needed for Lifebook s6410)."); 1269 "Use alternative interface for lcd_levels (needed for Lifebook s6410).");
1101module_param(disable_brightness_keys, uint, 0644);
1102MODULE_PARM_DESC(disable_brightness_keys,
1103 "Disable brightness keys (eg. if they are already handled by the generic ACPI_VIDEO device).");
1104module_param(disable_brightness_adjust, uint, 0644); 1270module_param(disable_brightness_adjust, uint, 0644);
1105MODULE_PARM_DESC(disable_brightness_adjust, "Disable brightness adjustment ."); 1271MODULE_PARM_DESC(disable_brightness_adjust, "Disable brightness adjustment .");
1106#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG 1272#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
@@ -1108,12 +1274,13 @@ module_param_named(debug, dbg_level, uint, 0644);
1108MODULE_PARM_DESC(debug, "Sets debug level bit-mask"); 1274MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
1109#endif 1275#endif
1110 1276
1111MODULE_AUTHOR("Jonathan Woithe, Peter Gruber"); 1277MODULE_AUTHOR("Jonathan Woithe, Peter Gruber, Tony Vroon");
1112MODULE_DESCRIPTION("Fujitsu laptop extras support"); 1278MODULE_DESCRIPTION("Fujitsu laptop extras support");
1113MODULE_VERSION(FUJITSU_DRIVER_VERSION); 1279MODULE_VERSION(FUJITSU_DRIVER_VERSION);
1114MODULE_LICENSE("GPL"); 1280MODULE_LICENSE("GPL");
1115 1281
1116MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*"); 1282MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1D3:*:cvrS6410:*");
1283MODULE_ALIAS("dmi:*:svnFUJITSUSIEMENS:*:pvr:rvnFUJITSU:rnFJNB1E6:*:cvrS6420:*");
1117MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*"); 1284MODULE_ALIAS("dmi:*:svnFUJITSU:*:pvr:rvnFUJITSU:rnFJNB19C:*:cvrS7020:*");
1118 1285
1119static struct pnp_device_id pnp_ids[] = { 1286static struct pnp_device_id pnp_ids[] = {