Module Name: src Committed By: macallan Date: Wed Oct 6 02:24:36 UTC 2010
Modified Files: src/sys/dev/wsfb: genfb.c genfbvar.h Log Message: add support for backlight control via machine dependent callbacks To generate a diff of this commit: cvs rdiff -u -r1.30 -r1.31 src/sys/dev/wsfb/genfb.c cvs rdiff -u -r1.15 -r1.16 src/sys/dev/wsfb/genfbvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/wsfb/genfb.c diff -u src/sys/dev/wsfb/genfb.c:1.30 src/sys/dev/wsfb/genfb.c:1.31 --- src/sys/dev/wsfb/genfb.c:1.30 Tue Aug 31 02:49:17 2010 +++ src/sys/dev/wsfb/genfb.c Wed Oct 6 02:24:35 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: genfb.c,v 1.30 2010/08/31 02:49:17 macallan Exp $ */ +/* $NetBSD: genfb.c,v 1.31 2010/10/06 02:24:35 macallan Exp $ */ /*- * Copyright (c) 2007 Michael Lorenz @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: genfb.c,v 1.30 2010/08/31 02:49:17 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: genfb.c,v 1.31 2010/10/06 02:24:35 macallan Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -73,6 +73,13 @@ static int genfb_putpalreg(struct genfb_softc *, uint8_t, uint8_t, uint8_t, uint8_t); +static void genfb_brightness_up(device_t); +static void genfb_brightness_down(device_t); +/* set backlight level */ +static void genfb_set_backlight(struct genfb_softc *, int); +/* turn backlight on and off without messing with the level */ +static void genfb_switch_backlight(struct genfb_softc *, int); + extern const u_char rasops_cmap[768]; static int genfb_cnattach_called = 0; @@ -95,13 +102,16 @@ genfb_init(struct genfb_softc *sc) { prop_dictionary_t dict; - uint64_t cmap_cb, pmf_cb; + uint64_t cmap_cb, pmf_cb, bl_cb; uint32_t fboffset; + bool console; dict = device_properties(&sc->sc_dev); #ifdef GENFB_DEBUG printf(prop_dictionary_externalize(dict)); #endif + prop_dictionary_get_bool(dict, "is_console", &console); + if (!prop_dictionary_get_uint32(dict, "width", &sc->sc_width)) { GPRINTF("no width property\n"); return; @@ -141,12 +151,35 @@ if (cmap_cb != 0) sc->sc_cmcb = (void *)(vaddr_t)cmap_cb; } + /* optional pmf callback */ sc->sc_pmfcb = NULL; if (prop_dictionary_get_uint64(dict, "pmf_callback", &pmf_cb)) { if (pmf_cb != 0) sc->sc_pmfcb = (void *)(vaddr_t)pmf_cb; } + + /* optional backlight control callback */ + sc->sc_backlight = NULL; + if (prop_dictionary_get_uint64(dict, "backlight_callback", &bl_cb)) { + if (bl_cb != 0) { + sc->sc_backlight = (void *)(vaddr_t)bl_cb; + sc->sc_backlight_on = 1; + aprint_naive_dev(&sc->sc_dev, + "enabling backlight control\n"); + sc->sc_backlight_level = + sc->sc_backlight->gpc_get_parameter( + sc->sc_backlight->gpc_cookie); + if (console) { + pmf_event_register(&sc->sc_dev, + PMFE_DISPLAY_BRIGHTNESS_UP, + genfb_brightness_up, TRUE); + pmf_event_register(&sc->sc_dev, + PMFE_DISPLAY_BRIGHTNESS_DOWN, + genfb_brightness_down, TRUE); + } + } + } } int @@ -308,6 +341,7 @@ struct genfb_softc *sc = vd->cookie; struct wsdisplay_fbinfo *wdf; struct vcons_screen *ms = vd->active; + struct wsdisplay_param *param; int new_mode, error; switch (cmd) { @@ -382,6 +416,37 @@ #else return ENODEV; #endif + case WSDISPLAYIO_GETPARAM: + param = (struct wsdisplay_param *)data; + if (sc->sc_backlight == NULL) + return EPASSTHROUGH; + switch (param->param) { + case WSDISPLAYIO_PARAM_BRIGHTNESS: + param->min = 0; + param->max = 255; + param->curval = sc->sc_backlight_level; + return 0; + case WSDISPLAYIO_PARAM_BACKLIGHT: + param->min = 0; + param->max = 1; + param->curval = sc->sc_backlight_on; + return 0; + } + return EPASSTHROUGH; + + case WSDISPLAYIO_SETPARAM: + param = (struct wsdisplay_param *)data; + if (sc->sc_backlight == NULL) + return EPASSTHROUGH; + switch (param->param) { + case WSDISPLAYIO_PARAM_BRIGHTNESS: + genfb_set_backlight(sc, param->curval); + return 0; + case WSDISPLAYIO_PARAM_BACKLIGHT: + genfb_switch_backlight(sc, param->curval); + return 0; + } + return EPASSTHROUGH; default: if (sc->sc_ops.genfb_ioctl) return sc->sc_ops.genfb_ioctl(sc, vs, cmd, @@ -571,3 +636,59 @@ return sc->sc_ops.genfb_borrow(sc, addr, hdlp); return 0; } + +static void +genfb_set_backlight(struct genfb_softc *sc, int level) +{ + + KASSERT(sc->sc_backlight != NULL); + + /* + * should we do nothing when backlight is off, should we just store the + * level and use it when turning back on or should we just flip sc_bl_on + * and turn the backlight on? + * For now turn it on so a crashed screensaver can't get the user stuck + * with a dark screen as long as hotkeys work + */ + if (level > 255) level = 255; + if (level < 0) level = 0; + if (level == sc->sc_backlight_level) + return; + sc->sc_backlight_level = level; + if (sc->sc_backlight_on == 0) + sc->sc_backlight_on = 1; + sc->sc_backlight->gpc_set_parameter( + sc->sc_backlight->gpc_cookie, level); +} + +static void +genfb_switch_backlight(struct genfb_softc *sc, int on) +{ + int level; + + KASSERT(sc->sc_backlight != NULL); + + if (on == sc->sc_backlight_on) + return; + sc->sc_backlight_on = on; + level = on ? sc->sc_backlight_level : 0; + sc->sc_backlight->gpc_set_parameter( + sc->sc_backlight->gpc_cookie, level); +} + + +static void +genfb_brightness_up(device_t dev) +{ + struct genfb_softc *sc = device_private(dev); + + genfb_set_backlight(sc, sc->sc_backlight_level + 8); +} + +static void +genfb_brightness_down(device_t dev) +{ + struct genfb_softc *sc = device_private(dev); + + genfb_set_backlight(sc, sc->sc_backlight_level - 8); +} Index: src/sys/dev/wsfb/genfbvar.h diff -u src/sys/dev/wsfb/genfbvar.h:1.15 src/sys/dev/wsfb/genfbvar.h:1.16 --- src/sys/dev/wsfb/genfbvar.h:1.15 Tue Aug 31 02:49:17 2010 +++ src/sys/dev/wsfb/genfbvar.h Wed Oct 6 02:24:35 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: genfbvar.h,v 1.15 2010/08/31 02:49:17 macallan Exp $ */ +/* $NetBSD: genfbvar.h,v 1.16 2010/10/06 02:24:35 macallan Exp $ */ /*- * Copyright (c) 2007 Michael Lorenz @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: genfbvar.h,v 1.15 2010/08/31 02:49:17 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: genfbvar.h,v 1.16 2010/10/06 02:24:35 macallan Exp $"); #ifndef GENFBVAR_H #define GENFBVAR_H @@ -66,6 +66,12 @@ void (*gcc_set_mapreg)(void *, int, int, int, int); }; +struct genfb_parameter_callback{ + void *gpc_cookie; + void (*gpc_set_parameter)(void *, int); + int (*gpc_get_parameter)(void *); +}; + struct genfb_pmf_callback { bool (*gpc_suspend)(device_t, const pmf_qual_t *); bool (*gpc_resume)(device_t, const pmf_qual_t *); @@ -81,6 +87,8 @@ struct wsscreen_list sc_screenlist; struct genfb_colormap_callback *sc_cmcb; struct genfb_pmf_callback *sc_pmfcb; + struct genfb_parameter_callback *sc_backlight; + int sc_backlight_level, sc_backlight_on; void *sc_fbaddr; /* kva */ #ifdef GENFB_SHADOWFB void *sc_shadowfb;