On Tue, Mar 05, 2019 at 02:03:13PM -0600, joshua stein wrote:
> 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.
>
This patch fixes both the brightness buttons and the backlight keyboard
reporting in wsconsctl on my x280.
If this doesn't break older models ok jturner@.
>
> 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
>
--
James Turner