Here we go again...
On at least the ThinkPad X1C6, the screen brightness keys (F5
and
F6) do not work and "wsconsctl keyboard.backlight" doesn't
report
the correct value when the keyboard backlight is adjusted with
Fn+Space.
These are both caused by the default event mask not including
these
events, so explicitly enable them.
But then acpithinkpad has to actually do something for the
screen
brightness keys, but it tries the very old CMOS method which
doesn't
work on these newer machines[0]. So make it use the ACPI
method.
I renamed thinkpad_[gs]et_backlight to
thinkpad_[gs]et_kbd_backlight
because it was confusing that they have nothing to do with
screen
backlight.
0. "newer machines" being those with MHKV reporting version 2.
If
this diff breaks on older "newer machines", this metric will
have to
be changed to something else.
Index: sys/dev/acpi/acpithinkpad.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpithinkpad.c,v
retrieving revision 1.61
diff -u -p -u -p -r1.61 acpithinkpad.c
--- sys/dev/acpi/acpithinkpad.c 1 Jul 2018 19:40:49 -0000
1.61
+++ sys/dev/acpi/acpithinkpad.c 5 Mar 2019 20:00:23 -0000
@@ -124,6 +124,10 @@
#define THINKPAD_ADAPTIVE_MODE_HOME 1
#define THINKPAD_ADAPTIVE_MODE_FUNCTION 3
+#define THINKPAD_MASK_BRIGHTNESS_UP (1 << 15)
+#define THINKPAD_MASK_BRIGHTNESS_DOWN (1 << 16)
+#define THINKPAD_MASK_KBD_BACKLIGHT (1 << 17)
+
struct acpithinkpad_softc {
struct device sc_dev;
@@ -134,6 +138,8 @@ struct acpithinkpad_softc {
struct ksensor sc_sens[THINKPAD_NSENSORS];
struct ksensordev sc_sensdev;
+ uint64_t sc_hkey_version;
+
uint64_t sc_thinklight;
const char *sc_thinklight_get;
const char *sc_thinklight_set;
@@ -161,8 +167,8 @@ int thinkpad_activate(struct device *,
i
/* wscons hook functions */
void thinkpad_get_thinklight(struct acpithinkpad_softc *);
void thinkpad_set_thinklight(void *, int);
-int thinkpad_get_backlight(struct wskbd_backlight *);
-int thinkpad_set_backlight(struct wskbd_backlight *);
+int thinkpad_get_kbd_backlight(struct wskbd_backlight *);
+int thinkpad_set_kbd_backlight(struct wskbd_backlight *);
extern int (*wskbd_get_backlight)(struct wskbd_backlight *);
extern int (*wskbd_set_backlight)(struct wskbd_backlight *);
void thinkpad_get_brightness(struct acpithinkpad_softc *);
@@ -284,6 +290,10 @@ thinkpad_attach(struct device *parent, s
printf("\n");
+ if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "MHKV",
0, NULL,
+ &sc->sc_hkey_version))
+ sc->sc_hkey_version = THINKPAD_HKEY_VERSION1;
+
#if NAUDIO > 0 && NWSKBD > 0
/* Defer speaker mute */
if (thinkpad_get_volume_mute(sc) == 1)
@@ -299,14 +309,14 @@ thinkpad_attach(struct device *parent, s
0, NULL, &sc->sc_thinklight) == 0) {
sc->sc_thinklight_get = "KLCG";
sc->sc_thinklight_set = "KLCS";
- wskbd_get_backlight = thinkpad_get_backlight;
- wskbd_set_backlight = thinkpad_set_backlight;
+ wskbd_get_backlight = thinkpad_get_kbd_backlight;
+ wskbd_set_backlight = thinkpad_set_kbd_backlight;
} else if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode,
"MLCG",
0, NULL, &sc->sc_thinklight) == 0) {
sc->sc_thinklight_get = "MLCG";
sc->sc_thinklight_set = "MLCS";
- wskbd_get_backlight = thinkpad_get_backlight;
- wskbd_set_backlight = thinkpad_set_backlight;
+ wskbd_get_backlight = thinkpad_get_kbd_backlight;
+ wskbd_set_backlight = thinkpad_set_kbd_backlight;
}
if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "PBLG",
@@ -327,13 +337,19 @@ thinkpad_enable_events(struct acpithinkp
int64_t mask;
int i;
- /* Get the supported event mask */
+ /* Get the default event mask */
if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "MHKA",
0, NULL, &mask)) {
printf("%s: no MHKA\n", DEVNAME(sc));
return (1);
}
+ /* Enable events we need to know about */
+ mask |= (THINKPAD_MASK_BRIGHTNESS_UP |
THINKPAD_MASK_BRIGHTNESS_DOWN |
+ THINKPAD_MASK_KBD_BACKLIGHT);
+
+ DPRINTF(("%s: setting event mask to 0x%llx\n",
DEVNAME(sc), mask));
+
/* Update hotkey mask */
bzero(args, sizeof(args));
args[0].type = args[1].type = AML_OBJTYPE_INTEGER;
@@ -380,6 +396,8 @@ thinkpad_hotkey(struct aml_node *node, i
if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode,
"MHKP",
0, NULL, &event))
break;
+
+ DPRINTF(("%s: event 0x%03llx\n", DEVNAME(sc),
event));
if (event == 0)
break;
@@ -535,13 +553,37 @@ thinkpad_volume_mute(struct acpithinkpad
int
thinkpad_brightness_up(struct acpithinkpad_softc *sc)
{
- return (thinkpad_cmos(sc, THINKPAD_CMOS_BRIGHTNESS_UP));
+ int b;
+
+ if (sc->sc_hkey_version == THINKPAD_HKEY_VERSION2) {
+ thinkpad_get_brightness(sc);
+ b = sc->sc_brightness & 0xff;
+ if (b < ((sc->sc_brightness >> 8) & 0xff)) {
+ sc->sc_brightness = b + 1;
+ thinkpad_set_brightness(sc, 0);
+ }
+
+ return (0);
+ } else
+ return (thinkpad_cmos(sc,
THINKPAD_CMOS_BRIGHTNESS_UP));
}
int
thinkpad_brightness_down(struct acpithinkpad_softc *sc)
{
- return (thinkpad_cmos(sc, THINKPAD_CMOS_BRIGHTNESS_DOWN));
+ int b;
+
+ if (sc->sc_hkey_version == THINKPAD_HKEY_VERSION2) {
+ thinkpad_get_brightness(sc);
+ b = sc->sc_brightness & 0xff;
+ if (b > 0) {
+ sc->sc_brightness = b - 1;
+ thinkpad_set_brightness(sc, 0);
+ }
+
+ return (0);
+ } else
+ return (thinkpad_cmos(sc,
THINKPAD_CMOS_BRIGHTNESS_DOWN));
}
int
@@ -620,7 +662,7 @@ thinkpad_set_thinklight(void *arg0, int
}
int
-thinkpad_get_backlight(struct wskbd_backlight *kbl)
+thinkpad_get_kbd_backlight(struct wskbd_backlight *kbl)
{
struct acpithinkpad_softc *sc =
acpithinkpad_cd.cd_devs[0];
@@ -637,7 +679,7 @@ thinkpad_get_backlight(struct wskbd_back
}
int
-thinkpad_set_backlight(struct wskbd_backlight *kbl)
+thinkpad_set_kbd_backlight(struct wskbd_backlight *kbl)
{
struct acpithinkpad_softc *sc =
acpithinkpad_cd.cd_devs[0];
int maxval;
@@ -664,6 +706,8 @@ thinkpad_get_brightness(struct acpithink
{
aml_evalinteger(sc->sc_acpi, sc->sc_devnode,
"PBLG", 0, NULL, &sc->sc_brightness);
+
+ DPRINTF(("%s: %s: 0x%llx\n", DEVNAME(sc), __func__,
sc->sc_brightness));
}
void
@@ -672,11 +716,15 @@ thinkpad_set_brightness(void *arg0, int
struct acpithinkpad_softc *sc = arg0;
struct aml_value arg;
+ DPRINTF(("%s: %s: 0x%llx\n", DEVNAME(sc), __func__,
sc->sc_brightness));
+
memset(&arg, 0, sizeof(arg));
arg.type = AML_OBJTYPE_INTEGER;
arg.v_integer = sc->sc_brightness & 0xff;
aml_evalname(sc->sc_acpi, sc->sc_devnode,
"PBLS", 1, &arg, NULL);
+
+ thinkpad_get_brightness(sc);
}
int