b5cf2a
From 714fe15daa07e7691c9731c88de71aa57f84b6c2 Mon Sep 17 00:00:00 2001
b5cf2a
From: Hans de Goede <hdegoede@redhat.com>
b5cf2a
Date: Wed, 3 Jan 2018 11:13:54 +0100
b5cf2a
Subject: [PATCH] platform/x86: dell-laptop: Filter out spurious keyboard
b5cf2a
 backlight change events
b5cf2a
b5cf2a
On some Dell XPS models WMI events of type 0x0000 reporting a keycode of
b5cf2a
0xe00c get reported when the brightness of the LCD panel changes.
b5cf2a
b5cf2a
This leads to us reporting false-positive kbd_led change events to
b5cf2a
userspace which in turn leads to the kbd backlight OSD showing when it
b5cf2a
should not.
b5cf2a
b5cf2a
We already read the current keyboard backlight brightness value when
b5cf2a
reporting events because the led_classdev_notify_brightness_hw_changed
b5cf2a
API requires this. Compare this value to the last known value and filter
b5cf2a
out duplicate events, fixing this.
b5cf2a
b5cf2a
Note the fixed issue is esp. a problem on XPS models with an ambient light
b5cf2a
sensor and automatic brightness adjustments turned on, this causes the kbd
b5cf2a
backlight OSD to show all the time there.
b5cf2a
b5cf2a
BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1514969
b5cf2a
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
b5cf2a
---
b5cf2a
 drivers/platform/x86/dell-laptop.c | 24 ++++++++++++++++++++++--
b5cf2a
 1 file changed, 22 insertions(+), 2 deletions(-)
b5cf2a
b5cf2a
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
b5cf2a
index cd4725e7e0b5..2ef3297a9efc 100644
b5cf2a
--- a/drivers/platform/x86/dell-laptop.c
b5cf2a
+++ b/drivers/platform/x86/dell-laptop.c
b5cf2a
@@ -1133,6 +1133,7 @@ static u8 kbd_previous_mode_bit;
b5cf2a
 
b5cf2a
 static bool kbd_led_present;
b5cf2a
 static DEFINE_MUTEX(kbd_led_mutex);
b5cf2a
+static enum led_brightness kbd_led_level;
b5cf2a
 
b5cf2a
 /*
b5cf2a
  * NOTE: there are three ways to set the keyboard backlight level.
b5cf2a
@@ -1947,6 +1948,7 @@ static enum led_brightness kbd_led_level_get(struct led_classdev *led_cdev)
b5cf2a
 static int kbd_led_level_set(struct led_classdev *led_cdev,
b5cf2a
 			     enum led_brightness value)
b5cf2a
 {
b5cf2a
+	enum led_brightness new_value = value;
b5cf2a
 	struct kbd_state state;
b5cf2a
 	struct kbd_state new_state;
b5cf2a
 	u16 num;
b5cf2a
@@ -1976,6 +1978,9 @@ static int kbd_led_level_set(struct led_classdev *led_cdev,
b5cf2a
 	}
b5cf2a
 
b5cf2a
 out:
b5cf2a
+	if (ret == 0)
b5cf2a
+		kbd_led_level = new_value;
b5cf2a
+
b5cf2a
 	mutex_unlock(&kbd_led_mutex);
b5cf2a
 	return ret;
b5cf2a
 }
b5cf2a
@@ -2003,6 +2008,9 @@ static int __init kbd_led_init(struct device *dev)
b5cf2a
 		if (kbd_led.max_brightness)
b5cf2a
 			kbd_led.max_brightness--;
b5cf2a
 	}
b5cf2a
+
b5cf2a
+	kbd_led_level = kbd_led_level_get(NULL);
b5cf2a
+
b5cf2a
 	ret = led_classdev_register(dev, &kbd_led);
b5cf2a
 	if (ret)
b5cf2a
 		kbd_led_present = false;
b5cf2a
@@ -2027,13 +2035,25 @@ static void kbd_led_exit(void)
b5cf2a
 static int dell_laptop_notifier_call(struct notifier_block *nb,
b5cf2a
 				     unsigned long action, void *data)
b5cf2a
 {
b5cf2a
+	bool changed = false;
b5cf2a
+	enum led_brightness new_kbd_led_level;
b5cf2a
+
b5cf2a
 	switch (action) {
b5cf2a
 	case DELL_LAPTOP_KBD_BACKLIGHT_BRIGHTNESS_CHANGED:
b5cf2a
 		if (!kbd_led_present)
b5cf2a
 			break;
b5cf2a
 
b5cf2a
-		led_classdev_notify_brightness_hw_changed(&kbd_led,
b5cf2a
-						kbd_led_level_get(&kbd_led));
b5cf2a
+		mutex_lock(&kbd_led_mutex);
b5cf2a
+		new_kbd_led_level = kbd_led_level_get(&kbd_led);
b5cf2a
+		if (kbd_led_level != new_kbd_led_level) {
b5cf2a
+			kbd_led_level = new_kbd_led_level;
b5cf2a
+			changed = true;
b5cf2a
+		}
b5cf2a
+		mutex_unlock(&kbd_led_mutex);
b5cf2a
+
b5cf2a
+		if (changed)
b5cf2a
+			led_classdev_notify_brightness_hw_changed(&kbd_led,
b5cf2a
+								kbd_led_level);
b5cf2a
 		break;
b5cf2a
 	}
b5cf2a
 
b5cf2a
-- 
b5cf2a
2.14.3
b5cf2a