aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/x86/asus-laptop.c79
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 */
172ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ 173ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */
173ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); 174ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST");
174 175
176/* Keyboard light */
177ASUS_HANDLE(kled_set, ASUS_HOTK_PREFIX "SLKB");
178ASUS_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);
263ASUS_LED(rled, "record", 1); 268ASUS_LED(rled, "record", 1);
264ASUS_LED(pled, "phone", 1); 269ASUS_LED(pled, "phone", 1);
265ASUS_LED(gled, "gaming", 1); 270ASUS_LED(gled, "gaming", 1);
271ASUS_LED(kled, "kbd_backlight", 3);
266 272
267struct key_entry { 273struct key_entry {
268 char type; 274 char type;
@@ -419,6 +425,60 @@ ASUS_LED_HANDLER(rled, RLED_ON);
419ASUS_LED_HANDLER(tled, TLED_ON); 425ASUS_LED_HANDLER(tled, TLED_ON);
420ASUS_LED_HANDLER(gled, GLED_ON); 426ASUS_LED_HANDLER(gled, GLED_ON);
421 427
428/*
429 * Keyboard backlight
430 */
431static 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, &params, &kblv);
444 if (ACPI_FAILURE(rv)) {
445 pr_warning("Error reading kled level\n");
446 return 0;
447 }
448 return kblv;
449}
450
451static 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
465static 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
472static void kled_led_update(struct work_struct *ignored)
473{
474 set_kled_lvl(kled_led_wk);
475}
476
477static enum led_brightness kled_led_get(struct led_classdev *led_cdev)
478{
479 return get_kled_lvl();
480}
481
422static int get_lcd_state(void) 482static 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
1249static void asus_input_exit(void) 1317static 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;
1331out5: 1404out6:
1332 rv = -ENOMEM; 1405 rv = -ENOMEM;
1406 ASUS_LED_UNREGISTER(kled);
1407out5:
1333 ASUS_LED_UNREGISTER(gled); 1408 ASUS_LED_UNREGISTER(gled);
1334out4: 1409out4:
1335 ASUS_LED_UNREGISTER(pled); 1410 ASUS_LED_UNREGISTER(pled);