Annotation of sys/arch/sparc/dev/tcx.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: tcx.c,v 1.30 2007/03/13 19:40:48 miod Exp $ */
! 2: /* $NetBSD: tcx.c,v 1.8 1997/07/29 09:58:14 fair Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 2002, 2003 Miodrag Vallat. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 19: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 22: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 25: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 26: * POSSIBILITY OF SUCH DAMAGE.
! 27: *
! 28: *
! 29: * Copyright (c) 1996 The NetBSD Foundation, Inc.
! 30: * All rights reserved.
! 31: *
! 32: * This code is derived from software contributed to The NetBSD Foundation
! 33: * by Paul Kranenburg.
! 34: *
! 35: * Redistribution and use in source and binary forms, with or without
! 36: * modification, are permitted provided that the following conditions
! 37: * are met:
! 38: * 1. Redistributions of source code must retain the above copyright
! 39: * notice, this list of conditions and the following disclaimer.
! 40: * 2. Redistributions in binary form must reproduce the above copyright
! 41: * notice, this list of conditions and the following disclaimer in the
! 42: * documentation and/or other materials provided with the distribution.
! 43: * 3. All advertising materials mentioning features or use of this software
! 44: * must display the following acknowledgement:
! 45: * This product includes software developed by the NetBSD
! 46: * Foundation, Inc. and its contributors.
! 47: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 48: * contributors may be used to endorse or promote products derived
! 49: * from this software without specific prior written permission.
! 50: *
! 51: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 52: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 53: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 54: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
! 55: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 56: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 57: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 58: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 59: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 60: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 61: * POSSIBILITY OF SUCH DAMAGE.
! 62: */
! 63:
! 64: /*
! 65: * color display (TCX) driver.
! 66: */
! 67:
! 68: #include <sys/param.h>
! 69: #include <sys/systm.h>
! 70: #include <sys/buf.h>
! 71: #include <sys/device.h>
! 72: #include <sys/ioctl.h>
! 73: #include <sys/malloc.h>
! 74: #include <sys/mman.h>
! 75: #include <sys/tty.h>
! 76: #include <sys/conf.h>
! 77:
! 78: #include <uvm/uvm_extern.h>
! 79:
! 80: #include <machine/autoconf.h>
! 81: #include <machine/pmap.h>
! 82: #include <machine/cpu.h>
! 83: #include <machine/conf.h>
! 84:
! 85: #include <dev/wscons/wsconsio.h>
! 86: #include <dev/wscons/wsdisplayvar.h>
! 87: #include <dev/rasops/rasops.h>
! 88: #include <machine/fbvar.h>
! 89:
! 90: #include <sparc/dev/btreg.h>
! 91: #include <sparc/dev/btvar.h>
! 92: #include <sparc/dev/tcxreg.h>
! 93: #include <sparc/dev/sbusvar.h>
! 94:
! 95: #include <dev/cons.h> /* for prom console hook */
! 96:
! 97: /* per-display variables */
! 98: struct tcx_softc {
! 99: struct sunfb sc_sunfb; /* common base part */
! 100: struct rom_reg sc_phys[TCX_NREG]; /* phys addr of h/w */
! 101: volatile struct bt_regs *sc_bt; /* Brooktree registers */
! 102: volatile struct tcx_thc *sc_thc; /* THC registers */
! 103: volatile u_int8_t *sc_dfb8; /* 8 bit plane */
! 104: volatile u_int32_t *sc_dfb24; /* S24 24 bit plane */
! 105: volatile u_int32_t *sc_cplane; /* S24 control plane */
! 106: union bt_cmap sc_cmap; /* Brooktree color map */
! 107: struct intrhand sc_ih;
! 108: };
! 109:
! 110: void tcx_burner(void *, u_int, u_int);
! 111: int tcx_intr(void *);
! 112: int tcx_ioctl(void *, u_long, caddr_t, int, struct proc *);
! 113: static __inline__
! 114: void tcx_loadcmap_deferred(struct tcx_softc *, u_int, u_int);
! 115: paddr_t tcx_mmap(void *, off_t, int);
! 116: void tcx_reset(struct tcx_softc *, int);
! 117: void tcx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
! 118: void tcx_prom(void *);
! 119:
! 120: struct wsdisplay_accessops tcx_accessops = {
! 121: tcx_ioctl,
! 122: tcx_mmap,
! 123: NULL, /* alloc_screen */
! 124: NULL, /* free_screen */
! 125: NULL, /* show_screen */
! 126: NULL, /* load_font */
! 127: NULL, /* scrollback */
! 128: NULL, /* getchar */
! 129: tcx_burner,
! 130: NULL /* pollc */
! 131: };
! 132:
! 133: int tcxmatch(struct device *, void *, void *);
! 134: void tcxattach(struct device *, struct device *, void *);
! 135:
! 136: struct cfattach tcx_ca = {
! 137: sizeof(struct tcx_softc), tcxmatch, tcxattach
! 138: };
! 139:
! 140: struct cfdriver tcx_cd = {
! 141: NULL, "tcx", DV_DULL
! 142: };
! 143:
! 144: /*
! 145: * There are three ways to access the framebuffer memory of the S24:
! 146: * - 26 bits per pixel, in 32-bit words; the low-order 24 bits are blue,
! 147: * green and red values, and the other two bits select the display modes,
! 148: * per pixel.
! 149: * - 24 bits per pixel, in 32-bit words; the high-order byte reads as zero,
! 150: * and is ignored on writes (so the mode bits can not be altered).
! 151: * - 8 bits per pixel, unpadded; writes to this space do not modify the
! 152: * other 18 bits, which are hidden.
! 153: *
! 154: * The entry-level tcx found on the SPARCstation 4 can only provide the 8-bit
! 155: * mode.
! 156: */
! 157: #define TCX_CTL_8_MAPPED 0x00000000 /* 8 bits, uses colormap */
! 158: #define TCX_CTL_24_MAPPED 0x01000000 /* 24 bits, uses colormap */
! 159: #define TCX_CTL_24_LEVEL 0x03000000 /* 24 bits, true color */
! 160: #define TCX_CTL_PIXELMASK 0x00ffffff /* mask for index/level */
! 161:
! 162: int
! 163: tcxmatch(struct device *parent, void *vcf, void *aux)
! 164: {
! 165: struct confargs *ca = aux;
! 166: struct romaux *ra = &ca->ca_ra;
! 167:
! 168: if (strcmp(ra->ra_name, "SUNW,tcx") != 0)
! 169: return (0);
! 170:
! 171: return (1);
! 172: }
! 173:
! 174: void
! 175: tcxattach(struct device *parent, struct device *self, void *args)
! 176: {
! 177: struct tcx_softc *sc = (struct tcx_softc *)self;
! 178: struct confargs *ca = args;
! 179: int node, pri, i;
! 180: int isconsole = 0;
! 181: char *nam = NULL;
! 182:
! 183: pri = ca->ca_ra.ra_intr[0].int_pri;
! 184: printf(" pri %d", pri);
! 185:
! 186: node = ca->ca_ra.ra_node;
! 187:
! 188: if (ca->ca_ra.ra_nreg < TCX_NREG) {
! 189: printf(": expected %d registers, got %d\n",
! 190: TCX_NREG, ca->ca_ra.ra_nreg);
! 191: return;
! 192: }
! 193:
! 194: /* Copy register address spaces */
! 195: for (i = 0; i < TCX_NREG; i++)
! 196: sc->sc_phys[i] = ca->ca_ra.ra_reg[i];
! 197:
! 198: sc->sc_bt = (volatile struct bt_regs *)
! 199: mapiodev(&ca->ca_ra.ra_reg[TCX_REG_CMAP], 0, sizeof *sc->sc_bt);
! 200: sc->sc_thc = (volatile struct tcx_thc *)
! 201: mapiodev(&ca->ca_ra.ra_reg[TCX_REG_THC],
! 202: 0x1000, sizeof *sc->sc_thc);
! 203:
! 204: isconsole = node == fbnode;
! 205:
! 206: fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
! 207: if (node_has_property(node, "tcx-8-bit")) {
! 208: sc->sc_dfb8 = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_DFB8], 0,
! 209: round_page(sc->sc_sunfb.sf_fbsize));
! 210: sc->sc_dfb24 = NULL;
! 211: sc->sc_cplane = NULL;
! 212: } else {
! 213: sc->sc_dfb8 = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_DFB8], 0,
! 214: round_page(sc->sc_sunfb.sf_fbsize));
! 215:
! 216: /* map the 24 bit and control planes for S24 framebuffers */
! 217: sc->sc_dfb24 = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_DFB24], 0,
! 218: round_page(sc->sc_sunfb.sf_fbsize * 4));
! 219: sc->sc_cplane = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_RDFB32], 0,
! 220: round_page(sc->sc_sunfb.sf_fbsize * 4));
! 221: }
! 222:
! 223: /* reset cursor & frame buffer controls */
! 224: sc->sc_sunfb.sf_depth = 0; /* force action */
! 225: tcx_reset(sc, 8);
! 226:
! 227: /* enable video */
! 228: tcx_burner(sc, 1, 0);
! 229:
! 230: sc->sc_sunfb.sf_ro.ri_hw = sc;
! 231: sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_dfb8;
! 232: fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);
! 233: fbwscons_setcolormap(&sc->sc_sunfb, tcx_setcolor);
! 234:
! 235: sc->sc_ih.ih_fun = tcx_intr;
! 236: sc->sc_ih.ih_arg = sc;
! 237: intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname);
! 238:
! 239: if (isconsole) {
! 240: fbwscons_console_init(&sc->sc_sunfb, -1);
! 241: shutdownhook_establish(tcx_prom, sc);
! 242: }
! 243:
! 244: nam = getpropstring(node, "model");
! 245: if (*nam != '\0')
! 246: printf(": %s\n%s", nam, self->dv_xname);
! 247: printf(": %dx%d, id %d, rev %d, sense %d\n",
! 248: sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height,
! 249: (sc->sc_thc->thc_config & THC_CFG_FBID) >> THC_CFG_FBID_SHIFT,
! 250: (sc->sc_thc->thc_config & THC_CFG_REV) >> THC_CFG_REV_SHIFT,
! 251: (sc->sc_thc->thc_config & THC_CFG_SENSE) >> THC_CFG_SENSE_SHIFT
! 252: );
! 253:
! 254: fbwscons_attach(&sc->sc_sunfb, &tcx_accessops, isconsole);
! 255: }
! 256:
! 257: int
! 258: tcx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
! 259: {
! 260: struct tcx_softc *sc = dev;
! 261: struct wsdisplay_cmap *cm;
! 262: struct wsdisplay_fbinfo *wdf;
! 263: int error;
! 264:
! 265: /*
! 266: * Note that, although the emulation (text) mode is running in 8-bit
! 267: * mode, if the frame buffer is able to run in 24-bit mode, it will
! 268: * be advertized as such.
! 269: */
! 270: switch (cmd) {
! 271: case WSDISPLAYIO_GTYPE:
! 272: *(u_int *)data = WSDISPLAY_TYPE_SUNTCX;
! 273: break;
! 274: case WSDISPLAYIO_GINFO:
! 275: wdf = (struct wsdisplay_fbinfo *)data;
! 276: wdf->height = sc->sc_sunfb.sf_height;
! 277: wdf->width = sc->sc_sunfb.sf_width;
! 278: wdf->depth = sc->sc_sunfb.sf_depth;
! 279: wdf->cmsize = sc->sc_cplane == NULL ? 256 : 0;
! 280: break;
! 281: case WSDISPLAYIO_GETSUPPORTEDDEPTH:
! 282: if (sc->sc_cplane != NULL)
! 283: *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
! 284: else
! 285: return (-1);
! 286: break;
! 287: case WSDISPLAYIO_LINEBYTES:
! 288: if (sc->sc_cplane == NULL)
! 289: *(u_int *)data = sc->sc_sunfb.sf_linebytes;
! 290: else
! 291: *(u_int *)data = sc->sc_sunfb.sf_linebytes * 4;
! 292: break;
! 293:
! 294: case WSDISPLAYIO_GETCMAP:
! 295: if (sc->sc_cplane == NULL) {
! 296: cm = (struct wsdisplay_cmap *)data;
! 297: error = bt_getcmap(&sc->sc_cmap, cm);
! 298: if (error)
! 299: return (error);
! 300: }
! 301: break;
! 302: case WSDISPLAYIO_PUTCMAP:
! 303: if (sc->sc_cplane == NULL) {
! 304: cm = (struct wsdisplay_cmap *)data;
! 305: error = bt_putcmap(&sc->sc_cmap, cm);
! 306: if (error)
! 307: return (error);
! 308: tcx_loadcmap_deferred(sc, cm->index, cm->count);
! 309: }
! 310: break;
! 311:
! 312: case WSDISPLAYIO_SMODE:
! 313: if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
! 314: /* Back from X11 to text mode */
! 315: tcx_reset(sc, 8);
! 316: } else {
! 317: /* Starting X11, try to switch to 24 bit mode */
! 318: if (sc->sc_cplane != NULL)
! 319: tcx_reset(sc, 32);
! 320: }
! 321: break;
! 322:
! 323: case WSDISPLAYIO_SVIDEO:
! 324: case WSDISPLAYIO_GVIDEO:
! 325: break;
! 326:
! 327: default:
! 328: return (-1); /* not supported yet */
! 329: }
! 330:
! 331: return (0);
! 332: }
! 333:
! 334: void
! 335: tcx_reset(struct tcx_softc *sc, int depth)
! 336: {
! 337: volatile struct bt_regs *bt;
! 338:
! 339: /* Hide the cursor, just in case */
! 340: sc->sc_thc->thc_cursoraddr = THC_CURSOFF;
! 341:
! 342: /* Enable cursor in Brooktree DAC. */
! 343: bt = sc->sc_bt;
! 344: bt->bt_addr = 0x06 << 24;
! 345: bt->bt_ctrl |= 0x03 << 24;
! 346:
! 347: /*
! 348: * Change mode if appropriate
! 349: */
! 350: if (sc->sc_sunfb.sf_depth != depth) {
! 351: if (sc->sc_cplane != NULL) {
! 352: volatile u_int32_t *cptr;
! 353: u_int32_t pixel;
! 354: int ramsize;
! 355:
! 356: cptr = sc->sc_cplane;
! 357: ramsize = sc->sc_sunfb.sf_fbsize;
! 358:
! 359: if (depth == 8) {
! 360: while (ramsize-- != 0) {
! 361: pixel = (*cptr & TCX_CTL_PIXELMASK);
! 362: *cptr++ = pixel | TCX_CTL_8_MAPPED;
! 363: }
! 364: } else {
! 365: while (ramsize-- != 0) {
! 366: *cptr++ = TCX_CTL_24_LEVEL;
! 367: }
! 368: }
! 369: }
! 370:
! 371: if (depth == 8)
! 372: fbwscons_setcolormap(&sc->sc_sunfb, tcx_setcolor);
! 373: }
! 374:
! 375: sc->sc_sunfb.sf_depth = depth;
! 376: }
! 377:
! 378: void
! 379: tcx_prom(void *v)
! 380: {
! 381: struct tcx_softc *sc = v;
! 382: extern struct consdev consdev_prom;
! 383:
! 384: if (sc->sc_sunfb.sf_depth != 8) {
! 385: /*
! 386: * Select 8-bit mode.
! 387: */
! 388: tcx_reset(sc, 8);
! 389:
! 390: /*
! 391: * Go back to prom output for the last few messages, so they
! 392: * will be displayed correctly.
! 393: */
! 394: cn_tab = &consdev_prom;
! 395: }
! 396: }
! 397:
! 398: void
! 399: tcx_burner(void *v, u_int on, u_int flags)
! 400: {
! 401: struct tcx_softc *sc = v;
! 402: int s;
! 403: u_int32_t thcm;
! 404:
! 405: s = splhigh();
! 406: thcm = sc->sc_thc->thc_hcmisc;
! 407: if (on) {
! 408: thcm |= THC_MISC_VIDEN;
! 409: thcm &= ~(THC_MISC_VSYNC_DISABLE | THC_MISC_HSYNC_DISABLE);
! 410: } else {
! 411: thcm &= ~THC_MISC_VIDEN;
! 412: if (flags & WSDISPLAY_BURN_VBLANK)
! 413: thcm |= THC_MISC_VSYNC_DISABLE | THC_MISC_HSYNC_DISABLE;
! 414: }
! 415: sc->sc_thc->thc_hcmisc = thcm;
! 416: splx(s);
! 417: }
! 418:
! 419: paddr_t
! 420: tcx_mmap(void *v, off_t offset, int prot)
! 421: {
! 422: struct tcx_softc *sc = v;
! 423:
! 424: if (offset & PGOFSET || offset < 0)
! 425: return (-1);
! 426:
! 427: /* Allow mapping as a dumb framebuffer from offset 0 */
! 428: if (sc->sc_sunfb.sf_depth == 8 && offset < sc->sc_sunfb.sf_fbsize)
! 429: return (REG2PHYS(&sc->sc_phys[TCX_REG_DFB8], offset) | PMAP_NC);
! 430: else if (sc->sc_sunfb.sf_depth != 8 &&
! 431: offset < sc->sc_sunfb.sf_fbsize * 4)
! 432: return (REG2PHYS(&sc->sc_phys[TCX_REG_DFB24], offset) |
! 433: PMAP_NC);
! 434:
! 435: return (-1);
! 436: }
! 437:
! 438: void
! 439: tcx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
! 440: {
! 441: struct tcx_softc *sc = v;
! 442:
! 443: bt_setcolor(&sc->sc_cmap, sc->sc_bt, index, r, g, b, 1);
! 444: }
! 445:
! 446: static __inline__ void
! 447: tcx_loadcmap_deferred(struct tcx_softc *sc, u_int start, u_int ncolors)
! 448: {
! 449: u_int32_t thcm;
! 450:
! 451: thcm = sc->sc_thc->thc_hcmisc;
! 452: thcm |= THC_MISC_INTEN;
! 453: sc->sc_thc->thc_hcmisc = thcm;
! 454: }
! 455:
! 456: int
! 457: tcx_intr(void *v)
! 458: {
! 459: struct tcx_softc *sc = v;
! 460: u_int32_t thcm;
! 461:
! 462: thcm = sc->sc_thc->thc_hcmisc;
! 463: if (thcm & THC_MISC_INTEN) {
! 464: thcm &= ~(THC_MISC_INTR | THC_MISC_INTEN);
! 465:
! 466: /* Acknowledge the interrupt */
! 467: sc->sc_thc->thc_hcmisc = thcm | THC_MISC_INTR;
! 468:
! 469: bt_loadcmap(&sc->sc_cmap, sc->sc_bt, 0, 256, 1);
! 470:
! 471: /* Disable further interrupts now */
! 472: sc->sc_thc->thc_hcmisc = thcm;
! 473:
! 474: return (1);
! 475: }
! 476:
! 477: return (0);
! 478: }
CVSweb