Annotation of sys/arch/sparc/dev/cgtwelve.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: cgtwelve.c,v 1.16 2007/03/13 19:40:48 miod Exp $ */
2:
3: /*
4: * Copyright (c) 2002, 2003 Miodrag Vallat. All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25: * POSSIBILITY OF SUCH DAMAGE.
26: */
27:
28: /*
29: * cgtwelve (GS) accelerated 24-bit framebuffer driver.
30: *
31: * Enough experiments and SMI's cg12reg.h made this possible.
32: */
33:
34: /*
35: * The cgtwelve framebuffer is a 3-slot SBUS card, that will fit only in
36: * SPARCstation 1, 1+, 2 and 5, or in an xbox SBUS extension.
37: *
38: * It is a 24-bit 3D accelerated framebuffer made by Matrox, featuring 4MB
39: * (regular model) or 8MB (high-res model) of video memory, a complex
40: * windowing engine, double buffering modes, three video planes (overlay,
41: * 8 bit and 24 bit color), and a lot of colormap combinations.
42: *
43: * All of this is driven by a set of three Bt462 ramdacs (latched unless
44: * explicitely programmed), and a couple of other Matrox-specific chips.
45: *
46: * XXX The high res card is untested.
47: */
48:
49: #include <sys/param.h>
50: #include <sys/systm.h>
51: #include <sys/buf.h>
52: #include <sys/device.h>
53: #include <sys/ioctl.h>
54: #include <sys/malloc.h>
55: #include <sys/mman.h>
56: #include <sys/tty.h>
57: #include <sys/conf.h>
58:
59: #include <uvm/uvm_extern.h>
60:
61: #include <machine/autoconf.h>
62: #include <machine/pmap.h>
63: #include <machine/cpu.h>
64: #include <machine/conf.h>
65:
66: #include <dev/wscons/wsconsio.h>
67: #include <dev/wscons/wsdisplayvar.h>
68: #include <dev/rasops/rasops.h>
69: #include <machine/fbvar.h>
70:
71: #include <sparc/dev/cgtwelvereg.h>
72: #include <sparc/dev/sbusvar.h>
73:
74: #include <dev/cons.h> /* for prom console hook */
75:
76: /* per-display variables */
77: struct cgtwelve_softc {
78: struct sunfb sc_sunfb; /* common base device */
79: struct rom_reg sc_phys;
80:
81: volatile struct cgtwelve_dpu *sc_dpu;
82: volatile struct cgtwelve_apu *sc_apu;
83: volatile struct cgtwelve_dac *sc_ramdac; /* RAMDAC registers */
84: volatile u_char *sc_overlay; /* overlay or enable plane */
85: volatile u_long *sc_inten; /* true color plane */
86:
87: int sc_highres;
88: };
89:
90: int cgtwelve_ioctl(void *, u_long, caddr_t, int, struct proc *);
91: paddr_t cgtwelve_mmap(void *, off_t, int);
92: void cgtwelve_prom(void *);
93: static __inline__
94: void cgtwelve_ramdac_wraddr(struct cgtwelve_softc *, u_int32_t);
95: void cgtwelve_reset(struct cgtwelve_softc *, int);
96:
97: struct wsdisplay_accessops cgtwelve_accessops = {
98: cgtwelve_ioctl,
99: cgtwelve_mmap,
100: NULL, /* alloc_screen */
101: NULL, /* free_screen */
102: NULL, /* show_screen */
103: NULL, /* load_font */
104: NULL, /* scrollback */
105: NULL, /* getchar */
106: NULL, /* burner */
107: NULL /* pollc */
108: };
109:
110: int cgtwelvematch(struct device *, void *, void *);
111: void cgtwelveattach(struct device *, struct device *, void *);
112:
113: struct cfattach cgtwelve_ca = {
114: sizeof(struct cgtwelve_softc), cgtwelvematch, cgtwelveattach
115: };
116:
117: struct cfdriver cgtwelve_cd = {
118: NULL, "cgtwelve", DV_DULL
119: };
120:
121:
122: int
123: cgtwelvematch(struct device *parent, void *vcf, void *aux)
124: {
125: struct cfdata *cf = vcf;
126: struct confargs *ca = aux;
127: struct romaux *ra = &ca->ca_ra;
128:
129: if (strcmp(cf->cf_driver->cd_name, ra->ra_name) != 0)
130: return (0);
131:
132: return (1);
133: }
134:
135: void
136: cgtwelveattach(struct device *parent, struct device *self, void *args)
137: {
138: struct cgtwelve_softc *sc = (struct cgtwelve_softc *)self;
139: struct confargs *ca = args;
140: int node;
141: int isconsole = 0;
142: char *ps;
143:
144: node = ca->ca_ra.ra_node;
145:
146: printf(": %s", getpropstring(node, "model"));
147: ps = getpropstring(node, "dev_id");
148: if (*ps != '\0')
149: printf(" (%s)", ps);
150: printf("\n");
151:
152: isconsole = node == fbnode;
153:
154: sc->sc_phys = ca->ca_ra.ra_reg[0];
155:
156: /*
157: * Map registers
158: */
159: sc->sc_dpu = (struct cgtwelve_dpu *)mapiodev(ca->ca_ra.ra_reg,
160: CG12_OFF_DPU, sizeof(struct cgtwelve_dpu));
161: sc->sc_apu = (struct cgtwelve_apu *)mapiodev(ca->ca_ra.ra_reg,
162: CG12_OFF_APU, sizeof(struct cgtwelve_apu));
163: sc->sc_ramdac = (struct cgtwelve_dac *)mapiodev(ca->ca_ra.ra_reg,
164: CG12_OFF_DAC, sizeof(struct cgtwelve_dac));
165:
166: /*
167: * The console is using the 1-bit overlay plane, while the prom
168: * will correctly report 32 bit depth.
169: */
170: fb_setsize(&sc->sc_sunfb, 1, CG12_WIDTH, CG12_HEIGHT,
171: node, ca->ca_bustype);
172: sc->sc_sunfb.sf_depth = 1;
173: sc->sc_sunfb.sf_linebytes = sc->sc_sunfb.sf_width / 8;
174: sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height *
175: sc->sc_sunfb.sf_linebytes;
176:
177: sc->sc_highres = sc->sc_sunfb.sf_width == CG12_WIDTH_HR;
178:
179: /*
180: * Map planes
181: */
182: sc->sc_overlay = mapiodev(ca->ca_ra.ra_reg,
183: sc->sc_highres ? CG12_OFF_OVERLAY0_HR : CG12_OFF_OVERLAY0,
184: round_page(sc->sc_highres ? CG12_SIZE_OVERLAY_HR :
185: CG12_SIZE_OVERLAY));
186: sc->sc_inten = mapiodev(ca->ca_ra.ra_reg,
187: sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN,
188: round_page(sc->sc_highres ? CG12_SIZE_COLOR24_HR :
189: CG12_SIZE_COLOR24));
190:
191: /* reset cursor & frame buffer controls */
192: sc->sc_sunfb.sf_depth = 0; /* force action */
193: cgtwelve_reset(sc, 1);
194:
195: sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_overlay;
196: sc->sc_sunfb.sf_ro.ri_hw = sc;
197: fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);
198:
199: if (isconsole) {
200: fbwscons_console_init(&sc->sc_sunfb, -1);
201: shutdownhook_establish(cgtwelve_prom, sc);
202: }
203:
204: printf("%s: %dx%d", self->dv_xname,
205: sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
206: ps = getpropstring(node, "ucoderev");
207: if (*ps != '\0')
208: printf(", microcode rev. %s", ps);
209: printf("\n");
210:
211: fbwscons_attach(&sc->sc_sunfb, &cgtwelve_accessops, isconsole);
212: }
213:
214: int
215: cgtwelve_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
216: {
217: struct cgtwelve_softc *sc = dev;
218: struct wsdisplay_fbinfo *wdf;
219:
220: /*
221: * Note that, although the emulation (text) mode is running in the
222: * overlay plane, we advertize the frame buffer as the full-blown
223: * 32-bit beast it is.
224: */
225: switch (cmd) {
226: case WSDISPLAYIO_GTYPE:
227: *(u_int *)data = WSDISPLAY_TYPE_SUNCG12;
228: break;
229: case WSDISPLAYIO_GINFO:
230: wdf = (struct wsdisplay_fbinfo *)data;
231: wdf->height = sc->sc_sunfb.sf_height;
232: wdf->width = sc->sc_sunfb.sf_width;
233: wdf->depth = 32;
234: wdf->cmsize = 0;
235: break;
236: case WSDISPLAYIO_GETSUPPORTEDDEPTH:
237: *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
238: break;
239: case WSDISPLAYIO_LINEBYTES:
240: *(u_int *)data = sc->sc_sunfb.sf_linebytes * 32;
241: break;
242:
243: case WSDISPLAYIO_GETCMAP:
244: case WSDISPLAYIO_PUTCMAP:
245: break;
246:
247: case WSDISPLAYIO_SMODE:
248: if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
249: /* Back from X11 to text mode */
250: cgtwelve_reset(sc, 1);
251: } else {
252: /* Starting X11, switch to 32 bit mode */
253: cgtwelve_reset(sc, 32);
254: }
255: break;
256:
257: case WSDISPLAYIO_SVIDEO:
258: case WSDISPLAYIO_GVIDEO:
259: break;
260:
261: default:
262: return (-1); /* not supported yet */
263: }
264:
265: return (0);
266: }
267:
268: void
269: cgtwelve_reset(struct cgtwelve_softc *sc, int depth)
270: {
271: u_int32_t c;
272:
273: if (sc->sc_sunfb.sf_depth != depth) {
274: if (depth == 1) {
275: /*
276: * Select the enable plane as sc_overlay, and fill it.
277: */
278: sc->sc_apu->hpage = sc->sc_highres ?
279: CG12_HPAGE_ENABLE_HR : CG12_HPAGE_ENABLE;
280: sc->sc_apu->haccess = CG12_HACCESS_ENABLE;
281: sc->sc_dpu->pln_sl_host = CG12_PLN_SL_ENABLE;
282: sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_ENABLE;
283: sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_ENABLE;
284:
285: memset((void *)sc->sc_overlay, 0xff, sc->sc_highres ?
286: CG12_SIZE_ENABLE_HR : CG12_SIZE_ENABLE);
287:
288: /*
289: * Select the overlay plane as sc_overlay.
290: */
291: sc->sc_apu->hpage = sc->sc_highres ?
292: CG12_HPAGE_OVERLAY_HR : CG12_HPAGE_OVERLAY;
293: sc->sc_apu->haccess = CG12_HACCESS_OVERLAY;
294: sc->sc_dpu->pln_sl_host = CG12_PLN_SL_OVERLAY;
295: sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_OVERLAY;
296: sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_OVERLAY;
297:
298: /*
299: * Upload a strict mono colormap, or the text
300: * upon returning from 32 bit mode would appear
301: * as (slightly dark) white on white.
302: */
303: cgtwelve_ramdac_wraddr(sc, 0);
304: sc->sc_ramdac->color = 0x00000000;
305: for (c = 1; c < 256; c++)
306: sc->sc_ramdac->color = 0x00ffffff;
307: } else {
308: /*
309: * Select the overlay plane as sc_overlay.
310: */
311: sc->sc_apu->hpage = sc->sc_highres ?
312: CG12_HPAGE_OVERLAY_HR : CG12_HPAGE_OVERLAY;
313: sc->sc_apu->haccess = CG12_HACCESS_OVERLAY;
314: sc->sc_dpu->pln_sl_host = CG12_PLN_SL_OVERLAY;
315: sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_OVERLAY;
316: sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_OVERLAY;
317:
318: /*
319: * Do not attempt to somewhat preserve screen
320: * contents - reading the overlay plane and writing
321: * to the color plane at the same time is not
322: * reliable, and allocating memory to save a copy
323: * of the overlay plane would be awful.
324: */
325: bzero((void *)sc->sc_overlay, sc->sc_highres ?
326: CG12_SIZE_OVERLAY_HR : CG12_SIZE_OVERLAY);
327:
328: /*
329: * Select the enable plane as sc_overlay, and clear it.
330: */
331: sc->sc_apu->hpage = sc->sc_highres ?
332: CG12_HPAGE_ENABLE_HR : CG12_HPAGE_ENABLE;
333: sc->sc_apu->haccess = CG12_HACCESS_ENABLE;
334: sc->sc_dpu->pln_sl_host = CG12_PLN_SL_ENABLE;
335: sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_ENABLE;
336: sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_ENABLE;
337:
338: bzero((void *)sc->sc_overlay, sc->sc_highres ?
339: CG12_SIZE_ENABLE_HR : CG12_SIZE_ENABLE);
340:
341: /*
342: * Select the intensity (color) plane, and clear it.
343: */
344: sc->sc_apu->hpage = sc->sc_highres ?
345: CG12_HPAGE_24BIT_HR : CG12_HPAGE_24BIT;
346: sc->sc_apu->haccess = CG12_HACCESS_24BIT;
347: sc->sc_dpu->pln_sl_host = CG12_PLN_SL_24BIT;
348: sc->sc_dpu->pln_rd_msk_host = CG12_PLN_RD_24BIT;
349: sc->sc_dpu->pln_wr_msk_host = CG12_PLN_WR_24BIT;
350:
351: memset((void *)sc->sc_inten, 0x00ffffff,
352: sc->sc_highres ?
353: CG12_SIZE_COLOR24_HR : CG12_SIZE_COLOR24);
354:
355: /*
356: * Use a direct colormap (ramp)
357: */
358: cgtwelve_ramdac_wraddr(sc, 0);
359: for (c = 0; c < 256; c++)
360: sc->sc_ramdac->color = c | (c << 8) | (c << 16);
361: }
362: }
363:
364: sc->sc_sunfb.sf_depth = depth;
365: }
366:
367: paddr_t
368: cgtwelve_mmap(void *v, off_t offset, int prot)
369: {
370: struct cgtwelve_softc *sc = v;
371:
372: if (offset & PGOFSET || offset < 0)
373: return (-1);
374:
375: /*
376: * Note that mmap() will invoke this function only if we are NOT
377: * in emulation mode, so we can assume 32 bit mode safely here.
378: */
379: if (offset < sc->sc_sunfb.sf_fbsize * 32) {
380: return (REG2PHYS(&sc->sc_phys,
381: (sc->sc_highres ? CG12_OFF_INTEN_HR :
382: CG12_OFF_INTEN) + offset) | PMAP_NC);
383: }
384:
385: return (-1);
386: }
387:
388: /*
389: * Simple Bt462 programming routines.
390: */
391:
392: static __inline__ void
393: cgtwelve_ramdac_wraddr(struct cgtwelve_softc *sc, u_int32_t addr)
394: {
395: sc->sc_ramdac->addr_lo = (addr & 0xff);
396: sc->sc_ramdac->addr_hi = ((addr >> 8) & 0xff);
397: }
398:
399: /*
400: * Shutdown hook used to restore PROM-compatible video mode on shutdown,
401: * so that the PROM prompt is visible again.
402: */
403: void
404: cgtwelve_prom(v)
405: void *v;
406: {
407: struct cgtwelve_softc *sc = v;
408: extern struct consdev consdev_prom;
409:
410: if (sc->sc_sunfb.sf_depth != 1) {
411: cgtwelve_reset(sc, 1);
412:
413: /*
414: * Go back to prom output for the last few messages, so they
415: * will be displayed correctly.
416: */
417: cn_tab = &consdev_prom;
418: }
419: }
CVSweb