acpi_button.c revision 118783
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 118783 2003-08-11 15:34:43Z njl $
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#include <dev/acpica/acpivar.h>
3867761Smsmith
39118783Snjl/* Hooks for the ACPI CA debugging infrastructure */
4077432Smsmith#define _COMPONENT	ACPI_BUTTON
4191123SmsmithACPI_MODULE_NAME("BUTTON")
4269744Smsmith
4367761Smsmithstruct acpi_button_softc {
4467761Smsmith    device_t	button_dev;
4567761Smsmith    ACPI_HANDLE	button_handle;
4667761Smsmith    boolean_t	button_type;	/* Power or Sleep Button */
47118783Snjl#define		ACPI_POWER_BUTTON	0
48118783Snjl#define		ACPI_SLEEP_BUTTON	1
4967761Smsmith};
5067761Smsmith
51118783Snjl#define		ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP	0x80
52118783Snjl#define		ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP	0x02
53118783Snjl
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);
58118783Snjlstatic void 	acpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify,
59118783Snjl					   void *context);
6067761Smsmithstatic void	acpi_button_notify_pressed_for_sleep(void *arg);
6167761Smsmithstatic void	acpi_button_notify_pressed_for_wakeup(void *arg);
6267761Smsmith
6367761Smsmithstatic device_method_t acpi_button_methods[] = {
6467761Smsmith    /* Device interface */
6567761Smsmith    DEVMETHOD(device_probe,	acpi_button_probe),
6667761Smsmith    DEVMETHOD(device_attach,	acpi_button_attach),
67100497Siwasaki    DEVMETHOD(device_suspend,	acpi_button_suspend),
68118049Stakawata    DEVMETHOD(device_shutdown,	acpi_button_suspend),
69100497Siwasaki    DEVMETHOD(device_resume,	acpi_button_resume),
7067761Smsmith
7167761Smsmith    {0, 0}
7267761Smsmith};
7367761Smsmith
7467761Smsmithstatic driver_t acpi_button_driver = {
7567761Smsmith    "acpi_button",
7667761Smsmith    acpi_button_methods,
7767761Smsmith    sizeof(struct acpi_button_softc),
7867761Smsmith};
7967761Smsmith
8089054Smsmithstatic devclass_t acpi_button_devclass;
81118783SnjlDRIVER_MODULE(acpi_button, acpi, acpi_button_driver, acpi_button_devclass,
82118783Snjl	      0, 0);
8367761Smsmith
8467761Smsmithstatic int
8567761Smsmithacpi_button_probe(device_t dev)
8667761Smsmith{
8767761Smsmith    struct acpi_button_softc	*sc;
8867761Smsmith
8967761Smsmith    sc = device_get_softc(dev);
9067761Smsmith    if (acpi_get_type(dev) == ACPI_TYPE_DEVICE) {
9169744Smsmith	if (!acpi_disabled("button")) {
9269744Smsmith	    if (acpi_MatchHid(dev, "PNP0C0C")) {
9380067Smsmith		device_set_desc(dev, "Power Button");
9469744Smsmith		sc->button_type = ACPI_POWER_BUTTON;
95118783Snjl		return (0);
9669744Smsmith	    }
9769744Smsmith	    if (acpi_MatchHid(dev, "PNP0C0E")) {
9880067Smsmith		device_set_desc(dev, "Sleep Button");
9969744Smsmith		sc->button_type = ACPI_SLEEP_BUTTON;
100118783Snjl		return (0);
10169744Smsmith	    }
10267761Smsmith	}
10367761Smsmith    }
104118783Snjl    return (ENXIO);
10567761Smsmith}
10667761Smsmith
10767761Smsmithstatic int
10867761Smsmithacpi_button_attach(device_t dev)
10967761Smsmith{
11067761Smsmith    struct acpi_button_softc	*sc;
11167761Smsmith    ACPI_STATUS			status;
11267761Smsmith
11396926Speter    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
11469744Smsmith
11567761Smsmith    sc = device_get_softc(dev);
11667761Smsmith    sc->button_dev = dev;
11767761Smsmith    sc->button_handle = acpi_get_handle(dev);
11867761Smsmith
119118783Snjl    status = AcpiInstallNotifyHandler(sc->button_handle, ACPI_DEVICE_NOTIFY,
120118783Snjl				      acpi_button_notify_handler, sc);
121118783Snjl    if (ACPI_FAILURE(status)) {
122118783Snjl	device_printf(sc->button_dev, "couldn't install Notify handler - %s\n",
123118783Snjl		      AcpiFormatException(status));
124118783Snjl	return_VALUE (ENXIO);
12567761Smsmith    }
126100497Siwasaki    acpi_device_enable_wake_capability(sc->button_handle, 1);
127118783Snjl    return_VALUE (0);
12867761Smsmith}
12967761Smsmith
130100497Siwasakistatic int
131100497Siwasakiacpi_button_suspend(device_t dev)
132100497Siwasaki{
133100497Siwasaki    struct acpi_button_softc	*sc;
134100497Siwasaki
135100497Siwasaki    sc = device_get_softc(dev);
136100497Siwasaki    acpi_device_enable_wake_event(sc->button_handle);
137100497Siwasaki    return (0);
138100497Siwasaki}
139100497Siwasaki
140100497Siwasakistatic int
141100497Siwasakiacpi_button_resume(device_t dev)
142100497Siwasaki{
143100497Siwasaki    return (0);
144100497Siwasaki}
145100497Siwasaki
14667761Smsmithstatic void
14767761Smsmithacpi_button_notify_pressed_for_sleep(void *arg)
14867761Smsmith{
14967761Smsmith    struct acpi_button_softc	*sc;
15067761Smsmith    struct acpi_softc		*acpi_sc;
15167761Smsmith
15296926Speter    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
15369744Smsmith
15467761Smsmith    sc = (struct acpi_button_softc *)arg;
15567761Smsmith    acpi_sc = acpi_device_get_parent_softc(sc->button_dev);
156118783Snjl    if (acpi_sc == NULL)
15769744Smsmith	return_VOID;
15867761Smsmith
15967761Smsmith    switch (sc->button_type) {
16067761Smsmith    case ACPI_POWER_BUTTON:
16197274Sbde	ACPI_VPRINT(sc->button_dev, acpi_sc, "power button pressed\n");
16267761Smsmith	acpi_eventhandler_power_button_for_sleep((void *)acpi_sc);
16367761Smsmith	break;
16467761Smsmith    case ACPI_SLEEP_BUTTON:
16597274Sbde	ACPI_VPRINT(sc->button_dev, acpi_sc, "sleep button pressed\n");
16667761Smsmith	acpi_eventhandler_sleep_button_for_sleep((void *)acpi_sc);
16767761Smsmith	break;
16867761Smsmith    default:
16969744Smsmith	break;		/* unknown button type */
17067761Smsmith    }
17167761Smsmith}
17267761Smsmith
17367761Smsmithstatic void
17467761Smsmithacpi_button_notify_pressed_for_wakeup(void *arg)
17567761Smsmith{
17667761Smsmith    struct acpi_button_softc	*sc;
17767761Smsmith    struct acpi_softc		*acpi_sc;
17867761Smsmith
17996926Speter    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
18069744Smsmith
18167761Smsmith    sc = (struct acpi_button_softc *)arg;
18267761Smsmith    acpi_sc = acpi_device_get_parent_softc(sc->button_dev);
183118783Snjl    if (acpi_sc == NULL)
18469744Smsmith	return_VOID;
18567761Smsmith
18667761Smsmith    switch (sc->button_type) {
18767761Smsmith    case ACPI_POWER_BUTTON:
18897274Sbde	ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by power button\n");
18967761Smsmith	acpi_eventhandler_power_button_for_wakeup((void *)acpi_sc);
19067761Smsmith	break;
19167761Smsmith    case ACPI_SLEEP_BUTTON:
19297274Sbde	ACPI_VPRINT(sc->button_dev, acpi_sc, "wakeup by sleep button\n");
19367761Smsmith	acpi_eventhandler_sleep_button_for_wakeup((void *)acpi_sc);
19467761Smsmith	break;
19567761Smsmith    default:
19669744Smsmith	break;		/* unknown button type */
19767761Smsmith    }
19867761Smsmith}
19967761Smsmith
20067761Smsmithstatic void
20167761Smsmithacpi_button_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
20267761Smsmith{
20367761Smsmith    struct acpi_button_softc	*sc = (struct acpi_button_softc *)context;
20467761Smsmith
20596926Speter    ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify);
20669744Smsmith
20767761Smsmith    switch (notify) {
20867761Smsmith    case ACPI_NOTIFY_BUTTON_PRESSED_FOR_SLEEP:
209118783Snjl	AcpiOsQueueForExecution(OSD_PRIORITY_LO,
210118783Snjl				acpi_button_notify_pressed_for_sleep, sc);
21167761Smsmith	break;
21267761Smsmith    case ACPI_NOTIFY_BUTTON_PRESSED_FOR_WAKEUP:
213118783Snjl	AcpiOsQueueForExecution(OSD_PRIORITY_LO,
214118783Snjl				acpi_button_notify_pressed_for_wakeup, sc);
21567761Smsmith	break;
21667761Smsmith    default:
21769744Smsmith	break;		/* unknown notification value */
21867761Smsmith    }
21967761Smsmith}
220