gpiobacklight.c revision 299395
1178476Sjb/*- 2178476Sjb * Copyright (c) 2015-2016 Oleksandr Tymoshenko <gonzo@freebsd.org> 3178476Sjb * All rights reserved. 4178476Sjb * 5178476Sjb * Redistribution and use in source and binary forms, with or without 6178476Sjb * modification, are permitted provided that the following conditions 7178476Sjb * are met: 8178476Sjb * 1. Redistributions of source code must retain the above copyright 9178476Sjb * notice, this list of conditions and the following disclaimer. 10178476Sjb * 2. Redistributions in binary form must reproduce the above copyright 11178476Sjb * notice, this list of conditions and the following disclaimer in the 12178476Sjb * documentation and/or other materials provided with the distribution. 13178476Sjb * 14178476Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15178476Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16178476Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17178476Sjb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18178476Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19178476Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20178476Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21178476Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22178476Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23178476Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24178476Sjb * SUCH DAMAGE. 25178476Sjb */ 26178476Sjb 27178476Sjb#include <sys/cdefs.h> 28178476Sjb__FBSDID("$FreeBSD: head/sys/dev/gpio/gpiobacklight.c 299395 2016-05-11 00:26:52Z gonzo $"); 29178476Sjb 30178476Sjb#include "opt_platform.h" 31178476Sjb 32178476Sjb#include <sys/param.h> 33178476Sjb#include <sys/systm.h> 34178476Sjb#include <sys/bus.h> 35178476Sjb#include <sys/gpio.h> 36178476Sjb#include <sys/kernel.h> 37178476Sjb#include <sys/lock.h> 38178476Sjb#include <sys/malloc.h> 39178476Sjb#include <sys/module.h> 40178476Sjb#include <sys/mutex.h> 41178476Sjb#include <sys/sysctl.h> 42178476Sjb 43178476Sjb#include <dev/fdt/fdt_common.h> 44178476Sjb#include <dev/ofw/ofw_bus.h> 45178476Sjb 46178476Sjb#include <dev/gpio/gpiobusvar.h> 47178476Sjb 48178476Sjbstruct gpiobacklight_softc 49{ 50 gpio_pin_t sc_pin; 51 struct sysctl_oid *sc_oid; 52 bool sc_brightness; 53}; 54 55static int gpiobacklight_sysctl(SYSCTL_HANDLER_ARGS); 56static void gpiobacklight_update_brightness(struct gpiobacklight_softc *); 57static int gpiobacklight_probe(device_t); 58static int gpiobacklight_attach(device_t); 59static int gpiobacklight_detach(device_t); 60 61static void 62gpiobacklight_update_brightness(struct gpiobacklight_softc *sc) 63{ 64 65 if (sc->sc_pin) 66 gpio_pin_set_active(sc->sc_pin, sc->sc_brightness); 67} 68 69static int 70gpiobacklight_sysctl(SYSCTL_HANDLER_ARGS) 71{ 72 struct gpiobacklight_softc *sc; 73 int error; 74 int brightness; 75 76 sc = (struct gpiobacklight_softc*)arg1; 77 78 brightness = sc->sc_brightness; 79 error = sysctl_handle_int(oidp, &brightness, 0, req); 80 81 if (error != 0 || req->newptr == NULL) 82 return (error); 83 84 sc->sc_brightness = (brightness > 0); 85 gpiobacklight_update_brightness(sc); 86 87 return (0); 88} 89 90static int 91gpiobacklight_probe(device_t dev) 92{ 93 94 if (!ofw_bus_is_compatible(dev, "gpio-backlight")) 95 return (ENXIO); 96 97 device_set_desc(dev, "GPIO backlight"); 98 99 return (0); 100} 101 102static int 103gpiobacklight_attach(device_t dev) 104{ 105 struct gpiobacklight_softc *sc; 106 struct sysctl_ctx_list *ctx; 107 struct sysctl_oid *tree; 108 phandle_t node; 109 110 sc = device_get_softc(dev); 111 112 if ((node = ofw_bus_get_node(dev)) == -1) 113 return (ENXIO); 114 115 if (OF_hasprop(node, "default-on")) 116 sc->sc_brightness = true; 117 else 118 sc->sc_brightness = false; 119 120 gpio_pin_get_by_ofw_idx(dev, node, 0, &sc->sc_pin); 121 if (sc->sc_pin == NULL) { 122 device_printf(dev, "failed to map GPIO pin\n"); 123 return (ENXIO); 124 } 125 126 gpio_pin_setflags(sc->sc_pin, GPIO_PIN_OUTPUT); 127 128 gpiobacklight_update_brightness(sc); 129 130 /* Init backlight interface */ 131 ctx = device_get_sysctl_ctx(dev); 132 tree = device_get_sysctl_tree(dev); 133 sc->sc_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 134 "brightness", CTLTYPE_INT | CTLFLAG_RW, sc, 0, 135 gpiobacklight_sysctl, "I", "backlight brightness"); 136 137 return (0); 138} 139 140static int 141gpiobacklight_detach(device_t dev) 142{ 143 struct gpiobacklight_softc *sc; 144 145 sc = device_get_softc(dev); 146 147 if (sc->sc_pin) 148 gpio_pin_release(sc->sc_pin); 149 150 return (0); 151} 152 153static devclass_t gpiobacklight_devclass; 154 155static device_method_t gpiobacklight_methods[] = { 156 /* Device interface */ 157 DEVMETHOD(device_probe, gpiobacklight_probe), 158 DEVMETHOD(device_attach, gpiobacklight_attach), 159 DEVMETHOD(device_detach, gpiobacklight_detach), 160 161 DEVMETHOD_END 162}; 163 164static driver_t gpiobacklight_driver = { 165 "gpiobacklight", 166 gpiobacklight_methods, 167 sizeof(struct gpiobacklight_softc), 168}; 169 170DRIVER_MODULE(gpiobacklight, simplebus, gpiobacklight_driver, 171 gpiobacklight_devclass, 0, 0); 172MODULE_DEPEND(gpiobacklight, gpiobus, 1, 1, 1); 173