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