/* $NetBSD$ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. * 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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 __KERNEL_RCSID(0, "$NetBSD$"); #include #include #include #include #include #include #define ADB_BRT_ID 31 /* $OpenBSD: ofw_machdep.h,v 1.3 2003/06/02 16:16:27 miod Exp $ */ /* * For some reason, setting the brightness under 0x29 from OF switches the * backlight off, and it won't be switched on again until you set the * brightness above 0x33. All hail hysteresis! -- miod */ #define MIN_BRIGHTNESS 0x34 #define MAX_BRIGHTNESS 0xff #define STEP_BRIGHTNESS 8 #define DEFAULT_BRIGHTNESS 0x80 /* $NetBSD: abtn.c,v 1.11 2005/12/11 12:18:03 christos Exp $ */ #define BUTTON_BRIGHTER 0x09 #define BUTTON_DIMMER 0x0a struct ofbrt_softc { struct device sc_dev; int sc_ih; /* OFW device handle */ int origaddr; /* ADB device type */ int adbaddr; /* current ADB address */ int handler_id; int brightness; /* backlight brightness */ }; static int ofbrt_match(struct device *, struct cfdata *, void *); static void ofbrt_attach(struct device *, struct device *, void *); CFATTACH_DECL(ofbrt, sizeof(struct ofbrt_softc), ofbrt_match, ofbrt_attach, NULL, NULL); static int of_has_brt(void); static void of_set_brightness(int, int); static int of_get_brightness(int); static void ofbrt_adbcomplete(caddr_t, caddr_t, int); static int ofbrt_match(struct device *parent, struct cfdata *match, void *aux) { struct adb_attach_args *aa = aux; /* If we're the right driver, and the machine has OFW support * for brightness control, and the console output is on the * panel. */ if (aa->origaddr == ADBADDR_MISC && aa->handler_id == ADB_BRT_ID && of_has_brt() && ofb_is_console()) return 1; return 0; } static void ofbrt_attach(struct device *parent, struct device *self, void *aux) { struct ofbrt_softc *sc = (struct ofbrt_softc *)self; struct adb_attach_args *aa = aux; ADBSetInfoBlock adbinfo; int bright; int chosen, stdout; /* Get handle to display device handle . */ /* Home brewed OF node locator */ chosen = OF_finddevice("/chosen"); if ( chosen == -1 ) printf("Couldn't find /chosen \n"); /* XXX: reprobe PCI */ if (OF_getprop(chosen, "stdout", &stdout, 4) == -1) printf(" couldn't find property /chosen: stdout \n"); sc->sc_ih = stdout; sc->brightness = bright = of_get_brightness(sc->sc_ih); of_set_brightness(sc->sc_ih, bright); sc->origaddr = aa->origaddr; sc->adbaddr = aa->adbaddr; sc->handler_id = aa->handler_id; adbinfo.siServiceRtPtr = (Ptr)ofbrt_adbcomplete; adbinfo.siDataAreaAddr = (caddr_t)sc; SetADBInfo(&adbinfo, sc->adbaddr); printf("Open Firmware brightness control \n"); } int of_has_brt() { int ofnode; char type[16]; /* Look for the backlight node */ ofnode = getnodebyname(0, "backlight"); if (ofnode == -1) return 0; /* Ok. This is a bit paranoid. */ OF_getprop(ofnode, "device_type", type, sizeof(type)); if (strcmp(type, "backlight") == 0) return 1; return 0; } void of_set_brightness(int ihandle, int brightness) { if (brightness < MIN_BRIGHTNESS) brightness = MIN_BRIGHTNESS; else if (brightness > MAX_BRIGHTNESS) brightness = MAX_BRIGHTNESS; /* * The OF method is called "set-contrast" but affects brightness. * Don't ask. */ OF_call_method_1("set-contrast", ihandle, 1, brightness); } int of_get_brightness(int ihandle) { return 0; } extern struct cfdriver akbd_cd; /* adb keyboard driver hook. Process brightness hotkeys. */ void ofbrt_adbcomplete(buffer, data, adb_command) caddr_t buffer, data; int adb_command; { struct ofbrt_softc *sc = (struct ofbrt_softc *)data; u_int cmd; cmd = buffer[1]; switch (cmd) { case BUTTON_DIMMER: sc->brightness -= 8; if (sc->brightness < MIN_BRIGHTNESS) sc->brightness = MIN_BRIGHTNESS; of_set_brightness(sc->sc_ih, sc->brightness); printf("ofbrt: BUTTON_DIMMER pressed \n"); break; case BUTTON_BRIGHTER: sc->brightness += 8; if (sc->brightness > MAX_BRIGHTNESS) sc->brightness = MAX_BRIGHTNESS; of_set_brightness(sc->sc_ih, sc->brightness); printf("ofbrt: BUTTON_BRIGHTER pressed \n"); break; default: break; } /* Pass up the keystroke in any case. */ // kbd_passup(akbd_cd.cd_devs[0],cmd); }