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