diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/fdt/files.fdt | 8 | ||||
-rw-r--r-- | sys/dev/fdt/simplefb.c | 243 |
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); +} |