Module Name:    src
Committed By:   jakllsch
Date:           Sun Apr 11 22:42:30 UTC 2010

Modified Files:
        src/sys/arch/i386/conf: ALL
        src/sys/dev/acpi: files.acpi
Added Files:
        src/sys/dev/acpi: valz_acpi.c

Log Message:
Add valz(4), a simple driver to handle the backlight keys on some
Toshiba laptops.  As of yet only tested on a Satellite A135-S4527.


To generate a diff of this commit:
cvs rdiff -u -r1.253 -r1.254 src/sys/arch/i386/conf/ALL
cvs rdiff -u -r1.71 -r1.72 src/sys/dev/acpi/files.acpi
cvs rdiff -u -r0 -r1.1 src/sys/dev/acpi/valz_acpi.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/i386/conf/ALL
diff -u src/sys/arch/i386/conf/ALL:1.253 src/sys/arch/i386/conf/ALL:1.254
--- src/sys/arch/i386/conf/ALL:1.253	Thu Apr  8 17:50:34 2010
+++ src/sys/arch/i386/conf/ALL	Sun Apr 11 22:42:30 2010
@@ -1,4 +1,4 @@
-# $NetBSD: ALL,v 1.253 2010/04/08 17:50:34 jruoho Exp $
+# $NetBSD: ALL,v 1.254 2010/04/11 22:42:30 jakllsch Exp $
 # From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
 #
 # ALL machine description file
@@ -17,7 +17,7 @@
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident 		"ALL-$Revision: 1.253 $"
+#ident 		"ALL-$Revision: 1.254 $"
 
 maxusers	64		# estimated number of users
 
@@ -406,6 +406,9 @@
 # Toshiba Libretto devices
 vald* at acpi?
 
+# Toshiba LCD brightness
+valz* at acpi?
+
 # Plug-and-Play BIOS and attached devices
 
 pnpbios*	at mainbus?

Index: src/sys/dev/acpi/files.acpi
diff -u src/sys/dev/acpi/files.acpi:1.71 src/sys/dev/acpi/files.acpi:1.72
--- src/sys/dev/acpi/files.acpi:1.71	Sat Apr 10 17:55:24 2010
+++ src/sys/dev/acpi/files.acpi	Sun Apr 11 22:42:30 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: files.acpi,v 1.71 2010/04/10 17:55:24 jruoho Exp $
+#	$NetBSD: files.acpi,v 1.72 2010/04/11 22:42:30 jakllsch Exp $
 
 include "dev/acpi/acpica/files.acpica"
 
@@ -132,6 +132,11 @@
 attach	vald at acpinodebus with vald_acpi
 file	dev/acpi/vald_acpi.c		vald_acpi
 
+# Toshiba backlight hotkeys
+device	valz
+attach	valz at acpinodebus
+file	dev/acpi/valz_acpi.c valz
+
 # Sony SPIC (jog dial etc.)
 attach	spic at acpinodebus with spic_acpi
 file	dev/acpi/spic_acpi.c		spic_acpi

Added files:

