diff options
Diffstat (limited to 'drivers/platform/x86/asus-laptop.c')
-rw-r--r-- | drivers/platform/x86/asus-laptop.c | 463 |
1 files changed, 204 insertions, 259 deletions
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index b756e07d41b4..d65df92e2acc 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
@@ -29,7 +29,7 @@ | |||
29 | * John Belmonte - ACPI code for Toshiba laptop was a good starting point. | 29 | * John Belmonte - ACPI code for Toshiba laptop was a good starting point. |
30 | * Eric Burghard - LED display support for W1N | 30 | * Eric Burghard - LED display support for W1N |
31 | * Josh Green - Light Sens support | 31 | * Josh Green - Light Sens support |
32 | * Thomas Tuttle - His first patch for led support was very helpfull | 32 | * Thomas Tuttle - His first patch for led support was very helpful |
33 | * Sam Lin - GPS support | 33 | * Sam Lin - GPS support |
34 | */ | 34 | */ |
35 | 35 | ||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/input/sparse-keymap.h> | 50 | #include <linux/input/sparse-keymap.h> |
51 | #include <linux/rfkill.h> | 51 | #include <linux/rfkill.h> |
52 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
53 | #include <linux/dmi.h> | ||
53 | #include <acpi/acpi_drivers.h> | 54 | #include <acpi/acpi_drivers.h> |
54 | #include <acpi/acpi_bus.h> | 55 | #include <acpi/acpi_bus.h> |
55 | 56 | ||
@@ -81,6 +82,8 @@ MODULE_PARM_DESC(wapf, "WAPF value"); | |||
81 | 82 | ||
82 | static int wlan_status = 1; | 83 | static int wlan_status = 1; |
83 | static int bluetooth_status = 1; | 84 | static int bluetooth_status = 1; |
85 | static int wimax_status = -1; | ||
86 | static int wwan_status = -1; | ||
84 | 87 | ||
85 | module_param(wlan_status, int, 0444); | 88 | module_param(wlan_status, int, 0444); |
86 | MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot " | 89 | MODULE_PARM_DESC(wlan_status, "Set the wireless status on boot " |
@@ -92,6 +95,16 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " | |||
92 | "(0 = disabled, 1 = enabled, -1 = don't do anything). " | 95 | "(0 = disabled, 1 = enabled, -1 = don't do anything). " |
93 | "default is 1"); | 96 | "default is 1"); |
94 | 97 | ||
98 | module_param(wimax_status, int, 0444); | ||
99 | MODULE_PARM_DESC(wimax_status, "Set the wireless status on boot " | ||
100 | "(0 = disabled, 1 = enabled, -1 = don't do anything). " | ||
101 | "default is 1"); | ||
102 | |||
103 | module_param(wwan_status, int, 0444); | ||
104 | MODULE_PARM_DESC(wwan_status, "Set the wireless status on boot " | ||
105 | "(0 = disabled, 1 = enabled, -1 = don't do anything). " | ||
106 | "default is 1"); | ||
107 | |||
95 | /* | 108 | /* |
96 | * Some events we use, same for all Asus | 109 | * Some events we use, same for all Asus |
97 | */ | 110 | */ |
@@ -114,6 +127,8 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " | |||
114 | */ | 127 | */ |
115 | #define WL_RSTS 0x01 /* internal Wifi */ | 128 | #define WL_RSTS 0x01 /* internal Wifi */ |
116 | #define BT_RSTS 0x02 /* internal Bluetooth */ | 129 | #define BT_RSTS 0x02 /* internal Bluetooth */ |
130 | #define WM_RSTS 0x08 /* internal wimax */ | ||
131 | #define WW_RSTS 0x20 /* internal wwan */ | ||
117 | 132 | ||
118 | /* LED */ | 133 | /* LED */ |
119 | #define METHOD_MLED "MLED" | 134 | #define METHOD_MLED "MLED" |
@@ -132,52 +147,20 @@ MODULE_PARM_DESC(bluetooth_status, "Set the wireless status on boot " | |||
132 | */ | 147 | */ |
133 | #define METHOD_WLAN "WLED" | 148 | #define METHOD_WLAN "WLED" |
134 | #define METHOD_BLUETOOTH "BLED" | 149 | #define METHOD_BLUETOOTH "BLED" |
150 | |||
151 | /* WWAN and WIMAX */ | ||
152 | #define METHOD_WWAN "GSMC" | ||
153 | #define METHOD_WIMAX "WMXC" | ||
154 | |||
135 | #define METHOD_WL_STATUS "RSTS" | 155 | #define METHOD_WL_STATUS "RSTS" |
136 | 156 | ||
137 | /* Brightness */ | 157 | /* Brightness */ |
138 | #define METHOD_BRIGHTNESS_SET "SPLV" | 158 | #define METHOD_BRIGHTNESS_SET "SPLV" |
139 | #define METHOD_BRIGHTNESS_GET "GPLV" | 159 | #define METHOD_BRIGHTNESS_GET "GPLV" |
140 | 160 | ||
141 | /* Backlight */ | ||
142 | static acpi_handle lcd_switch_handle; | ||
143 | static char *lcd_switch_paths[] = { | ||
144 | "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ | ||
145 | "\\_SB.PCI0.ISA.EC0._Q10", /* A1x */ | ||
146 | "\\_SB.PCI0.PX40.ECD0._Q10", /* L3C */ | ||
147 | "\\_SB.PCI0.PX40.EC0.Q10", /* M1A */ | ||
148 | "\\_SB.PCI0.LPCB.EC0._Q10", /* P30 */ | ||
149 | "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */ | ||
150 | "\\_SB.PCI0.PX40.Q10", /* S1x */ | ||
151 | "\\Q10"}; /* A2x, L2D, L3D, M2E */ | ||
152 | |||
153 | /* Display */ | 161 | /* Display */ |
154 | #define METHOD_SWITCH_DISPLAY "SDSP" | 162 | #define METHOD_SWITCH_DISPLAY "SDSP" |
155 | 163 | ||
156 | static acpi_handle display_get_handle; | ||
157 | static char *display_get_paths[] = { | ||
158 | /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */ | ||
159 | "\\_SB.PCI0.P0P1.VGA.GETD", | ||
160 | /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */ | ||
161 | "\\_SB.PCI0.P0P2.VGA.GETD", | ||
162 | /* A6V A6Q */ | ||
163 | "\\_SB.PCI0.P0P3.VGA.GETD", | ||
164 | /* A6T, A6M */ | ||
165 | "\\_SB.PCI0.P0PA.VGA.GETD", | ||
166 | /* L3C */ | ||
167 | "\\_SB.PCI0.PCI1.VGAC.NMAP", | ||
168 | /* Z96F */ | ||
169 | "\\_SB.PCI0.VGA.GETD", | ||
170 | /* A2D */ | ||
171 | "\\ACTD", | ||
172 | /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */ | ||
173 | "\\ADVG", | ||
174 | /* P30 */ | ||
175 | "\\DNXT", | ||
176 | /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */ | ||
177 | "\\INFB", | ||
178 | /* A3F A6F A3N A3L M6N W3N W6A */ | ||
179 | "\\SSTE"}; | ||
180 | |||
181 | #define METHOD_ALS_CONTROL "ALSC" /* Z71A Z71V */ | 164 | #define METHOD_ALS_CONTROL "ALSC" /* Z71A Z71V */ |
182 | #define METHOD_ALS_LEVEL "ALSL" /* Z71A Z71V */ | 165 | #define METHOD_ALS_LEVEL "ALSL" /* Z71A Z71V */ |
183 | 166 | ||
@@ -227,7 +210,6 @@ struct asus_laptop { | |||
227 | 210 | ||
228 | int wireless_status; | 211 | int wireless_status; |
229 | bool have_rsts; | 212 | bool have_rsts; |
230 | int lcd_state; | ||
231 | 213 | ||
232 | struct rfkill *gps_rfkill; | 214 | struct rfkill *gps_rfkill; |
233 | 215 | ||
@@ -236,7 +218,6 @@ struct asus_laptop { | |||
236 | u8 light_level; /* light sensor level */ | 218 | u8 light_level; /* light sensor level */ |
237 | u8 light_switch; /* light sensor switch value */ | 219 | u8 light_switch; /* light sensor switch value */ |
238 | u16 event_count[128]; /* count for each event TODO make this better */ | 220 | u16 event_count[128]; /* count for each event TODO make this better */ |
239 | u16 *keycode_map; | ||
240 | }; | 221 | }; |
241 | 222 | ||
242 | static const struct key_entry asus_keymap[] = { | 223 | static const struct key_entry asus_keymap[] = { |
@@ -278,6 +259,7 @@ static const struct key_entry asus_keymap[] = { | |||
278 | {KE_KEY, 0x99, { KEY_PHONE } }, | 259 | {KE_KEY, 0x99, { KEY_PHONE } }, |
279 | {KE_KEY, 0xc4, { KEY_KBDILLUMUP } }, | 260 | {KE_KEY, 0xc4, { KEY_KBDILLUMUP } }, |
280 | {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } }, | 261 | {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } }, |
262 | {KE_KEY, 0xb5, { KEY_CALC } }, | ||
281 | {KE_END, 0}, | 263 | {KE_END, 0}, |
282 | }; | 264 | }; |
283 | 265 | ||
@@ -336,7 +318,7 @@ static int acpi_check_handle(acpi_handle handle, const char *method, | |||
336 | 318 | ||
337 | if (status != AE_OK) { | 319 | if (status != AE_OK) { |
338 | if (ret) | 320 | if (ret) |
339 | pr_warning("Error finding %s\n", method); | 321 | pr_warn("Error finding %s\n", method); |
340 | return -ENODEV; | 322 | return -ENODEV; |
341 | } | 323 | } |
342 | return 0; | 324 | return 0; |
@@ -401,7 +383,7 @@ static int asus_kled_lvl(struct asus_laptop *asus) | |||
401 | rv = acpi_evaluate_integer(asus->handle, METHOD_KBD_LIGHT_GET, | 383 | rv = acpi_evaluate_integer(asus->handle, METHOD_KBD_LIGHT_GET, |
402 | ¶ms, &kblv); | 384 | ¶ms, &kblv); |
403 | if (ACPI_FAILURE(rv)) { | 385 | if (ACPI_FAILURE(rv)) { |
404 | pr_warning("Error reading kled level\n"); | 386 | pr_warn("Error reading kled level\n"); |
405 | return -ENODEV; | 387 | return -ENODEV; |
406 | } | 388 | } |
407 | return kblv; | 389 | return kblv; |
@@ -415,7 +397,7 @@ static int asus_kled_set(struct asus_laptop *asus, int kblv) | |||
415 | kblv = 0; | 397 | kblv = 0; |
416 | 398 | ||
417 | if (write_acpi_int(asus->handle, METHOD_KBD_LIGHT_SET, kblv)) { | 399 | if (write_acpi_int(asus->handle, METHOD_KBD_LIGHT_SET, kblv)) { |
418 | pr_warning("Keyboard LED display write failed\n"); | 400 | pr_warn("Keyboard LED display write failed\n"); |
419 | return -EINVAL; | 401 | return -EINVAL; |
420 | } | 402 | } |
421 | return 0; | 403 | return 0; |
@@ -540,48 +522,6 @@ error: | |||
540 | /* | 522 | /* |
541 | * Backlight device | 523 | * Backlight device |
542 | */ | 524 | */ |
543 | static int asus_lcd_status(struct asus_laptop *asus) | ||
544 | { | ||
545 | return asus->lcd_state; | ||
546 | } | ||
547 | |||
548 | static int asus_lcd_set(struct asus_laptop *asus, int value) | ||
549 | { | ||
550 | int lcd = 0; | ||
551 | acpi_status status = 0; | ||
552 | |||
553 | lcd = !!value; | ||
554 | |||
555 | if (lcd == asus_lcd_status(asus)) | ||
556 | return 0; | ||
557 | |||
558 | if (!lcd_switch_handle) | ||
559 | return -ENODEV; | ||
560 | |||
561 | status = acpi_evaluate_object(lcd_switch_handle, | ||
562 | NULL, NULL, NULL); | ||
563 | |||
564 | if (ACPI_FAILURE(status)) { | ||
565 | pr_warning("Error switching LCD\n"); | ||
566 | return -ENODEV; | ||
567 | } | ||
568 | |||
569 | asus->lcd_state = lcd; | ||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | static void lcd_blank(struct asus_laptop *asus, int blank) | ||
574 | { | ||
575 | struct backlight_device *bd = asus->backlight_device; | ||
576 | |||
577 | asus->lcd_state = (blank == FB_BLANK_UNBLANK); | ||
578 | |||
579 | if (bd) { | ||
580 | bd->props.power = blank; | ||
581 | backlight_update_status(bd); | ||
582 | } | ||
583 | } | ||
584 | |||
585 | static int asus_read_brightness(struct backlight_device *bd) | 525 | static int asus_read_brightness(struct backlight_device *bd) |
586 | { | 526 | { |
587 | struct asus_laptop *asus = bl_get_data(bd); | 527 | struct asus_laptop *asus = bl_get_data(bd); |
@@ -591,7 +531,7 @@ static int asus_read_brightness(struct backlight_device *bd) | |||
591 | rv = acpi_evaluate_integer(asus->handle, METHOD_BRIGHTNESS_GET, | 531 | rv = acpi_evaluate_integer(asus->handle, METHOD_BRIGHTNESS_GET, |
592 | NULL, &value); | 532 | NULL, &value); |
593 | if (ACPI_FAILURE(rv)) | 533 | if (ACPI_FAILURE(rv)) |
594 | pr_warning("Error reading brightness\n"); | 534 | pr_warn("Error reading brightness\n"); |
595 | 535 | ||
596 | return value; | 536 | return value; |
597 | } | 537 | } |
@@ -601,7 +541,7 @@ static int asus_set_brightness(struct backlight_device *bd, int value) | |||
601 | struct asus_laptop *asus = bl_get_data(bd); | 541 | struct asus_laptop *asus = bl_get_data(bd); |
602 | 542 | ||
603 | if (write_acpi_int(asus->handle, METHOD_BRIGHTNESS_SET, value)) { | 543 | if (write_acpi_int(asus->handle, METHOD_BRIGHTNESS_SET, value)) { |
604 | pr_warning("Error changing brightness\n"); | 544 | pr_warn("Error changing brightness\n"); |
605 | return -EIO; | 545 | return -EIO; |
606 | } | 546 | } |
607 | return 0; | 547 | return 0; |
@@ -609,19 +549,12 @@ static int asus_set_brightness(struct backlight_device *bd, int value) | |||
609 | 549 | ||
610 | static int update_bl_status(struct backlight_device *bd) | 550 | static int update_bl_status(struct backlight_device *bd) |
611 | { | 551 | { |
612 | struct asus_laptop *asus = bl_get_data(bd); | ||
613 | int rv; | ||
614 | int value = bd->props.brightness; | 552 | int value = bd->props.brightness; |
615 | 553 | ||
616 | rv = asus_set_brightness(bd, value); | 554 | return asus_set_brightness(bd, value); |
617 | if (rv) | ||
618 | return rv; | ||
619 | |||
620 | value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0; | ||
621 | return asus_lcd_set(asus, value); | ||
622 | } | 555 | } |
623 | 556 | ||
624 | static struct backlight_ops asusbl_ops = { | 557 | static const struct backlight_ops asusbl_ops = { |
625 | .get_brightness = asus_read_brightness, | 558 | .get_brightness = asus_read_brightness, |
626 | .update_status = update_bl_status, | 559 | .update_status = update_bl_status, |
627 | }; | 560 | }; |
@@ -639,29 +572,29 @@ static int asus_backlight_notify(struct asus_laptop *asus) | |||
639 | static int asus_backlight_init(struct asus_laptop *asus) | 572 | static int asus_backlight_init(struct asus_laptop *asus) |
640 | { | 573 | { |
641 | struct backlight_device *bd; | 574 | struct backlight_device *bd; |
642 | struct device *dev = &asus->platform_device->dev; | ||
643 | struct backlight_properties props; | 575 | struct backlight_properties props; |
644 | 576 | ||
645 | if (!acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) && | 577 | if (acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) || |
646 | !acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) && | 578 | acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL)) |
647 | lcd_switch_handle) { | 579 | return 0; |
648 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
649 | props.max_brightness = 15; | ||
650 | |||
651 | bd = backlight_device_register(ASUS_LAPTOP_FILE, dev, | ||
652 | asus, &asusbl_ops, &props); | ||
653 | if (IS_ERR(bd)) { | ||
654 | pr_err("Could not register asus backlight device\n"); | ||
655 | asus->backlight_device = NULL; | ||
656 | return PTR_ERR(bd); | ||
657 | } | ||
658 | |||
659 | asus->backlight_device = bd; | ||
660 | 580 | ||
661 | bd->props.power = FB_BLANK_UNBLANK; | 581 | memset(&props, 0, sizeof(struct backlight_properties)); |
662 | bd->props.brightness = asus_read_brightness(bd); | 582 | props.max_brightness = 15; |
663 | backlight_update_status(bd); | 583 | props.type = BACKLIGHT_PLATFORM; |
584 | |||
585 | bd = backlight_device_register(ASUS_LAPTOP_FILE, | ||
586 | &asus->platform_device->dev, asus, | ||
587 | &asusbl_ops, &props); | ||
588 | if (IS_ERR(bd)) { | ||
589 | pr_err("Could not register asus backlight device\n"); | ||
590 | asus->backlight_device = NULL; | ||
591 | return PTR_ERR(bd); | ||
664 | } | 592 | } |
593 | |||
594 | asus->backlight_device = bd; | ||
595 | bd->props.brightness = asus_read_brightness(bd); | ||
596 | bd->props.power = FB_BLANK_UNBLANK; | ||
597 | backlight_update_status(bd); | ||
665 | return 0; | 598 | return 0; |
666 | } | 599 | } |
667 | 600 | ||
@@ -797,7 +730,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, | |||
797 | rv = parse_arg(buf, count, &value); | 730 | rv = parse_arg(buf, count, &value); |
798 | if (rv > 0) { | 731 | if (rv > 0) { |
799 | if (write_acpi_int(asus->handle, METHOD_LEDD, value)) { | 732 | if (write_acpi_int(asus->handle, METHOD_LEDD, value)) { |
800 | pr_warning("LED display write failed\n"); | 733 | pr_warn("LED display write failed\n"); |
801 | return -ENODEV; | 734 | return -ENODEV; |
802 | } | 735 | } |
803 | asus->ledd_status = (u32) value; | 736 | asus->ledd_status = (u32) value; |
@@ -819,7 +752,7 @@ static int asus_wireless_status(struct asus_laptop *asus, int mask) | |||
819 | rv = acpi_evaluate_integer(asus->handle, METHOD_WL_STATUS, | 752 | rv = acpi_evaluate_integer(asus->handle, METHOD_WL_STATUS, |
820 | NULL, &status); | 753 | NULL, &status); |
821 | if (ACPI_FAILURE(rv)) { | 754 | if (ACPI_FAILURE(rv)) { |
822 | pr_warning("Error reading Wireless status\n"); | 755 | pr_warn("Error reading Wireless status\n"); |
823 | return -EINVAL; | 756 | return -EINVAL; |
824 | } | 757 | } |
825 | return !!(status & mask); | 758 | return !!(status & mask); |
@@ -831,7 +764,7 @@ static int asus_wireless_status(struct asus_laptop *asus, int mask) | |||
831 | static int asus_wlan_set(struct asus_laptop *asus, int status) | 764 | static int asus_wlan_set(struct asus_laptop *asus, int status) |
832 | { | 765 | { |
833 | if (write_acpi_int(asus->handle, METHOD_WLAN, !!status)) { | 766 | if (write_acpi_int(asus->handle, METHOD_WLAN, !!status)) { |
834 | pr_warning("Error setting wlan status to %d", status); | 767 | pr_warn("Error setting wlan status to %d\n", status); |
835 | return -EIO; | 768 | return -EIO; |
836 | } | 769 | } |
837 | return 0; | 770 | return 0; |
@@ -859,7 +792,7 @@ static ssize_t store_wlan(struct device *dev, struct device_attribute *attr, | |||
859 | static int asus_bluetooth_set(struct asus_laptop *asus, int status) | 792 | static int asus_bluetooth_set(struct asus_laptop *asus, int status) |
860 | { | 793 | { |
861 | if (write_acpi_int(asus->handle, METHOD_BLUETOOTH, !!status)) { | 794 | if (write_acpi_int(asus->handle, METHOD_BLUETOOTH, !!status)) { |
862 | pr_warning("Error setting bluetooth status to %d", status); | 795 | pr_warn("Error setting bluetooth status to %d\n", status); |
863 | return -EIO; | 796 | return -EIO; |
864 | } | 797 | } |
865 | return 0; | 798 | return 0; |
@@ -883,49 +816,72 @@ static ssize_t store_bluetooth(struct device *dev, | |||
883 | } | 816 | } |
884 | 817 | ||
885 | /* | 818 | /* |
886 | * Display | 819 | * Wimax |
887 | */ | 820 | */ |
888 | static void asus_set_display(struct asus_laptop *asus, int value) | 821 | static int asus_wimax_set(struct asus_laptop *asus, int status) |
889 | { | 822 | { |
890 | /* no sanity check needed for now */ | 823 | if (write_acpi_int(asus->handle, METHOD_WIMAX, !!status)) { |
891 | if (write_acpi_int(asus->handle, METHOD_SWITCH_DISPLAY, value)) | 824 | pr_warn("Error setting wimax status to %d\n", status); |
892 | pr_warning("Error setting display\n"); | 825 | return -EIO; |
893 | return; | 826 | } |
827 | return 0; | ||
894 | } | 828 | } |
895 | 829 | ||
896 | static int read_display(struct asus_laptop *asus) | 830 | static ssize_t show_wimax(struct device *dev, |
831 | struct device_attribute *attr, char *buf) | ||
897 | { | 832 | { |
898 | unsigned long long value = 0; | 833 | struct asus_laptop *asus = dev_get_drvdata(dev); |
899 | acpi_status rv = AE_OK; | ||
900 | 834 | ||
901 | /* | 835 | return sprintf(buf, "%d\n", asus_wireless_status(asus, WM_RSTS)); |
902 | * In most of the case, we know how to set the display, but sometime | 836 | } |
903 | * we can't read it | ||
904 | */ | ||
905 | if (display_get_handle) { | ||
906 | rv = acpi_evaluate_integer(display_get_handle, NULL, | ||
907 | NULL, &value); | ||
908 | if (ACPI_FAILURE(rv)) | ||
909 | pr_warning("Error reading display status\n"); | ||
910 | } | ||
911 | 837 | ||
912 | value &= 0x0F; /* needed for some models, shouldn't hurt others */ | 838 | static ssize_t store_wimax(struct device *dev, |
839 | struct device_attribute *attr, const char *buf, | ||
840 | size_t count) | ||
841 | { | ||
842 | struct asus_laptop *asus = dev_get_drvdata(dev); | ||
913 | 843 | ||
914 | return value; | 844 | return sysfs_acpi_set(asus, buf, count, METHOD_WIMAX); |
915 | } | 845 | } |
916 | 846 | ||
917 | /* | 847 | /* |
918 | * Now, *this* one could be more user-friendly, but so far, no-one has | 848 | * Wwan |
919 | * complained. The significance of bits is the same as in store_disp() | ||
920 | */ | 849 | */ |
921 | static ssize_t show_disp(struct device *dev, | 850 | static int asus_wwan_set(struct asus_laptop *asus, int status) |
922 | struct device_attribute *attr, char *buf) | 851 | { |
852 | if (write_acpi_int(asus->handle, METHOD_WWAN, !!status)) { | ||
853 | pr_warn("Error setting wwan status to %d\n", status); | ||
854 | return -EIO; | ||
855 | } | ||
856 | return 0; | ||
857 | } | ||
858 | |||
859 | static ssize_t show_wwan(struct device *dev, | ||
860 | struct device_attribute *attr, char *buf) | ||
923 | { | 861 | { |
924 | struct asus_laptop *asus = dev_get_drvdata(dev); | 862 | struct asus_laptop *asus = dev_get_drvdata(dev); |
925 | 863 | ||
926 | if (!display_get_handle) | 864 | return sprintf(buf, "%d\n", asus_wireless_status(asus, WW_RSTS)); |
927 | return -ENODEV; | 865 | } |
928 | return sprintf(buf, "%d\n", read_display(asus)); | 866 | |
867 | static ssize_t store_wwan(struct device *dev, | ||
868 | struct device_attribute *attr, const char *buf, | ||
869 | size_t count) | ||
870 | { | ||
871 | struct asus_laptop *asus = dev_get_drvdata(dev); | ||
872 | |||
873 | return sysfs_acpi_set(asus, buf, count, METHOD_WWAN); | ||
874 | } | ||
875 | |||
876 | /* | ||
877 | * Display | ||
878 | */ | ||
879 | static void asus_set_display(struct asus_laptop *asus, int value) | ||
880 | { | ||
881 | /* no sanity check needed for now */ | ||
882 | if (write_acpi_int(asus->handle, METHOD_SWITCH_DISPLAY, value)) | ||
883 | pr_warn("Error setting display\n"); | ||
884 | return; | ||
929 | } | 885 | } |
930 | 886 | ||
931 | /* | 887 | /* |
@@ -953,7 +909,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr, | |||
953 | static void asus_als_switch(struct asus_laptop *asus, int value) | 909 | static void asus_als_switch(struct asus_laptop *asus, int value) |
954 | { | 910 | { |
955 | if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value)) | 911 | if (write_acpi_int(asus->handle, METHOD_ALS_CONTROL, value)) |
956 | pr_warning("Error setting light sensor switch\n"); | 912 | pr_warn("Error setting light sensor switch\n"); |
957 | asus->light_switch = value; | 913 | asus->light_switch = value; |
958 | } | 914 | } |
959 | 915 | ||
@@ -981,7 +937,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, | |||
981 | static void asus_als_level(struct asus_laptop *asus, int value) | 937 | static void asus_als_level(struct asus_laptop *asus, int value) |
982 | { | 938 | { |
983 | if (write_acpi_int(asus->handle, METHOD_ALS_LEVEL, value)) | 939 | if (write_acpi_int(asus->handle, METHOD_ALS_LEVEL, value)) |
984 | pr_warning("Error setting light sensor level\n"); | 940 | pr_warn("Error setting light sensor level\n"); |
985 | asus->light_level = value; | 941 | asus->light_level = value; |
986 | } | 942 | } |
987 | 943 | ||
@@ -1020,7 +976,7 @@ static int asus_gps_status(struct asus_laptop *asus) | |||
1020 | rv = acpi_evaluate_integer(asus->handle, METHOD_GPS_STATUS, | 976 | rv = acpi_evaluate_integer(asus->handle, METHOD_GPS_STATUS, |
1021 | NULL, &status); | 977 | NULL, &status); |
1022 | if (ACPI_FAILURE(rv)) { | 978 | if (ACPI_FAILURE(rv)) { |
1023 | pr_warning("Error reading GPS status\n"); | 979 | pr_warn("Error reading GPS status\n"); |
1024 | return -ENODEV; | 980 | return -ENODEV; |
1025 | } | 981 | } |
1026 | return !!status; | 982 | return !!status; |
@@ -1065,9 +1021,9 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr, | |||
1065 | */ | 1021 | */ |
1066 | static int asus_gps_rfkill_set(void *data, bool blocked) | 1022 | static int asus_gps_rfkill_set(void *data, bool blocked) |
1067 | { | 1023 | { |
1068 | acpi_handle handle = data; | 1024 | struct asus_laptop *asus = data; |
1069 | 1025 | ||
1070 | return asus_gps_switch(handle, !blocked); | 1026 | return asus_gps_switch(asus, !blocked); |
1071 | } | 1027 | } |
1072 | 1028 | ||
1073 | static const struct rfkill_ops asus_gps_rfkill_ops = { | 1029 | static const struct rfkill_ops asus_gps_rfkill_ops = { |
@@ -1094,7 +1050,7 @@ static int asus_rfkill_init(struct asus_laptop *asus) | |||
1094 | 1050 | ||
1095 | asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev, | 1051 | asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev, |
1096 | RFKILL_TYPE_GPS, | 1052 | RFKILL_TYPE_GPS, |
1097 | &asus_gps_rfkill_ops, NULL); | 1053 | &asus_gps_rfkill_ops, asus); |
1098 | if (!asus->gps_rfkill) | 1054 | if (!asus->gps_rfkill) |
1099 | return -EINVAL; | 1055 | return -EINVAL; |
1100 | 1056 | ||
@@ -1130,7 +1086,6 @@ static int asus_input_init(struct asus_laptop *asus) | |||
1130 | input->phys = ASUS_LAPTOP_FILE "/input0"; | 1086 | input->phys = ASUS_LAPTOP_FILE "/input0"; |
1131 | input->id.bustype = BUS_HOST; | 1087 | input->id.bustype = BUS_HOST; |
1132 | input->dev.parent = &asus->platform_device->dev; | 1088 | input->dev.parent = &asus->platform_device->dev; |
1133 | input_set_drvdata(input, asus); | ||
1134 | 1089 | ||
1135 | error = sparse_keymap_setup(input, asus_keymap, NULL); | 1090 | error = sparse_keymap_setup(input, asus_keymap, NULL); |
1136 | if (error) { | 1091 | if (error) { |
@@ -1159,6 +1114,7 @@ static void asus_input_exit(struct asus_laptop *asus) | |||
1159 | sparse_keymap_free(asus->inputdev); | 1114 | sparse_keymap_free(asus->inputdev); |
1160 | input_unregister_device(asus->inputdev); | 1115 | input_unregister_device(asus->inputdev); |
1161 | } | 1116 | } |
1117 | asus->inputdev = NULL; | ||
1162 | } | 1118 | } |
1163 | 1119 | ||
1164 | /* | 1120 | /* |
@@ -1169,15 +1125,6 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) | |||
1169 | struct asus_laptop *asus = acpi_driver_data(device); | 1125 | struct asus_laptop *asus = acpi_driver_data(device); |
1170 | u16 count; | 1126 | u16 count; |
1171 | 1127 | ||
1172 | /* | ||
1173 | * We need to tell the backlight device when the backlight power is | ||
1174 | * switched | ||
1175 | */ | ||
1176 | if (event == ATKD_LCD_ON) | ||
1177 | lcd_blank(asus, FB_BLANK_UNBLANK); | ||
1178 | else if (event == ATKD_LCD_OFF) | ||
1179 | lcd_blank(asus, FB_BLANK_POWERDOWN); | ||
1180 | |||
1181 | /* TODO Find a better way to handle events count. */ | 1128 | /* TODO Find a better way to handle events count. */ |
1182 | count = asus->event_count[event % 128]++; | 1129 | count = asus->event_count[event % 128]++; |
1183 | acpi_bus_generate_proc_event(asus->device, event, count); | 1130 | acpi_bus_generate_proc_event(asus->device, event, count); |
@@ -1200,111 +1147,111 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) | |||
1200 | 1147 | ||
1201 | static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL); | 1148 | static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL); |
1202 | static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan); | 1149 | static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan); |
1203 | static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, show_bluetooth, | 1150 | static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, |
1204 | store_bluetooth); | 1151 | show_bluetooth, store_bluetooth); |
1205 | static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp); | 1152 | static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax); |
1153 | static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan); | ||
1154 | static DEVICE_ATTR(display, S_IWUSR, NULL, store_disp); | ||
1206 | static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd); | 1155 | static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd); |
1207 | static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl); | 1156 | static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl); |
1208 | static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw); | 1157 | static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw); |
1209 | static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps); | 1158 | static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps); |
1210 | 1159 | ||
1211 | static void asus_sysfs_exit(struct asus_laptop *asus) | 1160 | static struct attribute *asus_attributes[] = { |
1212 | { | 1161 | &dev_attr_infos.attr, |
1213 | struct platform_device *device = asus->platform_device; | 1162 | &dev_attr_wlan.attr, |
1214 | 1163 | &dev_attr_bluetooth.attr, | |
1215 | device_remove_file(&device->dev, &dev_attr_infos); | 1164 | &dev_attr_wimax.attr, |
1216 | device_remove_file(&device->dev, &dev_attr_wlan); | 1165 | &dev_attr_wwan.attr, |
1217 | device_remove_file(&device->dev, &dev_attr_bluetooth); | 1166 | &dev_attr_display.attr, |
1218 | device_remove_file(&device->dev, &dev_attr_display); | 1167 | &dev_attr_ledd.attr, |
1219 | device_remove_file(&device->dev, &dev_attr_ledd); | 1168 | &dev_attr_ls_level.attr, |
1220 | device_remove_file(&device->dev, &dev_attr_ls_switch); | 1169 | &dev_attr_ls_switch.attr, |
1221 | device_remove_file(&device->dev, &dev_attr_ls_level); | 1170 | &dev_attr_gps.attr, |
1222 | device_remove_file(&device->dev, &dev_attr_gps); | 1171 | NULL |
1223 | } | 1172 | }; |
1224 | 1173 | ||
1225 | static int asus_sysfs_init(struct asus_laptop *asus) | 1174 | static mode_t asus_sysfs_is_visible(struct kobject *kobj, |
1175 | struct attribute *attr, | ||
1176 | int idx) | ||
1226 | { | 1177 | { |
1227 | struct platform_device *device = asus->platform_device; | 1178 | struct device *dev = container_of(kobj, struct device, kobj); |
1228 | int err; | 1179 | struct platform_device *pdev = to_platform_device(dev); |
1180 | struct asus_laptop *asus = platform_get_drvdata(pdev); | ||
1181 | acpi_handle handle = asus->handle; | ||
1182 | bool supported; | ||
1229 | 1183 | ||
1230 | err = device_create_file(&device->dev, &dev_attr_infos); | 1184 | if (attr == &dev_attr_wlan.attr) { |
1231 | if (err) | 1185 | supported = !acpi_check_handle(handle, METHOD_WLAN, NULL); |
1232 | return err; | ||
1233 | 1186 | ||
1234 | if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) { | 1187 | } else if (attr == &dev_attr_bluetooth.attr) { |
1235 | err = device_create_file(&device->dev, &dev_attr_wlan); | 1188 | supported = !acpi_check_handle(handle, METHOD_BLUETOOTH, NULL); |
1236 | if (err) | ||
1237 | return err; | ||
1238 | } | ||
1239 | 1189 | ||
1240 | if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) { | 1190 | } else if (attr == &dev_attr_display.attr) { |
1241 | err = device_create_file(&device->dev, &dev_attr_bluetooth); | 1191 | supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL); |
1242 | if (err) | ||
1243 | return err; | ||
1244 | } | ||
1245 | 1192 | ||
1246 | if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) { | 1193 | } else if (attr == &dev_attr_wimax.attr) { |
1247 | err = device_create_file(&device->dev, &dev_attr_display); | 1194 | supported = |
1248 | if (err) | 1195 | !acpi_check_handle(asus->handle, METHOD_WIMAX, NULL); |
1249 | return err; | ||
1250 | } | ||
1251 | 1196 | ||
1252 | if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) { | 1197 | } else if (attr == &dev_attr_wwan.attr) { |
1253 | err = device_create_file(&device->dev, &dev_attr_ledd); | 1198 | supported = !acpi_check_handle(asus->handle, METHOD_WWAN, NULL); |
1254 | if (err) | ||
1255 | return err; | ||
1256 | } | ||
1257 | 1199 | ||
1258 | if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) && | 1200 | } else if (attr == &dev_attr_ledd.attr) { |
1259 | !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) { | 1201 | supported = !acpi_check_handle(handle, METHOD_LEDD, NULL); |
1260 | err = device_create_file(&device->dev, &dev_attr_ls_switch); | 1202 | |
1261 | if (err) | 1203 | } else if (attr == &dev_attr_ls_switch.attr || |
1262 | return err; | 1204 | attr == &dev_attr_ls_level.attr) { |
1263 | err = device_create_file(&device->dev, &dev_attr_ls_level); | 1205 | supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) && |
1264 | if (err) | 1206 | !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL); |
1265 | return err; | ||
1266 | } | ||
1267 | 1207 | ||
1268 | if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) && | 1208 | } else if (attr == &dev_attr_gps.attr) { |
1269 | !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) && | 1209 | supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) && |
1270 | !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) { | 1210 | !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) && |
1271 | err = device_create_file(&device->dev, &dev_attr_gps); | 1211 | !acpi_check_handle(handle, METHOD_GPS_STATUS, NULL); |
1272 | if (err) | 1212 | } else { |
1273 | return err; | 1213 | supported = true; |
1274 | } | 1214 | } |
1275 | 1215 | ||
1276 | return err; | 1216 | return supported ? attr->mode : 0; |
1277 | } | 1217 | } |
1278 | 1218 | ||
1219 | |||
1220 | static const struct attribute_group asus_attr_group = { | ||
1221 | .is_visible = asus_sysfs_is_visible, | ||
1222 | .attrs = asus_attributes, | ||
1223 | }; | ||
1224 | |||
1279 | static int asus_platform_init(struct asus_laptop *asus) | 1225 | static int asus_platform_init(struct asus_laptop *asus) |
1280 | { | 1226 | { |
1281 | int err; | 1227 | int result; |
1282 | 1228 | ||
1283 | asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1); | 1229 | asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1); |
1284 | if (!asus->platform_device) | 1230 | if (!asus->platform_device) |
1285 | return -ENOMEM; | 1231 | return -ENOMEM; |
1286 | platform_set_drvdata(asus->platform_device, asus); | 1232 | platform_set_drvdata(asus->platform_device, asus); |
1287 | 1233 | ||
1288 | err = platform_device_add(asus->platform_device); | 1234 | result = platform_device_add(asus->platform_device); |
1289 | if (err) | 1235 | if (result) |
1290 | goto fail_platform_device; | 1236 | goto fail_platform_device; |
1291 | 1237 | ||
1292 | err = asus_sysfs_init(asus); | 1238 | result = sysfs_create_group(&asus->platform_device->dev.kobj, |
1293 | if (err) | 1239 | &asus_attr_group); |
1240 | if (result) | ||
1294 | goto fail_sysfs; | 1241 | goto fail_sysfs; |
1242 | |||
1295 | return 0; | 1243 | return 0; |
1296 | 1244 | ||
1297 | fail_sysfs: | 1245 | fail_sysfs: |
1298 | asus_sysfs_exit(asus); | ||
1299 | platform_device_del(asus->platform_device); | 1246 | platform_device_del(asus->platform_device); |
1300 | fail_platform_device: | 1247 | fail_platform_device: |
1301 | platform_device_put(asus->platform_device); | 1248 | platform_device_put(asus->platform_device); |
1302 | return err; | 1249 | return result; |
1303 | } | 1250 | } |
1304 | 1251 | ||
1305 | static void asus_platform_exit(struct asus_laptop *asus) | 1252 | static void asus_platform_exit(struct asus_laptop *asus) |
1306 | { | 1253 | { |
1307 | asus_sysfs_exit(asus); | 1254 | sysfs_remove_group(&asus->platform_device->dev.kobj, &asus_attr_group); |
1308 | platform_device_unregister(asus->platform_device); | 1255 | platform_device_unregister(asus->platform_device); |
1309 | } | 1256 | } |
1310 | 1257 | ||
@@ -1315,26 +1262,6 @@ static struct platform_driver platform_driver = { | |||
1315 | } | 1262 | } |
1316 | }; | 1263 | }; |
1317 | 1264 | ||
1318 | static int asus_handle_init(char *name, acpi_handle * handle, | ||
1319 | char **paths, int num_paths) | ||
1320 | { | ||
1321 | int i; | ||
1322 | acpi_status status; | ||
1323 | |||
1324 | for (i = 0; i < num_paths; i++) { | ||
1325 | status = acpi_get_handle(NULL, paths[i], handle); | ||
1326 | if (ACPI_SUCCESS(status)) | ||
1327 | return 0; | ||
1328 | } | ||
1329 | |||
1330 | *handle = NULL; | ||
1331 | return -ENODEV; | ||
1332 | } | ||
1333 | |||
1334 | #define ASUS_HANDLE_INIT(object) \ | ||
1335 | asus_handle_init(#object, &object##_handle, object##_paths, \ | ||
1336 | ARRAY_SIZE(object##_paths)) | ||
1337 | |||
1338 | /* | 1265 | /* |
1339 | * This function is used to initialize the context with right values. In this | 1266 | * This function is used to initialize the context with right values. In this |
1340 | * method, we can make all the detection we want, and modify the asus_laptop | 1267 | * method, we can make all the detection we want, and modify the asus_laptop |
@@ -1357,7 +1284,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus) | |||
1357 | */ | 1284 | */ |
1358 | status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus->dsdt_info); | 1285 | status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus->dsdt_info); |
1359 | if (ACPI_FAILURE(status)) | 1286 | if (ACPI_FAILURE(status)) |
1360 | pr_warning("Couldn't get the DSDT table header\n"); | 1287 | pr_warn("Couldn't get the DSDT table header\n"); |
1361 | 1288 | ||
1362 | /* We have to write 0 on init this far for all ASUS models */ | 1289 | /* We have to write 0 on init this far for all ASUS models */ |
1363 | if (write_acpi_int_ret(asus->handle, "INIT", 0, &buffer)) { | 1290 | if (write_acpi_int_ret(asus->handle, "INIT", 0, &buffer)) { |
@@ -1369,7 +1296,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus) | |||
1369 | status = | 1296 | status = |
1370 | acpi_evaluate_integer(asus->handle, "BSTS", NULL, &bsts_result); | 1297 | acpi_evaluate_integer(asus->handle, "BSTS", NULL, &bsts_result); |
1371 | if (ACPI_FAILURE(status)) | 1298 | if (ACPI_FAILURE(status)) |
1372 | pr_warning("Error calling BSTS\n"); | 1299 | pr_warn("Error calling BSTS\n"); |
1373 | else if (bsts_result) | 1300 | else if (bsts_result) |
1374 | pr_notice("BSTS called, 0x%02x returned\n", | 1301 | pr_notice("BSTS called, 0x%02x returned\n", |
1375 | (uint) bsts_result); | 1302 | (uint) bsts_result); |
@@ -1408,7 +1335,8 @@ static int asus_laptop_get_info(struct asus_laptop *asus) | |||
1408 | 1335 | ||
1409 | /* | 1336 | /* |
1410 | * The HWRS method return informations about the hardware. | 1337 | * The HWRS method return informations about the hardware. |
1411 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. | 1338 | * 0x80 bit is for WLAN, 0x100 for Bluetooth, |
1339 | * 0x40 for WWAN, 0x10 for WIMAX. | ||
1412 | * The significance of others is yet to be found. | 1340 | * The significance of others is yet to be found. |
1413 | */ | 1341 | */ |
1414 | status = | 1342 | status = |
@@ -1419,17 +1347,11 @@ static int asus_laptop_get_info(struct asus_laptop *asus) | |||
1419 | if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) | 1347 | if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) |
1420 | asus->have_rsts = true; | 1348 | asus->have_rsts = true; |
1421 | 1349 | ||
1422 | /* Scheduled for removal */ | ||
1423 | ASUS_HANDLE_INIT(lcd_switch); | ||
1424 | ASUS_HANDLE_INIT(display_get); | ||
1425 | |||
1426 | kfree(model); | 1350 | kfree(model); |
1427 | 1351 | ||
1428 | return AE_OK; | 1352 | return AE_OK; |
1429 | } | 1353 | } |
1430 | 1354 | ||
1431 | static bool asus_device_present; | ||
1432 | |||
1433 | static int __devinit asus_acpi_init(struct asus_laptop *asus) | 1355 | static int __devinit asus_acpi_init(struct asus_laptop *asus) |
1434 | { | 1356 | { |
1435 | int result = 0; | 1357 | int result = 0; |
@@ -1453,6 +1375,12 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) | |||
1453 | if (wlan_status >= 0) | 1375 | if (wlan_status >= 0) |
1454 | asus_wlan_set(asus, !!wlan_status); | 1376 | asus_wlan_set(asus, !!wlan_status); |
1455 | 1377 | ||
1378 | if (wimax_status >= 0) | ||
1379 | asus_wimax_set(asus, !!wimax_status); | ||
1380 | |||
1381 | if (wwan_status >= 0) | ||
1382 | asus_wwan_set(asus, !!wwan_status); | ||
1383 | |||
1456 | /* Keyboard Backlight is on by default */ | 1384 | /* Keyboard Backlight is on by default */ |
1457 | if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL)) | 1385 | if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL)) |
1458 | asus_kled_set(asus, 1); | 1386 | asus_kled_set(asus, 1); |
@@ -1470,10 +1398,25 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus) | |||
1470 | asus_als_level(asus, asus->light_level); | 1398 | asus_als_level(asus, asus->light_level); |
1471 | } | 1399 | } |
1472 | 1400 | ||
1473 | asus->lcd_state = 1; /* LCD should be on when the module load */ | ||
1474 | return result; | 1401 | return result; |
1475 | } | 1402 | } |
1476 | 1403 | ||
1404 | static void __devinit asus_dmi_check(void) | ||
1405 | { | ||
1406 | const char *model; | ||
1407 | |||
1408 | model = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
1409 | if (!model) | ||
1410 | return; | ||
1411 | |||
1412 | /* On L1400B WLED control the sound card, don't mess with it ... */ | ||
1413 | if (strncmp(model, "L1400B", 6) == 0) { | ||
1414 | wlan_status = -1; | ||
1415 | } | ||
1416 | } | ||
1417 | |||
1418 | static bool asus_device_present; | ||
1419 | |||
1477 | static int __devinit asus_acpi_add(struct acpi_device *device) | 1420 | static int __devinit asus_acpi_add(struct acpi_device *device) |
1478 | { | 1421 | { |
1479 | struct asus_laptop *asus; | 1422 | struct asus_laptop *asus; |
@@ -1490,6 +1433,8 @@ static int __devinit asus_acpi_add(struct acpi_device *device) | |||
1490 | device->driver_data = asus; | 1433 | device->driver_data = asus; |
1491 | asus->device = device; | 1434 | asus->device = device; |
1492 | 1435 | ||
1436 | asus_dmi_check(); | ||
1437 | |||
1493 | result = asus_acpi_init(asus); | 1438 | result = asus_acpi_init(asus); |
1494 | if (result) | 1439 | if (result) |
1495 | goto fail_platform; | 1440 | goto fail_platform; |