diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-03-01 19:17:19 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2009-03-01 19:17:19 +0000 |
commit | 89abda1fc2cdb1c5eeac917a3f490dfc68917eb9 (patch) | |
tree | 1407c42b91481564a6f27eed893358f7722b615d /sys/arch | |
parent | 1c8bbc2c97407968f152a20323b5031df8ca5f8c (diff) |
An accelerated framebuffer driver for the Tech Source Raptor GFX cards built
around the Number 0 Imagine-128 chip. Colormap support is still missing.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc64/conf/files.sparc64 | 6 | ||||
-rw-r--r-- | sys/arch/sparc64/dev/raptor.c | 541 |
2 files changed, 546 insertions, 1 deletions
diff --git a/sys/arch/sparc64/conf/files.sparc64 b/sys/arch/sparc64/conf/files.sparc64 index ccf34ead7dc..5ce0610ab91 100644 --- a/sys/arch/sparc64/conf/files.sparc64 +++ b/sys/arch/sparc64/conf/files.sparc64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.sparc64,v 1.117 2009/01/12 20:11:13 kettenis Exp $ +# $OpenBSD: files.sparc64,v 1.118 2009/03/01 19:17:18 kettenis Exp $ # $NetBSD: files.sparc64,v 1.50 2001/08/10 20:53:50 eeh Exp $ # maxpartitions must be first item in files.${ARCH} @@ -133,6 +133,10 @@ device ifb: ifb_ident, wsemuldisplaydev, rasops_bswap, rasops8 attach ifb at pci file arch/sparc64/dev/ifb.c ifb +device raptor: wsemuldisplaydev, rasops_bswap, rasops8 +attach raptor at pci +file arch/sparc64/dev/raptor.c raptor + device sbbc attach sbbc at pci file arch/sparc64/dev/sbbc.c sbbc needs-flag diff --git a/sys/arch/sparc64/dev/raptor.c b/sys/arch/sparc64/dev/raptor.c new file mode 100644 index 00000000000..4b1438dc088 --- /dev/null +++ b/sys/arch/sparc64/dev/raptor.c @@ -0,0 +1,541 @@ +/* $OpenBSD: raptor.c,v 1.1 2009/03/01 19:17:18 kettenis Exp $ */ + +/* + * Copyright (c) 2009 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/device.h> +#include <sys/pciio.h> +#include <sys/systm.h> + +#include <machine/autoconf.h> +#include <machine/bus.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsdisplayvar.h> + +#include <dev/rasops/rasops.h> + +#include <machine/fbvar.h> + +/* + * Tech Source uses the Raptor name for most of its graphics cards. + * This driver supports the origional Raptor GFX cards built around + * the Number 9 Imagine-128 chips. + * + * Official documentation for the Imagine-128 isn't available. The + * information used for writing this driver comes mostly from the Xorg + * i128 driver. + */ + +#define I128_INTM 0x4004 +#define I128_FLOW 0x4008 +#define I128_FLOW_DEB 0x00000001 +#define I128_FLOW_MCB 0x00000002 +#define I128_FLOW_CLP 0x00000004 +#define I128_FLOW_PRV 0x00000008 +#define I128_FLOW_ACTIVE 0x0000000f +#define I128_BUSY 0x400c +#define I128_BUSY_BUSY 0x00000001 +#define I128_BUF_CTRL 0x4020 +#define I128_BC_PSIZ_8B 0x00000000 +#define I128_BC_PSIZ_16B 0x01000000 +#define I128_BC_PSIZ_32B 0x02000000 +#define I128_DE_PGE 0x4024 +#define I128_DE_SORG 0x4028 +#define I128_DE_DORG 0x402c +#define I128_DE_MSRC 0x4030 +#define I128_DE_WKEY 0x4038 +#define I128_DE_ZPTCH 0x403c +#define I128_DE_SPTCH 0x4040 +#define I128_DE_DPTCH 0x4044 +#define I128_CMD 0x4048 +#define I128_CMD_OPC 0x4050 +#define I128_CO_BITBLT 0x00000001 +#define I128_CMD_ROP 0x4054 +#define I128_CR_COPY 0x0000000c +#define I128_CMD_STYLE 0x4058 +#define I128_CS_SOLID 0x00000001 +#define I128_CMD_PATRN 0x405c +#define I128_CMD_CLP 0x4060 +#define I128_CMD_HDF 0x4064 +#define I128_FORE 0x4068 +#define I128_MASK 0x4070 +#define I128_RMSK 0x4074 +#define I128_LPAT 0x4078 +#define I128_PCTRL 0x407c +#define I128_CLPTL 0x4080 +#define I128_CLPBR 0x4084 +#define I128_XY0_SRC 0x4088 +#define I128_XY1_DST 0x408c +#define I128_XY2_WH 0x4090 +#define I128_XY3_DIR 0x4094 +#define I128_DIR_BT 0x00000001 +#define I128_DIR_RL 0x00000002 +#define I128_XY4_ZM 0x4098 +#define I128_ZOOM_NONE 0x00000000 +#define I128_ACNTRL 0x416c + +#define I128_COORDS(x, y) ((x << 16) | (y)) + + +#ifdef APERTURE +extern int allowaperture; +#endif + +struct raptor_softc { + struct sunfb sc_sunfb; + + bus_space_tag_t sc_memt; + bus_space_handle_t sc_memh; + bus_addr_t sc_membase; + bus_size_t sc_memsize; + + bus_space_tag_t sc_mmiot; + bus_space_handle_t sc_mmioh; + bus_addr_t sc_mmiobase; + bus_size_t sc_mmiosize; + + pcitag_t sc_pcitag; + + int sc_mode; +}; + +int raptor_ioctl(void *, u_long, caddr_t, int, struct proc *); +paddr_t raptor_mmap(void *, off_t, int); + +struct wsdisplay_accessops raptor_accessops = { + raptor_ioctl, + raptor_mmap, + NULL, /* alloc_screen */ + NULL, /* free_screen */ + NULL, /* show_screen */ + NULL, /* load_font */ + NULL, /* scrollback */ + NULL, /* getchar */ + NULL, /* burner */ + NULL /* pollc */ +}; + +int raptor_match(struct device *, void *, void *); +void raptor_attach(struct device *, struct device *, void *); + +struct cfattach raptor_ca = { + sizeof(struct raptor_softc), raptor_match, raptor_attach +}; + +struct cfdriver raptor_cd = { + NULL, "raptor", DV_DULL +}; + +int raptor_is_console(int); + +void raptor_copycols(void *, int, int, int, int); +void raptor_erasecols(void *, int, int, int, long); +void raptor_copyrows(void *, int, int, int); +void raptor_eraserows(void *, int, int, long); + +void raptor_init(struct raptor_softc *); +int raptor_wait(struct raptor_softc *); +void raptor_copyrect(struct raptor_softc *, int, int, int, int, int, int); +void raptor_fillrect(struct raptor_softc *, int, int, int, int, int); + +int +raptor_match(struct device *parent, void *cf, void *aux) +{ + struct pci_attach_args *pa = aux; + int node; + char *name; + + node = PCITAG_NODE(pa->pa_tag); + name = getpropstring(node, "name"); + if (strcmp(name, "TECH-SOURCE,raptor") == 0 || + strcmp(name, "TSI,raptor") == 0) + return (10); + + return (0); +} + +void +raptor_attach(struct device *parent, struct device *self, void *aux) +{ + struct raptor_softc *sc = (struct raptor_softc *)self; + struct pci_attach_args *pa = aux; + struct rasops_info *ri; + int node, console; + char *model; + + sc->sc_pcitag = pa->pa_tag; + + node = PCITAG_NODE(pa->pa_tag); + console = raptor_is_console(node); + + printf("\n"); + + model = getpropstring(node, "model"); + printf("%s: %s", self->dv_xname, model); + + if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM, + BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh, + &sc->sc_membase, &sc->sc_memsize, 0)) { + printf("\n%s: can't map video memory\n", self->dv_xname); + return; + } + + if (pci_mapreg_map(pa, 0x20, PCI_MAPREG_TYPE_MEM, 0, + &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase, + &sc->sc_mmiosize, 0)) { + bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_memsize); + printf("\n%s: can't map mmio\n", self->dv_xname); + return; + } + + fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0); + + printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); + + ri = &sc->sc_sunfb.sf_ro; + ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh); + ri->ri_hw = sc; + + fbwscons_init(&sc->sc_sunfb, RI_BSWAP, console); + sc->sc_mode = WSDISPLAYIO_MODE_EMUL; + + raptor_init(sc); + ri->ri_ops.copyrows = raptor_copyrows; + ri->ri_ops.copycols = raptor_copycols; + ri->ri_ops.eraserows = raptor_eraserows; + ri->ri_ops.erasecols = raptor_erasecols; + + if (console) + fbwscons_console_init(&sc->sc_sunfb, -1); + fbwscons_attach(&sc->sc_sunfb, &raptor_accessops, console); +} + +int +raptor_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + struct raptor_softc *sc = v; + struct wsdisplay_fbinfo *wdf; + struct pcisel *sel; + + switch (cmd) { + case WSDISPLAYIO_GTYPE: + *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN; + break; + case WSDISPLAYIO_SMODE: + sc->sc_mode = *(u_int *)data; +#if 0 + if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { + if (sc->sc_console) /* XXX needs sc_ofhandle */ + fbwscons_setcolormap(&sc->sc_sunfb, + raptor_setcolor); + } +#endif + break; + case WSDISPLAYIO_GINFO: + wdf = (void *)data; + wdf->height = sc->sc_sunfb.sf_height; + wdf->width = sc->sc_sunfb.sf_width; + wdf->depth = sc->sc_sunfb.sf_depth; + wdf->cmsize = 256; + break; + case WSDISPLAYIO_LINEBYTES: + *(u_int *)data = sc->sc_sunfb.sf_linebytes; + break; + +#if 0 + case WSDISPLAYIO_GETCMAP: + if (sc->sc_console == 0) + return (EINVAL); + return raptor_getcmap(sc, (struct wsdisplay_cmap *)data); + case WSDISPLAYIO_PUTCMAP: + if (sc->sc_console == 0) + return (EINVAL); + return raptor_putcmap(sc, (struct wsdisplay_cmap *)data); +#endif + + case WSDISPLAYIO_GPCIID: + sel = (struct pcisel *)data; + sel->pc_bus = PCITAG_BUS(sc->sc_pcitag); + sel->pc_dev = PCITAG_DEV(sc->sc_pcitag); + sel->pc_func = PCITAG_FUN(sc->sc_pcitag); + break; + + case WSDISPLAYIO_SVIDEO: + case WSDISPLAYIO_GVIDEO: + break; + + case WSDISPLAYIO_GCURPOS: + case WSDISPLAYIO_SCURPOS: + case WSDISPLAYIO_GCURMAX: + case WSDISPLAYIO_GCURSOR: + case WSDISPLAYIO_SCURSOR: + default: + return -1; /* not supported yet */ + } + + return (0); +} + +paddr_t +raptor_mmap(void *v, off_t off, int prot) +{ + struct raptor_softc *sc = v; + + if (off & PGOFSET) + return (-1); + + switch (sc->sc_mode) { + case WSDISPLAYIO_MODE_MAPPED: +#ifdef APERTURE + if (allowaperture == 0) + return (-1); +#endif + + if (sc->sc_mmiosize == 0) + return (-1); + + if (off >= sc->sc_membase && + off < (sc->sc_membase + sc->sc_memsize)) + return (bus_space_mmap(sc->sc_memt, + sc->sc_membase, off - sc->sc_membase, + prot, BUS_SPACE_MAP_LINEAR)); + + if (off >= sc->sc_mmiobase && + off < (sc->sc_mmiobase + sc->sc_mmiosize)) + return (bus_space_mmap(sc->sc_mmiot, + sc->sc_mmiobase, off - sc->sc_mmiobase, + prot, BUS_SPACE_MAP_LINEAR)); + break; + + case WSDISPLAYIO_MODE_DUMBFB: + if (off >= 0 && off < sc->sc_memsize) + return (bus_space_mmap(sc->sc_memt, sc->sc_membase, + off, prot, BUS_SPACE_MAP_LINEAR)); + break; + } + + return (-1); +} + +int +raptor_is_console(int node) +{ + extern int fbnode; + + return (fbnode == node); +} + +/* + * Accelerated routines. + */ + +void +raptor_copycols(void *cookie, int row, int src, int dst, int num) +{ + struct rasops_info *ri = cookie; + struct raptor_softc *sc = ri->ri_hw; + + num *= ri->ri_font->fontwidth; + src *= ri->ri_font->fontwidth; + dst *= ri->ri_font->fontwidth; + row *= ri->ri_font->fontheight; + + raptor_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row, + ri->ri_xorigin + dst, ri->ri_yorigin + row, + num, ri->ri_font->fontheight); +} + +void +raptor_erasecols(void *cookie, int row, int col, int num, long attr) +{ + struct rasops_info *ri = cookie; + struct raptor_softc *sc = ri->ri_hw; + int bg, fg; + + ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); + + row *= ri->ri_font->fontheight; + col *= ri->ri_font->fontwidth; + num *= ri->ri_font->fontwidth; + + raptor_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row, + num, ri->ri_font->fontheight, ri->ri_devcmap[bg]); +} + +void +raptor_copyrows(void *cookie, int src, int dst, int num) +{ + struct rasops_info *ri = cookie; + struct raptor_softc *sc = ri->ri_hw; + + num *= ri->ri_font->fontheight; + src *= ri->ri_font->fontheight; + dst *= ri->ri_font->fontheight; + + raptor_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src, + ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num); +} + +void +raptor_eraserows(void *cookie, int row, int num, long attr) +{ + struct rasops_info *ri = cookie; + struct raptor_softc *sc = ri->ri_hw; + int bg, fg; + int x, y, w; + + ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); + + if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) { + num = ri->ri_height; + x = y = 0; + w = ri->ri_width; + } else { + num *= ri->ri_font->fontheight; + x = ri->ri_xorigin; + y = ri->ri_yorigin + row * ri->ri_font->fontheight; + w = ri->ri_emuwidth; + } + raptor_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]); +} + +void +raptor_init(struct raptor_softc *sc) +{ + /* Configure pixel format based on depth. */ + switch(sc->sc_sunfb.sf_depth) { + case 8: + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, + I128_BUF_CTRL, I128_BC_PSIZ_8B); + break; + case 16: + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, + I128_BUF_CTRL, I128_BC_PSIZ_16B); + break; + case 24: + case 32: + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, + I128_BUF_CTRL, I128_BC_PSIZ_32B); + break; + default: + panic("unsupported depth\n"); + break; + } + + /* Mostly magic. */ + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_PGE, 0); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_SORG, 0); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_DORG, 0); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_MSRC, 0); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_WKEY, 0); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_SPTCH, + sc->sc_sunfb.sf_linebytes); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_DPTCH, + sc->sc_sunfb.sf_linebytes); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_DE_ZPTCH, + sc->sc_sunfb.sf_linebytes); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_RMSK, 0); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY4_ZM, + I128_ZOOM_NONE); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_LPAT, + 0xffffffff); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_PCTRL, 0); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_CLPTL, 0); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_CLPBR, + (4095 << 16) | 2047); +#if 0 + /* XXX For some reason this makes schizo(4) freak out. */ + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_ACNTRL, 0); +#endif + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_INTM, 3); +} + +int +raptor_wait(struct raptor_softc *sc) +{ + int i; + + for (i = 1000000; i != 0; i--) { + if ((bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, + I128_FLOW) & I128_FLOW_ACTIVE) == 0) + break; + DELAY(1); + } + + return i; +} + +void +raptor_copyrect(struct raptor_softc *sc, int sx, int sy, int dx, int dy, + int w, int h) +{ + int dir = 0; + + while (bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, + I128_BUSY) & I128_BUSY_BUSY) + DELAY(1); + + if (sx < dx) { + sx += w - 1; + dx += w - 1; + dir |= I128_DIR_RL; + } + if (sy < dy) { + sy += h - 1; + dy += h - 1; + dir |= I128_DIR_BT; + } + + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_CMD, + I128_CR_COPY << 8 | I128_CO_BITBLT); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY3_DIR, dir); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY2_WH, + I128_COORDS(w , h)); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY0_SRC, + I128_COORDS(sx, sy)); + /* Must be last; triggers operation. */ + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY1_DST, + I128_COORDS(dx, dy)); + + raptor_wait(sc); +} + +void +raptor_fillrect(struct raptor_softc *sc, int x, int y, int w, int h, int color) +{ + while (bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, + I128_BUSY) & I128_BUSY_BUSY) + DELAY(1); + + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_CMD, + I128_CS_SOLID << 16 | I128_CR_COPY << 8 | I128_CO_BITBLT); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_FORE, color); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY3_DIR, 0); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY2_WH, + I128_COORDS(w, h)); + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY0_SRC, 0); + /* Must be last; triggers operation. */ + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, I128_XY1_DST, + I128_COORDS(x, y)); + + raptor_wait(sc); +} |