I'm trying to fix a minor annoyance on my x240: the speaker mute key
LED-state is not respected at boot. Pressing the mute key will mute the
speaker while the expected behavior is to unmute. The LED-state will
remain out-of-sync until I run `mixerctl -t outputs.master.mute`.

I've managed to determine if the speaker is muted in the acpithinkpad(4)
attach function by reading from the embedded controller. However,
calling wskbd_set_mixervolume at this stage returns ENODEV. I assume the
audio device has not been attached yet. I'm new to kernel development
and therefore wonder if this approach makes sense. If true, is it
possible to postpone a task to run once a certain device has attached?

Any feedback would be appreciated.

Index: acpithinkpad.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpithinkpad.c,v
retrieving revision 1.52
diff -u -p -r1.52 acpithinkpad.c
--- acpithinkpad.c      5 May 2016 05:12:49 -0000       1.52
+++ acpithinkpad.c      12 Sep 2016 15:03:31 -0000
@@ -105,9 +105,12 @@
 #define THINKPAD_NSENSORS 9
 #define THINKPAD_NTEMPSENSORS 8
 
+#define THINKPAD_ECOFFSET_VOLUME       0x30
 #define THINKPAD_ECOFFSET_FANLO                0x84
 #define THINKPAD_ECOFFSET_FANHI                0x85
 
+#define THINKPAD_ECMASK_VOLUME_MUTE    0x40
+
 #define        THINKPAD_ADAPTIVE_MODE_HOME     1
 #define        THINKPAD_ADAPTIVE_MODE_FUNCTION 3
 
@@ -252,6 +255,7 @@ thinkpad_attach(struct device *parent, s
 {
        struct acpithinkpad_softc *sc = (struct acpithinkpad_softc *)self;
        struct acpi_attach_args *aa = aux;
+       uint8_t vol = 0;
 
        sc->sc_acpi = (struct acpi_softc *)parent;
        sc->sc_devnode = aa->aaa_node;
@@ -282,6 +286,16 @@ thinkpad_attach(struct device *parent, s
                ws_get_param = thinkpad_get_param;
                ws_set_param = thinkpad_set_param;
        }
+
+#if NAUDIO > 0 && NWSKBD > 0
+       if (sc->sc_acpi->sc_ec != NULL) {
+               acpiec_read(sc->sc_acpi->sc_ec, THINKPAD_ECOFFSET_VOLUME,
+                   1, &vol);
+               if ((vol & THINKPAD_ECMASK_VOLUME_MUTE)
+                   == THINKPAD_ECMASK_VOLUME_MUTE)
+                       wskbd_set_mixervolume(0, 1);
+       }
+#endif
 
        /* Run thinkpad_hotkey on button presses */
        aml_register_notify(sc->sc_devnode, aa->aaa_dev,

Reply via email to