aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorCorentin Chary <corentincj@iksaif.net>2009-08-28 08:56:50 -0400
committerLen Brown <len.brown@intel.com>2009-08-28 15:21:13 -0400
commitb7d3fbc2ed624cc216adda0f2574570e6d6d6aed (patch)
treef15a61d393a6e12618ba7074aa5cf1eb14813a70 /drivers/platform
parent977c328d81e31fde70c5ba381d9cf7357451dd74 (diff)
asus-laptop: Add support for Keyboard backlight
Add support for keyboard backlight found in Asus U50VG. The SMC driver for the Apples does it via LED. To be consistent with that we create /sys/class/leds/asus::kbd_backlight/ to control the keyboard backlight. SLKB and GLKB are used to get/set the backlight. On the U50VG is supports 4 brightness level, but this may change with other models. SLKB take a 8 bit integer where the higher bit is used to toggle the backlight, and the over 7 bits control the brightness level. Signed-off-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/platform')
-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);