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