platform/x86: thinkpad_acpi: Call led_classdev_notify_brightness_hw_changed on kbd...
authorHans de Goede <hdegoede@redhat.com>
Thu, 9 Feb 2017 15:44:13 +0000 (16:44 +0100)
committerDarren Hart <dvhart@linux.intel.com>
Sat, 25 Feb 2017 07:48:52 +0000 (23:48 -0800)
Make thinkpad_acpi call led_classdev_notify_brightness_hw_changed on the
kbd_led led_classdev registered by thinkpad_acpi when the kbd backlight
brightness is changed through the hotkey.

This will allow userspace to monitor (poll) for brightness changes on
these LEDs caused by the hotkey.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Pavel Machek <pavel@ucw.cz>
drivers/platform/x86/thinkpad_acpi.c

index f51833f792979e23b47a3ba8df92df36908c40b4..1d18b32628ecbf501aff7193fc857b0126a56f58 100644 (file)
@@ -163,6 +163,7 @@ enum tpacpi_hkey_event_t {
        TP_HKEY_EV_HOTKEY_BASE          = 0x1001, /* first hotkey (FN+F1) */
        TP_HKEY_EV_BRGHT_UP             = 0x1010, /* Brightness up */
        TP_HKEY_EV_BRGHT_DOWN           = 0x1011, /* Brightness down */
+       TP_HKEY_EV_KBD_LIGHT            = 0x1012, /* Thinklight/kbd backlight */
        TP_HKEY_EV_VOL_UP               = 0x1015, /* Volume up or unmute */
        TP_HKEY_EV_VOL_DOWN             = 0x1016, /* Volume down or unmute */
        TP_HKEY_EV_VOL_MUTE             = 0x1017, /* Mixer output mute */
@@ -1957,7 +1958,7 @@ enum {    /* Positions of some of the keys in hotkey masks */
        TP_ACPI_HKEY_HIBERNATE_MASK     = 1 << TP_ACPI_HOTKEYSCAN_FNF12,
        TP_ACPI_HKEY_BRGHTUP_MASK       = 1 << TP_ACPI_HOTKEYSCAN_FNHOME,
        TP_ACPI_HKEY_BRGHTDWN_MASK      = 1 << TP_ACPI_HOTKEYSCAN_FNEND,
-       TP_ACPI_HKEY_THNKLGHT_MASK      = 1 << TP_ACPI_HOTKEYSCAN_FNPAGEUP,
+       TP_ACPI_HKEY_KBD_LIGHT_MASK     = 1 << TP_ACPI_HOTKEYSCAN_FNPAGEUP,
        TP_ACPI_HKEY_ZOOM_MASK          = 1 << TP_ACPI_HOTKEYSCAN_FNSPACE,
        TP_ACPI_HKEY_VOLUP_MASK         = 1 << TP_ACPI_HOTKEYSCAN_VOLUMEUP,
        TP_ACPI_HKEY_VOLDWN_MASK        = 1 << TP_ACPI_HOTKEYSCAN_VOLUMEDOWN,
@@ -2342,7 +2343,7 @@ static void hotkey_read_nvram(struct tp_nvram_state *n, const u32 m)
                n->display_toggle = !!(d & TP_NVRAM_MASK_HKT_DISPLAY);
                n->hibernate_toggle = !!(d & TP_NVRAM_MASK_HKT_HIBERNATE);
        }
-       if (m & TP_ACPI_HKEY_THNKLGHT_MASK) {
+       if (m & TP_ACPI_HKEY_KBD_LIGHT_MASK) {
                d = nvram_read_byte(TP_NVRAM_ADDR_THINKLIGHT);
                n->thinklight_toggle = !!(d & TP_NVRAM_MASK_THINKLIGHT);
        }
@@ -5082,15 +5083,26 @@ static struct ibm_struct video_driver_data = {
  * Keyboard backlight subdriver
  */
 
+static enum led_brightness kbdlight_brightness;
+static DEFINE_MUTEX(kbdlight_mutex);
+
 static int kbdlight_set_level(int level)
 {
+       int ret = 0;
+
        if (!hkey_handle)
                return -ENXIO;
 
+       mutex_lock(&kbdlight_mutex);
+
        if (!acpi_evalf(hkey_handle, NULL, "MLCS", "dd", level))
-               return -EIO;
+               ret = -EIO;
+       else
+               kbdlight_brightness = level;
 
-       return 0;
+       mutex_unlock(&kbdlight_mutex);
+
+       return ret;
 }
 
 static int kbdlight_get_level(void)
@@ -5175,6 +5187,7 @@ static struct tpacpi_led_classdev tpacpi_led_kbdlight = {
        .led_classdev = {
                .name           = "tpacpi::kbd_backlight",
                .max_brightness = 2,
+               .flags          = LED_BRIGHT_HW_CHANGED,
                .brightness_set_blocking = &kbdlight_sysfs_set,
                .brightness_get = &kbdlight_sysfs_get,
        }
@@ -5194,6 +5207,7 @@ static int __init kbdlight_init(struct ibm_init_struct *iibm)
                return 1;
        }
 
+       kbdlight_brightness = kbdlight_sysfs_get(NULL);
        tp_features.kbdlight = 1;
 
        rc = led_classdev_register(&tpacpi_pdev->dev,
@@ -5203,6 +5217,8 @@ static int __init kbdlight_init(struct ibm_init_struct *iibm)
                return rc;
        }
 
+       tpacpi_hotkey_driver_mask_set(hotkey_driver_mask |
+                                     TP_ACPI_HKEY_KBD_LIGHT_MASK);
        return 0;
 }
 
@@ -9119,6 +9135,24 @@ static void tpacpi_driver_event(const unsigned int hkey_event)
                        volume_alsa_notify_change();
                }
        }
+       if (tp_features.kbdlight && hkey_event == TP_HKEY_EV_KBD_LIGHT) {
+               enum led_brightness brightness;
+
+               mutex_lock(&kbdlight_mutex);
+
+               /*
+                * Check the brightness actually changed, setting the brightness
+                * through kbdlight_set_level() also triggers this event.
+                */
+               brightness = kbdlight_sysfs_get(NULL);
+               if (kbdlight_brightness != brightness) {
+                       kbdlight_brightness = brightness;
+                       led_classdev_notify_brightness_hw_changed(
+                               &tpacpi_led_kbdlight.led_classdev, brightness);
+               }
+
+               mutex_unlock(&kbdlight_mutex);
+       }
 }
 
 static void hotkey_driver_event(const unsigned int scancode)