xref: /netbsd-src/sys/arch/evbarm/netwalker/netwalker_backlight.c (revision 2bd1432c88573054d9e5d00b69e495cb3aaef816)
1*2bd1432cShkenken /*	$NetBSD: netwalker_backlight.c,v 1.3 2020/05/20 05:10:42 hkenken Exp $	*/
2b9040788Shkenken 
3b9040788Shkenken /*
4b9040788Shkenken  * Copyright (c) 2014  Genetec Corporation.  All rights reserved.
5b9040788Shkenken  * Written by Hashimoto Kenichi for Genetec Corporation.
6b9040788Shkenken  *
7b9040788Shkenken  * Redistribution and use in source and binary forms, with or without
8b9040788Shkenken  * modification, are permitted provided that the following conditions
9b9040788Shkenken  * are met:
10b9040788Shkenken  * 1. Redistributions of source code must retain the above copyright
11b9040788Shkenken  *    notice, this list of conditions and the following disclaimer.
12b9040788Shkenken  * 2. Redistributions in binary form must reproduce the above copyright
13b9040788Shkenken  *    notice, this list of conditions and the following disclaimer in the
14b9040788Shkenken  *    documentation and/or other materials provided with the distribution.
15b9040788Shkenken  *
16b9040788Shkenken  * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
17b9040788Shkenken  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18b9040788Shkenken  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19b9040788Shkenken  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
20b9040788Shkenken  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21b9040788Shkenken  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22b9040788Shkenken  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23b9040788Shkenken  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24b9040788Shkenken  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25b9040788Shkenken  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26b9040788Shkenken  * POSSIBILITY OF SUCH DAMAGE.
27b9040788Shkenken  */
28b9040788Shkenken 
29b9040788Shkenken #include <sys/cdefs.h>
30*2bd1432cShkenken __KERNEL_RCSID(0, "$NetBSD: netwalker_backlight.c,v 1.3 2020/05/20 05:10:42 hkenken Exp $");
31b9040788Shkenken 
32b9040788Shkenken #include <sys/param.h>
33b9040788Shkenken #include <sys/bus.h>
34b9040788Shkenken #include <sys/systm.h>
35b9040788Shkenken #include <sys/device.h>
36b9040788Shkenken #include <sys/pmf.h>
37b9040788Shkenken 
38*2bd1432cShkenken #include <dev/pwm/pwmvar.h>
39*2bd1432cShkenken 
40b9040788Shkenken #include <dev/wscons/wsconsio.h>
41b9040788Shkenken #include <dev/wscons/wsdisplayvar.h>
427bb55e03Shkenken #include <dev/wsfb/genfbvar.h>
43b9040788Shkenken 
44b9040788Shkenken #include <dev/sysmon/sysmonvar.h>
45b9040788Shkenken #include <dev/sysmon/sysmon_taskq.h>
46b9040788Shkenken 
47b9040788Shkenken #include <arm/imx/imx51reg.h>
48b9040788Shkenken #include <arm/imx/imx51var.h>
49b9040788Shkenken #include <arm/imx/imx51_ccmvar.h>
50b9040788Shkenken #include <arm/imx/imxpwmvar.h>
51b9040788Shkenken 
52b9040788Shkenken #include <evbarm/netwalker/netwalker_backlightvar.h>
53b9040788Shkenken 
547bb55e03Shkenken #define BRIGHTNESS_MAX	255
55b9040788Shkenken 
56b9040788Shkenken struct netwalker_backlight_softc {
57b9040788Shkenken 	struct imxpwm_softc sc_imxpwm;
58b9040788Shkenken 
59b9040788Shkenken 	int sc_brightness;
60b9040788Shkenken 	bool sc_islit;
61b9040788Shkenken };
62b9040788Shkenken 
63b9040788Shkenken static struct netwalker_backlight_softc *netwalker_backlight_sc;
64b9040788Shkenken 
657bb55e03Shkenken static struct genfb_parameter_callback gpc_backlight;
667bb55e03Shkenken static struct genfb_parameter_callback gpc_brightness;
677bb55e03Shkenken 
68b9040788Shkenken static int netwalker_backlight_match(device_t, cfdata_t, void *);
69b9040788Shkenken static void netwalker_backlight_attach(device_t, device_t, void *);
70b9040788Shkenken static int netwalker_backlight_detach(device_t, int);
71b9040788Shkenken 
72b9040788Shkenken CFATTACH_DECL_NEW(netwalker_backlight, sizeof(struct netwalker_backlight_softc),
73b9040788Shkenken     netwalker_backlight_match, netwalker_backlight_attach, netwalker_backlight_detach, NULL);
74b9040788Shkenken 
75b9040788Shkenken static bool netwalker_backlight_resume(device_t, const pmf_qual_t *);
76b9040788Shkenken static bool netwalker_backlight_suspend(device_t, const pmf_qual_t *);
77b9040788Shkenken static void netwalker_backlight_on(device_t);
78b9040788Shkenken static void netwalker_backlight_off(device_t);
79b9040788Shkenken static void netwalker_brightness_up(device_t);
80b9040788Shkenken static void netwalker_brightness_down(device_t);
81b9040788Shkenken static void netwalker_set_brightness(struct netwalker_backlight_softc *, int);
82b9040788Shkenken 
83b9040788Shkenken static int
netwalker_backlight_match(device_t parent,cfdata_t cf,void * aux)84b9040788Shkenken netwalker_backlight_match(device_t parent, cfdata_t cf, void * aux)
85b9040788Shkenken {
86b9040788Shkenken 	return imxpwm_match(parent, cf, aux);
87b9040788Shkenken }
88b9040788Shkenken 
89b9040788Shkenken static void
netwalker_backlight_attach(device_t parent,device_t self,void * aux)90b9040788Shkenken netwalker_backlight_attach(device_t parent, device_t self, void *aux)
91b9040788Shkenken {
92b9040788Shkenken 	struct netwalker_backlight_softc *sc = device_private(self);
93b9040788Shkenken 	struct imxpwm_softc *imxpwm = &sc->sc_imxpwm;
94b9040788Shkenken 
95b9040788Shkenken 	imxpwm->sc_dev = self;
96b9040788Shkenken 	imxpwm->sc_handler = NULL;
97b9040788Shkenken 	imxpwm->sc_cookie = sc;
98b9040788Shkenken 	imxpwm_attach(imxpwm, aux);
99b9040788Shkenken 
100b9040788Shkenken 	aprint_normal(": LCD BackLight Control\n");
101b9040788Shkenken 	aprint_naive(": LCD BackLight Control\n");
102b9040788Shkenken 
103b9040788Shkenken 	netwalker_backlight_sc = sc;
104b9040788Shkenken 
105b9040788Shkenken 	/* BackLight 100% On */
106b9040788Shkenken 	sc->sc_islit = true;
107*2bd1432cShkenken 	netwalker_set_brightness(sc, BRIGHTNESS_MAX);
108b9040788Shkenken 
109b9040788Shkenken 	if (!pmf_device_register(self, netwalker_backlight_suspend,
110b9040788Shkenken 		netwalker_backlight_resume))
111b9040788Shkenken 		aprint_error_dev(self,
112b9040788Shkenken 		    "couldn't establish backlight handler\n");
113b9040788Shkenken 
114b9040788Shkenken 	if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_UP,
115b9040788Shkenken 		netwalker_brightness_up, true))
116b9040788Shkenken 		aprint_error_dev(self,
117b9040788Shkenken 		    "couldn't register BRIGHTNESS UP event handler\n");
118b9040788Shkenken 	if (!pmf_event_register(self, PMFE_DISPLAY_BRIGHTNESS_DOWN,
119b9040788Shkenken 		netwalker_brightness_down, true))
120b9040788Shkenken 		aprint_error_dev(self,
121b9040788Shkenken 		    "couldn't register BRIGHTNESS DOWN event handler\n");
122b9040788Shkenken 	if (!pmf_event_register(self, PMFE_DISPLAY_ON,
123b9040788Shkenken 		netwalker_backlight_on, true))
124b9040788Shkenken 		aprint_error_dev(self,
125b9040788Shkenken 		    "couldn't register DISPLAY ON event handler\n");
126b9040788Shkenken 	if (!pmf_event_register(self, PMFE_DISPLAY_OFF,
127b9040788Shkenken 		netwalker_backlight_off, true))
128b9040788Shkenken 		aprint_error_dev(self,
129b9040788Shkenken 		    "couldn't register DISPLAY OFF event handler\n");
130b9040788Shkenken 	if (!pmf_event_register(self, PMFE_CHASSIS_LID_OPEN,
131b9040788Shkenken 		netwalker_backlight_on, true))
132b9040788Shkenken 		aprint_error_dev(self,
133b9040788Shkenken 		    "couldn't register LID OPEN event handler\n");
134b9040788Shkenken 	if (!pmf_event_register(self, PMFE_CHASSIS_LID_CLOSE,
135b9040788Shkenken 		netwalker_backlight_off, true))
136b9040788Shkenken 		aprint_error_dev(self,
137b9040788Shkenken 		    "couldn't register LID CLOSE event handler\n");
138b9040788Shkenken }
139b9040788Shkenken 
140b9040788Shkenken static int
netwalker_backlight_detach(device_t self,int flags)141b9040788Shkenken netwalker_backlight_detach(device_t self, int flags)
142b9040788Shkenken {
143b9040788Shkenken 	struct netwalker_backlight_softc *sc = device_private(self);
144b9040788Shkenken 
145*2bd1432cShkenken 	netwalker_set_brightness(sc, 0);
146b9040788Shkenken 	pmf_device_deregister(self);
147b9040788Shkenken 	return 0;
148b9040788Shkenken }
149b9040788Shkenken 
1507bb55e03Shkenken static int
netwalker_backlight_get_backlight(void * cookie,int * state)1517bb55e03Shkenken netwalker_backlight_get_backlight(void *cookie, int *state)
1527bb55e03Shkenken {
1537bb55e03Shkenken 	struct netwalker_backlight_softc *sc = *(struct netwalker_backlight_softc **)cookie;
1547bb55e03Shkenken 	*state = sc->sc_islit;
1557bb55e03Shkenken 	return 0;
1567bb55e03Shkenken }
1577bb55e03Shkenken 
1587bb55e03Shkenken static int
netwalker_backlight_set_backlight(void * cookie,int state)1597bb55e03Shkenken netwalker_backlight_set_backlight(void *cookie, int state)
1607bb55e03Shkenken {
1617bb55e03Shkenken 	struct netwalker_backlight_softc *sc = *(struct netwalker_backlight_softc **)cookie;
1627bb55e03Shkenken 
1637bb55e03Shkenken 	KASSERT(state >= 0 && state <= 1);
1647bb55e03Shkenken 
1657bb55e03Shkenken 	sc->sc_islit = state;
1667bb55e03Shkenken 	netwalker_set_brightness(sc, sc->sc_brightness);
1677bb55e03Shkenken 
1687bb55e03Shkenken 	return 0;
1697bb55e03Shkenken }
1707bb55e03Shkenken 
1717bb55e03Shkenken static int
netwalker_backlight_get_brightness(void * cookie,int * level)1727bb55e03Shkenken netwalker_backlight_get_brightness(void *cookie, int *level)
1737bb55e03Shkenken {
1747bb55e03Shkenken 	struct netwalker_backlight_softc *sc = *(struct netwalker_backlight_softc **)cookie;
1757bb55e03Shkenken 
1767bb55e03Shkenken 	if (sc->sc_brightness < 0)
1777bb55e03Shkenken 		return ENODEV;
1787bb55e03Shkenken 
1797bb55e03Shkenken 	*level = sc->sc_brightness;
1807bb55e03Shkenken 	return 0;
1817bb55e03Shkenken }
1827bb55e03Shkenken 
1837bb55e03Shkenken static int
netwalker_backlight_set_brightness(void * cookie,int level)1847bb55e03Shkenken netwalker_backlight_set_brightness(void *cookie, int level)
1857bb55e03Shkenken {
1867bb55e03Shkenken 	struct netwalker_backlight_softc *sc = *(struct netwalker_backlight_softc **)cookie;
1877bb55e03Shkenken 
188*2bd1432cShkenken 	KASSERT(level >= 0 && level <= BRIGHTNESS_MAX);
1897bb55e03Shkenken 
1907bb55e03Shkenken 	sc->sc_brightness = level;
1917bb55e03Shkenken 	netwalker_set_brightness(sc, sc->sc_brightness);
1927bb55e03Shkenken 
1937bb55e03Shkenken 	return 0;
1947bb55e03Shkenken }
1957bb55e03Shkenken 
1967bb55e03Shkenken static int
netwalker_backlight_upd_brightness(void * cookie,int delta)1977bb55e03Shkenken netwalker_backlight_upd_brightness(void *cookie, int delta)
1987bb55e03Shkenken {
1997bb55e03Shkenken 	struct netwalker_backlight_softc *sc = *(struct netwalker_backlight_softc **)cookie;
2007bb55e03Shkenken 
2017bb55e03Shkenken 	if (sc->sc_brightness < 0)
2027bb55e03Shkenken 		return ENODEV;
2037bb55e03Shkenken 
2047bb55e03Shkenken 	sc->sc_brightness += delta;
2057bb55e03Shkenken 	if (sc->sc_brightness < 0) sc->sc_brightness = 0;
206*2bd1432cShkenken 	if (sc->sc_brightness > BRIGHTNESS_MAX) sc->sc_brightness = BRIGHTNESS_MAX;
2077bb55e03Shkenken 	netwalker_set_brightness(sc, sc->sc_brightness);
2087bb55e03Shkenken 
2097bb55e03Shkenken 	return 0;
2107bb55e03Shkenken }
2117bb55e03Shkenken 
2127bb55e03Shkenken void
netwalker_backlight_genfb_parameter_set(prop_dictionary_t dict)2137bb55e03Shkenken netwalker_backlight_genfb_parameter_set(prop_dictionary_t dict)
2147bb55e03Shkenken {
2157bb55e03Shkenken 	gpc_backlight.gpc_cookie = (void *)&netwalker_backlight_sc;
2167bb55e03Shkenken 	gpc_backlight.gpc_set_parameter = netwalker_backlight_set_backlight;
2177bb55e03Shkenken 	gpc_backlight.gpc_get_parameter = netwalker_backlight_get_backlight;
2187bb55e03Shkenken 	gpc_backlight.gpc_upd_parameter = NULL;
2197bb55e03Shkenken 	prop_dictionary_set_uint64(dict, "backlight_callback",
2207bb55e03Shkenken 	    (uint64_t)(uintptr_t)&gpc_backlight);
2217bb55e03Shkenken 
2227bb55e03Shkenken 	gpc_brightness.gpc_cookie = (void *)&netwalker_backlight_sc;
2237bb55e03Shkenken 	gpc_brightness.gpc_set_parameter = netwalker_backlight_set_brightness;
2247bb55e03Shkenken 	gpc_brightness.gpc_get_parameter = netwalker_backlight_get_brightness;
2257bb55e03Shkenken 	gpc_brightness.gpc_upd_parameter = netwalker_backlight_upd_brightness;
2267bb55e03Shkenken 	prop_dictionary_set_uint64(dict, "brightness_callback",
2277bb55e03Shkenken 	    (uint64_t)(uintptr_t)&gpc_brightness);
2287bb55e03Shkenken }
2297bb55e03Shkenken 
230b9040788Shkenken /*
231b9040788Shkenken  * Power management
232b9040788Shkenken  */
233b9040788Shkenken static bool
netwalker_backlight_suspend(device_t dv,const pmf_qual_t * qual)234b9040788Shkenken netwalker_backlight_suspend(device_t dv, const pmf_qual_t *qual)
235b9040788Shkenken {
236b9040788Shkenken 	netwalker_backlight_off(dv);
237b9040788Shkenken  	return true;
238b9040788Shkenken }
239b9040788Shkenken 
240b9040788Shkenken static bool
netwalker_backlight_resume(device_t dv,const pmf_qual_t * qual)241b9040788Shkenken netwalker_backlight_resume(device_t dv, const pmf_qual_t *qual)
242b9040788Shkenken {
243b9040788Shkenken 	netwalker_backlight_on(dv);
244b9040788Shkenken 	return true;
245b9040788Shkenken }
246b9040788Shkenken 
247b9040788Shkenken static void
netwalker_backlight_on(device_t dv)248b9040788Shkenken netwalker_backlight_on(device_t dv)
249b9040788Shkenken {
250b9040788Shkenken 	struct netwalker_backlight_softc *sc = device_private(dv);
251b9040788Shkenken 	sc->sc_islit = true;
252b9040788Shkenken 	netwalker_set_brightness(sc, sc->sc_brightness);
253b9040788Shkenken }
254b9040788Shkenken 
255b9040788Shkenken static void
netwalker_backlight_off(device_t dv)256b9040788Shkenken netwalker_backlight_off(device_t dv)
257b9040788Shkenken {
258b9040788Shkenken 	struct netwalker_backlight_softc *sc = device_private(dv);
259b9040788Shkenken 	sc->sc_islit = false;
260b9040788Shkenken 	netwalker_set_brightness(sc, sc->sc_brightness);
261b9040788Shkenken }
262b9040788Shkenken 
263b9040788Shkenken static void
netwalker_brightness_up(device_t dv)264b9040788Shkenken netwalker_brightness_up(device_t dv)
265b9040788Shkenken {
266b9040788Shkenken 	struct netwalker_backlight_softc *sc = device_private(dv);
267b9040788Shkenken 	netwalker_set_brightness(sc, sc->sc_brightness + 1);
268b9040788Shkenken }
269b9040788Shkenken 
270b9040788Shkenken static void
netwalker_brightness_down(device_t dv)271b9040788Shkenken netwalker_brightness_down(device_t dv)
272b9040788Shkenken {
273b9040788Shkenken 	struct netwalker_backlight_softc *sc = device_private(dv);
274b9040788Shkenken 	netwalker_set_brightness(sc, sc->sc_brightness - 1);
275b9040788Shkenken }
276b9040788Shkenken 
277b9040788Shkenken static void
netwalker_set_pwm(struct netwalker_backlight_softc * sc,int val)278*2bd1432cShkenken netwalker_set_pwm(struct netwalker_backlight_softc *sc, int val)
279*2bd1432cShkenken {
280*2bd1432cShkenken 	pwm_tag_t pwm = &sc->sc_imxpwm.sc_pwm;
281*2bd1432cShkenken 	struct pwm_config conf;
282*2bd1432cShkenken 
283*2bd1432cShkenken 	pwm_disable(pwm);
284*2bd1432cShkenken 	pwm_get_config(pwm, &conf);
285*2bd1432cShkenken 	conf.duty_cycle = (conf.period * val) / BRIGHTNESS_MAX;
286*2bd1432cShkenken 	pwm_set_config(pwm, &conf);
287*2bd1432cShkenken 	pwm_enable(pwm);
288*2bd1432cShkenken }
289*2bd1432cShkenken 
290*2bd1432cShkenken static void
netwalker_set_brightness(struct netwalker_backlight_softc * sc,int newval)291b9040788Shkenken netwalker_set_brightness(struct netwalker_backlight_softc *sc, int newval)
292b9040788Shkenken {
293b9040788Shkenken 	if (newval < 0)
294b9040788Shkenken 		newval = 0;
295b9040788Shkenken 	else if (newval > BRIGHTNESS_MAX)
296b9040788Shkenken 		newval = BRIGHTNESS_MAX;
297b9040788Shkenken 	sc->sc_brightness = newval;
298b9040788Shkenken 
299b9040788Shkenken 	if (sc->sc_islit)
300*2bd1432cShkenken 		netwalker_set_pwm(sc, sc->sc_brightness);
301b9040788Shkenken 	else
302*2bd1432cShkenken 		netwalker_set_pwm(sc, 0);
303b9040788Shkenken }
304b9040788Shkenken 
305b9040788Shkenken int
netwalker_lcd_param_ioctl(u_long cmd,struct wsdisplay_param * dp)306b9040788Shkenken netwalker_lcd_param_ioctl(u_long cmd, struct wsdisplay_param *dp)
307b9040788Shkenken {
308b9040788Shkenken 	struct netwalker_backlight_softc *sc = netwalker_backlight_sc;
309b9040788Shkenken 	int rv = EINVAL;
310b9040788Shkenken 
311b9040788Shkenken 	switch (dp->param) {
312b9040788Shkenken 	case WSDISPLAYIO_PARAM_BACKLIGHT:
313b9040788Shkenken 		if (cmd == WSDISPLAYIO_GETPARAM) {
314b9040788Shkenken 			dp->min = 0;
315b9040788Shkenken 			dp->max = 1;
316b9040788Shkenken 			dp->curval = sc->sc_islit ? 1 : 0;
317b9040788Shkenken 			rv = 0;
318b9040788Shkenken 		} else if (cmd == WSDISPLAYIO_SETPARAM) {
319b9040788Shkenken 			if (dp->curval != 0)
320b9040788Shkenken 				netwalker_backlight_on(sc->sc_imxpwm.sc_dev);
321b9040788Shkenken 			else
322b9040788Shkenken 				netwalker_backlight_off(sc->sc_imxpwm.sc_dev);
323b9040788Shkenken 			rv = 0;
324b9040788Shkenken 		}
325b9040788Shkenken 		break;
326b9040788Shkenken 
327b9040788Shkenken 	case WSDISPLAYIO_PARAM_CONTRAST:
328b9040788Shkenken 		/* unsupported */
329b9040788Shkenken 		rv = ENOTSUP;
330b9040788Shkenken 		break;
331b9040788Shkenken 
332b9040788Shkenken 	case WSDISPLAYIO_PARAM_BRIGHTNESS:
333b9040788Shkenken 		if (cmd == WSDISPLAYIO_GETPARAM) {
334b9040788Shkenken 			dp->min = 0;
335b9040788Shkenken 			dp->max = BRIGHTNESS_MAX;
336b9040788Shkenken 			dp->curval = sc->sc_brightness;
337b9040788Shkenken 			rv = 0;
338b9040788Shkenken 		} else if (cmd == WSDISPLAYIO_SETPARAM) {
339b9040788Shkenken 			netwalker_set_brightness(sc, dp->curval);
340b9040788Shkenken 			rv = 0;
341b9040788Shkenken 		}
342b9040788Shkenken 		break;
343b9040788Shkenken 	}
344b9040788Shkenken 
345b9040788Shkenken 	return rv;
346b9040788Shkenken }
347