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 = &param;
+		params.Count = 1;
+
+		rv = AcpiEvaluateObject(sc->sc_node->ad_handle,
+		    ASUS_METHOD_CFVS, &params, &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
 

Reply via email to