Annotation of sys/arch/sparc/dev/tcx.c, Revision 1.1.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