xref: /freebsd/sys/dev/acpica/acpi_button.c (revision 67ce1673)
115e32d5dSMike Smith /*-
215e32d5dSMike Smith  * Copyright (c) 2000 Mitsaru IWASAKI <iwasaki@jp.freebsd.org>
315e32d5dSMike Smith  * Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
415e32d5dSMike Smith  * Copyright (c) 2000 BSDi
515e32d5dSMike Smith  * All rights reserved.
615e32d5dSMike Smith  *
715e32d5dSMike Smith  * Redistribution and use in source and binary forms, with or without
815e32d5dSMike Smith  * modification, are permitted provided that the following conditions
915e32d5dSMike Smith  * are met:
1015e32d5dSMike Smith  * 1. Redistributions of source code must retain the above copyright
1115e32d5dSMike Smith  *    notice, this list of conditions and the following disclaimer.
1215e32d5dSMike Smith  * 2. Redistributions in binary form must reproduce the above copyright
1315e32d5dSMike Smith  *    notice, this list of conditions and the following disclaimer in the
1415e32d5dSMike Smith  *    documentation and/or other materials provided with the distribution.
1515e32d5dSMike Smith  *
1615e32d5dSMike Smith  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1715e32d5dSMike Smith  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1815e32d5dSMike Smith  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1915e32d5dSMike Smith  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2015e32d5dSMike Smith  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2115e32d5dSMike Smith  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2215e32d5dSMike Smith  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2315e32d5dSMike Smith  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2415e32d5dSMike Smith  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2515e32d5dSMike Smith  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2615e32d5dSMike Smith  * SUCH DAMAGE.
2715e32d5dSMike Smith  *
2815e32d5dSMike Smith  *	$FreeBSD$
2915e32d5dSMike Smith  */
3015e32d5dSMike Smith 
3115e32d5dSMike Smith #include "opt_acpi.h"
3215e32d5dSMike Smith #include <sys/param.h>
3315e32d5dSMike Smith #include <sys/kernel.h>
3415e32d5dSMike Smith #include <sys/bus.h>
3515e32d5dSMike Smith 
3615e32d5dSMike Smith #include "acpi.h"
3715e32d5dSMike Smith 
3815e32d5dSMike Smith #include <dev/acpica/acpivar.h>
3915e32d5dSMike Smith 
400ae55423SMike Smith /*
410ae55423SMike Smith  * Hooks for the ACPI CA debugging infrastructure
420ae55423SMike Smith  */
432a4ac806SMike Smith #define _COMPONENT	ACPI_BUTTON
440ae55423SMike Smith MODULE_NAME("BUTTON")
450ae55423SMike Smith 
4615e32d5dSMike Smith struct acpi_button_softc {
4715e32d5dSMike Smith     device_t	button_dev;
4815e32d5dSMike Smith     ACPI_HANDLE	button_handle;
4915e32d5dSMike Smith #define ACPI_POWER_BUTTON	0
5015e32d5dSMike Smith #define ACPI_SLEEP_BUTTON	1
5115e32d5dSMike Smith     boolean_t	button_type;	/* Power or Sleep Button */
5215e32d5dSMike Smith };
5315e32d5dSMike Smith 
5415e32d5dSMike Smith static int	acpi_button_probe(device_t dev);
5515e32d5dSMike Smith static int	acpi_button_attach(device_t dev);
5615e32d5dSMike Smith static void 	acpi_button_notify_handler(ACPI_HANDLE h,UINT32 notify, void *context);
5715e32d5dSMike Smith static void	acpi_button_notify_pressed_for_sleep(void *arg);
5815e32d5dSMike Smith static void	acpi_button_notify_pressed_for_wakeup(void *arg);
5915e32d5dSMike Smith 
6015e32d5dSMike Smith static device_method_t acpi_button_methods[] = {
6115e32d5dSMike Smith     /* Device interface */
6215e32d5dSMike Smith     DEVMETHOD(device_probe,	acpi_button_probe),
6315e32d5dSMike Smith     DEVMETHOD(device_attach,	acpi_button_attach),
6415e32d5dSMike Smith 
6515e32d5dSMike Smith     {0, 0}
6615e32d5dSMike Smith };
6715e32d5dSMike Smith 
6815e32d5dSMike Smith static driver_t acpi_button_driver = {
6915e32d5dSMike Smith     "acpi_button",
7015e32d5dSMike Smith     acpi_button_methods,
7115e32d5dSMike Smith     sizeof(struct acpi_button_softc),
7215e32d5dSMike Smith };
7315e32d5dSMike Smith 
7415e32d5dSMike Smith devclass_t acpi_button_devclass;
7515e32d5dSMike Smith DRIVER_MODULE(acpi_button, acpi, acpi_button_driver, acpi_button_devclass, 0, 0);
7615e32d5dSMike Smith 
7715e32d5dSMike Smith static int
7815e32d5dSMike Smith acpi_button_probe(device_t dev)
7915e32d5dSMike Smith {
8015e32d5dSMike Smith     struct acpi_button_softc	*sc;
8115e32d5dSMike Smith 
8215e32d5dSMike Smith     sc = device_get_softc(dev);
8315e32d5dSMike Smith     if (acpi_get_type(dev) == ACPI_TYPE_DEVICE) {
840ae55423SMike Smith 	if (!acpi_disabled("button")) {
8515e32d5dSMike Smith 	    if (acpi_MatchHid(dev, "PNP0C0C")) {
8667ce1673SMike Smith 		device_set_desc(dev, "Power Button");
8715e32d5dSMike Smith 		sc->button_type = ACPI_POWER_BUTTON;
8815e32d5dSMike Smith 		return(0);
8915e32d5dSMike Smith 	    }
9015e32d5dSMike Smith 	    if (acpi_MatchHid(dev, "PNP0C0E")) {
9167ce1673SMike Smith 		device_set_desc(dev, "Sleep Button");
9215e32d5dSMike Smith 		sc->button_type = ACPI_SLEEP_BUTTON;
9315e32d5dSMike Smith 		return(0);
9415e32d5dSMike Smith 	    }
950ae55423SMike Smith 	}
9615e32d5dSMike Smith     }
9715e32d5dSMike Smith     return(ENXIO);
9815e32d5dSMike Smith }
9915e32d5dSMike Smith 
10015e32d5dSMike Smith static int
10115e32d5dSMike Smith acpi_button_attach(device_t dev)
10215e32d5dSMike Smith {
10315e32d5dSMike Smith     struct acpi_button_softc	*sc;
10415e32d5dSMike Smith     ACPI_STATUS			status;
10515e32d5dSMike Smith 
1062a4ac806SMike Smith     FUNCTION_TRACE(__func__);
1070ae55423SMike Smith 
10815e32d5dSMike Smith     sc = device_get_softc(dev);
10915e32d5dSMike Smith     sc->button_dev = dev;
11015e32d5dSMike Smith     sc->button_handle = acpi_get_handle(dev);
11115e32d5dSMike Smith 
11215e32d5dSMike Smith     if ((status = AcpiInstallNotifyHandler(sc->button_handle, ACPI_DEVICE_NOTIFY,
11315e32d5dSMike Smith 					   acpi_button_notify_handler, sc)) != AE_OK) {
11415e32d5dSMike Smith 	device_printf(sc->button_dev, "couldn't install Notify handler - %s\n", acpi_strerror(status));
1150ae55423SMike Smith 	return_VALUE(ENXIO);
11615e32d5dSMike Smith     }
1170ae55423SMike Smith     return_VALUE(0);
11815e32d5dSMike Smith }
11915e32d5dSMike Smith 
12015e32d5dSMike Smith static void
12115e32d5dSMike Smith acpi_button_notify_pressed_for_sleep(void *arg)
12215e32d5dSMike Smith {
12315e32d5dSMike Smith     struct acpi_button_softc	*sc;
12415e32d5dSMike Smith     struct acpi_softc		*acpi_sc;
12515e32d5dSMike Smith 
1262a4ac806SMike Smith     FUNCTION_TRACE(__func__);
1270ae55423SMike Smith 
12815e32d5dSMike Smith     sc = (struct acpi_button_softc *)arg;
12915e32d5dSMike Smith     acpi_sc = acpi_device_get_parent_softc(sc->button_dev);
13015e32d5dSMike Smith     if (acpi_sc == NULL) {
1310ae55423SMike Smith 	return_VOID;
13215e32d5dSMike Smith     }
13315e32d5dSMike Smith 
13415e32d5dSMike Smith     switch (sc->button_type) {
13515e32d5dSMike Smith     case ACPI_POWER_BUTTON:
13667ce1673SMike Smith 	device_printf(sc->button_dev, "power button pressed\n", sc->button_type);
13715e32d5dSMike Smith 	acpi_eventhandler_power_button_for_sleep((void *)acpi_sc);
13815e32d5dSMike Smith 	break;
13915e32d5dSMike Smith     case ACPI_SLEEP_BUTTON:
14067ce1673SMike Smith 	device_printf(sc->button_dev, "sleep button pressed\n", sc->button_type);
14115e32d5dSMike Smith 	acpi_eventhandler_sleep_button_for_sleep((void *)acpi_sc);
14215e32d5dSMike Smith 	break;
14315e32d5dSMike Smith     default:
1440ae55423SMike Smith 	break;		/* unknown button type */
14515e32d5dSMike Smith     }
1460ae55423SMike Smith     return_VOID;
14715e32d5dSMike Smith }
14815e32d5dSMike Smith 
14915e32d5dSMike Smith static void
15015e32d5dSMike Smith acpi_button_notify_pressed_for_wakeup(void *arg)
15115e32d5dSMike Smith {
15215e32d5dSMike Smith     struct acpi_button_softc	*sc;
15315e32d5dSMike Smith     struct acpi_softc		*acpi_sc;
15415e32d5dSMike Smith 
1552a4ac806SMike Smith     FUNCTION_TRACE(__func__);
1560ae55423SMike Smith 
15715e32d5dSMike Smith     sc = (struct acpi_button_softc *)arg;
15815e32d5dSMike Smith     acpi_sc = acpi_device_get_parent_softc(sc->button_dev);
15915e32d5dSMike Smith     if (acpi_sc == NULL) {
1600ae55423SMike Smith 	return_VOID;
16115e32d5dSMike Smith     }
16215e32d5dSMike Smith 
16315e32d5dSMike Smith     switch (sc->button_type) {
16415e32d5dSMike Smith     case ACPI_POWER_BUTTON:
16567ce1673SMike Smith 	device_printf(sc->button_dev, "wakeup by power button\n", sc->button_type);
16615e32d5dSMike Smith 	acpi_eventhandler_power_button_for_wakeup((void *)acpi_sc);
16715e32d5dSMike Smith 	break;
16815e32d5dSMike Smith     case ACPI_SLEEP_BUTTON:
16967ce1673SMike Smith 	device_printf(sc->button_dev, "wakeup by sleep button\n", sc->button_type);
17015e32d5dSMike Smith 	acpi_eventhandler_sleep_button_for_wakeup((void *)acpi_sc);
17115e32d5dSMike Smith 	break;
17215e32d5dSMike Smith     default:
1730ae55423SMike Smith 	break;		/* unknown button type */
17415e32d5dSMike Smith     }
1750ae55423SMike Smith     return_VOID;
17615e32d5dSMike Smith }
17715e32d5dSMike Smith 
17815e32d5dSMike Smith /* XXX maybe not here */
17915e32d5dSMike Smith #define ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP	0x80
18015e32d5dSMike Smith #define ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP	0x02
18115e32d5dSMike Smith 
18215e32d5dSMike Smith static void
18315e32d5dSMike Smith acpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
18415e32d5dSMike Smith {
18515e32d5dSMike Smith     struct acpi_button_softc	*sc = (struct acpi_button_softc *)context;
18615e32d5dSMike Smith 
1872a4ac806SMike Smith     FUNCTION_TRACE_U32(__func__, notify);
1880ae55423SMike Smith 
18915e32d5dSMike Smith     switch (notify) {
19015e32d5dSMike Smith     case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP:
19115e32d5dSMike Smith 	AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_sleep, sc);
19215e32d5dSMike Smith 	break;
19315e32d5dSMike Smith     case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP:
19415e32d5dSMike Smith 	AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_wakeup, sc);
19515e32d5dSMike Smith 	break;
19615e32d5dSMike Smith     default:
1970ae55423SMike Smith 	break;		/* unknown notification value */
19815e32d5dSMike Smith     }
1990ae55423SMike Smith     return_VOID;
20015e32d5dSMike Smith }
20115e32d5dSMike Smith 
20215e32d5dSMike Smith 
203