diff options
-rw-r--r-- | drivers/platform/x86/asus-laptop.c | 362 |
1 files changed, 209 insertions, 153 deletions
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 4ff30ca4df12..58a4864096d9 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
@@ -196,6 +196,34 @@ ASUS_HANDLE(kled_set, ASUS_LAPTOP_PREFIX "SLKB"); | |||
196 | ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB"); | 196 | ASUS_HANDLE(kled_get, ASUS_LAPTOP_PREFIX "GLKB"); |
197 | 197 | ||
198 | /* | 198 | /* |
199 | * Define a specific led structure to keep the main structure clean | ||
200 | */ | ||
201 | #define ASUS_DEFINE_LED(object) \ | ||
202 | int object##_wk; \ | ||
203 | struct work_struct object##_work; \ | ||
204 | struct led_classdev object; | ||
205 | |||
206 | |||
207 | #define led_to_asus(led_cdev, led) \ | ||
208 | container_of(container_of(led_cdev, struct asus_laptop_leds, \ | ||
209 | led), \ | ||
210 | struct asus_laptop, leds) | ||
211 | #define work_to_asus(work, led) \ | ||
212 | container_of(container_of(work, struct asus_laptop_leds, \ | ||
213 | led##_work), \ | ||
214 | struct asus_laptop, leds) | ||
215 | |||
216 | struct asus_laptop_leds { | ||
217 | ASUS_DEFINE_LED(mled) | ||
218 | ASUS_DEFINE_LED(tled) | ||
219 | ASUS_DEFINE_LED(rled) | ||
220 | ASUS_DEFINE_LED(pled) | ||
221 | ASUS_DEFINE_LED(gled) | ||
222 | ASUS_DEFINE_LED(kled) | ||
223 | struct workqueue_struct *workqueue; | ||
224 | }; | ||
225 | |||
226 | /* | ||
199 | * This is the main structure, we can use it to store anything interesting | 227 | * This is the main structure, we can use it to store anything interesting |
200 | * about the hotk device | 228 | * about the hotk device |
201 | */ | 229 | */ |
@@ -206,7 +234,11 @@ struct asus_laptop { | |||
206 | struct platform_device *platform_device; | 234 | struct platform_device *platform_device; |
207 | struct acpi_device *device; /* the device we are in */ | 235 | struct acpi_device *device; /* the device we are in */ |
208 | struct backlight_device *backlight_device; | 236 | struct backlight_device *backlight_device; |
237 | |||
209 | struct input_dev *inputdev; | 238 | struct input_dev *inputdev; |
239 | struct key_entry *keymap; | ||
240 | |||
241 | struct asus_laptop_leds leds; | ||
210 | 242 | ||
211 | acpi_handle handle; /* the handle of the hotk device */ | 243 | acpi_handle handle; /* the handle of the hotk device */ |
212 | char status; /* status of the hotk, for LEDs, ... */ | 244 | char status; /* status of the hotk, for LEDs, ... */ |
@@ -217,10 +249,6 @@ struct asus_laptop { | |||
217 | u16 *keycode_map; | 249 | u16 *keycode_map; |
218 | }; | 250 | }; |
219 | 251 | ||
220 | static struct asus_laptop *asus; | ||
221 | |||
222 | static struct workqueue_struct *led_workqueue; | ||
223 | |||
224 | /* | 252 | /* |
225 | * The backlight class declaration | 253 | * The backlight class declaration |
226 | */ | 254 | */ |
@@ -237,8 +265,6 @@ static struct backlight_ops asusbl_ops = { | |||
237 | static enum led_brightness object##_led_get( \ | 265 | static enum led_brightness object##_led_get( \ |
238 | struct led_classdev *led_cdev); \ | 266 | struct led_classdev *led_cdev); \ |
239 | static void object##_led_update(struct work_struct *ignored); \ | 267 | static void object##_led_update(struct work_struct *ignored); \ |
240 | static int object##_led_wk; \ | ||
241 | static DECLARE_WORK(object##_led_work, object##_led_update); \ | ||
242 | static struct led_classdev object##_led = { \ | 268 | static struct led_classdev object##_led = { \ |
243 | .name = "asus::" ledname, \ | 269 | .name = "asus::" ledname, \ |
244 | .brightness_set = object##_led_set, \ | 270 | .brightness_set = object##_led_set, \ |
@@ -261,7 +287,7 @@ struct key_entry { | |||
261 | 287 | ||
262 | enum { KE_KEY, KE_END }; | 288 | enum { KE_KEY, KE_END }; |
263 | 289 | ||
264 | static struct key_entry asus_keymap[] = { | 290 | static const struct key_entry asus_keymap[] = { |
265 | {KE_KEY, 0x02, KEY_SCREENLOCK}, | 291 | {KE_KEY, 0x02, KEY_SCREENLOCK}, |
266 | {KE_KEY, 0x05, KEY_WLAN}, | 292 | {KE_KEY, 0x05, KEY_WLAN}, |
267 | {KE_KEY, 0x08, KEY_F13}, | 293 | {KE_KEY, 0x08, KEY_F13}, |
@@ -333,7 +359,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val) | |||
333 | return write_acpi_int_ret(handle, method, val, NULL); | 359 | return write_acpi_int_ret(handle, method, val, NULL); |
334 | } | 360 | } |
335 | 361 | ||
336 | static int read_wireless_status(int mask) | 362 | static int read_wireless_status(struct asus_laptop *asus, int mask) |
337 | { | 363 | { |
338 | unsigned long long status; | 364 | unsigned long long status; |
339 | acpi_status rv = AE_OK; | 365 | acpi_status rv = AE_OK; |
@@ -350,7 +376,7 @@ static int read_wireless_status(int mask) | |||
350 | return (asus->status & mask) ? 1 : 0; | 376 | return (asus->status & mask) ? 1 : 0; |
351 | } | 377 | } |
352 | 378 | ||
353 | static int read_gps_status(void) | 379 | static int read_gps_status(struct asus_laptop *asus) |
354 | { | 380 | { |
355 | unsigned long long status; | 381 | unsigned long long status; |
356 | acpi_status rv = AE_OK; | 382 | acpi_status rv = AE_OK; |
@@ -365,18 +391,19 @@ static int read_gps_status(void) | |||
365 | } | 391 | } |
366 | 392 | ||
367 | /* Generic LED functions */ | 393 | /* Generic LED functions */ |
368 | static int read_status(int mask) | 394 | static int read_status(struct asus_laptop *asus, int mask) |
369 | { | 395 | { |
370 | /* There is a special method for both wireless devices */ | 396 | /* There is a special method for both wireless devices */ |
371 | if (mask == BT_ON || mask == WL_ON) | 397 | if (mask == BT_ON || mask == WL_ON) |
372 | return read_wireless_status(mask); | 398 | return read_wireless_status(asus, mask); |
373 | else if (mask == GPS_ON) | 399 | else if (mask == GPS_ON) |
374 | return read_gps_status(); | 400 | return read_gps_status(asus); |
375 | 401 | ||
376 | return (asus->status & mask) ? 1 : 0; | 402 | return (asus->status & mask) ? 1 : 0; |
377 | } | 403 | } |
378 | 404 | ||
379 | static void write_status(acpi_handle handle, int out, int mask) | 405 | static void write_status(struct asus_laptop *asus, acpi_handle handle, |
406 | int out, int mask) | ||
380 | { | 407 | { |
381 | asus->status = (out) ? (asus->status | mask) : (asus->status & ~mask); | 408 | asus->status = (out) ? (asus->status | mask) : (asus->status & ~mask); |
382 | 409 | ||
@@ -405,13 +432,19 @@ static void write_status(acpi_handle handle, int out, int mask) | |||
405 | static void object##_led_set(struct led_classdev *led_cdev, \ | 432 | static void object##_led_set(struct led_classdev *led_cdev, \ |
406 | enum led_brightness value) \ | 433 | enum led_brightness value) \ |
407 | { \ | 434 | { \ |
408 | object##_led_wk = (value > 0) ? 1 : 0; \ | 435 | struct asus_laptop *asus = \ |
409 | queue_work(led_workqueue, &object##_led_work); \ | 436 | led_to_asus(led_cdev, object); \ |
437 | \ | ||
438 | asus->leds.object##_wk = (value > 0) ? 1 : 0; \ | ||
439 | queue_work(asus->leds.workqueue, \ | ||
440 | &asus->leds.object##_work); \ | ||
410 | } \ | 441 | } \ |
411 | static void object##_led_update(struct work_struct *ignored) \ | 442 | static void object##_led_update(struct work_struct *work) \ |
412 | { \ | 443 | { \ |
413 | int value = object##_led_wk; \ | 444 | struct asus_laptop *asus = work_to_asus(work, object); \ |
414 | write_status(object##_set_handle, value, (mask)); \ | 445 | \ |
446 | int value = asus->leds.object##_wk; \ | ||
447 | write_status(asus, object##_set_handle, value, (mask)); \ | ||
415 | } \ | 448 | } \ |
416 | static enum led_brightness object##_led_get( \ | 449 | static enum led_brightness object##_led_get( \ |
417 | struct led_classdev *led_cdev) \ | 450 | struct led_classdev *led_cdev) \ |
@@ -448,7 +481,7 @@ static int get_kled_lvl(void) | |||
448 | return kblv; | 481 | return kblv; |
449 | } | 482 | } |
450 | 483 | ||
451 | static int set_kled_lvl(int kblv) | 484 | static int set_kled_lvl(struct asus_laptop *asus, int kblv) |
452 | { | 485 | { |
453 | if (kblv > 0) | 486 | if (kblv > 0) |
454 | kblv = (1 << 7) | (kblv & 0x7F); | 487 | kblv = (1 << 7) | (kblv & 0x7F); |
@@ -465,13 +498,17 @@ static int set_kled_lvl(int kblv) | |||
465 | static void kled_led_set(struct led_classdev *led_cdev, | 498 | static void kled_led_set(struct led_classdev *led_cdev, |
466 | enum led_brightness value) | 499 | enum led_brightness value) |
467 | { | 500 | { |
468 | kled_led_wk = value; | 501 | struct asus_laptop *asus = led_to_asus(led_cdev, kled); |
469 | queue_work(led_workqueue, &kled_led_work); | 502 | |
503 | asus->leds.kled_wk = value; | ||
504 | queue_work(asus->leds.workqueue, &asus->leds.kled_work); | ||
470 | } | 505 | } |
471 | 506 | ||
472 | static void kled_led_update(struct work_struct *ignored) | 507 | static void kled_led_update(struct work_struct *work) |
473 | { | 508 | { |
474 | set_kled_lvl(kled_led_wk); | 509 | struct asus_laptop *asus = work_to_asus(work, kled); |
510 | |||
511 | set_kled_lvl(asus, asus->leds.kled_wk); | ||
475 | } | 512 | } |
476 | 513 | ||
477 | static enum led_brightness kled_led_get(struct led_classdev *led_cdev) | 514 | static enum led_brightness kled_led_get(struct led_classdev *led_cdev) |
@@ -479,19 +516,19 @@ static enum led_brightness kled_led_get(struct led_classdev *led_cdev) | |||
479 | return get_kled_lvl(); | 516 | return get_kled_lvl(); |
480 | } | 517 | } |
481 | 518 | ||
482 | static int get_lcd_state(void) | 519 | static int get_lcd_state(struct asus_laptop *asus) |
483 | { | 520 | { |
484 | return read_status(LCD_ON); | 521 | return read_status(asus, LCD_ON); |
485 | } | 522 | } |
486 | 523 | ||
487 | static int set_lcd_state(int value) | 524 | static int set_lcd_state(struct asus_laptop *asus, int value) |
488 | { | 525 | { |
489 | int lcd = 0; | 526 | int lcd = 0; |
490 | acpi_status status = 0; | 527 | acpi_status status = 0; |
491 | 528 | ||
492 | lcd = value ? 1 : 0; | 529 | lcd = value ? 1 : 0; |
493 | 530 | ||
494 | if (lcd == get_lcd_state()) | 531 | if (lcd == get_lcd_state(asus)) |
495 | return 0; | 532 | return 0; |
496 | 533 | ||
497 | if (lcd_switch_handle) { | 534 | if (lcd_switch_handle) { |
@@ -502,11 +539,11 @@ static int set_lcd_state(int value) | |||
502 | pr_warning("Error switching LCD\n"); | 539 | pr_warning("Error switching LCD\n"); |
503 | } | 540 | } |
504 | 541 | ||
505 | write_status(NULL, lcd, LCD_ON); | 542 | write_status(asus, NULL, lcd, LCD_ON); |
506 | return 0; | 543 | return 0; |
507 | } | 544 | } |
508 | 545 | ||
509 | static void lcd_blank(int blank) | 546 | static void lcd_blank(struct asus_laptop *asus, int blank) |
510 | { | 547 | { |
511 | struct backlight_device *bd = asus->backlight_device; | 548 | struct backlight_device *bd = asus->backlight_device; |
512 | 549 | ||
@@ -539,6 +576,7 @@ static int set_brightness(struct backlight_device *bd, int value) | |||
539 | 576 | ||
540 | static int update_bl_status(struct backlight_device *bd) | 577 | static int update_bl_status(struct backlight_device *bd) |
541 | { | 578 | { |
579 | struct asus_laptop *asus = bl_get_data(bd); | ||
542 | int rv; | 580 | int rv; |
543 | int value = bd->props.brightness; | 581 | int value = bd->props.brightness; |
544 | 582 | ||
@@ -547,7 +585,7 @@ static int update_bl_status(struct backlight_device *bd) | |||
547 | return rv; | 585 | return rv; |
548 | 586 | ||
549 | value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0; | 587 | value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0; |
550 | return set_lcd_state(value); | 588 | return set_lcd_state(asus, value); |
551 | } | 589 | } |
552 | 590 | ||
553 | /* | 591 | /* |
@@ -562,6 +600,7 @@ static int update_bl_status(struct backlight_device *bd) | |||
562 | static ssize_t show_infos(struct device *dev, | 600 | static ssize_t show_infos(struct device *dev, |
563 | struct device_attribute *attr, char *page) | 601 | struct device_attribute *attr, char *page) |
564 | { | 602 | { |
603 | struct asus_laptop *asus = dev_get_drvdata(dev); | ||
565 | int len = 0; | 604 | int len = 0; |
566 | unsigned long long temp; | 605 | unsigned long long temp; |
567 | char buf[16]; /* enough for all info */ | 606 | char buf[16]; /* enough for all info */ |
@@ -638,7 +677,8 @@ static int parse_arg(const char *buf, unsigned long count, int *val) | |||
638 | return count; | 677 | return count; |
639 | } | 678 | } |
640 | 679 | ||
641 | static ssize_t store_status(const char *buf, size_t count, | 680 | static ssize_t store_status(struct asus_laptop *asus, |
681 | const char *buf, size_t count, | ||
642 | acpi_handle handle, int mask) | 682 | acpi_handle handle, int mask) |
643 | { | 683 | { |
644 | int rv, value; | 684 | int rv, value; |
@@ -648,7 +688,7 @@ static ssize_t store_status(const char *buf, size_t count, | |||
648 | if (rv > 0) | 688 | if (rv > 0) |
649 | out = value ? 1 : 0; | 689 | out = value ? 1 : 0; |
650 | 690 | ||
651 | write_status(handle, out, mask); | 691 | write_status(asus, handle, out, mask); |
652 | 692 | ||
653 | return rv; | 693 | return rv; |
654 | } | 694 | } |
@@ -659,12 +699,15 @@ static ssize_t store_status(const char *buf, size_t count, | |||
659 | static ssize_t show_ledd(struct device *dev, | 699 | static ssize_t show_ledd(struct device *dev, |
660 | struct device_attribute *attr, char *buf) | 700 | struct device_attribute *attr, char *buf) |
661 | { | 701 | { |
702 | struct asus_laptop *asus = dev_get_drvdata(dev); | ||
703 | |||
662 | return sprintf(buf, "0x%08x\n", asus->ledd_status); | 704 | return sprintf(buf, "0x%08x\n", asus->ledd_status); |
663 | } | 705 | } |
664 | 706 | ||
665 | static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, | 707 | static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, |
666 | const char *buf, size_t count) | 708 | const char *buf, size_t count) |
667 | { | 709 | { |
710 | struct asus_laptop *asus = dev_get_drvdata(dev); | ||
668 | int rv, value; | 711 | int rv, value; |
669 | 712 | ||
670 | rv = parse_arg(buf, count, &value); | 713 | rv = parse_arg(buf, count, &value); |
@@ -683,13 +726,17 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, | |||
683 | static ssize_t show_wlan(struct device *dev, | 726 | static ssize_t show_wlan(struct device *dev, |
684 | struct device_attribute *attr, char *buf) | 727 | struct device_attribute *attr, char *buf) |
685 | { | 728 | { |
686 | return sprintf(buf, "%d\n", read_status(WL_ON)); | 729 | struct asus_laptop *asus = dev_get_drvdata(dev); |
730 | |||
731 | return sprintf(buf, "%d\n", read_status(asus, WL_ON)); | ||
687 | } | 732 | } |
688 | 733 | ||
689 | static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, | 734 | static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, |
690 | const char *buf, size_t count) | 735 | const char *buf, size_t count) |
691 | { | 736 | { |
692 | return store_status(buf, count, wl_switch_handle, WL_ON); | 737 | struct asus_laptop *asus = dev_get_drvdata(dev); |
738 | |||
739 | return store_status(asus, buf, count, wl_switch_handle, WL_ON); | ||
693 | } | 740 | } |
694 | 741 | ||
695 | /* | 742 | /* |
@@ -698,20 +745,24 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, | |||
698 | static ssize_t show_bluetooth(struct device *dev, | 745 | static ssize_t show_bluetooth(struct device *dev, |
699 | struct device_attribute *attr, char *buf) | 746 | struct device_attribute *attr, char *buf) |
700 | { | 747 | { |
701 | return sprintf(buf, "%d\n", read_status(BT_ON)); | 748 | struct asus_laptop *asus = dev_get_drvdata(dev); |
749 | |||
750 | return sprintf(buf, "%d\n", read_status(asus, BT_ON)); | ||
702 | } | 751 | } |
703 | 752 | ||
704 | static ssize_t store_bluetooth(struct device *dev, | 753 | static ssize_t store_bluetooth(struct device *dev, |
705 | struct device_attribute *attr, const char *buf, | 754 | struct device_attribute *attr, const char *buf, |
706 | size_t count) | 755 | size_t count) |
707 | { | 756 | { |
708 | return store_status(buf, count, bt_switch_handle, BT_ON); | 757 | struct asus_laptop *asus = dev_get_drvdata(dev); |
758 | |||
759 | return store_status(asus, buf, count, bt_switch_handle, BT_ON); | ||
709 | } | 760 | } |
710 | 761 | ||
711 | /* | 762 | /* |
712 | * Display | 763 | * Display |
713 | */ | 764 | */ |
714 | static void set_display(int value) | 765 | static void set_display(struct asus_laptop *asus, int value) |
715 | { | 766 | { |
716 | /* no sanity check needed for now */ | 767 | /* no sanity check needed for now */ |
717 | if (write_acpi_int(display_set_handle, NULL, value)) | 768 | if (write_acpi_int(display_set_handle, NULL, value)) |
@@ -719,7 +770,7 @@ static void set_display(int value) | |||
719 | return; | 770 | return; |
720 | } | 771 | } |
721 | 772 | ||
722 | static int read_display(void) | 773 | static int read_display(struct asus_laptop *asus) |
723 | { | 774 | { |
724 | unsigned long long value = 0; | 775 | unsigned long long value = 0; |
725 | acpi_status rv = AE_OK; | 776 | acpi_status rv = AE_OK; |
@@ -747,7 +798,9 @@ static int read_display(void) | |||
747 | static ssize_t show_disp(struct device *dev, | 798 | static ssize_t show_disp(struct device *dev, |
748 | struct device_attribute *attr, char *buf) | 799 | struct device_attribute *attr, char *buf) |
749 | { | 800 | { |
750 | return sprintf(buf, "%d\n", read_display()); | 801 | struct asus_laptop *asus = dev_get_drvdata(dev); |
802 | |||
803 | return sprintf(buf, "%d\n", read_display(asus)); | ||
751 | } | 804 | } |
752 | 805 | ||
753 | /* | 806 | /* |
@@ -760,18 +813,19 @@ static ssize_t show_disp(struct device *dev, | |||
760 | static ssize_t store_disp(struct device *dev, struct device_attribute *attr, | 813 | static ssize_t store_disp(struct device *dev, struct device_attribute *attr, |
761 | const char *buf, size_t count) | 814 | const char *buf, size_t count) |
762 | { | 815 | { |
816 | struct asus_laptop *asus = dev_get_drvdata(dev); | ||
763 | int rv, value; | 817 | int rv, value; |
764 | 818 | ||
765 | rv = parse_arg(buf, count, &value); | 819 | rv = parse_arg(buf, count, &value); |
766 | if (rv > 0) | 820 | if (rv > 0) |
767 | set_display(value); | 821 | set_display(asus, value); |
768 | return rv; | 822 | return rv; |
769 | } | 823 | } |
770 | 824 | ||
771 | /* | 825 | /* |
772 | * Light Sens | 826 | * Light Sens |
773 | */ | 827 | */ |
774 | static void set_light_sens_switch(int value) | 828 | static void set_light_sens_switch(struct asus_laptop *asus, int value) |
775 | { | 829 | { |
776 | if (write_acpi_int(ls_switch_handle, NULL, value)) | 830 | if (write_acpi_int(ls_switch_handle, NULL, value)) |
777 | pr_warning("Error setting light sensor switch\n"); | 831 | pr_warning("Error setting light sensor switch\n"); |
@@ -781,22 +835,25 @@ static void set_light_sens_switch(int value) | |||
781 | static ssize_t show_lssw(struct device *dev, | 835 | static ssize_t show_lssw(struct device *dev, |
782 | struct device_attribute *attr, char *buf) | 836 | struct device_attribute *attr, char *buf) |
783 | { | 837 | { |
838 | struct asus_laptop *asus = dev_get_drvdata(dev); | ||
839 | |||
784 | return sprintf(buf, "%d\n", asus->light_switch); | 840 | return sprintf(buf, "%d\n", asus->light_switch); |
785 | } | 841 | } |
786 | 842 | ||
787 | static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, | 843 | static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, |
788 | const char *buf, size_t count) | 844 | const char *buf, size_t count) |
789 | { | 845 | { |
846 | struct asus_laptop *asus = dev_get_drvdata(dev); | ||
790 | int rv, value; | 847 | int rv, value; |
791 | 848 | ||
792 | rv = parse_arg(buf, count, &value); | 849 | rv = parse_arg(buf, count, &value); |
793 | if (rv > 0) | 850 | if (rv > 0) |
794 | set_light_sens_switch(value ? 1 : 0); | 851 | set_light_sens_switch(asus, value ? 1 : 0); |
795 | 852 | ||
796 | return rv; | 853 | return rv; |
797 | } | 854 | } |
798 | 855 | ||
799 | static void set_light_sens_level(int value) | 856 | static void set_light_sens_level(struct asus_laptop *asus, int value) |
800 | { | 857 | { |
801 | if (write_acpi_int(ls_level_handle, NULL, value)) | 858 | if (write_acpi_int(ls_level_handle, NULL, value)) |
802 | pr_warning("Error setting light sensor level\n"); | 859 | pr_warning("Error setting light sensor level\n"); |
@@ -806,19 +863,22 @@ static void set_light_sens_level(int value) | |||
806 | static ssize_t show_lslvl(struct device *dev, | 863 | static ssize_t show_lslvl(struct device *dev, |
807 | struct device_attribute *attr, char *buf) | 864 | struct device_attribute *attr, char *buf) |
808 | { | 865 | { |
866 | struct asus_laptop *asus = dev_get_drvdata(dev); | ||
867 | |||
809 | return sprintf(buf, "%d\n", asus->light_level); | 868 | return sprintf(buf, "%d\n", asus->light_level); |
810 | } | 869 | } |
811 | 870 | ||
812 | static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, | 871 | static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, |
813 | const char *buf, size_t count) | 872 | const char *buf, size_t count) |
814 | { | 873 | { |
874 | struct asus_laptop *asus = dev_get_drvdata(dev); | ||
815 | int rv, value; | 875 | int rv, value; |
816 | 876 | ||
817 | rv = parse_arg(buf, count, &value); | 877 | rv = parse_arg(buf, count, &value); |
818 | if (rv > 0) { | 878 | if (rv > 0) { |
819 | value = (0 < value) ? ((15 < value) ? 15 : value) : 0; | 879 | value = (0 < value) ? ((15 < value) ? 15 : value) : 0; |
820 | /* 0 <= value <= 15 */ | 880 | /* 0 <= value <= 15 */ |
821 | set_light_sens_level(value); | 881 | set_light_sens_level(asus, value); |
822 | } | 882 | } |
823 | 883 | ||
824 | return rv; | 884 | return rv; |
@@ -830,34 +890,40 @@ static ssize_t store_lslvl(struct device *dev, struct device_attribute *attr, | |||
830 | static ssize_t show_gps(struct device *dev, | 890 | static ssize_t show_gps(struct device *dev, |
831 | struct device_attribute *attr, char *buf) | 891 | struct device_attribute *attr, char *buf) |
832 | { | 892 | { |
833 | return sprintf(buf, "%d\n", read_status(GPS_ON)); | 893 | struct asus_laptop *asus = dev_get_drvdata(dev); |
894 | |||
895 | return sprintf(buf, "%d\n", read_status(asus, GPS_ON)); | ||
834 | } | 896 | } |
835 | 897 | ||
836 | static ssize_t store_gps(struct device *dev, struct device_attribute *attr, | 898 | static ssize_t store_gps(struct device *dev, struct device_attribute *attr, |
837 | const char *buf, size_t count) | 899 | const char *buf, size_t count) |
838 | { | 900 | { |
839 | return store_status(buf, count, NULL, GPS_ON); | 901 | struct asus_laptop *asus = dev_get_drvdata(dev); |
902 | |||
903 | return store_status(asus, buf, count, NULL, GPS_ON); | ||
840 | } | 904 | } |
841 | 905 | ||
842 | /* | 906 | /* |
843 | * Hotkey functions | 907 | * Hotkey functions |
844 | */ | 908 | */ |
845 | static struct key_entry *asus_get_entry_by_scancode(int code) | 909 | static struct key_entry *asus_get_entry_by_scancode(struct asus_laptop *asus, |
910 | int code) | ||
846 | { | 911 | { |
847 | struct key_entry *key; | 912 | struct key_entry *key; |
848 | 913 | ||
849 | for (key = asus_keymap; key->type != KE_END; key++) | 914 | for (key = asus->keymap; key->type != KE_END; key++) |
850 | if (code == key->code) | 915 | if (code == key->code) |
851 | return key; | 916 | return key; |
852 | 917 | ||
853 | return NULL; | 918 | return NULL; |
854 | } | 919 | } |
855 | 920 | ||
856 | static struct key_entry *asus_get_entry_by_keycode(int code) | 921 | static struct key_entry *asus_get_entry_by_keycode(struct asus_laptop *asus, |
922 | int code) | ||
857 | { | 923 | { |
858 | struct key_entry *key; | 924 | struct key_entry *key; |
859 | 925 | ||
860 | for (key = asus_keymap; key->type != KE_END; key++) | 926 | for (key = asus->keymap; key->type != KE_END; key++) |
861 | if (code == key->keycode && key->type == KE_KEY) | 927 | if (code == key->keycode && key->type == KE_KEY) |
862 | return key; | 928 | return key; |
863 | 929 | ||
@@ -866,7 +932,8 @@ static struct key_entry *asus_get_entry_by_keycode(int code) | |||
866 | 932 | ||
867 | static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode) | 933 | static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode) |
868 | { | 934 | { |
869 | struct key_entry *key = asus_get_entry_by_scancode(scancode); | 935 | struct asus_laptop *asus = input_get_drvdata(dev); |
936 | struct key_entry *key = asus_get_entry_by_scancode(asus, scancode); | ||
870 | 937 | ||
871 | if (key && key->type == KE_KEY) { | 938 | if (key && key->type == KE_KEY) { |
872 | *keycode = key->keycode; | 939 | *keycode = key->keycode; |
@@ -878,18 +945,19 @@ static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode) | |||
878 | 945 | ||
879 | static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) | 946 | static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) |
880 | { | 947 | { |
948 | struct asus_laptop *asus = input_get_drvdata(dev); | ||
881 | struct key_entry *key; | 949 | struct key_entry *key; |
882 | int old_keycode; | 950 | int old_keycode; |
883 | 951 | ||
884 | if (keycode < 0 || keycode > KEY_MAX) | 952 | if (keycode < 0 || keycode > KEY_MAX) |
885 | return -EINVAL; | 953 | return -EINVAL; |
886 | 954 | ||
887 | key = asus_get_entry_by_scancode(scancode); | 955 | key = asus_get_entry_by_scancode(asus, scancode); |
888 | if (key && key->type == KE_KEY) { | 956 | if (key && key->type == KE_KEY) { |
889 | old_keycode = key->keycode; | 957 | old_keycode = key->keycode; |
890 | key->keycode = keycode; | 958 | key->keycode = keycode; |
891 | set_bit(keycode, dev->keybit); | 959 | set_bit(keycode, dev->keybit); |
892 | if (!asus_get_entry_by_keycode(old_keycode)) | 960 | if (!asus_get_entry_by_keycode(asus, old_keycode)) |
893 | clear_bit(old_keycode, dev->keybit); | 961 | clear_bit(old_keycode, dev->keybit); |
894 | return 0; | 962 | return 0; |
895 | } | 963 | } |
@@ -899,6 +967,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) | |||
899 | 967 | ||
900 | static void asus_acpi_notify(struct acpi_device *device, u32 event) | 968 | static void asus_acpi_notify(struct acpi_device *device, u32 event) |
901 | { | 969 | { |
970 | struct asus_laptop *asus = acpi_driver_data(device); | ||
902 | static struct key_entry *key; | 971 | static struct key_entry *key; |
903 | u16 count; | 972 | u16 count; |
904 | 973 | ||
@@ -907,11 +976,11 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) | |||
907 | * switched | 976 | * switched |
908 | */ | 977 | */ |
909 | if (event == ATKD_LCD_ON) { | 978 | if (event == ATKD_LCD_ON) { |
910 | write_status(NULL, 1, LCD_ON); | 979 | write_status(asus, NULL, 1, LCD_ON); |
911 | lcd_blank(FB_BLANK_UNBLANK); | 980 | lcd_blank(asus, FB_BLANK_UNBLANK); |
912 | } else if (event == ATKD_LCD_OFF) { | 981 | } else if (event == ATKD_LCD_OFF) { |
913 | write_status(NULL, 0, LCD_ON); | 982 | write_status(asus, NULL, 0, LCD_ON); |
914 | lcd_blank(FB_BLANK_POWERDOWN); | 983 | lcd_blank(asus, FB_BLANK_POWERDOWN); |
915 | } | 984 | } |
916 | 985 | ||
917 | /* TODO Find a better way to handle events count. */ | 986 | /* TODO Find a better way to handle events count. */ |
@@ -922,7 +991,7 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) | |||
922 | count); | 991 | count); |
923 | 992 | ||
924 | if (asus->inputdev) { | 993 | if (asus->inputdev) { |
925 | key = asus_get_entry_by_scancode(event); | 994 | key = asus_get_entry_by_scancode(asus, event); |
926 | if (!key) | 995 | if (!key) |
927 | return ; | 996 | return ; |
928 | 997 | ||
@@ -978,13 +1047,14 @@ static struct attribute_group platform_attribute_group = { | |||
978 | .attrs = asuspf_attributes | 1047 | .attrs = asuspf_attributes |
979 | }; | 1048 | }; |
980 | 1049 | ||
981 | static int asus_platform_init(void) | 1050 | static int asus_platform_init(struct asus_laptop *asus) |
982 | { | 1051 | { |
983 | int result; | 1052 | int result; |
984 | 1053 | ||
985 | asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1); | 1054 | asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1); |
986 | if (!asus->platform_device) | 1055 | if (!asus->platform_device) |
987 | return -ENOMEM; | 1056 | return -ENOMEM; |
1057 | platform_set_drvdata(asus->platform_device, asus); | ||
988 | 1058 | ||
989 | result = platform_device_add(asus->platform_device); | 1059 | result = platform_device_add(asus->platform_device); |
990 | if (result) | 1060 | if (result) |
@@ -1003,7 +1073,7 @@ fail_platform_device: | |||
1003 | return result; | 1073 | return result; |
1004 | } | 1074 | } |
1005 | 1075 | ||
1006 | static void asus_platform_exit(void) | 1076 | static void asus_platform_exit(struct asus_laptop *asus) |
1007 | { | 1077 | { |
1008 | sysfs_remove_group(&asus->platform_device->dev.kobj, | 1078 | sysfs_remove_group(&asus->platform_device->dev.kobj, |
1009 | &platform_attribute_group); | 1079 | &platform_attribute_group); |
@@ -1012,12 +1082,12 @@ static void asus_platform_exit(void) | |||
1012 | 1082 | ||
1013 | static struct platform_driver platform_driver = { | 1083 | static struct platform_driver platform_driver = { |
1014 | .driver = { | 1084 | .driver = { |
1015 | .name = ASUS_LAPTOP_FILE, | 1085 | .name = ASUS_LAPTOP_FILE, |
1016 | .owner = THIS_MODULE, | 1086 | .owner = THIS_MODULE, |
1017 | } | 1087 | } |
1018 | }; | 1088 | }; |
1019 | 1089 | ||
1020 | static void asus_laptop_add_fs(void) | 1090 | static void asus_laptop_add_fs(struct asus_laptop *asus) |
1021 | { | 1091 | { |
1022 | ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL); | 1092 | ASUS_SET_DEVICE_ATTR(infos, 0444, show_infos, NULL); |
1023 | 1093 | ||
@@ -1187,7 +1257,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus) | |||
1187 | return AE_OK; | 1257 | return AE_OK; |
1188 | } | 1258 | } |
1189 | 1259 | ||
1190 | static int asus_input_init(struct device *dev) | 1260 | static int asus_input_init(struct asus_laptop *asus) |
1191 | { | 1261 | { |
1192 | const struct key_entry *key; | 1262 | const struct key_entry *key; |
1193 | int result; | 1263 | int result; |
@@ -1198,13 +1268,16 @@ static int asus_input_init(struct device *dev) | |||
1198 | return 0; | 1268 | return 0; |
1199 | } | 1269 | } |
1200 | asus->inputdev->name = "Asus Laptop extra buttons"; | 1270 | asus->inputdev->name = "Asus Laptop extra buttons"; |
1201 | asus->inputdev->dev.parent = dev; | 1271 | asus->inputdev->dev.parent = &asus->platform_device->dev; |
1202 | asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0"; | 1272 | asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0"; |
1203 | asus->inputdev->id.bustype = BUS_HOST; | 1273 | asus->inputdev->id.bustype = BUS_HOST; |
1204 | asus->inputdev->getkeycode = asus_getkeycode; | 1274 | asus->inputdev->getkeycode = asus_getkeycode; |
1205 | asus->inputdev->setkeycode = asus_setkeycode; | 1275 | asus->inputdev->setkeycode = asus_setkeycode; |
1276 | input_set_drvdata(asus->inputdev, asus); | ||
1206 | 1277 | ||
1207 | for (key = asus_keymap; key->type != KE_END; key++) { | 1278 | asus->keymap = kmemdup(asus_keymap, sizeof(asus_keymap), |
1279 | GFP_KERNEL); | ||
1280 | for (key = asus->keymap; key->type != KE_END; key++) { | ||
1208 | switch (key->type) { | 1281 | switch (key->type) { |
1209 | case KE_KEY: | 1282 | case KE_KEY: |
1210 | set_bit(EV_KEY, asus->inputdev->evbit); | 1283 | set_bit(EV_KEY, asus->inputdev->evbit); |
@@ -1220,40 +1293,44 @@ static int asus_input_init(struct device *dev) | |||
1220 | return result; | 1293 | return result; |
1221 | } | 1294 | } |
1222 | 1295 | ||
1223 | static void asus_backlight_exit(void) | 1296 | static void asus_backlight_exit(struct asus_laptop *asus) |
1224 | { | 1297 | { |
1225 | if (asus->backlight_device) | 1298 | if (asus->backlight_device) |
1226 | backlight_device_unregister(asus->backlight_device); | 1299 | backlight_device_unregister(asus->backlight_device); |
1227 | } | 1300 | } |
1228 | 1301 | ||
1229 | #define ASUS_LED_UNREGISTER(object) \ | 1302 | #define ASUS_LED_UNREGISTER(object) \ |
1230 | if (object##_led.dev) \ | 1303 | if (object##_led.dev) \ |
1231 | led_classdev_unregister(&object##_led) | 1304 | led_classdev_unregister(&object##_led) |
1232 | 1305 | ||
1233 | static void asus_led_exit(void) | 1306 | static void asus_led_exit(struct asus_laptop *asus) |
1234 | { | 1307 | { |
1235 | destroy_workqueue(led_workqueue); | ||
1236 | ASUS_LED_UNREGISTER(mled); | 1308 | ASUS_LED_UNREGISTER(mled); |
1237 | ASUS_LED_UNREGISTER(tled); | 1309 | ASUS_LED_UNREGISTER(tled); |
1238 | ASUS_LED_UNREGISTER(pled); | 1310 | ASUS_LED_UNREGISTER(pled); |
1239 | ASUS_LED_UNREGISTER(rled); | 1311 | ASUS_LED_UNREGISTER(rled); |
1240 | ASUS_LED_UNREGISTER(gled); | 1312 | ASUS_LED_UNREGISTER(gled); |
1241 | ASUS_LED_UNREGISTER(kled); | 1313 | ASUS_LED_UNREGISTER(kled); |
1314 | if (asus->leds.workqueue) { | ||
1315 | destroy_workqueue(asus->leds.workqueue); | ||
1316 | asus->leds.workqueue = NULL; | ||
1317 | } | ||
1242 | } | 1318 | } |
1243 | 1319 | ||
1244 | static void asus_input_exit(void) | 1320 | static void asus_input_exit(struct asus_laptop *asus) |
1245 | { | 1321 | { |
1246 | if (asus->inputdev) | 1322 | if (asus->inputdev) |
1247 | input_unregister_device(asus->inputdev); | 1323 | input_unregister_device(asus->inputdev); |
1248 | } | 1324 | } |
1249 | 1325 | ||
1250 | static int asus_backlight_init(struct device *dev) | 1326 | static int asus_backlight_init(struct asus_laptop *asus) |
1251 | { | 1327 | { |
1252 | struct backlight_device *bd; | 1328 | struct backlight_device *bd; |
1329 | struct device *dev = &asus->platform_device->dev; | ||
1253 | 1330 | ||
1254 | if (brightness_set_handle && lcd_switch_handle) { | 1331 | if (brightness_set_handle && lcd_switch_handle) { |
1255 | bd = backlight_device_register(ASUS_LAPTOP_FILE, dev, | 1332 | bd = backlight_device_register(ASUS_LAPTOP_FILE, dev, |
1256 | NULL, &asusbl_ops); | 1333 | asus, &asusbl_ops); |
1257 | if (IS_ERR(bd)) { | 1334 | if (IS_ERR(bd)) { |
1258 | pr_err("Could not register asus backlight device\n"); | 1335 | pr_err("Could not register asus backlight device\n"); |
1259 | asus->backlight_device = NULL; | 1336 | asus->backlight_device = NULL; |
@@ -1270,79 +1347,55 @@ static int asus_backlight_init(struct device *dev) | |||
1270 | return 0; | 1347 | return 0; |
1271 | } | 1348 | } |
1272 | 1349 | ||
1273 | static int asus_led_register(acpi_handle handle, | 1350 | /* |
1274 | struct led_classdev *ldev, struct device *dev) | 1351 | * Ugly macro, need to fix that later |
1275 | { | 1352 | */ |
1276 | if (!handle) | 1353 | #define ASUS_LED_REGISTER(asus, object, _name, max) \ |
1277 | return 0; | 1354 | do { \ |
1278 | 1355 | struct led_classdev *ldev = &asus->leds.object; \ | |
1279 | return led_classdev_register(dev, ldev); | 1356 | if (!object##_set_handle) \ |
1280 | } | 1357 | break ; \ |
1281 | 1358 | \ | |
1282 | #define ASUS_LED_REGISTER(object, device) \ | 1359 | INIT_WORK(&asus->leds.object##_work, object##_led_update); \ |
1283 | asus_led_register(object##_set_handle, &object##_led, device) | 1360 | ldev->name = "asus::" _name; \ |
1284 | 1361 | ldev->brightness_set = object##_led_set; \ | |
1285 | static int asus_led_init(struct device *dev) | 1362 | ldev->max_brightness = max; \ |
1363 | rv = led_classdev_register(&asus->platform_device->dev, ldev); \ | ||
1364 | if (rv) \ | ||
1365 | goto error; \ | ||
1366 | } while (0) | ||
1367 | |||
1368 | static int asus_led_init(struct asus_laptop *asus) | ||
1286 | { | 1369 | { |
1287 | int rv; | 1370 | int rv; |
1288 | 1371 | ||
1289 | rv = ASUS_LED_REGISTER(mled, dev); | ||
1290 | if (rv) | ||
1291 | goto out; | ||
1292 | |||
1293 | rv = ASUS_LED_REGISTER(tled, dev); | ||
1294 | if (rv) | ||
1295 | goto out1; | ||
1296 | |||
1297 | rv = ASUS_LED_REGISTER(rled, dev); | ||
1298 | if (rv) | ||
1299 | goto out2; | ||
1300 | |||
1301 | rv = ASUS_LED_REGISTER(pled, dev); | ||
1302 | if (rv) | ||
1303 | goto out3; | ||
1304 | |||
1305 | rv = ASUS_LED_REGISTER(gled, dev); | ||
1306 | if (rv) | ||
1307 | goto out4; | ||
1308 | |||
1309 | if (kled_set_handle && kled_get_handle) | ||
1310 | rv = ASUS_LED_REGISTER(kled, dev); | ||
1311 | if (rv) | ||
1312 | goto out5; | ||
1313 | |||
1314 | /* | 1372 | /* |
1315 | * Functions that actually update the LED's are called from a | 1373 | * Functions that actually update the LED's are called from a |
1316 | * workqueue. By doing this as separate work rather than when the LED | 1374 | * workqueue. By doing this as separate work rather than when the LED |
1317 | * subsystem asks, we avoid messing with the Asus ACPI stuff during a | 1375 | * subsystem asks, we avoid messing with the Asus ACPI stuff during a |
1318 | * potentially bad time, such as a timer interrupt. | 1376 | * potentially bad time, such as a timer interrupt. |
1319 | */ | 1377 | */ |
1320 | led_workqueue = create_singlethread_workqueue("led_workqueue"); | 1378 | asus->leds.workqueue = create_singlethread_workqueue("led_workqueue"); |
1321 | if (!led_workqueue) | 1379 | if (!asus->leds.workqueue) |
1322 | goto out6; | 1380 | return -ENOMEM; |
1323 | 1381 | ||
1324 | return 0; | 1382 | ASUS_LED_REGISTER(asus, mled, "mail", 1); |
1325 | out6: | 1383 | ASUS_LED_REGISTER(asus, tled, "touchpad", 1); |
1326 | rv = -ENOMEM; | 1384 | ASUS_LED_REGISTER(asus, rled, "record", 1); |
1327 | ASUS_LED_UNREGISTER(kled); | 1385 | ASUS_LED_REGISTER(asus, pled, "phone", 1); |
1328 | out5: | 1386 | ASUS_LED_REGISTER(asus, gled, "gaming", 1); |
1329 | ASUS_LED_UNREGISTER(gled); | 1387 | if (kled_set_handle && kled_get_handle) |
1330 | out4: | 1388 | ASUS_LED_REGISTER(asus, kled, "kbd_backlight", 3); |
1331 | ASUS_LED_UNREGISTER(pled); | 1389 | error: |
1332 | out3: | 1390 | if (rv) |
1333 | ASUS_LED_UNREGISTER(rled); | 1391 | asus_led_exit(asus); |
1334 | out2: | ||
1335 | ASUS_LED_UNREGISTER(tled); | ||
1336 | out1: | ||
1337 | ASUS_LED_UNREGISTER(mled); | ||
1338 | out: | ||
1339 | return rv; | 1392 | return rv; |
1340 | } | 1393 | } |
1341 | 1394 | ||
1342 | 1395 | ||
1343 | static bool asus_device_present; | 1396 | static bool asus_device_present; |
1344 | 1397 | ||
1345 | static int __devinit asus_acpi_init(struct acpi_device *device) | 1398 | static int __devinit asus_acpi_init(struct asus_laptop *asus) |
1346 | { | 1399 | { |
1347 | int result = 0; | 1400 | int result = 0; |
1348 | 1401 | ||
@@ -1358,22 +1411,22 @@ static int __devinit asus_acpi_init(struct acpi_device *device) | |||
1358 | if (result) | 1411 | if (result) |
1359 | return result; | 1412 | return result; |
1360 | 1413 | ||
1361 | asus_laptop_add_fs(); | 1414 | asus_laptop_add_fs(asus); |
1362 | 1415 | ||
1363 | /* WLED and BLED are on by default */ | 1416 | /* WLED and BLED are on by default */ |
1364 | write_status(bt_switch_handle, 1, BT_ON); | 1417 | write_status(asus, bt_switch_handle, 1, BT_ON); |
1365 | write_status(wl_switch_handle, 1, WL_ON); | 1418 | write_status(asus, wl_switch_handle, 1, WL_ON); |
1366 | 1419 | ||
1367 | /* If the h/w switch is off, we need to check the real status */ | 1420 | /* If the h/w switch is off, we need to check the real status */ |
1368 | write_status(NULL, read_status(BT_ON), BT_ON); | 1421 | write_status(asus, NULL, read_status(asus, BT_ON), BT_ON); |
1369 | write_status(NULL, read_status(WL_ON), WL_ON); | 1422 | write_status(asus, NULL, read_status(asus, WL_ON), WL_ON); |
1370 | 1423 | ||
1371 | /* LCD Backlight is on by default */ | 1424 | /* LCD Backlight is on by default */ |
1372 | write_status(NULL, 1, LCD_ON); | 1425 | write_status(asus, NULL, 1, LCD_ON); |
1373 | 1426 | ||
1374 | /* Keyboard Backlight is on by default */ | 1427 | /* Keyboard Backlight is on by default */ |
1375 | if (kled_set_handle) | 1428 | if (kled_set_handle) |
1376 | set_kled_lvl(1); | 1429 | set_kled_lvl(asus, 1); |
1377 | 1430 | ||
1378 | /* LED display is off by default */ | 1431 | /* LED display is off by default */ |
1379 | asus->ledd_status = 0xFFF; | 1432 | asus->ledd_status = 0xFFF; |
@@ -1383,18 +1436,19 @@ static int __devinit asus_acpi_init(struct acpi_device *device) | |||
1383 | hotk->light_level = 5; /* level 5 for sensor sensitivity */ | 1436 | hotk->light_level = 5; /* level 5 for sensor sensitivity */ |
1384 | 1437 | ||
1385 | if (ls_switch_handle) | 1438 | if (ls_switch_handle) |
1386 | set_light_sens_switch(asus->light_switch); | 1439 | set_light_sens_switch(asus, asus->light_switch); |
1387 | 1440 | ||
1388 | if (ls_level_handle) | 1441 | if (ls_level_handle) |
1389 | set_light_sens_level(asus->light_level); | 1442 | set_light_sens_level(asus, asus->light_level); |
1390 | 1443 | ||
1391 | /* GPS is on by default */ | 1444 | /* GPS is on by default */ |
1392 | write_status(NULL, 1, GPS_ON); | 1445 | write_status(asus, NULL, 1, GPS_ON); |
1393 | return result; | 1446 | return result; |
1394 | } | 1447 | } |
1395 | 1448 | ||
1396 | static int __devinit asus_acpi_add(struct acpi_device *device) | 1449 | static int __devinit asus_acpi_add(struct acpi_device *device) |
1397 | { | 1450 | { |
1451 | struct asus_laptop *asus; | ||
1398 | int result; | 1452 | int result; |
1399 | 1453 | ||
1400 | pr_notice("Asus Laptop Support version %s\n", | 1454 | pr_notice("Asus Laptop Support version %s\n", |
@@ -1408,7 +1462,7 @@ static int __devinit asus_acpi_add(struct acpi_device *device) | |||
1408 | device->driver_data = asus; | 1462 | device->driver_data = asus; |
1409 | asus->device = device; | 1463 | asus->device = device; |
1410 | 1464 | ||
1411 | result = asus_acpi_init(device); | 1465 | result = asus_acpi_init(asus); |
1412 | if (result) | 1466 | if (result) |
1413 | goto fail_platform; | 1467 | goto fail_platform; |
1414 | 1468 | ||
@@ -1416,22 +1470,22 @@ static int __devinit asus_acpi_add(struct acpi_device *device) | |||
1416 | * Register the platform device first. It is used as a parent for the | 1470 | * Register the platform device first. It is used as a parent for the |
1417 | * sub-devices below. | 1471 | * sub-devices below. |
1418 | */ | 1472 | */ |
1419 | result = asus_platform_init(); | 1473 | result = asus_platform_init(asus); |
1420 | if (result) | 1474 | if (result) |
1421 | goto fail_platform; | 1475 | goto fail_platform; |
1422 | 1476 | ||
1423 | if (!acpi_video_backlight_support()) { | 1477 | if (!acpi_video_backlight_support()) { |
1424 | result = asus_backlight_init(&asus->platform_device->dev); | 1478 | result = asus_backlight_init(asus); |
1425 | if (result) | 1479 | if (result) |
1426 | goto fail_backlight; | 1480 | goto fail_backlight; |
1427 | } else | 1481 | } else |
1428 | pr_info("Backlight controlled by ACPI video driver\n"); | 1482 | pr_info("Backlight controlled by ACPI video driver\n"); |
1429 | 1483 | ||
1430 | result = asus_input_init(&asus->platform_device->dev); | 1484 | result = asus_input_init(asus); |
1431 | if (result) | 1485 | if (result) |
1432 | goto fail_input; | 1486 | goto fail_input; |
1433 | 1487 | ||
1434 | result = asus_led_init(&asus->platform_device->dev); | 1488 | result = asus_led_init(asus); |
1435 | if (result) | 1489 | if (result) |
1436 | goto fail_led; | 1490 | goto fail_led; |
1437 | 1491 | ||
@@ -1439,11 +1493,11 @@ static int __devinit asus_acpi_add(struct acpi_device *device) | |||
1439 | return 0; | 1493 | return 0; |
1440 | 1494 | ||
1441 | fail_led: | 1495 | fail_led: |
1442 | asus_input_exit(); | 1496 | asus_input_exit(asus); |
1443 | fail_input: | 1497 | fail_input: |
1444 | asus_backlight_exit(); | 1498 | asus_backlight_exit(asus); |
1445 | fail_backlight: | 1499 | fail_backlight: |
1446 | asus_platform_exit(); | 1500 | asus_platform_exit(asus); |
1447 | fail_platform: | 1501 | fail_platform: |
1448 | kfree(asus->name); | 1502 | kfree(asus->name); |
1449 | kfree(asus); | 1503 | kfree(asus); |
@@ -1453,10 +1507,12 @@ fail_platform: | |||
1453 | 1507 | ||
1454 | static int asus_acpi_remove(struct acpi_device *device, int type) | 1508 | static int asus_acpi_remove(struct acpi_device *device, int type) |
1455 | { | 1509 | { |
1456 | asus_backlight_exit(); | 1510 | struct asus_laptop *asus = acpi_driver_data(device); |
1457 | asus_led_exit(); | 1511 | |
1458 | asus_input_exit(); | 1512 | asus_backlight_exit(asus); |
1459 | asus_platform_exit(); | 1513 | asus_led_exit(asus); |
1514 | asus_input_exit(asus); | ||
1515 | asus_platform_exit(asus); | ||
1460 | 1516 | ||
1461 | kfree(asus->name); | 1517 | kfree(asus->name); |
1462 | kfree(asus); | 1518 | kfree(asus); |