acpi_lid.c revision 1.38
11.38Sjruoho/* $NetBSD: acpi_lid.c,v 1.38 2010/04/14 19:27:28 jruoho Exp $ */ 21.1Sthorpej 31.1Sthorpej/* 41.7Sthorpej * Copyright 2001, 2003 Wasabi Systems, Inc. 51.1Sthorpej * All rights reserved. 61.1Sthorpej * 71.1Sthorpej * Written by Jason R. Thorpe for Wasabi Systems, Inc. 81.1Sthorpej * 91.1Sthorpej * Redistribution and use in source and binary forms, with or without 101.1Sthorpej * modification, are permitted provided that the following conditions 111.1Sthorpej * are met: 121.1Sthorpej * 1. Redistributions of source code must retain the above copyright 131.1Sthorpej * notice, this list of conditions and the following disclaimer. 141.1Sthorpej * 2. Redistributions in binary form must reproduce the above copyright 151.1Sthorpej * notice, this list of conditions and the following disclaimer in the 161.1Sthorpej * documentation and/or other materials provided with the distribution. 171.1Sthorpej * 3. All advertising materials mentioning features or use of this software 181.1Sthorpej * must display the following acknowledgement: 191.1Sthorpej * This product includes software developed for the NetBSD Project by 201.1Sthorpej * Wasabi Systems, Inc. 211.1Sthorpej * 4. The name of Wasabi Systems, Inc. may not be used to endorse 221.1Sthorpej * or promote products derived from this software without specific prior 231.1Sthorpej * written permission. 241.1Sthorpej * 251.1Sthorpej * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 261.1Sthorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 271.1Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 281.1Sthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 291.1Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 301.1Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 311.1Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 321.1Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 331.1Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 341.1Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 351.1Sthorpej * POSSIBILITY OF SUCH DAMAGE. 361.1Sthorpej */ 371.1Sthorpej 381.1Sthorpej/* 391.1Sthorpej * ACPI Lid Switch driver. 401.1Sthorpej */ 411.3Slukem 421.3Slukem#include <sys/cdefs.h> 431.38Sjruoho__KERNEL_RCSID(0, "$NetBSD: acpi_lid.c,v 1.38 2010/04/14 19:27:28 jruoho Exp $"); 441.1Sthorpej 451.1Sthorpej#include <sys/param.h> 461.1Sthorpej#include <sys/device.h> 471.35Sjruoho#include <sys/module.h> 481.36Sjruoho#include <sys/systm.h> 491.1Sthorpej 501.1Sthorpej#include <dev/acpi/acpireg.h> 511.1Sthorpej#include <dev/acpi/acpivar.h> 521.1Sthorpej 531.34Sjruoho#define _COMPONENT ACPI_LID_COMPONENT 541.34SjruohoACPI_MODULE_NAME ("acpi_lid") 551.32Sjruoho 561.1Sthorpejstruct acpilid_softc { 571.34Sjruoho struct acpi_devnode *sc_node; 581.34Sjruoho struct sysmon_pswitch sc_smpsw; 591.34Sjruoho uint64_t sc_status; 601.1Sthorpej}; 611.1Sthorpej 621.10Skochistatic const char * const lid_hid[] = { 631.10Skochi "PNP0C0D", 641.10Skochi NULL 651.10Skochi}; 661.10Skochi 671.25Sxtraemestatic int acpilid_match(device_t, cfdata_t, void *); 681.25Sxtraemestatic void acpilid_attach(device_t, device_t, void *); 691.26Sdyoungstatic int acpilid_detach(device_t, int); 701.15Skochistatic void acpilid_status_changed(void *); 711.38Sjruohostatic void acpilid_notify_handler(ACPI_HANDLE, uint32_t, void *); 721.22Sjmcneill 731.34SjruohoCFATTACH_DECL_NEW(acpilid, sizeof(struct acpilid_softc), 741.34Sjruoho acpilid_match, acpilid_attach, acpilid_detach, NULL); 751.34Sjruoho 761.1Sthorpej/* 771.1Sthorpej * acpilid_match: 781.1Sthorpej * 791.1Sthorpej * Autoconfiguration `match' routine. 801.1Sthorpej */ 811.15Skochistatic int 821.25Sxtraemeacpilid_match(device_t parent, cfdata_t match, void *aux) 831.1Sthorpej{ 841.1Sthorpej struct acpi_attach_args *aa = aux; 851.1Sthorpej 861.1Sthorpej if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 871.14Skochi return 0; 881.1Sthorpej 891.14Skochi return acpi_match_hid(aa->aa_node->ad_devinfo, lid_hid); 901.1Sthorpej} 911.1Sthorpej 921.1Sthorpej/* 931.1Sthorpej * acpilid_attach: 941.1Sthorpej * 951.1Sthorpej * Autoconfiguration `attach' routine. 961.1Sthorpej */ 971.15Skochistatic void 981.25Sxtraemeacpilid_attach(device_t parent, device_t self, void *aux) 991.1Sthorpej{ 1001.25Sxtraeme struct acpilid_softc *sc = device_private(self); 1011.1Sthorpej struct acpi_attach_args *aa = aux; 1021.1Sthorpej ACPI_STATUS rv; 1031.1Sthorpej 1041.19Skochi aprint_naive(": ACPI Lid Switch\n"); 1051.19Skochi aprint_normal(": ACPI Lid Switch\n"); 1061.1Sthorpej 1071.1Sthorpej sc->sc_node = aa->aa_node; 1081.1Sthorpej 1091.25Sxtraeme sc->sc_smpsw.smpsw_name = device_xname(self); 1101.8Sthorpej sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_LID; 1111.34Sjruoho 1121.37Sjruoho (void)pmf_device_register(self, NULL, NULL); 1131.34Sjruoho (void)sysmon_pswitch_register(&sc->sc_smpsw); 1141.7Sthorpej 1151.1Sthorpej rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle, 1161.25Sxtraeme ACPI_DEVICE_NOTIFY, acpilid_notify_handler, self); 1171.16Skochi 1181.34Sjruoho if (ACPI_FAILURE(rv)) 1191.34Sjruoho aprint_error_dev(self, "failed to register notify handler\n"); 1201.22Sjmcneill} 1211.22Sjmcneill 1221.26Sdyoungstatic int 1231.26Sdyoungacpilid_detach(device_t self, int flags) 1241.26Sdyoung{ 1251.26Sdyoung struct acpilid_softc *sc = device_private(self); 1261.26Sdyoung ACPI_STATUS rv; 1271.26Sdyoung 1281.26Sdyoung rv = AcpiRemoveNotifyHandler(sc->sc_node->ad_handle, 1291.26Sdyoung ACPI_DEVICE_NOTIFY, acpilid_notify_handler); 1301.34Sjruoho 1311.34Sjruoho if (ACPI_FAILURE(rv)) 1321.26Sdyoung return EBUSY; 1331.26Sdyoung 1341.26Sdyoung pmf_device_deregister(self); 1351.26Sdyoung sysmon_pswitch_unregister(&sc->sc_smpsw); 1361.26Sdyoung 1371.26Sdyoung return 0; 1381.26Sdyoung} 1391.26Sdyoung 1401.1Sthorpej/* 1411.1Sthorpej * acpilid_status_changed: 1421.1Sthorpej * 1431.1Sthorpej * Get, and possibly display, the lid status, and take action. 1441.1Sthorpej */ 1451.15Skochistatic void 1461.1Sthorpejacpilid_status_changed(void *arg) 1471.1Sthorpej{ 1481.34Sjruoho device_t dv = arg; 1491.34Sjruoho struct acpilid_softc *sc = device_private(dv); 1501.12Smycroft ACPI_STATUS rv; 1511.1Sthorpej 1521.34Sjruoho rv = acpi_eval_integer(sc->sc_node->ad_handle, "_LID", &sc->sc_status); 1531.34Sjruoho 1541.12Smycroft if (ACPI_FAILURE(rv)) 1551.1Sthorpej return; 1561.1Sthorpej 1571.34Sjruoho sysmon_pswitch_event(&sc->sc_smpsw, (sc->sc_status == 0) ? 1581.8Sthorpej PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED); 1591.1Sthorpej} 1601.1Sthorpej 1611.1Sthorpej/* 1621.1Sthorpej * acpilid_notify_handler: 1631.1Sthorpej * 1641.1Sthorpej * Callback from ACPI interrupt handler to notify us of an event. 1651.1Sthorpej */ 1661.15Skochistatic void 1671.34Sjruohoacpilid_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context) 1681.1Sthorpej{ 1691.34Sjruoho static const int handler = OSL_NOTIFY_HANDLER; 1701.25Sxtraeme device_t dv = context; 1711.1Sthorpej 1721.1Sthorpej switch (notify) { 1731.34Sjruoho 1741.1Sthorpej case ACPI_NOTIFY_LidStatusChanged: 1751.34Sjruoho (void)AcpiOsExecute(handler, acpilid_status_changed, dv); 1761.1Sthorpej break; 1771.1Sthorpej 1781.1Sthorpej default: 1791.34Sjruoho aprint_error_dev(dv, "unknown notify 0x%02X\n", notify); 1801.1Sthorpej } 1811.1Sthorpej} 1821.22Sjmcneill 1831.35Sjruoho#ifdef _MODULE 1841.35Sjruoho 1851.35SjruohoMODULE(MODULE_CLASS_DRIVER, acpilid, NULL); 1861.35SjruohoCFDRIVER_DECL(acpilid, DV_DULL, NULL); 1871.35Sjruoho 1881.35Sjruohostatic int acpilidloc[] = { -1 }; 1891.35Sjruohoextern struct cfattach acpilid_ca; 1901.35Sjruoho 1911.35Sjruohostatic struct cfparent acpiparent = { 1921.35Sjruoho "acpinodebus", NULL, DVUNIT_ANY 1931.35Sjruoho}; 1941.35Sjruoho 1951.35Sjruohostatic struct cfdata acpilid_cfdata[] = { 1961.35Sjruoho { 1971.35Sjruoho .cf_name = "acpilid", 1981.35Sjruoho .cf_atname = "acpilid", 1991.35Sjruoho .cf_unit = 0, 2001.35Sjruoho .cf_fstate = FSTATE_STAR, 2011.35Sjruoho .cf_loc = acpilidloc, 2021.35Sjruoho .cf_flags = 0, 2031.35Sjruoho .cf_pspec = &acpiparent, 2041.35Sjruoho }, 2051.35Sjruoho 2061.35Sjruoho { NULL } 2071.35Sjruoho}; 2081.35Sjruoho 2091.35Sjruohostatic int 2101.35Sjruohoacpilid_modcmd(modcmd_t cmd, void *context) 2111.35Sjruoho{ 2121.35Sjruoho int err; 2131.35Sjruoho 2141.35Sjruoho switch (cmd) { 2151.35Sjruoho 2161.35Sjruoho case MODULE_CMD_INIT: 2171.35Sjruoho 2181.35Sjruoho err = config_cfdriver_attach(&acpilid_cd); 2191.35Sjruoho 2201.35Sjruoho if (err != 0) 2211.35Sjruoho return err; 2221.35Sjruoho 2231.35Sjruoho err = config_cfattach_attach("acpilid", &acpilid_ca); 2241.35Sjruoho 2251.35Sjruoho if (err != 0) { 2261.35Sjruoho config_cfdriver_detach(&acpilid_cd); 2271.35Sjruoho return err; 2281.35Sjruoho } 2291.35Sjruoho 2301.35Sjruoho err = config_cfdata_attach(acpilid_cfdata, 1); 2311.35Sjruoho 2321.35Sjruoho if (err != 0) { 2331.35Sjruoho config_cfattach_detach("acpilid", &acpilid_ca); 2341.35Sjruoho config_cfdriver_detach(&acpilid_cd); 2351.35Sjruoho return err; 2361.35Sjruoho } 2371.35Sjruoho 2381.35Sjruoho return 0; 2391.35Sjruoho 2401.35Sjruoho case MODULE_CMD_FINI: 2411.35Sjruoho 2421.35Sjruoho err = config_cfdata_detach(acpilid_cfdata); 2431.35Sjruoho 2441.35Sjruoho if (err != 0) 2451.35Sjruoho return err; 2461.35Sjruoho 2471.35Sjruoho config_cfattach_detach("acpilid", &acpilid_ca); 2481.35Sjruoho config_cfdriver_detach(&acpilid_cd); 2491.35Sjruoho 2501.35Sjruoho return 0; 2511.35Sjruoho 2521.35Sjruoho default: 2531.35Sjruoho return ENOTTY; 2541.35Sjruoho } 2551.35Sjruoho} 2561.35Sjruoho 2571.35Sjruoho#endif /* _MODULE */ 258