140ebf162SOleksandr Tymoshenko /*- 226c36284SOleksandr Tymoshenko * Copyright (c) 2015-2016 Oleksandr Tymoshenko <gonzo@freebsd.org> 340ebf162SOleksandr Tymoshenko * All rights reserved. 440ebf162SOleksandr Tymoshenko * 540ebf162SOleksandr Tymoshenko * Redistribution and use in source and binary forms, with or without 640ebf162SOleksandr Tymoshenko * modification, are permitted provided that the following conditions 740ebf162SOleksandr Tymoshenko * are met: 840ebf162SOleksandr Tymoshenko * 1. Redistributions of source code must retain the above copyright 940ebf162SOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer. 1040ebf162SOleksandr Tymoshenko * 2. Redistributions in binary form must reproduce the above copyright 1140ebf162SOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer in the 1240ebf162SOleksandr Tymoshenko * documentation and/or other materials provided with the distribution. 1340ebf162SOleksandr Tymoshenko * 1440ebf162SOleksandr Tymoshenko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1540ebf162SOleksandr Tymoshenko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1640ebf162SOleksandr Tymoshenko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1740ebf162SOleksandr Tymoshenko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1840ebf162SOleksandr Tymoshenko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1940ebf162SOleksandr Tymoshenko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2040ebf162SOleksandr Tymoshenko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2140ebf162SOleksandr Tymoshenko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2240ebf162SOleksandr Tymoshenko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2340ebf162SOleksandr Tymoshenko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2440ebf162SOleksandr Tymoshenko * SUCH DAMAGE. 2540ebf162SOleksandr Tymoshenko */ 2640ebf162SOleksandr Tymoshenko 2740ebf162SOleksandr Tymoshenko #include <sys/cdefs.h> 2840ebf162SOleksandr Tymoshenko __FBSDID("$FreeBSD$"); 2940ebf162SOleksandr Tymoshenko 3040ebf162SOleksandr Tymoshenko #include "opt_platform.h" 3140ebf162SOleksandr Tymoshenko 3240ebf162SOleksandr Tymoshenko #include <sys/param.h> 3340ebf162SOleksandr Tymoshenko #include <sys/systm.h> 3440ebf162SOleksandr Tymoshenko #include <sys/bus.h> 3540ebf162SOleksandr Tymoshenko #include <sys/gpio.h> 3640ebf162SOleksandr Tymoshenko #include <sys/kernel.h> 3740ebf162SOleksandr Tymoshenko #include <sys/lock.h> 3840ebf162SOleksandr Tymoshenko #include <sys/malloc.h> 3940ebf162SOleksandr Tymoshenko #include <sys/module.h> 4040ebf162SOleksandr Tymoshenko #include <sys/mutex.h> 4140ebf162SOleksandr Tymoshenko #include <sys/sysctl.h> 4240ebf162SOleksandr Tymoshenko 4340ebf162SOleksandr Tymoshenko #include <dev/fdt/fdt_common.h> 4440ebf162SOleksandr Tymoshenko #include <dev/ofw/ofw_bus.h> 4540ebf162SOleksandr Tymoshenko 4640ebf162SOleksandr Tymoshenko #include <dev/gpio/gpiobusvar.h> 4740ebf162SOleksandr Tymoshenko 4840ebf162SOleksandr Tymoshenko struct gpiobacklight_softc 4940ebf162SOleksandr Tymoshenko { 5026c36284SOleksandr Tymoshenko gpio_pin_t sc_pin; 5140ebf162SOleksandr Tymoshenko struct sysctl_oid *sc_oid; 5226c36284SOleksandr Tymoshenko bool sc_brightness; 5340ebf162SOleksandr Tymoshenko }; 5440ebf162SOleksandr Tymoshenko 5540ebf162SOleksandr Tymoshenko static int gpiobacklight_sysctl(SYSCTL_HANDLER_ARGS); 5640ebf162SOleksandr Tymoshenko static void gpiobacklight_update_brightness(struct gpiobacklight_softc *); 5740ebf162SOleksandr Tymoshenko static int gpiobacklight_probe(device_t); 5840ebf162SOleksandr Tymoshenko static int gpiobacklight_attach(device_t); 5940ebf162SOleksandr Tymoshenko static int gpiobacklight_detach(device_t); 6040ebf162SOleksandr Tymoshenko 6140ebf162SOleksandr Tymoshenko static void 6240ebf162SOleksandr Tymoshenko gpiobacklight_update_brightness(struct gpiobacklight_softc *sc) 6340ebf162SOleksandr Tymoshenko { 6440ebf162SOleksandr Tymoshenko 6526c36284SOleksandr Tymoshenko if (sc->sc_pin) 6626c36284SOleksandr Tymoshenko gpio_pin_set_active(sc->sc_pin, sc->sc_brightness); 6740ebf162SOleksandr Tymoshenko } 6840ebf162SOleksandr Tymoshenko 6940ebf162SOleksandr Tymoshenko static int 7040ebf162SOleksandr Tymoshenko gpiobacklight_sysctl(SYSCTL_HANDLER_ARGS) 7140ebf162SOleksandr Tymoshenko { 7240ebf162SOleksandr Tymoshenko struct gpiobacklight_softc *sc; 7340ebf162SOleksandr Tymoshenko int error; 7440ebf162SOleksandr Tymoshenko int brightness; 7540ebf162SOleksandr Tymoshenko 7640ebf162SOleksandr Tymoshenko sc = (struct gpiobacklight_softc*)arg1; 7726c36284SOleksandr Tymoshenko 7840ebf162SOleksandr Tymoshenko brightness = sc->sc_brightness; 7940ebf162SOleksandr Tymoshenko error = sysctl_handle_int(oidp, &brightness, 0, req); 8040ebf162SOleksandr Tymoshenko 8140ebf162SOleksandr Tymoshenko if (error != 0 || req->newptr == NULL) 8240ebf162SOleksandr Tymoshenko return (error); 8340ebf162SOleksandr Tymoshenko 8426c36284SOleksandr Tymoshenko sc->sc_brightness = (brightness > 0); 8540ebf162SOleksandr Tymoshenko gpiobacklight_update_brightness(sc); 8640ebf162SOleksandr Tymoshenko 8726c36284SOleksandr Tymoshenko return (0); 8840ebf162SOleksandr Tymoshenko } 8940ebf162SOleksandr Tymoshenko 9040ebf162SOleksandr Tymoshenko static int 9140ebf162SOleksandr Tymoshenko gpiobacklight_probe(device_t dev) 9240ebf162SOleksandr Tymoshenko { 9340ebf162SOleksandr Tymoshenko 9440ebf162SOleksandr Tymoshenko if (!ofw_bus_is_compatible(dev, "gpio-backlight")) 9540ebf162SOleksandr Tymoshenko return (ENXIO); 9640ebf162SOleksandr Tymoshenko 9740ebf162SOleksandr Tymoshenko device_set_desc(dev, "GPIO backlight"); 9840ebf162SOleksandr Tymoshenko 9940ebf162SOleksandr Tymoshenko return (0); 10040ebf162SOleksandr Tymoshenko } 10140ebf162SOleksandr Tymoshenko 10240ebf162SOleksandr Tymoshenko static int 10340ebf162SOleksandr Tymoshenko gpiobacklight_attach(device_t dev) 10440ebf162SOleksandr Tymoshenko { 10540ebf162SOleksandr Tymoshenko struct gpiobacklight_softc *sc; 10640ebf162SOleksandr Tymoshenko struct sysctl_ctx_list *ctx; 10740ebf162SOleksandr Tymoshenko struct sysctl_oid *tree; 10840ebf162SOleksandr Tymoshenko phandle_t node; 10940ebf162SOleksandr Tymoshenko 11040ebf162SOleksandr Tymoshenko sc = device_get_softc(dev); 11140ebf162SOleksandr Tymoshenko 11240ebf162SOleksandr Tymoshenko if ((node = ofw_bus_get_node(dev)) == -1) 11340ebf162SOleksandr Tymoshenko return (ENXIO); 11440ebf162SOleksandr Tymoshenko 11540ebf162SOleksandr Tymoshenko if (OF_hasprop(node, "default-on")) 11626c36284SOleksandr Tymoshenko sc->sc_brightness = true; 11740ebf162SOleksandr Tymoshenko else 11826c36284SOleksandr Tymoshenko sc->sc_brightness = false; 11926c36284SOleksandr Tymoshenko 12026c36284SOleksandr Tymoshenko gpio_pin_get_by_ofw_idx(dev, node, 0, &sc->sc_pin); 12126c36284SOleksandr Tymoshenko if (sc->sc_pin == NULL) { 12226c36284SOleksandr Tymoshenko device_printf(dev, "failed to map GPIO pin\n"); 12326c36284SOleksandr Tymoshenko return (ENXIO); 12426c36284SOleksandr Tymoshenko } 12526c36284SOleksandr Tymoshenko 12626c36284SOleksandr Tymoshenko gpio_pin_setflags(sc->sc_pin, GPIO_PIN_OUTPUT); 12726c36284SOleksandr Tymoshenko 12826c36284SOleksandr Tymoshenko gpiobacklight_update_brightness(sc); 12940ebf162SOleksandr Tymoshenko 13040ebf162SOleksandr Tymoshenko /* Init backlight interface */ 13126c36284SOleksandr Tymoshenko ctx = device_get_sysctl_ctx(dev); 13226c36284SOleksandr Tymoshenko tree = device_get_sysctl_tree(dev); 13340ebf162SOleksandr Tymoshenko sc->sc_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 134*7029da5cSPawel Biernacki "brightness", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0, 13540ebf162SOleksandr Tymoshenko gpiobacklight_sysctl, "I", "backlight brightness"); 13640ebf162SOleksandr Tymoshenko 13740ebf162SOleksandr Tymoshenko return (0); 13840ebf162SOleksandr Tymoshenko } 13940ebf162SOleksandr Tymoshenko 14040ebf162SOleksandr Tymoshenko static int 14140ebf162SOleksandr Tymoshenko gpiobacklight_detach(device_t dev) 14240ebf162SOleksandr Tymoshenko { 14340ebf162SOleksandr Tymoshenko struct gpiobacklight_softc *sc; 14440ebf162SOleksandr Tymoshenko 14540ebf162SOleksandr Tymoshenko sc = device_get_softc(dev); 14626c36284SOleksandr Tymoshenko 14726c36284SOleksandr Tymoshenko if (sc->sc_pin) 14826c36284SOleksandr Tymoshenko gpio_pin_release(sc->sc_pin); 14926c36284SOleksandr Tymoshenko 15040ebf162SOleksandr Tymoshenko return (0); 15140ebf162SOleksandr Tymoshenko } 15240ebf162SOleksandr Tymoshenko 15340ebf162SOleksandr Tymoshenko static devclass_t gpiobacklight_devclass; 15440ebf162SOleksandr Tymoshenko 15540ebf162SOleksandr Tymoshenko static device_method_t gpiobacklight_methods[] = { 15640ebf162SOleksandr Tymoshenko /* Device interface */ 15740ebf162SOleksandr Tymoshenko DEVMETHOD(device_probe, gpiobacklight_probe), 15840ebf162SOleksandr Tymoshenko DEVMETHOD(device_attach, gpiobacklight_attach), 15940ebf162SOleksandr Tymoshenko DEVMETHOD(device_detach, gpiobacklight_detach), 16040ebf162SOleksandr Tymoshenko 16140ebf162SOleksandr Tymoshenko DEVMETHOD_END 16240ebf162SOleksandr Tymoshenko }; 16340ebf162SOleksandr Tymoshenko 16440ebf162SOleksandr Tymoshenko static driver_t gpiobacklight_driver = { 16540ebf162SOleksandr Tymoshenko "gpiobacklight", 16640ebf162SOleksandr Tymoshenko gpiobacklight_methods, 16740ebf162SOleksandr Tymoshenko sizeof(struct gpiobacklight_softc), 16840ebf162SOleksandr Tymoshenko }; 16940ebf162SOleksandr Tymoshenko 17026c36284SOleksandr Tymoshenko DRIVER_MODULE(gpiobacklight, simplebus, gpiobacklight_driver, 17126c36284SOleksandr Tymoshenko gpiobacklight_devclass, 0, 0); 17226c36284SOleksandr Tymoshenko MODULE_DEPEND(gpiobacklight, gpiobus, 1, 1, 1); 173