diff options
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 |