acpi_button.c revision 100497
167761Smsmith/*-
267761Smsmith * Copyright (c) 2000 Mitsaru IWASAKI <iwasaki@jp.freebsd.org>
367761Smsmith * Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
467761Smsmith * Copyright (c) 2000 BSDi
567761Smsmith * All rights reserved.
667761Smsmith *
767761Smsmith * Redistribution and use in source and binary forms, with or without
867761Smsmith * modification, are permitted provided that the following conditions
967761Smsmith * are met:
1067761Smsmith * 1. Redistributions of source code must retain the above copyright
1167761Smsmith *    notice, this list of conditions and the following disclaimer.
1267761Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1367761Smsmith *    notice, this list of conditions and the following disclaimer in the
1467761Smsmith *    documentation and/or other materials provided with the distribution.
1567761Smsmith *
1667761Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1767761Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1867761Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1967761Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2067761Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2167761Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2267761Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2367761Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2467761Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2567761Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2667761Smsmith * SUCH DAMAGE.
2767761Smsmith *
2867761Smsmith *	$FreeBSD: head/sys/dev/acpica/acpi_button.c 100497 2002-07-22 12:52:54Z iwasaki $
2967761Smsmith */
3067761Smsmith
3167761Smsmith#include "opt_acpi.h"
3267761Smsmith#include <sys/param.h>
3367761Smsmith#include <sys/kernel.h>
3467761Smsmith#include <sys/bus.h>
3567761Smsmith
3667761Smsmith#include "acpi.h"
3767761Smsmith
3867761Smsmith#include <dev/acpica/acpivar.h>
3967761Smsmith
4069744Smsmith/*
4169744Smsmith * Hooks for the ACPI CA debugging infrastructure
4269744Smsmith */
4377432Smsmith#define _COMPONENT	ACPI_BUTTON
4491123SmsmithACPI_MODULE_NAME("BUTTON")
4569744Smsmith
4667761Smsmithstruct acpi_button_softc {
4767761Smsmith    device_t	button_dev;
4867761Smsmith    ACPI_HANDLE	button_handle;
4967761Smsmith#define ACPI_POWER_BUTTON	0
5067761Smsmith#define ACPI_SLEEP_BUTTON	1
5167761Smsmith    boolean_t	button_type;	/* Power or Sleep Button */
5267761Smsmith};
5367761Smsmith
5467761Smsmithstatic int	acpi_button_probe(device_t dev);
5567761Smsmithstatic int	acpi_button_attach(device_t dev);
56100497Siwasakistatic int	acpi_button_suspend(device_t dev);
57100497Siwasakistatic int	acpi_button_resume(device_t dev);
5867761Smsmithstatic void 	acpi_button_notify_handler(ACPI_HANDLE h,UINT32 notify, void *context);
5967761Smsmithstatic void	acpi_button_notify_pressed_for_sleep(void *arg);
6067761Smsmithstatic void	acpi_button_notify_pressed_for_wakeup(void *arg);
6167761Smsmith
6267761Smsmithstatic device_method_t acpi_button_methods[] = {
6367761Smsmith    /* Device interface */
6467761Smsmith    DEVMETHOD(device_probe,	acpi_button_probe),
6567761Smsmith    DEVMETHOD(device_attach,	acpi_button_attach),
66100497Siwasaki    DEVMETHOD(device_suspend,	acpi_button_suspend),
67100497Siwasaki    DEVMETHOD(device_resume,	acpi_button_resume),
6867761Smsmith
6967761Smsmith    {0, 0}
7067761Smsmith};
7167761Smsmith
7267761Smsmithstatic driver_t acpi_button_driver = {
7367761Smsmith    "acpi_button",
7467761Smsmith    acpi_button_methods,
7567761Smsmith    sizeof(struct acpi_button_softc),
7667761Smsmith};
7767761Smsmith
7889054Smsmithstatic devclass_t acpi_button_devclass;
7967761SmsmithDRIVER_MODULE(acpi_button, acpi, acpi_button_driver, acpi_button_devclass, 0, 0);
8067761Smsmith
8167761Smsmithstatic int
8267761Smsmithacpi_button_probe(device_t dev)
8367761Smsmith{
8467761Smsmith    struct acpi_button_softc	*sc;
8567761Smsmith
8667761Smsmith    sc = device_get_softc(dev);
8767761Smsmith    if (acpi_get_type(dev) == ACPI_TYPE_DEVICE) {
8869744Smsmith	if (!acpi_disabled("button")) {
8969744Smsmith	    if (acpi_MatchHid(dev, "PNP0C0C")) {
9080067Smsmith		device_set_desc(dev, "Power Button");
9169744Smsmith		sc->button_type = ACPI_POWER_BUTTON;
9269744Smsmith		return(0);
9369744Smsmith	    }
9469744Smsmith	    if (acpi_MatchHid(dev, "PNP0C0E")) {
9580067Smsmith		device_set_desc(dev, "Sleep Button");
9669744Smsmith		sc->button_type = ACPI_SLEEP_BUTTON;
9769744Smsmith		return(0);
9869744Smsmith	    }
9967761Smsmith	}
10067761Smsmith    }
10167761Smsmith    return(ENXIO);
10267761Smsmith}
10367761Smsmith
10467761Smsmithstatic int
10567761Smsmithacpi_button_attach(device_t dev)
10667761Smsmith{
10767761Smsmith    struct acpi_button_softc	*sc;
10867761Smsmith    ACPI_STATUS			status;
10967761Smsmith
11096926Speter    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
11169744Smsmith
11267761Smsmith    sc = device_get_softc(dev);
11367761Smsmith    sc->button_dev = dev;
11467761Smsmith    sc->button_handle = acpi_get_handle(dev);
11567761Smsmith
11691123Smsmith    if (ACPI_FAILURE(status = AcpiInstallNotifyHandler(sc->button_handle, ACPI_DEVICE_NOTIFY,
11791123Smsmith					   acpi_button_notify_handler, sc))) {
11880078Smsmith	device_printf(sc->button_dev, "couldn't install Notify handler - %s\n", AcpiFormatException(status));
11969744Smsmith	return_VALUE(ENXIO);
12067761Smsmith    }
121100497Siwasaki    acpi_device_enable_wake_capability(sc->button_handle, 1);
12269744Smsmith    return_VALUE(0);
12367761Smsmith}
12467761Smsmith
125100497Siwasakistatic int
126100497Siwasakiacpi_button_suspend(device_t dev)
127100497Siwasaki{
128100497Siwasaki    struct acpi_button_softc	*sc;
129100497Siwasaki
130100497Siwasaki    sc = device_get_softc(dev);
131100497Siwasaki    acpi_device_enable_wake_event(sc->button_handle);
132100497Siwasaki    return (0);
133100497Siwasaki}
134100497Siwasaki
135100497Siwasakistatic int
136100497Siwasakiacpi_button_resume(device_t dev)
137100497Siwasaki{
138100497Siwasaki
139100497Siwasaki    return (0);
140100497Siwasaki}
141100497Siwasaki
14267761Smsmithstatic void
14367761Smsmithacpi_button_notify_pressed_for_sleep(void *arg)
14467761Smsmith{
14567761Smsmith    struct acpi_button_softc	*sc;
14667761Smsmith    struct acpi_softc		*acpi_sc;
14767761Smsmith
14896926Speter    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
14969744Smsmith
15067761Smsmith    sc = (struct acpi_button_softc *)arg;
15167761Smsmith    acpi_sc = acpi_device_get_parent_softc(sc->button_dev);
15267761Smsmith    if (acpi_sc == NULL) {
15369744Smsmith	return_VOID;
15467761Smsmith    }
15567761Smsmith
15667761Smsmith    switch (sc->button_type) {
15767761Smsmith    case ACPI_POWER_BUTTON:
15897274Sbde	ACPI_VPRINT(sc->button_dev, acpi_sc, "power button pressed\n");
15967761Smsmith	acpi_eventhandler_power_button_for_sleep((void *)acpi_sc);
16067761Smsmith	break;
16167761Smsmith    case ACPI_SLEEP_BUTTON:
16297274Sbde	ACPI_VPRINT(sc->button_dev, acpi_sc, "sleep button pressed\n");
16367761Smsmith	acpi_eventhandler_sleep_button_for_sleep((void *)acpi_sc);
16467761Smsmith	break;
16567761Smsmith    default:
16669744Smsmith	break;		/* unknown button type */
16767761Smsmith    }
16869744Smsmith    return_VOID;
16967761Smsmith}
17067761Smsmith
17167761Smsmithstatic void
17267761Smsmithacpi_button_notify_pressed_for_wakeup(void *arg)
17367761Smsmith{
17467761Smsmith    struct acpi_button_softc	*sc;
17567761Smsmith    struct acpi_softc		*acpi_sc;
17667761Smsmith
17796926Speter    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
17869744Smsmith
17967761Smsmith    sc = (struct acpi_button_softc *)arg;
18067761Smsmith    acpi_sc = acpi_device_get_parent_softc(sc->button_dev);
18167761Smsmith    if (acpi_sc == NULL) {
18269744Smsmith	return_VOID;
18367761Smsmith    }
18467761Smsmith
18567761Smsmith    switch (sc->button_type) {
18667761Smsmith    case ACPI_POWER_BUTTON:
18797274Sbde	ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by power button\n");
18867761Smsmith	acpi_eventhandler_power_button_for_wakeup((void *)acpi_sc);
18967761Smsmith	break;
19067761Smsmith    case ACPI_SLEEP_BUTTON:
19197274Sbde	ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by sleep button\n");
19267761Smsmith	acpi_eventhandler_sleep_button_for_wakeup((void *)acpi_sc);
19367761Smsmith	break;
19467761Smsmith    default:
19569744Smsmith	break;		/* unknown button type */
19667761Smsmith    }
19769744Smsmith    return_VOID;
19867761Smsmith}
19967761Smsmith
20067761Smsmith/* XXX maybe not here */
20167761Smsmith#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP	0x80
20267761Smsmith#define ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP	0x02
20367761Smsmith
20467761Smsmithstatic void
20567761Smsmithacpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
20667761Smsmith{
20767761Smsmith    struct acpi_button_softc	*sc = (struct acpi_button_softc *)context;
20867761Smsmith
20996926Speter    ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify);
21069744Smsmith
21167761Smsmith    switch (notify) {
21267761Smsmith    case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP:
21367761Smsmith	AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_sleep, sc);
21467761Smsmith	break;
21567761Smsmith    case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP:
21667761Smsmith	AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_button_notify_pressed_for_wakeup, sc);
21767761Smsmith	break;
21867761Smsmith    default:
21969744Smsmith	break;		/* unknown notification value */
22067761Smsmith    }
22169744Smsmith    return_VOID;
22267761Smsmith}
22367761Smsmith
22467761Smsmith
225