diff options
-rw-r--r-- | drivers/acpi/asus_acpi.c | 331 |
1 files changed, 223 insertions, 108 deletions
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index eb0b8fb837c6..e9ee4c52a5f6 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * asus_acpi.c - Asus Laptop ACPI Extras | 2 | * asus_acpi.c - Asus Laptop ACPI Extras |
3 | * | 3 | * |
4 | * | 4 | * |
5 | * Copyright (C) 2002, 2003, 2004 Julien Lerouge, Karol Kozimor | 5 | * Copyright (C) 2002-2005 Julien Lerouge, 2003-2006 Karol Kozimor |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -26,11 +26,8 @@ | |||
26 | * Pontus Fuchs - Helper functions, cleanup | 26 | * Pontus Fuchs - Helper functions, cleanup |
27 | * Johann Wiesner - Small compile fixes | 27 | * Johann Wiesner - Small compile fixes |
28 | * John Belmonte - ACPI code for Toshiba laptop was a good starting point. | 28 | * John Belmonte - ACPI code for Toshiba laptop was a good starting point. |
29 | * Éric Burghard - LED display support for W1N | ||
29 | * | 30 | * |
30 | * TODO: | ||
31 | * add Fn key status | ||
32 | * Add mode selection on module loading (parameter) -> still necessary? | ||
33 | * Complete display switching -- may require dirty hacks or calling _DOS? | ||
34 | */ | 31 | */ |
35 | 32 | ||
36 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
@@ -42,12 +39,14 @@ | |||
42 | #include <acpi/acpi_bus.h> | 39 | #include <acpi/acpi_bus.h> |
43 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
44 | 41 | ||
45 | #define ASUS_ACPI_VERSION "0.29" | 42 | #define ASUS_ACPI_VERSION "0.30" |
46 | 43 | ||
47 | #define PROC_ASUS "asus" //the directory | 44 | #define PROC_ASUS "asus" //the directory |
48 | #define PROC_MLED "mled" | 45 | #define PROC_MLED "mled" |
49 | #define PROC_WLED "wled" | 46 | #define PROC_WLED "wled" |
50 | #define PROC_TLED "tled" | 47 | #define PROC_TLED "tled" |
48 | #define PROC_BT "bluetooth" | ||
49 | #define PROC_LEDD "ledd" | ||
51 | #define PROC_INFO "info" | 50 | #define PROC_INFO "info" |
52 | #define PROC_LCD "lcd" | 51 | #define PROC_LCD "lcd" |
53 | #define PROC_BRN "brn" | 52 | #define PROC_BRN "brn" |
@@ -67,9 +66,10 @@ | |||
67 | /* | 66 | /* |
68 | * Flags for hotk status | 67 | * Flags for hotk status |
69 | */ | 68 | */ |
70 | #define MLED_ON 0x01 //is MLED ON ? | 69 | #define MLED_ON 0x01 //mail LED |
71 | #define WLED_ON 0x02 | 70 | #define WLED_ON 0x02 //wireless LED |
72 | #define TLED_ON 0x04 | 71 | #define TLED_ON 0x04 //touchpad LED |
72 | #define BT_ON 0x08 //internal Bluetooth | ||
73 | 73 | ||
74 | MODULE_AUTHOR("Julien Lerouge, Karol Kozimor"); | 74 | MODULE_AUTHOR("Julien Lerouge, Karol Kozimor"); |
75 | MODULE_DESCRIPTION(ACPI_HOTK_NAME); | 75 | MODULE_DESCRIPTION(ACPI_HOTK_NAME); |
@@ -92,7 +92,10 @@ struct model_data { | |||
92 | char *wled_status; //node to handle wled reading_______A | 92 | char *wled_status; //node to handle wled reading_______A |
93 | char *mt_tled; //method to handle tled_____________R | 93 | char *mt_tled; //method to handle tled_____________R |
94 | char *tled_status; //node to handle tled reading_______A | 94 | char *tled_status; //node to handle tled reading_______A |
95 | char *mt_lcd_switch; //method to turn LCD ON/OFF_________A | 95 | char *mt_ledd; //method to handle LED display______R |
96 | char *mt_bt_switch; //method to switch Bluetooth on/off_R | ||
97 | char *bt_status; //no model currently supports this__? | ||
98 | char *mt_lcd_switch; //method to turn LCD on/off_________A | ||
96 | char *lcd_status; //node to read LCD panel state______A | 99 | char *lcd_status; //node to read LCD panel state______A |
97 | char *brightness_up; //method to set brightness up_______A | 100 | char *brightness_up; //method to set brightness up_______A |
98 | char *brightness_down; //guess what ?______________________A | 101 | char *brightness_down; //guess what ?______________________A |
@@ -111,27 +114,31 @@ struct asus_hotk { | |||
111 | struct acpi_device *device; //the device we are in | 114 | struct acpi_device *device; //the device we are in |
112 | acpi_handle handle; //the handle of the hotk device | 115 | acpi_handle handle; //the handle of the hotk device |
113 | char status; //status of the hotk, for LEDs, ... | 116 | char status; //status of the hotk, for LEDs, ... |
117 | u32 ledd_status; //status of the LED display | ||
114 | struct model_data *methods; //methods available on the laptop | 118 | struct model_data *methods; //methods available on the laptop |
115 | u8 brightness; //brightness level | 119 | u8 brightness; //brightness level |
116 | enum { | 120 | enum { |
117 | A1x = 0, //A1340D, A1300F | 121 | A1x = 0, //A1340D, A1300F |
118 | A2x, //A2500H | 122 | A2x, //A2500H |
123 | A4G, //A4700G | ||
119 | D1x, //D1 | 124 | D1x, //D1 |
120 | L2D, //L2000D | 125 | L2D, //L2000D |
121 | L3C, //L3800C | 126 | L3C, //L3800C |
122 | L3D, //L3400D | 127 | L3D, //L3400D |
123 | L3H, //L3H, but also L2000E | 128 | L3H, //L3H, L2000E, L5D |
124 | L4R, //L4500R | 129 | L4R, //L4500R |
125 | L5x, //L5800C | 130 | L5x, //L5800C |
126 | L8L, //L8400L | 131 | L8L, //L8400L |
127 | M1A, //M1300A | 132 | M1A, //M1300A |
128 | M2E, //M2400E, L4400L | 133 | M2E, //M2400E, L4400L |
129 | M6N, //M6800N | 134 | M6N, //M6800N, W3400N |
130 | M6R, //M6700R | 135 | M6R, //M6700R, A3000G |
131 | P30, //Samsung P30 | 136 | P30, //Samsung P30 |
132 | S1x, //S1300A, but also L1400B and M2400A (L84F) | 137 | S1x, //S1300A, but also L1400B and M2400A (L84F) |
133 | S2x, //S200 (J1 reported), Victor MP-XP7210 | 138 | S2x, //S200 (J1 reported), Victor MP-XP7210 |
134 | xxN, //M2400N, M3700N, M5200N, S1300N, S5200N, W1OOON | 139 | W1N, //W1000N |
140 | W5A, //W5A | ||
141 | xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N | ||
135 | //(Centrino) | 142 | //(Centrino) |
136 | END_MODEL | 143 | END_MODEL |
137 | } model; //Models currently supported | 144 | } model; //Models currently supported |
@@ -149,17 +156,8 @@ struct asus_hotk { | |||
149 | 156 | ||
150 | static struct model_data model_conf[END_MODEL] = { | 157 | static struct model_data model_conf[END_MODEL] = { |
151 | /* | 158 | /* |
152 | * Those pathnames are relative to the HOTK / ATKD device : | ||
153 | * - mt_mled | ||
154 | * - mt_wled | ||
155 | * - brightness_set | ||
156 | * - brightness_get | ||
157 | * - display_set | ||
158 | * - display_get | ||
159 | * | ||
160 | * TODO I have seen a SWBX and AIBX method on some models, like L1400B, | 159 | * TODO I have seen a SWBX and AIBX method on some models, like L1400B, |
161 | * it seems to be a kind of switch, but what for ? | 160 | * it seems to be a kind of switch, but what for ? |
162 | * | ||
163 | */ | 161 | */ |
164 | 162 | ||
165 | { | 163 | { |
@@ -184,6 +182,16 @@ static struct model_data model_conf[END_MODEL] = { | |||
184 | .display_get = "\\INFB"}, | 182 | .display_get = "\\INFB"}, |
185 | 183 | ||
186 | { | 184 | { |
185 | .name = "A4G", | ||
186 | .mt_mled = "MLED", | ||
187 | /* WLED present, but not controlled by ACPI */ | ||
188 | .mt_lcd_switch = xxN_PREFIX "_Q10", | ||
189 | .brightness_set = "SPLV", | ||
190 | .brightness_get = "GPLV", | ||
191 | .display_set = "SDSP", | ||
192 | .display_get = "\\ADVG"}, | ||
193 | |||
194 | { | ||
187 | .name = "D1x", | 195 | .name = "D1x", |
188 | .mt_mled = "MLED", | 196 | .mt_mled = "MLED", |
189 | .mt_lcd_switch = "\\Q0D", | 197 | .mt_lcd_switch = "\\Q0D", |
@@ -302,7 +310,8 @@ static struct model_data model_conf[END_MODEL] = { | |||
302 | .brightness_set = "SPLV", | 310 | .brightness_set = "SPLV", |
303 | .brightness_get = "GPLV", | 311 | .brightness_get = "GPLV", |
304 | .display_set = "SDSP", | 312 | .display_set = "SDSP", |
305 | .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"}, | 313 | .display_get = "\\SSTE"}, |
314 | |||
306 | { | 315 | { |
307 | .name = "M6R", | 316 | .name = "M6R", |
308 | .mt_mled = "MLED", | 317 | .mt_mled = "MLED", |
@@ -312,7 +321,7 @@ static struct model_data model_conf[END_MODEL] = { | |||
312 | .brightness_set = "SPLV", | 321 | .brightness_set = "SPLV", |
313 | .brightness_get = "GPLV", | 322 | .brightness_get = "GPLV", |
314 | .display_set = "SDSP", | 323 | .display_set = "SDSP", |
315 | .display_get = "\\SSTE"}, | 324 | .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"}, |
316 | 325 | ||
317 | { | 326 | { |
318 | .name = "P30", | 327 | .name = "P30", |
@@ -345,6 +354,28 @@ static struct model_data model_conf[END_MODEL] = { | |||
345 | .brightness_down = S2x_PREFIX "_Q0A"}, | 354 | .brightness_down = S2x_PREFIX "_Q0A"}, |
346 | 355 | ||
347 | { | 356 | { |
357 | .name = "W1N", | ||
358 | .mt_mled = "MLED", | ||
359 | .mt_wled = "WLED", | ||
360 | .mt_ledd = "SLCM", | ||
361 | .mt_lcd_switch = xxN_PREFIX "_Q10", | ||
362 | .lcd_status = "\\BKLT", | ||
363 | .brightness_set = "SPLV", | ||
364 | .brightness_get = "GPLV", | ||
365 | .display_set = "SDSP", | ||
366 | .display_get = "\\ADVG"}, | ||
367 | |||
368 | { | ||
369 | .name = "W5A", | ||
370 | .mt_bt_switch = "BLED", | ||
371 | .mt_wled = "WLED", | ||
372 | .mt_lcd_switch = xxN_PREFIX "_Q10", | ||
373 | .brightness_set = "SPLV", | ||
374 | .brightness_get = "GPLV", | ||
375 | .display_set = "SDSP", | ||
376 | .display_get = "\\ADVG"}, | ||
377 | |||
378 | { | ||
348 | .name = "xxN", | 379 | .name = "xxN", |
349 | .mt_mled = "MLED", | 380 | .mt_mled = "MLED", |
350 | /* WLED present, but not controlled by ACPI */ | 381 | /* WLED present, but not controlled by ACPI */ |
@@ -563,6 +594,36 @@ proc_write_mled(struct file *file, const char __user * buffer, | |||
563 | } | 594 | } |
564 | 595 | ||
565 | /* | 596 | /* |
597 | * Proc handlers for LED display | ||
598 | */ | ||
599 | static int | ||
600 | proc_read_ledd(char *page, char **start, off_t off, int count, int *eof, | ||
601 | void *data) | ||
602 | { | ||
603 | return sprintf(page, "0x%08x\n", hotk->ledd_status); | ||
604 | } | ||
605 | |||
606 | static int | ||
607 | proc_write_ledd(struct file *file, const char __user * buffer, | ||
608 | unsigned long count, void *data) | ||
609 | { | ||
610 | int value; | ||
611 | |||
612 | count = parse_arg(buffer, count, &value); | ||
613 | if (count > 0) { | ||
614 | if (!write_acpi_int | ||
615 | (hotk->handle, hotk->methods->mt_ledd, value, NULL)) | ||
616 | printk(KERN_WARNING | ||
617 | "Asus ACPI: LED display write failed\n"); | ||
618 | else | ||
619 | hotk->ledd_status = (u32) value; | ||
620 | } else if (count < 0) | ||
621 | printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); | ||
622 | |||
623 | return count; | ||
624 | } | ||
625 | |||
626 | /* | ||
566 | * Proc handlers for WLED | 627 | * Proc handlers for WLED |
567 | */ | 628 | */ |
568 | static int | 629 | static int |
@@ -581,6 +642,25 @@ proc_write_wled(struct file *file, const char __user * buffer, | |||
581 | } | 642 | } |
582 | 643 | ||
583 | /* | 644 | /* |
645 | * Proc handlers for Bluetooth | ||
646 | */ | ||
647 | static int | ||
648 | proc_read_bluetooth(char *page, char **start, off_t off, int count, int *eof, | ||
649 | void *data) | ||
650 | { | ||
651 | return sprintf(page, "%d\n", read_led(hotk->methods->bt_status, BT_ON)); | ||
652 | } | ||
653 | |||
654 | static int | ||
655 | proc_write_bluetooth(struct file *file, const char __user * buffer, | ||
656 | unsigned long count, void *data) | ||
657 | { | ||
658 | /* Note: mt_bt_switch controls both internal Bluetooth adapter's | ||
659 | presence and its LED */ | ||
660 | return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0); | ||
661 | } | ||
662 | |||
663 | /* | ||
584 | * Proc handlers for TLED | 664 | * Proc handlers for TLED |
585 | */ | 665 | */ |
586 | static int | 666 | static int |
@@ -876,6 +956,11 @@ static int asus_hotk_add_fs(struct acpi_device *device) | |||
876 | mode, device); | 956 | mode, device); |
877 | } | 957 | } |
878 | 958 | ||
959 | if (hotk->methods->mt_ledd) { | ||
960 | asus_proc_add(PROC_LEDD, &proc_write_ledd, &proc_read_ledd, | ||
961 | mode, device); | ||
962 | } | ||
963 | |||
879 | if (hotk->methods->mt_mled) { | 964 | if (hotk->methods->mt_mled) { |
880 | asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled, | 965 | asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled, |
881 | mode, device); | 966 | mode, device); |
@@ -886,6 +971,11 @@ static int asus_hotk_add_fs(struct acpi_device *device) | |||
886 | mode, device); | 971 | mode, device); |
887 | } | 972 | } |
888 | 973 | ||
974 | if (hotk->methods->mt_bt_switch) { | ||
975 | asus_proc_add(PROC_BT, &proc_write_bluetooth, | ||
976 | &proc_read_bluetooth, mode, device); | ||
977 | } | ||
978 | |||
889 | /* | 979 | /* |
890 | * We need both read node and write method as LCD switch is also accessible | 980 | * We need both read node and write method as LCD switch is also accessible |
891 | * from keyboard | 981 | * from keyboard |
@@ -919,6 +1009,10 @@ static int asus_hotk_remove_fs(struct acpi_device *device) | |||
919 | remove_proc_entry(PROC_MLED, acpi_device_dir(device)); | 1009 | remove_proc_entry(PROC_MLED, acpi_device_dir(device)); |
920 | if (hotk->methods->mt_tled) | 1010 | if (hotk->methods->mt_tled) |
921 | remove_proc_entry(PROC_TLED, acpi_device_dir(device)); | 1011 | remove_proc_entry(PROC_TLED, acpi_device_dir(device)); |
1012 | if (hotk->methods->mt_ledd) | ||
1013 | remove_proc_entry(PROC_LEDD, acpi_device_dir(device)); | ||
1014 | if (hotk->methods->mt_bt_switch) | ||
1015 | remove_proc_entry(PROC_BT, acpi_device_dir(device)); | ||
922 | if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) | 1016 | if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) |
923 | remove_proc_entry(PROC_LCD, acpi_device_dir(device)); | 1017 | remove_proc_entry(PROC_LCD, acpi_device_dir(device)); |
924 | if ((hotk->methods->brightness_up | 1018 | if ((hotk->methods->brightness_up |
@@ -951,6 +1045,65 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
951 | } | 1045 | } |
952 | 1046 | ||
953 | /* | 1047 | /* |
1048 | * Match the model string to the list of supported models. Return END_MODEL if | ||
1049 | * no match or model is NULL. | ||
1050 | */ | ||
1051 | static int asus_model_match(char *model) | ||
1052 | { | ||
1053 | if (model == NULL) | ||
1054 | return END_MODEL; | ||
1055 | |||
1056 | if (strncmp(model, "L3D", 3) == 0) | ||
1057 | return L3D; | ||
1058 | else if (strncmp(model, "L2E", 3) == 0 || | ||
1059 | strncmp(model, "L3H", 3) == 0 || strncmp(model, "L5D", 3) == 0) | ||
1060 | return L3H; | ||
1061 | else if (strncmp(model, "L3", 2) == 0 || strncmp(model, "L2B", 3) == 0) | ||
1062 | return L3C; | ||
1063 | else if (strncmp(model, "L8L", 3) == 0) | ||
1064 | return L8L; | ||
1065 | else if (strncmp(model, "L4R", 3) == 0) | ||
1066 | return L4R; | ||
1067 | else if (strncmp(model, "M6N", 3) == 0 || strncmp(model, "W3N", 3) == 0) | ||
1068 | return M6N; | ||
1069 | else if (strncmp(model, "M6R", 3) == 0 || strncmp(model, "A3G", 3) == 0) | ||
1070 | return M6R; | ||
1071 | else if (strncmp(model, "M2N", 3) == 0 || | ||
1072 | strncmp(model, "M3N", 3) == 0 || | ||
1073 | strncmp(model, "M5N", 3) == 0 || | ||
1074 | strncmp(model, "M6N", 3) == 0 || | ||
1075 | strncmp(model, "S1N", 3) == 0 || | ||
1076 | strncmp(model, "S5N", 3) == 0 || strncmp(model, "W1N", 3) == 0) | ||
1077 | return xxN; | ||
1078 | else if (strncmp(model, "M1", 2) == 0) | ||
1079 | return M1A; | ||
1080 | else if (strncmp(model, "M2", 2) == 0 || strncmp(model, "L4E", 3) == 0) | ||
1081 | return M2E; | ||
1082 | else if (strncmp(model, "L2", 2) == 0) | ||
1083 | return L2D; | ||
1084 | else if (strncmp(model, "L8", 2) == 0) | ||
1085 | return S1x; | ||
1086 | else if (strncmp(model, "D1", 2) == 0) | ||
1087 | return D1x; | ||
1088 | else if (strncmp(model, "A1", 2) == 0) | ||
1089 | return A1x; | ||
1090 | else if (strncmp(model, "A2", 2) == 0) | ||
1091 | return A2x; | ||
1092 | else if (strncmp(model, "J1", 2) == 0) | ||
1093 | return S2x; | ||
1094 | else if (strncmp(model, "L5", 2) == 0) | ||
1095 | return L5x; | ||
1096 | else if (strncmp(model, "A4G", 3) == 0) | ||
1097 | return A4G; | ||
1098 | else if (strncmp(model, "W1N", 3) == 0) | ||
1099 | return W1N; | ||
1100 | else if (strncmp(model, "W5A", 3) == 0) | ||
1101 | return W5A; | ||
1102 | else | ||
1103 | return END_MODEL; | ||
1104 | } | ||
1105 | |||
1106 | /* | ||
954 | * This function is used to initialize the hotk with right values. In this | 1107 | * This function is used to initialize the hotk with right values. In this |
955 | * method, we can make all the detection we want, and modify the hotk struct | 1108 | * method, we can make all the detection we want, and modify the hotk struct |
956 | */ | 1109 | */ |
@@ -960,6 +1113,7 @@ static int asus_hotk_get_info(void) | |||
960 | struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; | 1113 | struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; |
961 | union acpi_object *model = NULL; | 1114 | union acpi_object *model = NULL; |
962 | int bsts_result; | 1115 | int bsts_result; |
1116 | char *string = NULL; | ||
963 | acpi_status status; | 1117 | acpi_status status; |
964 | 1118 | ||
965 | /* | 1119 | /* |
@@ -989,107 +1143,66 @@ static int asus_hotk_get_info(void) | |||
989 | printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", | 1143 | printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", |
990 | bsts_result); | 1144 | bsts_result); |
991 | 1145 | ||
992 | /* This is unlikely with implicit return */ | ||
993 | if (buffer.pointer == NULL) | ||
994 | return -EINVAL; | ||
995 | |||
996 | model = (union acpi_object *) buffer.pointer; | ||
997 | /* | 1146 | /* |
998 | * Samsung P30 has a device with a valid _HID whose INIT does not | 1147 | * Try to match the object returned by INIT to the specific model. |
999 | * return anything. It used to be possible to catch this exception, | 1148 | * Handle every possible object (or the lack of thereof) the DSDT |
1000 | * but the implicit return code will now happily confuse the | 1149 | * writers might throw at us. When in trouble, we pass NULL to |
1001 | * driver. We assume that every ACPI_TYPE_STRING is a valid model | 1150 | * asus_model_match() and try something completely different. |
1002 | * identifier but it's still possible to get completely bogus data. | ||
1003 | */ | 1151 | */ |
1004 | if (model->type == ACPI_TYPE_STRING) { | 1152 | if (buffer.pointer) { |
1005 | printk(KERN_NOTICE " %s model detected, ", model->string.pointer); | 1153 | model = (union acpi_object *)buffer.pointer; |
1006 | } else { | 1154 | switch (model->type) { |
1007 | if (asus_info && /* Samsung P30 */ | 1155 | case ACPI_TYPE_STRING: |
1156 | string = model->string.pointer; | ||
1157 | break; | ||
1158 | case ACPI_TYPE_BUFFER: | ||
1159 | string = model->buffer.pointer; | ||
1160 | break; | ||
1161 | default: | ||
1162 | kfree(model); | ||
1163 | break; | ||
1164 | } | ||
1165 | } | ||
1166 | hotk->model = asus_model_match(string); | ||
1167 | if (hotk->model == END_MODEL) { /* match failed */ | ||
1168 | if (asus_info && | ||
1008 | strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) { | 1169 | strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) { |
1009 | hotk->model = P30; | 1170 | hotk->model = P30; |
1010 | printk(KERN_NOTICE | 1171 | printk(KERN_NOTICE |
1011 | " Samsung P30 detected, supported\n"); | 1172 | " Samsung P30 detected, supported\n"); |
1012 | } else { | 1173 | } else { |
1013 | hotk->model = M2E; | 1174 | hotk->model = M2E; |
1014 | printk(KERN_WARNING " no string returned by INIT\n"); | 1175 | printk(KERN_NOTICE " unsupported model %s, trying " |
1015 | printk(KERN_WARNING " trying default values, supply " | 1176 | "default values\n", string); |
1016 | "the developers with your DSDT\n"); | 1177 | printk(KERN_NOTICE |
1178 | " send /proc/acpi/dsdt to the developers\n"); | ||
1017 | } | 1179 | } |
1018 | hotk->methods = &model_conf[hotk->model]; | 1180 | hotk->methods = &model_conf[hotk->model]; |
1019 | |||
1020 | kfree(model); | ||
1021 | |||
1022 | return AE_OK; | 1181 | return AE_OK; |
1023 | } | 1182 | } |
1024 | |||
1025 | hotk->model = END_MODEL; | ||
1026 | if (strncmp(model->string.pointer, "L3D", 3) == 0) | ||
1027 | hotk->model = L3D; | ||
1028 | else if (strncmp(model->string.pointer, "L3H", 3) == 0 || | ||
1029 | strncmp(model->string.pointer, "L2E", 3) == 0) | ||
1030 | hotk->model = L3H; | ||
1031 | else if (strncmp(model->string.pointer, "L3", 2) == 0 || | ||
1032 | strncmp(model->string.pointer, "L2B", 3) == 0) | ||
1033 | hotk->model = L3C; | ||
1034 | else if (strncmp(model->string.pointer, "L8L", 3) == 0) | ||
1035 | hotk->model = L8L; | ||
1036 | else if (strncmp(model->string.pointer, "L4R", 3) == 0) | ||
1037 | hotk->model = L4R; | ||
1038 | else if (strncmp(model->string.pointer, "M6N", 3) == 0) | ||
1039 | hotk->model = M6N; | ||
1040 | else if (strncmp(model->string.pointer, "M6R", 3) == 0) | ||
1041 | hotk->model = M6R; | ||
1042 | else if (strncmp(model->string.pointer, "M2N", 3) == 0 || | ||
1043 | strncmp(model->string.pointer, "M3N", 3) == 0 || | ||
1044 | strncmp(model->string.pointer, "M5N", 3) == 0 || | ||
1045 | strncmp(model->string.pointer, "M6N", 3) == 0 || | ||
1046 | strncmp(model->string.pointer, "S1N", 3) == 0 || | ||
1047 | strncmp(model->string.pointer, "S5N", 3) == 0 || | ||
1048 | strncmp(model->string.pointer, "W1N", 3) == 0) | ||
1049 | hotk->model = xxN; | ||
1050 | else if (strncmp(model->string.pointer, "M1", 2) == 0) | ||
1051 | hotk->model = M1A; | ||
1052 | else if (strncmp(model->string.pointer, "M2", 2) == 0 || | ||
1053 | strncmp(model->string.pointer, "L4E", 3) == 0) | ||
1054 | hotk->model = M2E; | ||
1055 | else if (strncmp(model->string.pointer, "L2", 2) == 0) | ||
1056 | hotk->model = L2D; | ||
1057 | else if (strncmp(model->string.pointer, "L8", 2) == 0) | ||
1058 | hotk->model = S1x; | ||
1059 | else if (strncmp(model->string.pointer, "D1", 2) == 0) | ||
1060 | hotk->model = D1x; | ||
1061 | else if (strncmp(model->string.pointer, "A1", 2) == 0) | ||
1062 | hotk->model = A1x; | ||
1063 | else if (strncmp(model->string.pointer, "A2", 2) == 0) | ||
1064 | hotk->model = A2x; | ||
1065 | else if (strncmp(model->string.pointer, "J1", 2) == 0) | ||
1066 | hotk->model = S2x; | ||
1067 | else if (strncmp(model->string.pointer, "L5", 2) == 0) | ||
1068 | hotk->model = L5x; | ||
1069 | |||
1070 | if (hotk->model == END_MODEL) { | ||
1071 | printk("unsupported, trying default values, supply the " | ||
1072 | "developers with your DSDT\n"); | ||
1073 | hotk->model = M2E; | ||
1074 | } else { | ||
1075 | printk("supported\n"); | ||
1076 | } | ||
1077 | |||
1078 | hotk->methods = &model_conf[hotk->model]; | 1183 | hotk->methods = &model_conf[hotk->model]; |
1184 | printk(KERN_NOTICE " %s model detected, supported\n", string); | ||
1079 | 1185 | ||
1080 | /* Sort of per-model blacklist */ | 1186 | /* Sort of per-model blacklist */ |
1081 | if (strncmp(model->string.pointer, "L2B", 3) == 0) | 1187 | if (strncmp(string, "L2B", 3) == 0) |
1082 | hotk->methods->lcd_status = NULL; | 1188 | hotk->methods->lcd_status = NULL; |
1083 | /* L2B is similar enough to L3C to use its settings, with this only | 1189 | /* L2B is similar enough to L3C to use its settings, with this only |
1084 | exception */ | 1190 | exception */ |
1085 | else if (strncmp(model->string.pointer, "S5N", 3) == 0 || | 1191 | else if (strncmp(string, "A3G", 3) == 0) |
1086 | strncmp(model->string.pointer, "M5N", 3) == 0) | 1192 | hotk->methods->lcd_status = "\\BLFG"; |
1193 | /* A3G is like M6R */ | ||
1194 | else if (strncmp(string, "S5N", 3) == 0 || | ||
1195 | strncmp(string, "M5N", 3) == 0 || | ||
1196 | strncmp(string, "W3N", 3) == 0) | ||
1087 | hotk->methods->mt_mled = NULL; | 1197 | hotk->methods->mt_mled = NULL; |
1088 | /* S5N and M5N have no MLED */ | 1198 | /* S5N, M5N and W3N have no MLED */ |
1089 | else if (strncmp(model->string.pointer, "M2N", 3) == 0 || | 1199 | else if (strncmp(string, "L5D", 3) == 0) |
1090 | strncmp(model->string.pointer, "W1N", 3) == 0) | 1200 | hotk->methods->mt_wled = NULL; |
1201 | /* L5D's WLED is not controlled by ACPI */ | ||
1202 | else if (strncmp(string, "M2N", 3) == 0 || | ||
1203 | strncmp(string, "S1N", 3) == 0) | ||
1091 | hotk->methods->mt_wled = "WLED"; | 1204 | hotk->methods->mt_wled = "WLED"; |
1092 | /* M2N and W1N have a usable WLED */ | 1205 | /* M2N and S1N have a usable WLED */ |
1093 | else if (asus_info) { | 1206 | else if (asus_info) { |
1094 | if (strncmp(asus_info->oem_table_id, "L1", 2) == 0) | 1207 | if (strncmp(asus_info->oem_table_id, "L1", 2) == 0) |
1095 | hotk->methods->mled_status = NULL; | 1208 | hotk->methods->mled_status = NULL; |
@@ -1164,8 +1277,7 @@ static int asus_hotk_add(struct acpi_device *device) | |||
1164 | /* For laptops without GPLV: init the hotk->brightness value */ | 1277 | /* For laptops without GPLV: init the hotk->brightness value */ |
1165 | if ((!hotk->methods->brightness_get) | 1278 | if ((!hotk->methods->brightness_get) |
1166 | && (!hotk->methods->brightness_status) | 1279 | && (!hotk->methods->brightness_status) |
1167 | && (hotk->methods->brightness_up | 1280 | && (hotk->methods->brightness_up && hotk->methods->brightness_down)) { |
1168 | && hotk->methods->brightness_down)) { | ||
1169 | status = | 1281 | status = |
1170 | acpi_evaluate_object(NULL, hotk->methods->brightness_down, | 1282 | acpi_evaluate_object(NULL, hotk->methods->brightness_down, |
1171 | NULL, NULL); | 1283 | NULL, NULL); |
@@ -1184,6 +1296,9 @@ static int asus_hotk_add(struct acpi_device *device) | |||
1184 | 1296 | ||
1185 | asus_hotk_found = 1; | 1297 | asus_hotk_found = 1; |
1186 | 1298 | ||
1299 | /* LED display is off by default */ | ||
1300 | hotk->ledd_status = 0xFFF; | ||
1301 | |||
1187 | end: | 1302 | end: |
1188 | if (result) { | 1303 | if (result) { |
1189 | kfree(hotk); | 1304 | kfree(hotk); |