diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2019-02-22 09:39:34 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2019-02-22 09:39:34 +0000 |
commit | afb9146375bcd625a277f562ca4118fbf63f824a (patch) | |
tree | aae71885873283c1da20354a5b8bc46663a17830 /sys | |
parent | 751a5c8ffa588e22091c5d35b0881f0dcdb13a48 (diff) |
Allow ssdfb(4) to be mmap(2)-able so that we can use its framebuffer
from the userland. Also allow changing the brightness levels so that
it can even be turned off to save power and to prevent burn in.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/fdt/ssdfb.c | 87 |
1 files changed, 81 insertions, 6 deletions
diff --git a/sys/dev/fdt/ssdfb.c b/sys/dev/fdt/ssdfb.c index cd741876d7f..105592d6194 100644 --- a/sys/dev/fdt/ssdfb.c +++ b/sys/dev/fdt/ssdfb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssdfb.c,v 1.9 2019/01/17 13:33:51 patrick Exp $ */ +/* $OpenBSD: ssdfb.c,v 1.10 2019/02/22 09:39:33 patrick Exp $ */ /* * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se> * @@ -22,8 +22,11 @@ #include <sys/malloc.h> #include <sys/stdint.h> +#include <uvm/uvm_extern.h> + #include <dev/i2c/i2cvar.h> #include <dev/spi/spivar.h> +#include <dev/usb/udlio.h> #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_gpio.h> @@ -74,6 +77,9 @@ struct ssdfb_softc { struct wsdisplay_emulops sc_riops; int (*sc_ri_do_cursor)(struct rasops_info *); + uint8_t sc_brightness; + int sc_mode; + uint8_t sc_column_range[2]; uint8_t sc_page_range[2]; @@ -294,9 +300,11 @@ ssdfb_attach(struct ssdfb_softc *sc) sc->sc_height = OF_getpropint(sc->sc_node, "solomon,height", 16); sc->sc_pgoff = OF_getpropint(sc->sc_node, "solomon,page-offset", 1); - sc->sc_fbsize = (sc->sc_width * sc->sc_height) / 8; + sc->sc_fbsize = round_page((sc->sc_width * sc->sc_height) / 8); sc->sc_fb = malloc(sc->sc_fbsize, M_DEVBUF, M_WAITOK | M_ZERO); + sc->sc_brightness = 223; + ri = &sc->sc_rinfo; ri->ri_bits = malloc(sc->sc_fbsize, M_DEVBUF, M_WAITOK | M_ZERO); ri->ri_bs = mallocarray(sc->sc_width * sc->sc_height, @@ -405,7 +413,7 @@ ssdfb_init(struct ssdfb_softc *sc) reg[1] |= 1 << 5; ssdfb_write_command(sc, reg, 2); reg[0] = SSDFB_SET_CONTRAST_CONTROL; - reg[1] = 223; + reg[1] = sc->sc_brightness; ssdfb_write_command(sc, reg, 2); reg[0] = SSDFB_SET_PRE_CHARGE_PERIOD; reg[1] = (OF_getpropint(sc->sc_node, "solomon,prechargep1", 2) & 0xf) << 0; @@ -582,14 +590,44 @@ ssdfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) { struct ssdfb_softc *sc = v; struct rasops_info *ri = &sc->sc_rinfo; + struct wsdisplay_param *dp = (struct wsdisplay_param *)data; struct wsdisplay_fbinfo *wdf; + struct udl_ioctl_damage *d; + int mode; + uint8_t reg[2]; switch (cmd) { case WSDISPLAYIO_GETPARAM: + switch (dp->param) { + case WSDISPLAYIO_PARAM_BRIGHTNESS: + dp->min = 0; + dp->max = 255; + dp->curval = sc->sc_brightness; + break; + default: + return (-1); + } + break; case WSDISPLAYIO_SETPARAM: - return (-1); + switch (dp->param) { + case WSDISPLAYIO_PARAM_BRIGHTNESS: + if (dp->curval == 0) { + reg[0] = SSDFB_SET_DISPLAY_OFF; + ssdfb_write_command(sc, reg, 1); + } else if (sc->sc_brightness == 0) { + reg[0] = SSDFB_SET_DISPLAY_ON; + ssdfb_write_command(sc, reg, 1); + } + reg[0] = SSDFB_SET_CONTRAST_CONTROL; + reg[1] = sc->sc_brightness = dp->curval; + ssdfb_write_command(sc, reg, 2); + break; + default: + return (-1); + } + break; case WSDISPLAYIO_GTYPE: - *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; + *(u_int *)data = WSDISPLAY_TYPE_DL; break; case WSDISPLAYIO_GINFO: wdf = (struct wsdisplay_fbinfo *)data; @@ -602,10 +640,37 @@ ssdfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) *(u_int *)data = ri->ri_stride; break; case WSDISPLAYIO_SMODE: + mode = *(u_int *)data; + switch (mode) { + case WSDISPLAYIO_MODE_EMUL: + if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) { + memset(ri->ri_bits, 0, sc->sc_fbsize); + ssdfb_partial(sc, 0, sc->sc_width, + 0, sc->sc_height); + sc->sc_mode = mode; + } + break; + case WSDISPLAYIO_MODE_DUMBFB: + if (sc->sc_mode != WSDISPLAYIO_MODE_DUMBFB) { + memset(ri->ri_bits, 0, sc->sc_fbsize); + ssdfb_partial(sc, 0, sc->sc_width, + 0, sc->sc_height); + sc->sc_mode = mode; + } + break; + case WSDISPLAYIO_MODE_MAPPED: + default: + return (-1); + } break; case WSDISPLAYIO_GETSUPPORTEDDEPTH: *(u_int *)data = WSDISPLAYIO_DEPTH_1; break; + case UDLIO_DAMAGE: + d = (struct udl_ioctl_damage *)data; + d->status = UDLIO_STATUS_OK; + ssdfb_partial(sc, d->x1, d->x2, d->y1, d->y2); + break; default: return (-1); } @@ -616,7 +681,17 @@ ssdfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) paddr_t ssdfb_mmap(void *v, off_t off, int prot) { - return -1; + struct ssdfb_softc *sc = v; + struct rasops_info *ri = &sc->sc_rinfo; + paddr_t pa; + + if (off >= sc->sc_fbsize || off < 0) + return (-1); + + if (!pmap_extract(pmap_kernel(), (vaddr_t)ri->ri_bits, &pa)) + return (-1); + + return (pa + off); } int |