Index: src/sys/dev/acpi/valz_acpi.c
diff -u /dev/null src/sys/dev/acpi/valz_acpi.c:1.1
--- /dev/null	Sun Apr 11 22:42:30 2010
+++ src/sys/dev/acpi/valz_acpi.c	Sun Apr 11 22:42:30 2010
@@ -0,0 +1,221 @@
+/*	$NetBSD: valz_acpi.c,v 1.1 2010/04/11 22:42:30 jakllsch Exp $	*/
+
+/*
+ * Copyright (c) 2010 Jonathan A. Kollasch
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: valz_acpi.c,v 1.1 2010/04/11 22:42:30 jakllsch Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/syslog.h>
+
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+
+struct valz_softc {
+	device_t sc_dev;
+	ACPI_HANDLE sc_lcd;
+};
+
+enum valz_action {
+	VALZ_BACKLIGHT_NOCHANGE,
+	VALZ_BACKLIGHT_DECREASE,
+	VALZ_BACKLIGHT_INCREASE,
+};
+
+static const char * const valz_hids[] = {
+	"TOS1900",
+	NULL
+};
+
+static int	valz_match(device_t, cfdata_t, void *);
+static void	valz_attach(device_t, device_t, void *);
+static ACPI_STATUS valz_check_bcl(ACPI_HANDLE, UINT32, void*, void **);
+static void	valz_locate_lcd(struct valz_softc *);
+static void	valz_lcd_notify_handler(ACPI_HANDLE, UINT32, void *);
+static void	valz_adjust_backlight(struct valz_softc *, enum valz_action);
+static void	valz_pmf_brightness_decrease(device_t);
+static void	valz_pmf_brightness_increase(device_t);
+
+CFATTACH_DECL_NEW(valz, sizeof(struct valz_softc),
+    valz_match, valz_attach, NULL, NULL);
+
+static int
+valz_match(device_t parent, cfdata_t match, void *aux)
+{
+	struct acpi_attach_args *aa = aux;
+
+	if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
+		return 0;
+
+	return acpi_match_hid(aa->aa_node->ad_devinfo, valz_hids);
+}
+
+static void
+valz_attach(device_t parent, device_t self, void *aux)
+{
+	struct valz_softc *sc;
+	ACPI_STATUS rv;
+
+	aprint_naive("\n");
+	aprint_normal("\n");
+
+	sc = device_private(self);
+	sc->sc_dev = self;
+	sc->sc_lcd = NULL;
+
+	valz_locate_lcd(sc);
+
+	if (sc->sc_lcd == NULL) {
+		aprint_error_dev(self, "failed to find a usable LCD\n");
+		return;
+	}
+
+	if(!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_DOWN,
+	    valz_pmf_brightness_decrease, false))
+		aprint_error_dev(self, "failed to register event handler\n");
+
+	if(!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_UP,
+	    valz_pmf_brightness_increase, false))
+		aprint_error_dev(self, "failed to register event handler\n");
+		
+	rv = AcpiInstallNotifyHandler(sc->sc_lcd, ACPI_DEVICE_NOTIFY,
+		valz_lcd_notify_handler, sc);
+	if (ACPI_FAILURE(rv))
+		aprint_error_dev(self, "failed to install notify handler; %s\n",
+		     AcpiFormatException(rv));
+}
+
+static void
+valz_lcd_notify_handler(ACPI_HANDLE handle, UINT32 notify, void *context)
+{
+	struct valz_softc *sc = context;
+
+	/* XXX magic */
+	switch (notify) {
+	case 0x86:
+		pmf_event_inject(sc->sc_dev, PMFE_DISPLAY_BRIGHTNESS_UP);
+		break;
+	case 0x87:
+		pmf_event_inject(sc->sc_dev, PMFE_DISPLAY_BRIGHTNESS_DOWN);
+		break;
+	default:
+		log(LOG_INFO, "%s: unknown notify: 0x%x\n",
+		    device_xname(sc->sc_dev), notify);
+		break;
+	}
+}
+
+static void
+valz_locate_lcd(struct valz_softc *sc)
+{
+	ACPI_HANDLE parent;
+	ACPI_STATUS rv;
+
+	rv = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &parent);
+	if (ACPI_FAILURE(rv))
+		return;
+
+        AcpiWalkNamespace(ACPI_TYPE_DEVICE, parent, 100,
+			  valz_check_bcl, NULL, sc, NULL);
+}
+
+static ACPI_STATUS
+valz_check_bcl(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
+{
+	struct valz_softc *sc = context;
+	ACPI_STATUS rv;
+	ACPI_BUFFER buf;
+
+	rv = acpi_eval_struct(handle, "_BCL", &buf);
+	if (ACPI_FAILURE(rv))
+		return AE_OK;
+
+	sc->sc_lcd = handle;
+
+	if (buf.Pointer)
+		AcpiOsFree(buf.Pointer);
+
+	return AE_OK;
+}
+
+static void
+valz_adjust_backlight(struct valz_softc *sc, enum valz_action action)
+{
+	ACPI_STATUS rv;
+	ACPI_INTEGER old_level, new_level;
+
+	if (sc->sc_lcd == NULL)
+		return;
+
+	/* Get current backlight level. */
+	rv = acpi_eval_integer(sc->sc_lcd, "_BQC", &old_level);
+	if (ACPI_FAILURE(rv)) {
+		log(LOG_CRIT, "%s: _BQC failed evaluation: %s\n",
+		    device_xname(sc->sc_dev), AcpiFormatException(rv));
+		return;
+	}
+
+	new_level = old_level;
+
+	switch (action) {
+	case VALZ_BACKLIGHT_DECREASE:
+		if(old_level >= 10)
+			new_level -= 10;
+		break;
+	case VALZ_BACKLIGHT_INCREASE:
+		if(old_level <= 60)
+			new_level += 10;
+		break;
+	default:
+		return;
+	}
+
+	if (new_level == old_level)
+		return;
+
+	rv = acpi_eval_set_integer(sc->sc_lcd, "_BCM", new_level);
+	if (ACPI_FAILURE(rv))
+		log(LOG_CRIT, "%s: _BCM failed evaluation: %s\n",
+		    device_xname(sc->sc_dev), AcpiFormatException(rv));
+}
+
+static void
+valz_pmf_brightness_decrease(device_t self)
+{
+	struct valz_softc *sc;
+	sc = device_private(self);
+	valz_adjust_backlight(sc, VALZ_BACKLIGHT_DECREASE);
+}
+
+static void
+valz_pmf_brightness_increase(device_t self)
+{
+	struct valz_softc *sc;
+	sc = device_private(self);
+	valz_adjust_backlight(sc, VALZ_BACKLIGHT_INCREASE);
+}

Reply via email to