summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2017-01-03 19:57:02 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2017-01-03 19:57:02 +0000
commit5961f14d8b15f5fd222eb33ceff265853b3a28c8 (patch)
tree1ef16c1089492643d4c6e4d25b22db9f8de0f989 /sys/dev
parent277251af7edb84d99cbef5aa7d6af1cd3845b8b6 (diff)
Add simplefb(4), a driver to support the framebuffer set up by the firmware
on some platforms that use device trees. Works on Allwinner (sunxi) and should also work on Raspberry Pi (broadcom) armv7 platforms. ok jsg@, visa@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fdt/files.fdt8
-rw-r--r--sys/dev/fdt/simplefb.c243
2 files changed, 251 insertions, 0 deletions
diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt
new file mode 100644
index 00000000000..bb184da34e8
--- /dev/null
+++ b/sys/dev/fdt/files.fdt
@@ -0,0 +1,8 @@
+# $OpenBSD: files.fdt,v 1.1 2017/01/03 19:57:01 kettenis Exp $
+#
+# Config file and device description for machine-independent FDT code.
+# Included by ports that need it.
+
+device simplefb: wsemuldisplaydev, rasops15, rasops16, rasops24, rasops32
+attach simplefb at fdt
+file dev/fdt/simplefb.c simplefb
diff --git a/sys/dev/fdt/simplefb.c b/sys/dev/fdt/simplefb.c
new file mode 100644
index 00000000000..2a3e1c7d715
--- /dev/null
+++ b/sys/dev/fdt/simplefb.c
@@ -0,0 +1,243 @@
+/* $OpenBSD: simplefb.c,v 1.1 2017/01/03 19:57:01 kettenis Exp $ */
+/*
+ * Copyright (c) 2016 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/rasops/rasops.h>
+
+struct simplefb_format {
+ const char *format;
+ int depth;
+ int rpos, rnum;
+ int gpos, gnum;
+ int bpos, bnum;
+};
+
+/*
+ * Supported pixel formats. Layout ommitted when it matches the
+ * rasops defaults.
+ */
+struct simplefb_format simplefb_formats[] = {
+ { "r5g6b5", 16 },
+ { "x1r5g5b5", 15 },
+ { "a1r5g5b5", 15 },
+ { "r8g8b8", 24 },
+ { "x8r8g8b8", 32 },
+ { "a8r8g8b8", 32 },
+ { "a8b8g8r8", 32, 0, 8, 8, 8, 16, 8 }
+};
+
+struct simplefb_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ struct rasops_info sc_ri;
+ struct wsscreen_descr sc_wsd;
+ struct wsscreen_list sc_wsl;
+ struct wsscreen_descr *sc_scrlist[1];
+
+ struct simplefb_format *sc_format;
+ paddr_t sc_paddr;
+ psize_t sc_psize;
+};
+
+int simplefb_match(struct device *, void *, void *);
+void simplefb_attach(struct device *, struct device *, void *);
+
+struct cfattach simplefb_ca = {
+ sizeof(struct simplefb_softc), simplefb_match, simplefb_attach
+};
+
+struct cfdriver simplefb_cd = {
+ NULL, "simplefb", DV_DULL
+};
+
+int simplefb_wsioctl(void *, u_long, caddr_t, int, struct proc *);
+paddr_t simplefb_wsmmap(void *, off_t, int);
+int simplefb_alloc_screen(void *, const struct wsscreen_descr *,
+ void **, int *, int *, long *);
+
+struct wsdisplay_accessops simplefb_accessops = {
+ .ioctl = simplefb_wsioctl,
+ .mmap = simplefb_wsmmap,
+ .alloc_screen = simplefb_alloc_screen,
+ .free_screen = rasops_free_screen,
+ .show_screen = rasops_show_screen,
+ .getchar = rasops_getchar,
+ .load_font = rasops_load_font,
+ .list_font = rasops_list_font,
+};
+
+int
+simplefb_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ return OF_is_compatible(faa->fa_node, "simple-framebuffer");
+}
+
+void
+simplefb_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct simplefb_softc *sc = (struct simplefb_softc *)self;
+ struct fdt_attach_args *faa = aux;
+ struct rasops_info *ri = &sc->sc_ri;
+ struct wsemuldisplaydev_attach_args waa;
+ char format[16];
+ int i;
+
+ if (faa->fa_nreg < 1)
+ return;
+
+ format[0] = 0;
+ OF_getprop(faa->fa_node, "format", format, sizeof(format));
+ format[sizeof(format) - 1] = 0;
+
+ for (i = 0; i < nitems(simplefb_formats); i++) {
+ if (strcmp(format, simplefb_formats[i].format) == 0) {
+ sc->sc_format = &simplefb_formats[i];
+ break;
+ }
+ }
+ if (sc->sc_format == NULL) {
+ printf(": unsupported format \"%s\"\n", format);
+ return;
+ }
+
+ sc->sc_iot = faa->fa_iot;
+ sc->sc_paddr = faa->fa_reg[0].addr;
+ sc->sc_psize = faa->fa_reg[0].size;
+ if (bus_space_map(sc->sc_iot, sc->sc_paddr, sc->sc_psize,
+ BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_ioh))
+ panic("%s: bus_space_map failed!", __func__);
+
+ ri->ri_width = OF_getpropint(faa->fa_node, "width", 0);
+ ri->ri_height = OF_getpropint(faa->fa_node, "height", 0);
+ ri->ri_stride = OF_getpropint(faa->fa_node, "stride", 0);
+ ri->ri_depth = sc->sc_format->depth;
+ ri->ri_rpos = sc->sc_format->rpos;
+ ri->ri_rnum = sc->sc_format->rnum;
+ ri->ri_gpos = sc->sc_format->gpos;
+ ri->ri_gnum = sc->sc_format->gnum;
+ ri->ri_bpos = sc->sc_format->bpos;
+ ri->ri_bnum = sc->sc_format->bnum;
+ ri->ri_flg = RI_CENTER | RI_CLEAR | RI_FULLCLEAR;
+ ri->ri_flg |= RI_VCONS | RI_WRONLY;
+ ri->ri_bits = bus_space_vaddr(sc->sc_iot, sc->sc_ioh);
+ ri->ri_hw = sc;
+
+ printf(": %dx%d\n", ri->ri_width, ri->ri_height);
+
+ rasops_init(ri, 160, 160);
+
+ strlcpy(sc->sc_wsd.name, "std", sizeof(sc->sc_wsd.name));
+ sc->sc_wsd.capabilities = ri->ri_caps;
+ sc->sc_wsd.nrows = ri->ri_rows;
+ sc->sc_wsd.ncols = ri->ri_cols;
+ sc->sc_wsd.textops = &ri->ri_ops;
+ sc->sc_wsd.fontwidth = ri->ri_font->fontwidth;
+ sc->sc_wsd.fontheight = ri->ri_font->fontheight;
+
+ sc->sc_scrlist[0] = &sc->sc_wsd;
+ sc->sc_wsl.nscreens = 1;
+ sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist;
+
+ memset(&waa, 0, sizeof(waa));
+ waa.scrdata = &sc->sc_wsl;
+ waa.accessops = &simplefb_accessops;
+ waa.accesscookie = ri;
+
+ config_found_sm(self, &waa, wsemuldisplaydevprint,
+ wsemuldisplaydevsubmatch);
+}
+
+int
+simplefb_wsioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+ struct rasops_info *ri = v;
+ struct wsdisplay_fbinfo *wdf;
+
+ switch (cmd) {
+ case WSDISPLAYIO_GTYPE:
+ *(int *)data = WSDISPLAY_TYPE_EFIFB;
+ return 0;
+ case WSDISPLAYIO_GINFO:
+ wdf = (struct wsdisplay_fbinfo *)data;
+ wdf->width = ri->ri_width;
+ wdf->height = ri->ri_height;
+ wdf->depth = ri->ri_depth;
+ wdf->cmsize = 0; /* color map is unavailable */
+ break;
+ case WSDISPLAYIO_LINEBYTES:
+ *(u_int *)data = ri->ri_stride;
+ break;
+ case WSDISPLAYIO_SMODE:
+ break;
+ case WSDISPLAYIO_GETSUPPORTEDDEPTH:
+ switch (ri->ri_depth) {
+ case 32:
+ *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
+ break;
+ case 24:
+ *(u_int *)data = WSDISPLAYIO_DEPTH_24_24;
+ break;
+ case 16:
+ *(u_int *)data = WSDISPLAYIO_DEPTH_16;
+ break;
+ case 15:
+ *(u_int *)data = WSDISPLAYIO_DEPTH_15;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+paddr_t
+simplefb_wsmmap(void *v, off_t off, int prot)
+{
+ struct rasops_info *ri = v;
+ struct simplefb_softc *sc = ri->ri_hw;
+
+ if (off < 0 || off >= sc->sc_psize)
+ return -1;
+
+ return sc->sc_paddr + off;
+}
+
+int
+simplefb_alloc_screen(void *v, const struct wsscreen_descr *type,
+ void **cookiep, int *curxp, int *curyp, long *attrp)
+{
+ return rasops_alloc_screen(v, cookiep, curxp, curyp, attrp);
+}