Module Name: src Committed By: snj Date: Sun Aug 30 03:01:26 UTC 2009
Modified Files: src/sys/dev/acpi [netbsd-5]: asus_acpi.c files.acpi Log Message: Pull up following revision(s) (requested by jmcneill in ticket #891): sys/dev/acpi/asus_acpi.c: revision 1.7 sys/dev/acpi/files.acpi: revision 1.54 - add experimental cpu fan/voltage switching support (sysctl hw.asus0.*) - add fan sensor - rename asus_softc_t -> struct asus_softc - add detach method - update copyright for 2009 To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.6.4.1 src/sys/dev/acpi/asus_acpi.c cvs rdiff -u -r1.52 -r1.52.8.1 src/sys/dev/acpi/files.acpi Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/acpi/asus_acpi.c diff -u src/sys/dev/acpi/asus_acpi.c:1.6 src/sys/dev/acpi/asus_acpi.c:1.6.4.1 --- src/sys/dev/acpi/asus_acpi.c:1.6 Sun Sep 21 21:15:28 2008 +++ src/sys/dev/acpi/asus_acpi.c Sun Aug 30 03:01:26 2009 @@ -1,7 +1,7 @@ -/* $NetBSD: asus_acpi.c,v 1.6 2008/09/21 21:15:28 jmcneill Exp $ */ +/* $NetBSD: asus_acpi.c,v 1.6.4.1 2009/08/30 03:01:26 snj Exp $ */ /*- - * Copyright (c) 2007, 2008 Jared D. McNeill <jmcne...@invisible.ca> + * Copyright (c) 2007, 2008, 2009 Jared D. McNeill <jmcne...@invisible.ca> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: asus_acpi.c,v 1.6 2008/09/21 21:15:28 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: asus_acpi.c,v 1.6.4.1 2009/08/30 03:01:26 snj Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -36,11 +36,11 @@ #include <sys/callout.h> #include <sys/kernel.h> #include <sys/device.h> -#include <sys/pmf.h> +#include <sys/sysctl.h> #include <dev/acpi/acpivar.h> -typedef struct asus_softc { +struct asus_softc { device_t sc_dev; struct acpi_devnode *sc_node; @@ -49,8 +49,18 @@ struct sysmon_pswitch sc_smpsw[ASUS_PSW_LAST]; bool sc_smpsw_valid; + struct sysmon_envsys *sc_sme; +#define ASUS_SENSOR_FAN 0 +#define ASUS_SENSOR_LAST 1 + envsys_data_t sc_sensor[ASUS_SENSOR_LAST]; + ACPI_INTEGER sc_brightness; -} asus_softc_t; + ACPI_INTEGER sc_cfvnum; + + struct sysctllog *sc_log; + int sc_cfv_mib; + int sc_cfvnum_mib; +}; #define ASUS_NOTIFY_WirelessSwitch 0x10 #define ASUS_NOTIFY_BrightnessLow 0x20 @@ -70,9 +80,15 @@ (ASUS_SDSP_LCD | ASUS_SDSP_CRT | ASUS_SDSP_TV | ASUS_SDSP_DVI) #define ASUS_METHOD_PBLG "PBLG" #define ASUS_METHOD_PBLS "PBLS" +#define ASUS_METHOD_CFVS "CFVS" +#define ASUS_METHOD_CFVG "CFVG" + +#define ASUS_EC_METHOD_FAN_RPMH "\\_SB.PCI0.SBRG.EC0.SC05" +#define ASUS_EC_METHOD_FAN_RPML "\\_SB.PCI0.SBRG.EC0.SC06" static int asus_match(device_t, cfdata_t, void *); static void asus_attach(device_t, device_t, void *); +static int asus_detach(device_t, int); static void asus_notify_handler(ACPI_HANDLE, UINT32, void *); @@ -80,8 +96,13 @@ static bool asus_suspend(device_t PMF_FN_PROTO); static bool asus_resume(device_t PMF_FN_PROTO); -CFATTACH_DECL_NEW(asus, sizeof(asus_softc_t), - asus_match, asus_attach, NULL, NULL); +static void asus_sysctl_setup(struct asus_softc *); + +static void asus_sensors_refresh(struct sysmon_envsys *, envsys_data_t *); +static bool asus_get_fan_speed(struct asus_softc *, uint32_t *); + +CFATTACH_DECL_NEW(asus, sizeof(struct asus_softc), + asus_match, asus_attach, asus_detach, NULL); static const char * const asus_ids[] = { "ASUS010", @@ -102,7 +123,7 @@ static void asus_attach(device_t parent, device_t self, void *opaque) { - asus_softc_t *sc = device_private(self); + struct asus_softc *sc = device_private(self); struct acpi_attach_args *aa = opaque; ACPI_STATUS rv; @@ -124,6 +145,27 @@ sc->sc_smpsw_valid = false; } + if (asus_get_fan_speed(sc, NULL) == false) + goto nosensors; + + sc->sc_sme = sysmon_envsys_create(); + + strcpy(sc->sc_sensor[ASUS_SENSOR_FAN].desc, "fan"); + sc->sc_sensor[ASUS_SENSOR_FAN].units = ENVSYS_SFANRPM; + sysmon_envsys_sensor_attach(sc->sc_sme, + &sc->sc_sensor[ASUS_SENSOR_FAN]); + + sc->sc_sme->sme_name = device_xname(self); + sc->sc_sme->sme_cookie = sc; + sc->sc_sme->sme_refresh = asus_sensors_refresh; + + if (sysmon_envsys_register(sc->sc_sme)) { + aprint_error_dev(self, "couldn't register with envsys\n"); + sysmon_envsys_destroy(sc->sc_sme); + sc->sc_sme = NULL; + } +nosensors: + rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle, ACPI_ALL_NOTIFY, asus_notify_handler, sc); if (ACPI_FAILURE(rv)) @@ -134,10 +176,29 @@ aprint_error_dev(self, "couldn't establish power handler\n"); } +static int +asus_detach(device_t self, int flags) +{ + struct asus_softc *sc = device_private(self); + int i; + + if (sc->sc_smpsw_valid) + for (i = 0; i < ASUS_PSW_LAST; i++) + sysmon_pswitch_unregister(&sc->sc_smpsw[i]); + + if (sc->sc_sme) + sysmon_envsys_unregister(sc->sc_sme); + if (sc->sc_log) + sysctl_teardown(&sc->sc_log); + pmf_device_deregister(self); + + return 0; +} + static void asus_notify_handler(ACPI_HANDLE hdl, UINT32 notify, void *opaque) { - asus_softc_t *sc = opaque; + struct asus_softc *sc = opaque; if (notify >= ASUS_NOTIFY_BrightnessLow && notify <= ASUS_NOTIFY_BrightnessHigh) { @@ -174,11 +235,12 @@ static void asus_init(device_t self) { - asus_softc_t *sc = device_private(self); + struct asus_softc *sc = device_private(self); ACPI_STATUS rv; ACPI_OBJECT param; ACPI_OBJECT_LIST params; ACPI_BUFFER ret; + ACPI_INTEGER cfv; ret.Pointer = NULL; ret.Length = ACPI_ALLOCATE_BUFFER; @@ -195,12 +257,20 @@ if (ret.Pointer) AcpiOsFree(ret.Pointer); + + rv = acpi_eval_integer(sc->sc_node->ad_handle, ASUS_METHOD_CFVG, &cfv); + if (ACPI_FAILURE(rv)) + return; + + sc->sc_cfvnum = (cfv >> 8) & 0xff; + + asus_sysctl_setup(sc); } static bool asus_suspend(device_t self PMF_FN_ARGS) { - asus_softc_t *sc = device_private(self); + struct asus_softc *sc = device_private(self); ACPI_STATUS rv; /* capture display brightness when we're sleeping */ @@ -216,7 +286,7 @@ static bool asus_resume(device_t self PMF_FN_ARGS) { - asus_softc_t *sc = device_private(self); + struct asus_softc *sc = device_private(self); ACPI_STATUS rv; ACPI_OBJECT param; ACPI_OBJECT_LIST params; @@ -240,3 +310,124 @@ return true; } + +static int +asus_sysctl_verify(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + struct asus_softc *sc; + ACPI_STATUS rv; + ACPI_INTEGER cfv; + ACPI_OBJECT param, retval; + ACPI_OBJECT_LIST params; + ACPI_BUFFER ret; + int err, tmp; + + node = *rnode; + sc = rnode->sysctl_data; + if (node.sysctl_num == sc->sc_cfv_mib) { + rv = acpi_eval_integer(sc->sc_node->ad_handle, + ASUS_METHOD_CFVG, &cfv); + if (ACPI_FAILURE(rv)) + return ENXIO; + tmp = cfv & 0xff; + node.sysctl_data = &tmp; + err = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (err || newp == NULL) + return err; + + if (tmp < 0 || tmp >= sc->sc_cfvnum) + return EINVAL; + + ret.Pointer = &retval; + ret.Length = sizeof(retval); + param.Type = ACPI_TYPE_INTEGER; + param.Integer.Value = tmp; + params.Pointer = ¶m; + params.Count = 1; + + rv = AcpiEvaluateObject(sc->sc_node->ad_handle, + ASUS_METHOD_CFVS, ¶ms, &ret); + if (ACPI_FAILURE(rv)) + return ENXIO; + } + + return 0; +} + +static void +asus_sysctl_setup(struct asus_softc *sc) +{ + const struct sysctlnode *node, *node_cfv, *node_ncfv; + int err, node_mib; + + if (sc->sc_cfvnum == 0) + return; + + err = sysctl_createv(&sc->sc_log, 0, NULL, NULL, 0, + CTLTYPE_NODE, "hw", NULL, NULL, 0, NULL, 0, CTL_HW, CTL_EOL); + if (err) + goto sysctl_err; + err = sysctl_createv(&sc->sc_log, 0, NULL, &node, 0, + CTLTYPE_NODE, device_xname(sc->sc_dev), NULL, NULL, 0, + NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL); + if (err) + goto sysctl_err; + node_mib = node->sysctl_num; + err = sysctl_createv(&sc->sc_log, 0, NULL, &node_ncfv, + CTLFLAG_READONLY, CTLTYPE_INT, "ncfv", + SYSCTL_DESCR("Number of CPU frequency/voltage modes"), + NULL, 0, &sc->sc_cfvnum, 0, + CTL_HW, node_mib, CTL_CREATE, CTL_EOL); + if (err) + goto sysctl_err; + sc->sc_cfvnum_mib = node_ncfv->sysctl_num; + err = sysctl_createv(&sc->sc_log, 0, NULL, &node_cfv, + CTLFLAG_READWRITE, CTLTYPE_INT, "cfv", + SYSCTL_DESCR("Current CPU frequency/voltage mode"), + asus_sysctl_verify, 0, sc, 0, + CTL_HW, node_mib, CTL_CREATE, CTL_EOL); + if (err) + goto sysctl_err; + sc->sc_cfv_mib = node_cfv->sysctl_num; + +sysctl_err: + aprint_error_dev(sc->sc_dev, "failed to add sysctl nodes. (%d)\n", err); +} + +static void +asus_sensors_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) +{ + struct asus_softc *sc = sme->sme_cookie; + uint32_t rpm; + + switch (edata->sensor) { + case ASUS_SENSOR_FAN: + if (asus_get_fan_speed(sc, &rpm)) { + edata->value_cur = rpm; + edata->state = ENVSYS_SVALID; + } else + edata->state = ENVSYS_SINVALID; + break; + } +} + +static bool +asus_get_fan_speed(struct asus_softc *sc, uint32_t *speed) +{ + ACPI_INTEGER rpmh, rpml; + ACPI_STATUS rv; + + rv = acpi_eval_integer(sc->sc_node->ad_handle, + ASUS_EC_METHOD_FAN_RPMH, &rpmh); + if (ACPI_FAILURE(rv)) + return false; + rv = acpi_eval_integer(sc->sc_node->ad_handle, + ASUS_EC_METHOD_FAN_RPML, &rpml); + if (ACPI_FAILURE(rv)) + return false; + + if (speed) + *speed = (rpmh << 8) | rpml; + return true; +} Index: src/sys/dev/acpi/files.acpi diff -u src/sys/dev/acpi/files.acpi:1.52 src/sys/dev/acpi/files.acpi:1.52.8.1 --- src/sys/dev/acpi/files.acpi:1.52 Sun May 18 22:05:59 2008 +++ src/sys/dev/acpi/files.acpi Sun Aug 30 03:01:26 2009 @@ -1,4 +1,4 @@ -# $NetBSD: files.acpi,v 1.52 2008/05/18 22:05:59 cegger Exp $ +# $NetBSD: files.acpi,v 1.52.8.1 2009/08/30 03:01:26 snj Exp $ include "dev/acpi/acpica/files.acpica" @@ -114,7 +114,7 @@ file dev/acpi/aiboost.c aiboost # ASUS hotkey device -device asus: sysmon_power +device asus: sysmon_envsys, sysmon_power attach asus at acpinodebus file dev/acpi/asus_acpi.c asus