acpi_lid.c revision 119529
167761Smsmith/*-
267761Smsmith * Copyright (c) 2000 Takanori Watanabe <takawata@jp.freebsd.org>
367761Smsmith * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
467761Smsmith * Copyright (c) 2000 Michael Smith <msmith@freebd.org>
567761Smsmith * Copyright (c) 2000 BSDi
667761Smsmith * All rights reserved.
767761Smsmith *
867761Smsmith * Redistribution and use in source and binary forms, with or without
967761Smsmith * modification, are permitted provided that the following conditions
1067761Smsmith * are met:
1167761Smsmith * 1. Redistributions of source code must retain the above copyright
1267761Smsmith *    notice, this list of conditions and the following disclaimer.
1367761Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1467761Smsmith *    notice, this list of conditions and the following disclaimer in the
1567761Smsmith *    documentation and/or other materials provided with the distribution.
1667761Smsmith *
1767761Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1867761Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1967761Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2067761Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2167761Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2267761Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2367761Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2467761Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2567761Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2667761Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2767761Smsmith * SUCH DAMAGE.
2867761Smsmith */
2967761Smsmith
30119418Sobrien#include <sys/cdefs.h>
31119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/acpica/acpi_lid.c 119529 2003-08-28 16:06:30Z njl $");
32119418Sobrien
3367761Smsmith#include "opt_acpi.h"
3467761Smsmith#include <sys/param.h>
3567761Smsmith#include <sys/kernel.h>
3667761Smsmith#include <sys/bus.h>
3774914Sjhb#include <sys/proc.h>
3867761Smsmith
3967761Smsmith#include "acpi.h"
4067761Smsmith#include <dev/acpica/acpivar.h>
4167761Smsmith
42119529Snjl/* Hooks for the ACPI CA debugging infrastructure */
4377432Smsmith#define _COMPONENT	ACPI_BUTTON
4491123SmsmithACPI_MODULE_NAME("LID")
4569744Smsmith
4667761Smsmithstruct acpi_lid_softc {
4767761Smsmith    device_t	lid_dev;
4867761Smsmith    ACPI_HANDLE	lid_handle;
4967761Smsmith    int		lid_status;	/* open or closed */
5067761Smsmith};
5167761Smsmith
5267761Smsmithstatic int	acpi_lid_probe(device_t dev);
5367761Smsmithstatic int	acpi_lid_attach(device_t dev);
54100497Siwasakistatic int	acpi_lid_suspend(device_t dev);
55100497Siwasakistatic int	acpi_lid_resume(device_t dev);
5667761Smsmithstatic void	acpi_lid_notify_status_changed(void *arg);
5767761Smsmithstatic void 	acpi_lid_notify_handler(ACPI_HANDLE h,UINT32 notify, void *context);
5867761Smsmith
5967761Smsmithstatic device_method_t acpi_lid_methods[] = {
6067761Smsmith    /* Device interface */
6167761Smsmith    DEVMETHOD(device_probe,	acpi_lid_probe),
6267761Smsmith    DEVMETHOD(device_attach,	acpi_lid_attach),
63100497Siwasaki    DEVMETHOD(device_suspend,	acpi_lid_suspend),
64100497Siwasaki    DEVMETHOD(device_resume,	acpi_lid_resume),
6567761Smsmith
6667761Smsmith    {0, 0}
6767761Smsmith};
6867761Smsmith
6967761Smsmithstatic driver_t acpi_lid_driver = {
7067761Smsmith    "acpi_lid",
7167761Smsmith    acpi_lid_methods,
7267761Smsmith    sizeof(struct acpi_lid_softc),
7367761Smsmith};
7467761Smsmith
7589054Smsmithstatic devclass_t acpi_lid_devclass;
7667761SmsmithDRIVER_MODULE(acpi_lid, acpi, acpi_lid_driver, acpi_lid_devclass, 0, 0);
7767761Smsmith
7867761Smsmithstatic int
7967761Smsmithacpi_lid_probe(device_t dev)
8067761Smsmith{
81119529Snjl    if (acpi_get_type(dev) == ACPI_TYPE_DEVICE && !acpi_disabled("lid") &&
8267761Smsmith	acpi_MatchHid(dev, "PNP0C0D")) {
83119529Snjl
8467761Smsmith	device_set_desc(dev, "Control Method Lid Switch");
85119529Snjl	return (0);
8667761Smsmith    }
87119529Snjl    return (ENXIO);
8867761Smsmith}
8967761Smsmith
9067761Smsmithstatic int
9167761Smsmithacpi_lid_attach(device_t dev)
9267761Smsmith{
9367761Smsmith    struct acpi_lid_softc	*sc;
9467761Smsmith
9596926Speter    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
9669744Smsmith
9767761Smsmith    sc = device_get_softc(dev);
9867761Smsmith    sc->lid_dev = dev;
9967761Smsmith    sc->lid_handle = acpi_get_handle(dev);
10067761Smsmith
101119529Snjl    /* Install notification handler */
102119529Snjl    AcpiInstallNotifyHandler(sc->lid_handle, ACPI_DEVICE_NOTIFY,
103119529Snjl			     acpi_lid_notify_handler, sc);
104100497Siwasaki    acpi_device_enable_wake_capability(sc->lid_handle, 1);
105119529Snjl
106119529Snjl    return_VALUE (0);
10767761Smsmith}
10867761Smsmith
109100497Siwasakistatic int
110100497Siwasakiacpi_lid_suspend(device_t dev)
111100497Siwasaki{
112100497Siwasaki    struct acpi_lid_softc	*sc;
113100497Siwasaki
114100497Siwasaki    sc = device_get_softc(dev);
115100497Siwasaki    acpi_device_enable_wake_event(sc->lid_handle);
116100497Siwasaki    return (0);
117100497Siwasaki}
118100497Siwasaki
119100497Siwasakistatic int
120100497Siwasakiacpi_lid_resume(device_t dev)
121100497Siwasaki{
122100497Siwasaki    return (0);
123100497Siwasaki}
124100497Siwasaki
12567761Smsmithstatic void
12667761Smsmithacpi_lid_notify_status_changed(void *arg)
12767761Smsmith{
12867761Smsmith    struct acpi_lid_softc	*sc;
12967761Smsmith    struct acpi_softc		*acpi_sc;
130119529Snjl    ACPI_STATUS			status;
13167761Smsmith
13296926Speter    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
13369744Smsmith
13467761Smsmith    sc = (struct acpi_lid_softc *)arg;
13567761Smsmith
13667761Smsmith    /*
13771872Smsmith     * Evaluate _LID and check the return value, update lid status.
13867761Smsmith     *	Zero:		The lid is closed
13967761Smsmith     *	Non-zero:	The lid is open
14067761Smsmith     */
141119529Snjl    status = acpi_EvaluateInteger(sc->lid_handle, "_LID", &sc->lid_status);
142119529Snjl    if (ACPI_FAILURE(status))
14369744Smsmith	return_VOID;
14467761Smsmith
14567761Smsmith    acpi_sc = acpi_device_get_parent_softc(sc->lid_dev);
146119529Snjl    if (acpi_sc == NULL)
14769744Smsmith        return_VOID;
14867761Smsmith
149119529Snjl    ACPI_VPRINT(sc->lid_dev, acpi_sc, "Lid %s\n",
150119529Snjl		sc->lid_status ? "opened" : "closed");
15186552Siwasaki
152119529Snjl    if (sc->lid_status == 0)
15367761Smsmith	EVENTHANDLER_INVOKE(acpi_sleep_event, acpi_sc->acpi_lid_switch_sx);
154119529Snjl    else
15567761Smsmith	EVENTHANDLER_INVOKE(acpi_wakeup_event, acpi_sc->acpi_lid_switch_sx);
15669744Smsmith
15769744Smsmith    return_VOID;
15867761Smsmith}
15967761Smsmith
16067761Smsmith/* XXX maybe not here */
16167761Smsmith#define	ACPI_NOTIFY_STATUS_CHANGED	0x80
16267761Smsmith
16367761Smsmithstatic void
16467761Smsmithacpi_lid_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
16567761Smsmith{
16667761Smsmith    struct acpi_lid_softc	*sc = (struct acpi_lid_softc *)context;
16767761Smsmith
16896926Speter    ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify);
16969744Smsmith
17067761Smsmith    switch (notify) {
17167761Smsmith    case ACPI_NOTIFY_STATUS_CHANGED:
172119529Snjl	AcpiOsQueueForExecution(OSD_PRIORITY_LO,
173119529Snjl				acpi_lid_notify_status_changed, sc);
17467761Smsmith	break;
17567761Smsmith    default:
176119529Snjl	break;
17767761Smsmith    }
178119529Snjl
17969744Smsmith    return_VOID;
18067761Smsmith}
18167761Smsmith
182