summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/fdt/ssdfb.c87
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