diff options
-rw-r--r-- | drivers/platform/x86/asus-laptop.c | 79 |
1 files changed, 77 insertions, 2 deletions
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 652902e6f205..0fb4e5971516 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
@@ -86,6 +86,7 @@ | |||
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 |
@@ -172,6 +173,10 @@ ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON"); /* R2H */ | |||
172 | ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ | 173 | ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ |
173 | ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); | 174 | ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); |
174 | 175 | ||
176 | /* Keyboard light */ | ||
177 | ASUS_HANDLE(kled_set, ASUS_HOTK_PREFIX "SLKB"); | ||
178 | ASUS_HANDLE(kled_get, ASUS_HOTK_PREFIX "GLKB"); | ||
179 | |||
175 | /* | 180 | /* |
176 | * This is the main structure, we can use it to store anything interesting | 181 | * This is the main structure, we can use it to store anything interesting |
177 | * about the hotk device | 182 | * about the hotk device |
@@ -263,6 +268,7 @@ ASUS_LED(tled, "touchpad", 1); | |||
263 | ASUS_LED(rled, "record", 1); | 268 | ASUS_LED(rled, "record", 1); |
264 | ASUS_LED(pled, "phone", 1); | 269 | ASUS_LED(pled, "phone", 1); |
265 | ASUS_LED(gled, "gaming", 1); | 270 | ASUS_LED(gled, "gaming", 1); |
271 | ASUS_LED(kled, "kbd_backlight", 3); | ||
266 | 272 | ||
267 | struct key_entry { | 273 | struct key_entry { |
268 | char type; | 274 | char type; |
@@ -419,6 +425,60 @@ ASUS_LED_HANDLER(rled, RLED_ON); | |||
419 | ASUS_LED_HANDLER(tled, TLED_ON); | 425 | ASUS_LED_HANDLER(tled, TLED_ON); |
420 | ASUS_LED_HANDLER(gled, GLED_ON); | 426 | ASUS_LED_HANDLER(gled, GLED_ON); |
421 | 427 | ||
428 | /* | ||
429 | * Keyboard backlight | ||
430 | */ | ||
431 | static int get_kled_lvl(void) | ||
432 | { | ||
433 | unsigned long long kblv; | ||
434 | struct acpi_object_list params; | ||
435 | union acpi_object in_obj; | ||
436 | acpi_status rv; | ||
437 | |||
438 | params.count = 1; | ||
439 | params.pointer = &in_obj; | ||
440 | in_obj.type = ACPI_TYPE_INTEGER; | ||
441 | in_obj.integer.value = 2; | ||
442 | |||
443 | rv = acpi_evaluate_integer(kled_get_handle, NULL, ¶ms, &kblv); | ||
444 | if (ACPI_FAILURE(rv)) { | ||
445 | pr_warning("Error reading kled level\n"); | ||
446 | return 0; | ||
447 | } | ||
448 | return kblv; | ||
449 | } | ||
450 | |||
451 | static int set_kled_lvl(int kblv) | ||
452 | { | ||
453 | if (kblv > 0) | ||
454 | kblv = (1 << 7) | (kblv & 0x7F); | ||
455 | else | ||
456 | kblv = 0; | ||
457 | |||
458 | if (write_acpi_int(kled_set_handle, NULL, kblv, NULL)) { | ||
459 | pr_warning("Keyboard LED display write failed\n"); | ||
460 | return -EINVAL; | ||
461 | } | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static void kled_led_set(struct led_classdev *led_cdev, | ||
466 | enum led_brightness value) | ||
467 | { | ||
468 | kled_led_wk = value; | ||
469 | queue_work(led_workqueue, &kled_led_work); | ||
470 | } | ||
471 | |||
472 | static void kled_led_update(struct work_struct *ignored) | ||
473 | { | ||
474 | set_kled_lvl(kled_led_wk); | ||
475 | } | ||
476 | |||
477 | static enum led_brightness kled_led_get(struct led_classdev *led_cdev) | ||
478 | { | ||
479 | return get_kled_lvl(); | ||
480 | } | ||
481 | |||
422 | static int get_lcd_state(void) | 482 | static int get_lcd_state(void) |
423 | { | 483 | { |
424 | return read_status(LCD_ON); | 484 | return read_status(LCD_ON); |
@@ -1059,6 +1119,9 @@ static int asus_hotk_get_info(void) | |||
1059 | 1119 | ||
1060 | ASUS_HANDLE_INIT(ledd_set); | 1120 | ASUS_HANDLE_INIT(ledd_set); |
1061 | 1121 | ||
1122 | ASUS_HANDLE_INIT(kled_set); | ||
1123 | ASUS_HANDLE_INIT(kled_get); | ||
1124 | |||
1062 | /* | 1125 | /* |
1063 | * The HWRS method return informations about the hardware. | 1126 | * The HWRS method return informations about the hardware. |
1064 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. | 1127 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. |
@@ -1190,6 +1253,10 @@ static int asus_hotk_add(struct acpi_device *device) | |||
1190 | /* LCD Backlight is on by default */ | 1253 | /* LCD Backlight is on by default */ |
1191 | write_status(NULL, 1, LCD_ON); | 1254 | write_status(NULL, 1, LCD_ON); |
1192 | 1255 | ||
1256 | /* Keyboard Backlight is on by default */ | ||
1257 | if (kled_set_handle) | ||
1258 | set_kled_lvl(1); | ||
1259 | |||
1193 | /* LED display is off by default */ | 1260 | /* LED display is off by default */ |
1194 | hotk->ledd_status = 0xFFF; | 1261 | hotk->ledd_status = 0xFFF; |
1195 | 1262 | ||
@@ -1244,6 +1311,7 @@ static void asus_led_exit(void) | |||
1244 | ASUS_LED_UNREGISTER(pled); | 1311 | ASUS_LED_UNREGISTER(pled); |
1245 | ASUS_LED_UNREGISTER(rled); | 1312 | ASUS_LED_UNREGISTER(rled); |
1246 | ASUS_LED_UNREGISTER(gled); | 1313 | ASUS_LED_UNREGISTER(gled); |
1314 | ASUS_LED_UNREGISTER(kled); | ||
1247 | } | 1315 | } |
1248 | 1316 | ||
1249 | static void asus_input_exit(void) | 1317 | static void asus_input_exit(void) |
@@ -1323,13 +1391,20 @@ static int asus_led_init(struct device *dev) | |||
1323 | if (rv) | 1391 | if (rv) |
1324 | goto out4; | 1392 | goto out4; |
1325 | 1393 | ||
1394 | if (kled_set_handle && kled_get_handle) | ||
1395 | rv = ASUS_LED_REGISTER(kled, dev); | ||
1396 | if (rv) | ||
1397 | goto out5; | ||
1398 | |||
1326 | led_workqueue = create_singlethread_workqueue("led_workqueue"); | 1399 | led_workqueue = create_singlethread_workqueue("led_workqueue"); |
1327 | if (!led_workqueue) | 1400 | if (!led_workqueue) |
1328 | goto out5; | 1401 | goto out6; |
1329 | 1402 | ||
1330 | return 0; | 1403 | return 0; |
1331 | out5: | 1404 | out6: |
1332 | rv = -ENOMEM; | 1405 | rv = -ENOMEM; |
1406 | ASUS_LED_UNREGISTER(kled); | ||
1407 | out5: | ||
1333 | ASUS_LED_UNREGISTER(gled); | 1408 | ASUS_LED_UNREGISTER(gled); |
1334 | out4: | 1409 | out4: |
1335 | ASUS_LED_UNREGISTER(pled); | 1410 | ASUS_LED_UNREGISTER(pled); |