Always call _PSW on _LID devices that support it to enable lid open to
authormarco <marco@openbsd.org>
Fri, 6 Aug 2010 21:12:27 +0000 (21:12 +0000)
committermarco <marco@openbsd.org>
Fri, 6 Aug 2010 21:12:27 +0000 (21:12 +0000)
resume the machine.  Conversely disable it when the machine wakes up.

Tested by several ok deraadt

sys/dev/acpi/acpi.c
sys/dev/acpi/acpibtn.c
sys/dev/acpi/acpidev.h

index 273a35c..a90f2f8 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.204 2010/08/06 14:20:14 deraadt Exp $ */
+/* $OpenBSD: acpi.c,v 1.205 2010/08/06 21:12:27 marco Exp $ */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -1809,6 +1809,9 @@ acpi_resume(struct acpi_softc *sc, int state)
                }
        }
 
+       /* disable _LID for wakeup */
+       acpibtn_disable_psw();
+
        /* Reset the indicator lights to "working" */
        if (sc->sc_sst) {
                env.v_integer = ACPI_SST_WORKING;
@@ -1850,6 +1853,9 @@ acpi_handle_suspend_failure(struct acpi_softc *sc)
                }
        }
 
+       /* disable _LID for wakeup */
+       acpibtn_disable_psw();
+
        /* Reset the indicator lights to "working" */
        if (sc->sc_sst) {
                env.v_integer = ACPI_SST_WORKING;
@@ -1919,6 +1925,9 @@ acpi_prepare_sleep_state(struct acpi_softc *sc, int state)
                        goto fail;
                }
 
+       /* enable _LID for wakeup */
+       acpibtn_enable_psw();
+
        /* Reset the indicator lights to "sleeping" */
        if (sc->sc_sst) {
                env.v_integer = ACPI_SST_SLEEPING;
index 278e296..274c956 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpibtn.c,v 1.31 2010/08/05 21:10:06 deraadt Exp $ */
+/* $OpenBSD: acpibtn.c,v 1.32 2010/08/06 21:12:27 marco Exp $ */
 /*
  * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
  *
@@ -47,13 +47,21 @@ struct acpibtn_softc {
        struct aml_node         *sc_devnode;
 
        int                     sc_btn_type;
-#define        ACPIBTN_UNKNOWN -1
-#define ACPIBTN_LID    0
-#define ACPIBTN_POWER  1
-#define ACPIBTN_SLEEP  2
+#define        ACPIBTN_UNKNOWN 0
+#define ACPIBTN_LID    1
+#define ACPIBTN_POWER  2
+#define ACPIBTN_SLEEP  3
 };
 
 int    acpibtn_getsta(struct acpibtn_softc *);
+int    acpibtn_setpsw(struct acpibtn_softc *, int);
+
+struct acpi_lid {
+       struct acpibtn_softc    *abl_softc;
+       SLIST_ENTRY(acpi_lid)   abl_link;
+};
+SLIST_HEAD(acpi_lid_head, acpi_lid) acpibtn_lids =
+    SLIST_HEAD_INITIALIZER(acpibtn_lids);
 
 struct cfattach acpibtn_ca = {
        sizeof(struct acpibtn_softc), acpibtn_match, acpibtn_attach
@@ -65,6 +73,40 @@ struct cfdriver acpibtn_cd = {
 
 const char *acpibtn_hids[] = { ACPI_DEV_LD, ACPI_DEV_PBD, ACPI_DEV_SBD, 0 };
 
+int
+acpibtn_setpsw(struct acpibtn_softc *sc, int psw)
+{
+       struct aml_value        val;
+
+       bzero(&val, sizeof val);
+       val.type = AML_OBJTYPE_INTEGER;
+       val.v_integer = psw;
+       val.length = 1;
+
+       return (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSW", 1, &val,
+           NULL));
+}
+
+void
+acpibtn_disable_psw(void)
+{
+       struct acpi_lid *lid;
+
+       /* disable _LID for wakeup */
+       SLIST_FOREACH(lid, &acpibtn_lids, abl_link)
+               acpibtn_setpsw(lid->abl_softc, 0);
+}
+
+void
+acpibtn_enable_psw(void)
+{
+       struct acpi_lid         *lid;
+
+       /* enable _LID for wakeup */
+       SLIST_FOREACH(lid, &acpibtn_lids, abl_link)
+               acpibtn_setpsw(lid->abl_softc, 1);
+}
+
 int
 acpibtn_match(struct device *parent, void *match, void *aux)
 {
@@ -80,26 +122,22 @@ acpibtn_attach(struct device *parent, struct device *self, void *aux)
 {
        struct acpibtn_softc    *sc = (struct acpibtn_softc *)self;
        struct acpi_attach_args *aa = aux;
+       struct acpi_lid         *lid;
 
        sc->sc_acpi = (struct acpi_softc *)parent;
        sc->sc_devnode = aa->aaa_node;
 
        if (!strcmp(aa->aaa_dev, ACPI_DEV_LD)) {
-               struct aml_value        val;
-
                sc->sc_btn_type = ACPIBTN_LID;
-               bzero(&val, sizeof val);
-               val.type = AML_OBJTYPE_INTEGER;
-               val.v_integer = 1;
-               val.length = 1;
-               (void) aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSW",
-                   1, &val, NULL);
+               if (acpibtn_setpsw(sc, 0) == 0) {
+                       lid = malloc(sizeof(*lid), M_DEVBUF, M_WAITOK | M_ZERO);
+                       lid->abl_softc = sc;
+                       SLIST_INSERT_HEAD(&acpibtn_lids, lid, abl_link);
+               }
        } else if (!strcmp(aa->aaa_dev, ACPI_DEV_PBD))
                sc->sc_btn_type = ACPIBTN_POWER;
        else if (!strcmp(aa->aaa_dev, ACPI_DEV_SBD))
                sc->sc_btn_type = ACPIBTN_SLEEP;
-       else
-               sc->sc_btn_type = ACPIBTN_UNKNOWN;
 
        acpibtn_getsta(sc);
 
index b0e2d42..c04d292 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpidev.h,v 1.31 2010/08/03 16:55:06 marco Exp $ */
+/* $OpenBSD: acpidev.h,v 1.32 2010/08/06 21:12:27 marco Exp $ */
 /*
  * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
@@ -334,4 +334,6 @@ struct acpiec_softc {
        int                     sc_gotsci;
 };
 
+void           acpibtn_disable_psw(void);
+void           acpibtn_enable_psw(void);
 #endif /* __DEV_ACPI_ACPIDEV_H__ */