Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Add valz(4), a simple driver to handle the backlight key...



details:   https://anonhg.NetBSD.org/src/rev/c920ff0d8f64
branches:  trunk
changeset: 753836:c920ff0d8f64
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Sun Apr 11 22:42:30 2010 +0000

description:
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.

diffstat:

 sys/arch/i386/conf/ALL   |    7 +-
 sys/dev/acpi/files.acpi  |    7 +-
 sys/dev/acpi/valz_acpi.c |  221 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 232 insertions(+), 3 deletions(-)

diffs (274 lines):

diff -r 61eca7103366 -r c920ff0d8f64 sys/arch/i386/conf/ALL
--- a/sys/arch/i386/conf/ALL    Sun Apr 11 21:34:18 2010 +0000
+++ b/sys/arch/i386/conf/ALL    Sun Apr 11 22:42:30 2010 +0000
@@ -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?
diff -r 61eca7103366 -r c920ff0d8f64 sys/dev/acpi/files.acpi
--- a/sys/dev/acpi/files.acpi   Sun Apr 11 21:34:18 2010 +0000
+++ b/sys/dev/acpi/files.acpi   Sun Apr 11 22:42:30 2010 +0000
@@ -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
diff -r 61eca7103366 -r c920ff0d8f64 sys/dev/acpi/valz_acpi.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/acpi/valz_acpi.c  Sun Apr 11 22:42:30 2010 +0000
@@ -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);
+}



Home | Main Index | Thread Index | Old Index