Home | History | Annotate | Line # | Download | only in netwalker
netwalker_backlight.c revision 1.1
      1 /*	$NetBSD: netwalker_backlight.c,v 1.1 2014/05/06 11:22:53 hkenken Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2014  Genetec Corporation.  All rights reserved.
      5  * Written by Hashimoto Kenichi for Genetec Corporation.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: netwalker_backlight.c,v 1.1 2014/05/06 11:22:53 hkenken Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/bus.h>
     34 #include <sys/systm.h>
     35 #include <sys/device.h>
     36 #include <sys/pmf.h>
     37 
     38 #include <dev/wscons/wsconsio.h>
     39 #include <dev/wscons/wsdisplayvar.h>
     40 
     41 #include <dev/sysmon/sysmonvar.h>
     42 #include <dev/sysmon/sysmon_taskq.h>
     43 
     44 #include <arm/imx/imx51reg.h>
     45 #include <arm/imx/imx51var.h>
     46 #include <arm/imx/imx51_ccmvar.h>
     47 #include <arm/imx/imxpwmvar.h>
     48 
     49 #include <evbarm/netwalker/netwalker_backlightvar.h>
     50 
     51 #define BRIGHTNESS_MAX	16
     52 
     53 struct netwalker_backlight_softc {
     54 	struct imxpwm_softc sc_imxpwm;
     55 
     56 	int sc_brightness;
     57 	bool sc_islit;
     58 };
     59 
     60 static struct netwalker_backlight_softc *netwalker_backlight_sc;
     61 
     62 static int netwalker_backlight_match(device_t, cfdata_t, void *);
     63 static void netwalker_backlight_attach(device_t, device_t, void *);
     64 static int netwalker_backlight_detach(device_t, int);
     65 
     66 CFATTACH_DECL_NEW(netwalker_backlight, sizeof(struct netwalker_backlight_softc),
     67     netwalker_backlight_match, netwalker_backlight_attach, netwalker_backlight_detach, NULL);
     68 
     69 static bool netwalker_backlight_resume(device_t, const pmf_qual_t *);
     70 static bool netwalker_backlight_suspend(device_t, const pmf_qual_t *);
     71 static void netwalker_backlight_on(device_t);
     72 static void netwalker_backlight_off(device_t);
     73 static void netwalker_brightness_up(device_t);
     74 static void netwalker_brightness_down(device_t);
     75 static void netwalker_set_brightness(struct netwalker_backlight_softc *, int);
     76 
     77 static int
     78 netwalker_backlight_match(device_t parent, cfdata_t cf, void * aux)
     79 {
     80 	return imxpwm_match(parent, cf, aux);
     81 }
     82 
     83 static void
     84 netwalker_backlight_attach(device_t parent, device_t self, void *aux)
     85 {
     86 	struct netwalker_backlight_softc *sc = device_private(self);
     87 	struct imxpwm_softc *imxpwm = &sc->sc_imxpwm;
     88 
     89 	imxpwm->sc_dev = self;
     90 	imxpwm->sc_hz = 1000; /* 1000 Hz */
     91 	imxpwm->sc_handler = NULL;
     92 	imxpwm->sc_cookie = sc;
     93 	imxpwm_attach(imxpwm, aux);
     94 
     95 	aprint_normal(": LCD BackLight Control\n");
     96 	aprint_naive(": LCD BackLight Control\n");
     97 
     98 	netwalker_backlight_sc = sc;
     99 
    100 	/* BackLight 100% On */
    101 	sc->sc_brightness = BRIGHTNESS_MAX;
    102 	sc->sc_islit = true;
    103 	imxpwm_set_pwm(imxpwm, 1000);
    104 
    105 	if (!pmf_device_register(self, netwalker_backlight_suspend,
    106 		netwalker_backlight_resume))
    107 		aprint_error_dev(self,
    108 		    "couldn't establish backlight handler\n");
    109 
    110 	if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_UP,
    111 		netwalker_brightness_up, true))
    112 		aprint_error_dev(self,
    113 		    "couldn't register BRIGHTNESS UP event handler\n");
    114 	if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_DOWN,
    115 		netwalker_brightness_down, true))
    116 		aprint_error_dev(self,
    117 		    "couldn't register BRIGHTNESS DOWN event handler\n");
    118 	if (!pmf_event_register(self, PMFE_DISPLAY_ON,
    119 		netwalker_backlight_on, true))
    120 		aprint_error_dev(self,
    121 		    "couldn't register DISPLAY ON event handler\n");
    122 	if (!pmf_event_register(self, PMFE_DISPLAY_OFF,
    123 		netwalker_backlight_off, true))
    124 		aprint_error_dev(self,
    125 		    "couldn't register DISPLAY OFF event handler\n");
    126 	if (!pmf_event_register(self, PMFE_CHASSIS_LID_OPEN,
    127 		netwalker_backlight_on, true))
    128 		aprint_error_dev(self,
    129 		    "couldn't register LID OPEN event handler\n");
    130 	if (!pmf_event_register(self, PMFE_CHASSIS_LID_CLOSE,
    131 		netwalker_backlight_off, true))
    132 		aprint_error_dev(self,
    133 		    "couldn't register LID CLOSE event handler\n");
    134 }
    135 
    136 static int
    137 netwalker_backlight_detach(device_t self, int flags)
    138 {
    139 	struct netwalker_backlight_softc *sc = device_private(self);
    140 	struct imxpwm_softc *imxpwm = &sc->sc_imxpwm;
    141 
    142 	imxpwm_set_pwm(imxpwm, 0);
    143 	pmf_device_deregister(self);
    144 	return 0;
    145 }
    146 
    147 /*
    148  * Power management
    149  */
    150 static bool
    151 netwalker_backlight_suspend(device_t dv, const pmf_qual_t *qual)
    152 {
    153 	netwalker_backlight_off(dv);
    154  	return true;
    155 }
    156 
    157 static bool
    158 netwalker_backlight_resume(device_t dv, const pmf_qual_t *qual)
    159 {
    160 	netwalker_backlight_on(dv);
    161 	return true;
    162 }
    163 
    164 static void
    165 netwalker_backlight_on(device_t dv)
    166 {
    167 	struct netwalker_backlight_softc *sc = device_private(dv);
    168 	sc->sc_islit = true;
    169 	netwalker_set_brightness(sc, sc->sc_brightness);
    170 }
    171 
    172 static void
    173 netwalker_backlight_off(device_t dv)
    174 {
    175 	struct netwalker_backlight_softc *sc = device_private(dv);
    176 	sc->sc_islit = false;
    177 	netwalker_set_brightness(sc, sc->sc_brightness);
    178 }
    179 
    180 static void
    181 netwalker_brightness_up(device_t dv)
    182 {
    183 	struct netwalker_backlight_softc *sc = device_private(dv);
    184 	netwalker_set_brightness(sc, sc->sc_brightness + 1);
    185 }
    186 
    187 static void
    188 netwalker_brightness_down(device_t dv)
    189 {
    190 	struct netwalker_backlight_softc *sc = device_private(dv);
    191 	netwalker_set_brightness(sc, sc->sc_brightness - 1);
    192 }
    193 
    194 static void
    195 netwalker_set_brightness(struct netwalker_backlight_softc *sc, int newval)
    196 {
    197 	struct imxpwm_softc *imxpwm = &sc->sc_imxpwm;
    198 
    199 	if (newval < 0)
    200 		newval = 0;
    201 	else if (newval > BRIGHTNESS_MAX)
    202 		newval = BRIGHTNESS_MAX;
    203 	sc->sc_brightness = newval;
    204 
    205 	if (sc->sc_islit)
    206 		imxpwm_set_pwm(imxpwm, 1000 * sc->sc_brightness / BRIGHTNESS_MAX);
    207 	else
    208 		imxpwm_set_pwm(imxpwm, 0);
    209 }
    210 
    211 int
    212 netwalker_lcd_param_ioctl(u_long cmd, struct wsdisplay_param *dp)
    213 {
    214 	struct netwalker_backlight_softc *sc = netwalker_backlight_sc;
    215 	int rv = EINVAL;
    216 
    217 	switch (dp->param) {
    218 	case WSDISPLAYIO_PARAM_BACKLIGHT:
    219 		if (cmd == WSDISPLAYIO_GETPARAM) {
    220 			dp->min = 0;
    221 			dp->max = 1;
    222 			dp->curval = sc->sc_islit ? 1 : 0;
    223 			rv = 0;
    224 		} else if (cmd == WSDISPLAYIO_SETPARAM) {
    225 			if (dp->curval != 0)
    226 				netwalker_backlight_on(sc->sc_imxpwm.sc_dev);
    227 			else
    228 				netwalker_backlight_off(sc->sc_imxpwm.sc_dev);
    229 			rv = 0;
    230 		}
    231 		break;
    232 
    233 	case WSDISPLAYIO_PARAM_CONTRAST:
    234 		/* unsupported */
    235 		rv = ENOTSUP;
    236 		break;
    237 
    238 	case WSDISPLAYIO_PARAM_BRIGHTNESS:
    239 		if (cmd == WSDISPLAYIO_GETPARAM) {
    240 			dp->min = 0;
    241 			dp->max = BRIGHTNESS_MAX;
    242 			dp->curval = sc->sc_brightness;
    243 			rv = 0;
    244 		} else if (cmd == WSDISPLAYIO_SETPARAM) {
    245 			netwalker_set_brightness(sc, dp->curval);
    246 			rv = 0;
    247 		}
    248 		break;
    249 	}
    250 
    251 	return rv;
    252 }
    253