xref: /netbsd-src/sys/arch/evbarm/netwalker/netwalker_backlight.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
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