diff options
Diffstat (limited to 'drivers/platform/x86/asus-laptop.c')
-rw-r--r-- | drivers/platform/x86/asus-laptop.c | 227 |
1 files changed, 173 insertions, 54 deletions
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index db657bbeec90..b39d2bb3e75b 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
@@ -77,15 +77,16 @@ | |||
77 | * Flags for hotk status | 77 | * Flags for hotk status |
78 | * WL_ON and BT_ON are also used for wireless_status() | 78 | * WL_ON and BT_ON are also used for wireless_status() |
79 | */ | 79 | */ |
80 | #define WL_ON 0x01 //internal Wifi | 80 | #define WL_ON 0x01 /* internal Wifi */ |
81 | #define BT_ON 0x02 //internal Bluetooth | 81 | #define BT_ON 0x02 /* internal Bluetooth */ |
82 | #define MLED_ON 0x04 //mail LED | 82 | #define MLED_ON 0x04 /* mail LED */ |
83 | #define TLED_ON 0x08 //touchpad LED | 83 | #define TLED_ON 0x08 /* touchpad LED */ |
84 | #define RLED_ON 0x10 //Record LED | 84 | #define RLED_ON 0x10 /* Record LED */ |
85 | #define PLED_ON 0x20 //Phone LED | 85 | #define PLED_ON 0x20 /* Phone LED */ |
86 | #define GLED_ON 0x40 //Gaming LED | 86 | #define GLED_ON 0x40 /* Gaming LED */ |
87 | #define LCD_ON 0x80 //LCD backlight | 87 | #define LCD_ON 0x80 /* LCD backlight */ |
88 | #define GPS_ON 0x100 //GPS | 88 | #define GPS_ON 0x100 /* GPS */ |
89 | #define KEY_ON 0x200 /* Keyboard backlight */ | ||
89 | 90 | ||
90 | #define ASUS_LOG ASUS_HOTK_FILE ": " | 91 | #define ASUS_LOG ASUS_HOTK_FILE ": " |
91 | #define ASUS_ERR KERN_ERR ASUS_LOG | 92 | #define ASUS_ERR KERN_ERR ASUS_LOG |
@@ -98,7 +99,8 @@ MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary"); | |||
98 | MODULE_DESCRIPTION(ASUS_HOTK_NAME); | 99 | MODULE_DESCRIPTION(ASUS_HOTK_NAME); |
99 | MODULE_LICENSE("GPL"); | 100 | MODULE_LICENSE("GPL"); |
100 | 101 | ||
101 | /* WAPF defines the behavior of the Fn+Fx wlan key | 102 | /* |
103 | * WAPF defines the behavior of the Fn+Fx wlan key | ||
102 | * The significance of values is yet to be found, but | 104 | * The significance of values is yet to be found, but |
103 | * most of the time: | 105 | * most of the time: |
104 | * 0x0 will do nothing | 106 | * 0x0 will do nothing |
@@ -125,7 +127,8 @@ ASUS_HANDLE(gled_set, ASUS_HOTK_PREFIX "GLED"); /* G1, G2 (probably) */ | |||
125 | /* LEDD */ | 127 | /* LEDD */ |
126 | ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM"); | 128 | ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM"); |
127 | 129 | ||
128 | /* Bluetooth and WLAN | 130 | /* |
131 | * Bluetooth and WLAN | ||
129 | * WLED and BLED are not handled like other XLED, because in some dsdt | 132 | * WLED and BLED are not handled like other XLED, because in some dsdt |
130 | * they also control the WLAN/Bluetooth device. | 133 | * they also control the WLAN/Bluetooth device. |
131 | */ | 134 | */ |
@@ -149,22 +152,32 @@ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ | |||
149 | 152 | ||
150 | /* Display */ | 153 | /* Display */ |
151 | ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP"); | 154 | ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP"); |
152 | ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L4R M6R A3G | 155 | ASUS_HANDLE(display_get, |
153 | M6A M6V VX-1 V6J V6V W3Z */ | 156 | /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */ |
154 | "\\_SB.PCI0.P0P2.VGA.GETD", /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V | 157 | "\\_SB.PCI0.P0P1.VGA.GETD", |
155 | S5A M5A z33A W1Jc W2V G1 */ | 158 | /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */ |
156 | "\\_SB.PCI0.P0P3.VGA.GETD", /* A6V A6Q */ | 159 | "\\_SB.PCI0.P0P2.VGA.GETD", |
157 | "\\_SB.PCI0.P0PA.VGA.GETD", /* A6T, A6M */ | 160 | /* A6V A6Q */ |
158 | "\\_SB.PCI0.PCI1.VGAC.NMAP", /* L3C */ | 161 | "\\_SB.PCI0.P0P3.VGA.GETD", |
159 | "\\_SB.PCI0.VGA.GETD", /* Z96F */ | 162 | /* A6T, A6M */ |
160 | "\\ACTD", /* A2D */ | 163 | "\\_SB.PCI0.P0PA.VGA.GETD", |
161 | "\\ADVG", /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */ | 164 | /* L3C */ |
162 | "\\DNXT", /* P30 */ | 165 | "\\_SB.PCI0.PCI1.VGAC.NMAP", |
163 | "\\INFB", /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */ | 166 | /* Z96F */ |
164 | "\\SSTE"); /* A3F A6F A3N A3L M6N W3N W6A */ | 167 | "\\_SB.PCI0.VGA.GETD", |
165 | 168 | /* A2D */ | |
166 | ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ | 169 | "\\ACTD", |
167 | ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ | 170 | /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */ |
171 | "\\ADVG", | ||
172 | /* P30 */ | ||
173 | "\\DNXT", | ||
174 | /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */ | ||
175 | "\\INFB", | ||
176 | /* A3F A6F A3N A3L M6N W3N W6A */ | ||
177 | "\\SSTE"); | ||
178 | |||
179 | ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ | ||
180 | ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ | ||
168 | 181 | ||
169 | /* GPS */ | 182 | /* GPS */ |
170 | /* R2H use different handle for GPS on/off */ | 183 | /* R2H use different handle for GPS on/off */ |
@@ -172,19 +185,23 @@ ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON"); /* R2H */ | |||
172 | ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ | 185 | ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ |
173 | ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); | 186 | ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); |
174 | 187 | ||
188 | /* Keyboard light */ | ||
189 | ASUS_HANDLE(kled_set, ASUS_HOTK_PREFIX "SLKB"); | ||
190 | ASUS_HANDLE(kled_get, ASUS_HOTK_PREFIX "GLKB"); | ||
191 | |||
175 | /* | 192 | /* |
176 | * This is the main structure, we can use it to store anything interesting | 193 | * This is the main structure, we can use it to store anything interesting |
177 | * about the hotk device | 194 | * about the hotk device |
178 | */ | 195 | */ |
179 | struct asus_hotk { | 196 | struct asus_hotk { |
180 | char *name; //laptop name | 197 | char *name; /* laptop name */ |
181 | struct acpi_device *device; //the device we are in | 198 | struct acpi_device *device; /* the device we are in */ |
182 | acpi_handle handle; //the handle of the hotk device | 199 | acpi_handle handle; /* the handle of the hotk device */ |
183 | char status; //status of the hotk, for LEDs, ... | 200 | char status; /* status of the hotk, for LEDs, ... */ |
184 | u32 ledd_status; //status of the LED display | 201 | u32 ledd_status; /* status of the LED display */ |
185 | u8 light_level; //light sensor level | 202 | u8 light_level; /* light sensor level */ |
186 | u8 light_switch; //light sensor switch value | 203 | u8 light_switch; /* light sensor switch value */ |
187 | u16 event_count[128]; //count for each event TODO make this better | 204 | u16 event_count[128]; /* count for each event TODO make this better */ |
188 | struct input_dev *inputdev; | 205 | struct input_dev *inputdev; |
189 | u16 *keycode_map; | 206 | u16 *keycode_map; |
190 | }; | 207 | }; |
@@ -237,28 +254,35 @@ static struct backlight_ops asusbl_ops = { | |||
237 | .update_status = update_bl_status, | 254 | .update_status = update_bl_status, |
238 | }; | 255 | }; |
239 | 256 | ||
240 | /* These functions actually update the LED's, and are called from a | 257 | /* |
258 | * These functions actually update the LED's, and are called from a | ||
241 | * workqueue. By doing this as separate work rather than when the LED | 259 | * workqueue. By doing this as separate work rather than when the LED |
242 | * subsystem asks, we avoid messing with the Asus ACPI stuff during a | 260 | * subsystem asks, we avoid messing with the Asus ACPI stuff during a |
243 | * potentially bad time, such as a timer interrupt. */ | 261 | * potentially bad time, such as a timer interrupt. |
262 | */ | ||
244 | static struct workqueue_struct *led_workqueue; | 263 | static struct workqueue_struct *led_workqueue; |
245 | 264 | ||
246 | #define ASUS_LED(object, ledname) \ | 265 | #define ASUS_LED(object, ledname, max) \ |
247 | static void object##_led_set(struct led_classdev *led_cdev, \ | 266 | static void object##_led_set(struct led_classdev *led_cdev, \ |
248 | enum led_brightness value); \ | 267 | enum led_brightness value); \ |
268 | static enum led_brightness object##_led_get( \ | ||
269 | struct led_classdev *led_cdev); \ | ||
249 | static void object##_led_update(struct work_struct *ignored); \ | 270 | static void object##_led_update(struct work_struct *ignored); \ |
250 | static int object##_led_wk; \ | 271 | static int object##_led_wk; \ |
251 | static DECLARE_WORK(object##_led_work, object##_led_update); \ | 272 | static DECLARE_WORK(object##_led_work, object##_led_update); \ |
252 | static struct led_classdev object##_led = { \ | 273 | static struct led_classdev object##_led = { \ |
253 | .name = "asus::" ledname, \ | 274 | .name = "asus::" ledname, \ |
254 | .brightness_set = object##_led_set, \ | 275 | .brightness_set = object##_led_set, \ |
276 | .brightness_get = object##_led_get, \ | ||
277 | .max_brightness = max \ | ||
255 | } | 278 | } |
256 | 279 | ||
257 | ASUS_LED(mled, "mail"); | 280 | ASUS_LED(mled, "mail", 1); |
258 | ASUS_LED(tled, "touchpad"); | 281 | ASUS_LED(tled, "touchpad", 1); |
259 | ASUS_LED(rled, "record"); | 282 | ASUS_LED(rled, "record", 1); |
260 | ASUS_LED(pled, "phone"); | 283 | ASUS_LED(pled, "phone", 1); |
261 | ASUS_LED(gled, "gaming"); | 284 | ASUS_LED(gled, "gaming", 1); |
285 | ASUS_LED(kled, "kbd_backlight", 3); | ||
262 | 286 | ||
263 | struct key_entry { | 287 | struct key_entry { |
264 | char type; | 288 | char type; |
@@ -278,16 +302,23 @@ static struct key_entry asus_keymap[] = { | |||
278 | {KE_KEY, 0x41, KEY_NEXTSONG}, | 302 | {KE_KEY, 0x41, KEY_NEXTSONG}, |
279 | {KE_KEY, 0x43, KEY_STOPCD}, | 303 | {KE_KEY, 0x43, KEY_STOPCD}, |
280 | {KE_KEY, 0x45, KEY_PLAYPAUSE}, | 304 | {KE_KEY, 0x45, KEY_PLAYPAUSE}, |
305 | {KE_KEY, 0x4c, KEY_MEDIA}, | ||
281 | {KE_KEY, 0x50, KEY_EMAIL}, | 306 | {KE_KEY, 0x50, KEY_EMAIL}, |
282 | {KE_KEY, 0x51, KEY_WWW}, | 307 | {KE_KEY, 0x51, KEY_WWW}, |
308 | {KE_KEY, 0x55, KEY_CALC}, | ||
283 | {KE_KEY, 0x5C, KEY_SCREENLOCK}, /* Screenlock */ | 309 | {KE_KEY, 0x5C, KEY_SCREENLOCK}, /* Screenlock */ |
284 | {KE_KEY, 0x5D, KEY_WLAN}, | 310 | {KE_KEY, 0x5D, KEY_WLAN}, |
311 | {KE_KEY, 0x5E, KEY_WLAN}, | ||
312 | {KE_KEY, 0x5F, KEY_WLAN}, | ||
313 | {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE}, | ||
285 | {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, | 314 | {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, |
286 | {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ | 315 | {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ |
287 | {KE_KEY, 0x82, KEY_CAMERA}, | 316 | {KE_KEY, 0x82, KEY_CAMERA}, |
288 | {KE_KEY, 0x8A, KEY_PROG1}, | 317 | {KE_KEY, 0x8A, KEY_PROG1}, |
289 | {KE_KEY, 0x95, KEY_MEDIA}, | 318 | {KE_KEY, 0x95, KEY_MEDIA}, |
290 | {KE_KEY, 0x99, KEY_PHONE}, | 319 | {KE_KEY, 0x99, KEY_PHONE}, |
320 | {KE_KEY, 0xc4, KEY_KBDILLUMUP}, | ||
321 | {KE_KEY, 0xc5, KEY_KBDILLUMDOWN}, | ||
291 | {KE_END, 0}, | 322 | {KE_END, 0}, |
292 | }; | 323 | }; |
293 | 324 | ||
@@ -301,8 +332,8 @@ static struct key_entry asus_keymap[] = { | |||
301 | static int write_acpi_int(acpi_handle handle, const char *method, int val, | 332 | static int write_acpi_int(acpi_handle handle, const char *method, int val, |
302 | struct acpi_buffer *output) | 333 | struct acpi_buffer *output) |
303 | { | 334 | { |
304 | struct acpi_object_list params; //list of input parameters (an int here) | 335 | struct acpi_object_list params; /* list of input parameters (an int) */ |
305 | union acpi_object in_obj; //the only param we use | 336 | union acpi_object in_obj; /* the only param we use */ |
306 | acpi_status status; | 337 | acpi_status status; |
307 | 338 | ||
308 | if (!handle) | 339 | if (!handle) |
@@ -399,6 +430,11 @@ static void write_status(acpi_handle handle, int out, int mask) | |||
399 | { \ | 430 | { \ |
400 | int value = object##_led_wk; \ | 431 | int value = object##_led_wk; \ |
401 | write_status(object##_set_handle, value, (mask)); \ | 432 | write_status(object##_set_handle, value, (mask)); \ |
433 | } \ | ||
434 | static enum led_brightness object##_led_get( \ | ||
435 | struct led_classdev *led_cdev) \ | ||
436 | { \ | ||
437 | return led_cdev->brightness; \ | ||
402 | } | 438 | } |
403 | 439 | ||
404 | ASUS_LED_HANDLER(mled, MLED_ON); | 440 | ASUS_LED_HANDLER(mled, MLED_ON); |
@@ -407,6 +443,60 @@ ASUS_LED_HANDLER(rled, RLED_ON); | |||
407 | ASUS_LED_HANDLER(tled, TLED_ON); | 443 | ASUS_LED_HANDLER(tled, TLED_ON); |
408 | ASUS_LED_HANDLER(gled, GLED_ON); | 444 | ASUS_LED_HANDLER(gled, GLED_ON); |
409 | 445 | ||
446 | /* | ||
447 | * Keyboard backlight | ||
448 | */ | ||
449 | static int get_kled_lvl(void) | ||
450 | { | ||
451 | unsigned long long kblv; | ||
452 | struct acpi_object_list params; | ||
453 | union acpi_object in_obj; | ||
454 | acpi_status rv; | ||
455 | |||
456 | params.count = 1; | ||
457 | params.pointer = &in_obj; | ||
458 | in_obj.type = ACPI_TYPE_INTEGER; | ||
459 | in_obj.integer.value = 2; | ||
460 | |||
461 | rv = acpi_evaluate_integer(kled_get_handle, NULL, ¶ms, &kblv); | ||
462 | if (ACPI_FAILURE(rv)) { | ||
463 | pr_warning("Error reading kled level\n"); | ||
464 | return 0; | ||
465 | } | ||
466 | return kblv; | ||
467 | } | ||
468 | |||
469 | static int set_kled_lvl(int kblv) | ||
470 | { | ||
471 | if (kblv > 0) | ||
472 | kblv = (1 << 7) | (kblv & 0x7F); | ||
473 | else | ||
474 | kblv = 0; | ||
475 | |||
476 | if (write_acpi_int(kled_set_handle, NULL, kblv, NULL)) { | ||
477 | pr_warning("Keyboard LED display write failed\n"); | ||
478 | return -EINVAL; | ||
479 | } | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static void kled_led_set(struct led_classdev *led_cdev, | ||
484 | enum led_brightness value) | ||
485 | { | ||
486 | kled_led_wk = value; | ||
487 | queue_work(led_workqueue, &kled_led_work); | ||
488 | } | ||
489 | |||
490 | static void kled_led_update(struct work_struct *ignored) | ||
491 | { | ||
492 | set_kled_lvl(kled_led_wk); | ||
493 | } | ||
494 | |||
495 | static enum led_brightness kled_led_get(struct led_classdev *led_cdev) | ||
496 | { | ||
497 | return get_kled_lvl(); | ||
498 | } | ||
499 | |||
410 | static int get_lcd_state(void) | 500 | static int get_lcd_state(void) |
411 | { | 501 | { |
412 | return read_status(LCD_ON); | 502 | return read_status(LCD_ON); |
@@ -498,7 +588,7 @@ static ssize_t show_infos(struct device *dev, | |||
498 | { | 588 | { |
499 | int len = 0; | 589 | int len = 0; |
500 | unsigned long long temp; | 590 | unsigned long long temp; |
501 | char buf[16]; //enough for all info | 591 | char buf[16]; /* enough for all info */ |
502 | acpi_status rv = AE_OK; | 592 | acpi_status rv = AE_OK; |
503 | 593 | ||
504 | /* | 594 | /* |
@@ -516,7 +606,17 @@ static ssize_t show_infos(struct device *dev, | |||
516 | */ | 606 | */ |
517 | rv = acpi_evaluate_integer(hotk->handle, "SFUN", NULL, &temp); | 607 | rv = acpi_evaluate_integer(hotk->handle, "SFUN", NULL, &temp); |
518 | if (!ACPI_FAILURE(rv)) | 608 | if (!ACPI_FAILURE(rv)) |
519 | len += sprintf(page + len, "SFUN value : 0x%04x\n", | 609 | len += sprintf(page + len, "SFUN value : %#x\n", |
610 | (uint) temp); | ||
611 | /* | ||
612 | * The HWRS method return informations about the hardware. | ||
613 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. | ||
614 | * The significance of others is yet to be found. | ||
615 | * If we don't find the method, we assume the device are present. | ||
616 | */ | ||
617 | rv = acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &temp); | ||
618 | if (!ACPI_FAILURE(rv)) | ||
619 | len += sprintf(page + len, "HRWS value : %#x\n", | ||
520 | (uint) temp); | 620 | (uint) temp); |
521 | /* | 621 | /* |
522 | * Another value for userspace: the ASYM method returns 0x02 for | 622 | * Another value for userspace: the ASYM method returns 0x02 for |
@@ -527,7 +627,7 @@ static ssize_t show_infos(struct device *dev, | |||
527 | */ | 627 | */ |
528 | rv = acpi_evaluate_integer(hotk->handle, "ASYM", NULL, &temp); | 628 | rv = acpi_evaluate_integer(hotk->handle, "ASYM", NULL, &temp); |
529 | if (!ACPI_FAILURE(rv)) | 629 | if (!ACPI_FAILURE(rv)) |
530 | len += sprintf(page + len, "ASYM value : 0x%04x\n", | 630 | len += sprintf(page + len, "ASYM value : %#x\n", |
531 | (uint) temp); | 631 | (uint) temp); |
532 | if (asus_info) { | 632 | if (asus_info) { |
533 | snprintf(buf, 16, "%d", asus_info->length); | 633 | snprintf(buf, 16, "%d", asus_info->length); |
@@ -648,8 +748,10 @@ static int read_display(void) | |||
648 | unsigned long long value = 0; | 748 | unsigned long long value = 0; |
649 | acpi_status rv = AE_OK; | 749 | acpi_status rv = AE_OK; |
650 | 750 | ||
651 | /* In most of the case, we know how to set the display, but sometime | 751 | /* |
652 | we can't read it */ | 752 | * In most of the case, we know how to set the display, but sometime |
753 | * we can't read it | ||
754 | */ | ||
653 | if (display_get_handle) { | 755 | if (display_get_handle) { |
654 | rv = acpi_evaluate_integer(display_get_handle, NULL, | 756 | rv = acpi_evaluate_integer(display_get_handle, NULL, |
655 | NULL, &value); | 757 | NULL, &value); |
@@ -1037,6 +1139,9 @@ static int asus_hotk_get_info(void) | |||
1037 | 1139 | ||
1038 | ASUS_HANDLE_INIT(ledd_set); | 1140 | ASUS_HANDLE_INIT(ledd_set); |
1039 | 1141 | ||
1142 | ASUS_HANDLE_INIT(kled_set); | ||
1143 | ASUS_HANDLE_INIT(kled_get); | ||
1144 | |||
1040 | /* | 1145 | /* |
1041 | * The HWRS method return informations about the hardware. | 1146 | * The HWRS method return informations about the hardware. |
1042 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. | 1147 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. |
@@ -1063,8 +1168,10 @@ static int asus_hotk_get_info(void) | |||
1063 | ASUS_HANDLE_INIT(display_set); | 1168 | ASUS_HANDLE_INIT(display_set); |
1064 | ASUS_HANDLE_INIT(display_get); | 1169 | ASUS_HANDLE_INIT(display_get); |
1065 | 1170 | ||
1066 | /* There is a lot of models with "ALSL", but a few get | 1171 | /* |
1067 | a real light sens, so we need to check it. */ | 1172 | * There is a lot of models with "ALSL", but a few get |
1173 | * a real light sens, so we need to check it. | ||
1174 | */ | ||
1068 | if (!ASUS_HANDLE_INIT(ls_switch)) | 1175 | if (!ASUS_HANDLE_INIT(ls_switch)) |
1069 | ASUS_HANDLE_INIT(ls_level); | 1176 | ASUS_HANDLE_INIT(ls_level); |
1070 | 1177 | ||
@@ -1168,6 +1275,10 @@ static int asus_hotk_add(struct acpi_device *device) | |||
1168 | /* LCD Backlight is on by default */ | 1275 | /* LCD Backlight is on by default */ |
1169 | write_status(NULL, 1, LCD_ON); | 1276 | write_status(NULL, 1, LCD_ON); |
1170 | 1277 | ||
1278 | /* Keyboard Backlight is on by default */ | ||
1279 | if (kled_set_handle) | ||
1280 | set_kled_lvl(1); | ||
1281 | |||
1171 | /* LED display is off by default */ | 1282 | /* LED display is off by default */ |
1172 | hotk->ledd_status = 0xFFF; | 1283 | hotk->ledd_status = 0xFFF; |
1173 | 1284 | ||
@@ -1222,6 +1333,7 @@ static void asus_led_exit(void) | |||
1222 | ASUS_LED_UNREGISTER(pled); | 1333 | ASUS_LED_UNREGISTER(pled); |
1223 | ASUS_LED_UNREGISTER(rled); | 1334 | ASUS_LED_UNREGISTER(rled); |
1224 | ASUS_LED_UNREGISTER(gled); | 1335 | ASUS_LED_UNREGISTER(gled); |
1336 | ASUS_LED_UNREGISTER(kled); | ||
1225 | } | 1337 | } |
1226 | 1338 | ||
1227 | static void asus_input_exit(void) | 1339 | static void asus_input_exit(void) |
@@ -1301,13 +1413,20 @@ static int asus_led_init(struct device *dev) | |||
1301 | if (rv) | 1413 | if (rv) |
1302 | goto out4; | 1414 | goto out4; |
1303 | 1415 | ||
1416 | if (kled_set_handle && kled_get_handle) | ||
1417 | rv = ASUS_LED_REGISTER(kled, dev); | ||
1418 | if (rv) | ||
1419 | goto out5; | ||
1420 | |||
1304 | led_workqueue = create_singlethread_workqueue("led_workqueue"); | 1421 | led_workqueue = create_singlethread_workqueue("led_workqueue"); |
1305 | if (!led_workqueue) | 1422 | if (!led_workqueue) |
1306 | goto out5; | 1423 | goto out6; |
1307 | 1424 | ||
1308 | return 0; | 1425 | return 0; |
1309 | out5: | 1426 | out6: |
1310 | rv = -ENOMEM; | 1427 | rv = -ENOMEM; |
1428 | ASUS_LED_UNREGISTER(kled); | ||
1429 | out5: | ||
1311 | ASUS_LED_UNREGISTER(gled); | 1430 | ASUS_LED_UNREGISTER(gled); |
1312 | out4: | 1431 | out4: |
1313 | ASUS_LED_UNREGISTER(pled); | 1432 | ASUS_LED_UNREGISTER(pled); |