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); +}