Annotation of sys/arch/sparc/dev/tvtwo.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: tvtwo.c,v 1.14 2007/03/13 19:40:48 miod Exp $ */
2: /*
3: * Copyright (c) 2003, 2006, Miodrag Vallat.
4: * 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: /*
30: * Driver for the Parallax XVideo and PowerVideo graphics boards.
31: *
32: * Some details about these board are available at:
33: * http://www.jlw.com/~woolsey/parallax/support/developers/xvideotech.html
34: */
35:
36: /*
37: * The Parallax XVideo series frame buffers are 8/24-bit accelerated
38: * frame buffers, with hardware MPEG capabilities using a CCube chipset.
39: */
40:
41: /*
42: * Currently, this driver can only handle the 8-bit and 24-bit planes of the
43: * frame buffer, in an unaccelerated mode.
44: *
45: * TODO:
46: * - nvram handling
47: * - use the accelerator
48: * - interface to the c^3
49: */
50:
51: #include <sys/param.h>
52: #include <sys/systm.h>
53: #include <sys/buf.h>
54: #include <sys/device.h>
55: #include <sys/ioctl.h>
56: #include <sys/mman.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/sbusvar.h>
72:
73: /*
74: * The memory layout of the board is as follows:
75: *
76: * PROM0 000000 - 00ffff
77: * overlay plane 010000 - 037fff
78: * registers 040000 - 0404d0
79: * CCube 050000 - 05ffff
80: * 8-bit plane 080000 - 17ffff
81: * 24-bit plane 200000 - 6fffff
82: * PROM1 7f0000 - 7fffff
83: *
84: * Older XVideo provide two sets of SBus registers:
85: * R0 040000 - 040800
86: * R1 080000 - 17d200
87: * While the more recent revisions provide only one register:
88: * R0 000000 - 7fffff
89: *
90: * We currently refuse to attach to the old version because mapping
91: * things requires us to play with the sbus register ranges, and I
92: * don't want to play this game without the hardware at hand -- miod
93: */
94:
95: #define PX_PROM0_OFFSET 0x000000
96: #define PX_OVERLAY_OFFSET 0x010000
97: #define PX_REG_OFFSET 0x040000
98: #define PX_CCUBE_OFFSET 0x050000
99: #define PX_PLANE8_OFFSET 0x080000
100: #define PX_PLANE24_OFFSET 0x200000
101: #define PX_PROM1_OFFSET 0x7f0000
102:
103: /*
104: * Partial registers layout
105: */
106:
107: #define PX_REG_DISPKLUDGE 0x00b8 /* write only */
108: #define DISPKLUDGE_DEFAULT 0xc41f
109: #define DISPKLUDGE_BLANK (1 << 12)
110: #define DISPKLUDGE_SYNC (1 << 13)
111:
112: #define PX_REG_BT463_RED 0x0480
113: #define PX_REG_BT463_GREEN 0x0490
114: #define PX_REG_BT463_BLUE 0x04a0
115: #define PX_REG_BT463_ALL 0x04b0
116:
117: #define PX_REG_SIZE 0x04d0
118:
119:
120: /* per-display variables */
121: struct tvtwo_softc {
122: struct sunfb sc_sunfb; /* common base device */
123: struct rom_reg sc_phys;
124:
125: volatile u_int8_t *sc_m8;
126: volatile u_int8_t *sc_m24;
127: volatile u_int8_t *sc_regs;
128: };
129:
130: int tvtwo_ioctl(void *, u_long, caddr_t, int, struct proc *);
131: paddr_t tvtwo_mmap(void *, off_t, int);
132: void tvtwo_burner(void *, u_int, u_int);
133:
134: struct wsdisplay_accessops tvtwo_accessops = {
135: tvtwo_ioctl,
136: tvtwo_mmap,
137: NULL, /* alloc_screen */
138: NULL, /* free_screen */
139: NULL, /* show_screen */
140: NULL, /* load_font */
141: NULL, /* scrollback */
142: NULL, /* getchar */
143: tvtwo_burner,
144: NULL /* pollc */
145: };
146:
147: void tvtwo_directcmap(struct tvtwo_softc *);
148: static __inline__
149: void tvtwo_ramdac_wraddr(struct tvtwo_softc *, u_int32_t);
150: void tvtwo_reset(struct tvtwo_softc *, u_int);
151: void tvtwo_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
152:
153: int tvtwomatch(struct device *, void *, void *);
154: void tvtwoattach(struct device *, struct device *, void *);
155:
156: struct cfattach tvtwo_ca = {
157: sizeof(struct tvtwo_softc), tvtwomatch, tvtwoattach
158: };
159:
160: struct cfdriver tvtwo_cd = {
161: NULL, "tvtwo", DV_DULL
162: };
163:
164: /*
165: * Default frame buffer resolution, depending upon the "freqcode"
166: */
167: #define NFREQCODE 5
168: const int defwidth[NFREQCODE] = { 1152, 1152, 1152, 1024, 640 };
169: const int defheight[NFREQCODE] = { 900, 900, 900, 768, 480 };
170:
171: /*
172: * Match an XVideo or PowerVideo card.
173: */
174: int
175: tvtwomatch(struct device *parent, void *vcf, void *aux)
176: {
177: struct confargs *ca = aux;
178: struct romaux *ra = &ca->ca_ra;
179:
180: if (strcmp(ra->ra_name, "PGI,tvtwo") == 0 ||
181: strcmp(ra->ra_name, "PGI,tvthree") == 0)
182: return (1);
183:
184: return (0);
185: }
186:
187: void
188: tvtwoattach(struct device *parent, struct device *self, void *args)
189: {
190: struct tvtwo_softc *sc = (struct tvtwo_softc *)self;
191: struct confargs *ca = args;
192: int node, width, height, freqcode;
193: int isconsole;
194: char *freqstring;
195:
196: node = ca->ca_ra.ra_node;
197:
198: printf(": %s", getpropstring(node, "model"));
199: printf(", revision %s\n", getpropstring(node, "revision"));
200:
201: /* We do not handle older boards yet. */
202: if (ca->ca_ra.ra_nreg != 1) {
203: printf("%s: old-style boards with %d registers are not supported\n"
204: "%s: please report this to <sparc@openbsd.org>\n",
205: self->dv_xname, ca->ca_ra.ra_nreg,
206: self->dv_xname);
207: return;
208: }
209:
210: isconsole = node == fbnode;
211:
212: /* Map registers. */
213: sc->sc_regs = mapiodev(ca->ca_ra.ra_reg, PX_REG_OFFSET, PX_REG_SIZE);
214:
215: /* Compute framebuffer size. */
216: freqstring = getpropstring(node, "freqcode");
217: freqcode = (int)*freqstring;
218: if (freqcode == 'g') {
219: width = height = 1024;
220: } else {
221: if (freqcode < '1' || freqcode > NFREQCODE + '0')
222: freqcode = 0;
223: else
224: freqcode -= '1';
225: width = defwidth[freqcode];
226: height = defheight[freqcode];
227: }
228:
229: width = getpropint(node, "hres", width);
230: height = getpropint(node, "vres", height);
231:
232: /*
233: * Since the depth property is usually missing, we could do
234: * fb_setsize(&sc->sc_sunfb, 8, width, height, node, ca->ca_bustype);
235: * but for safety in case it would exist and be set to 32, do it
236: * manually...
237: */
238: sc->sc_sunfb.sf_depth = 8;
239: sc->sc_sunfb.sf_width = width;
240: sc->sc_sunfb.sf_height = height;
241: sc->sc_sunfb.sf_linebytes = width >= 1024 ? width : 1024;
242: sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_linebytes * height;
243:
244: /* Map the frame buffer memory area we're interested in. */
245: sc->sc_phys = ca->ca_ra.ra_reg[0];
246: sc->sc_m8 = mapiodev(ca->ca_ra.ra_reg,
247: PX_PLANE8_OFFSET, round_page(sc->sc_sunfb.sf_fbsize));
248: sc->sc_m24 = mapiodev(ca->ca_ra.ra_reg,
249: PX_PLANE24_OFFSET, round_page(4 * sc->sc_sunfb.sf_fbsize));
250:
251: /* Enable video. */
252: tvtwo_burner(sc, 1, 0);
253:
254: sc->sc_sunfb.sf_ro.ri_hw = sc;
255: sc->sc_sunfb.sf_ro.ri_bits = (u_char *)sc->sc_m8;
256:
257: /*
258: * If the framebuffer width is under 1024, we will switch from
259: * the PROM font to the more adequate 8x16 font here.
260: */
261: fbwscons_init(&sc->sc_sunfb,
262: isconsole && (width >= 1024) ? RI_CLEARMARGINS : RI_CLEAR);
263: fbwscons_setcolormap(&sc->sc_sunfb, tvtwo_setcolor);
264:
265: if (isconsole) {
266: fbwscons_console_init(&sc->sc_sunfb,
267: width >= 1024 ? -1 : 0);
268: }
269:
270: printf("%s: %dx%d\n", self->dv_xname,
271: sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
272:
273: fbwscons_attach(&sc->sc_sunfb, &tvtwo_accessops, isconsole);
274: }
275:
276: int
277: tvtwo_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
278: {
279: struct tvtwo_softc *sc = dev;
280: struct wsdisplay_fbinfo *wdf;
281:
282: /*
283: * Note that, although the emulation (text) mode is running in a
284: * 8-bit plane, we advertize the frame buffer as 32-bit.
285: */
286: switch (cmd) {
287: case WSDISPLAYIO_GTYPE:
288: *(u_int *)data = WSDISPLAY_TYPE_SUN24;
289: break;
290: case WSDISPLAYIO_GINFO:
291: wdf = (struct wsdisplay_fbinfo *)data;
292: wdf->height = sc->sc_sunfb.sf_height;
293: wdf->width = sc->sc_sunfb.sf_width;
294: wdf->depth = 32;
295: wdf->cmsize = 0;
296: break;
297: case WSDISPLAYIO_GETSUPPORTEDDEPTH:
298: *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
299: break;
300: case WSDISPLAYIO_LINEBYTES:
301: *(u_int *)data = sc->sc_sunfb.sf_linebytes * 4;
302: break;
303:
304: case WSDISPLAYIO_GETCMAP:
305: case WSDISPLAYIO_PUTCMAP:
306: break;
307:
308: case WSDISPLAYIO_SMODE:
309: if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
310: /* Back from X11 to text mode */
311: tvtwo_reset(sc, 8);
312: } else {
313: /* Starting X11, initialize 32-bit mode */
314: tvtwo_reset(sc, 32);
315: }
316: break;
317:
318: case WSDISPLAYIO_SVIDEO:
319: case WSDISPLAYIO_GVIDEO:
320: break;
321:
322: case WSDISPLAYIO_GCURPOS:
323: case WSDISPLAYIO_SCURPOS:
324: case WSDISPLAYIO_GCURMAX:
325: case WSDISPLAYIO_GCURSOR:
326: case WSDISPLAYIO_SCURSOR:
327: default:
328: return (-1);
329: }
330:
331: return (0);
332: }
333:
334: paddr_t
335: tvtwo_mmap(void *v, off_t offset, int prot)
336: {
337: struct tvtwo_softc *sc = v;
338:
339: if (offset & PGOFSET)
340: return (-1);
341:
342: /* Allow mapping as a dumb framebuffer from offset 0 */
343: if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize * 4) {
344: return (REG2PHYS(&sc->sc_phys,
345: PX_PLANE24_OFFSET + offset) | PMAP_NC);
346: }
347:
348: return (-1);
349: }
350:
351: void
352: tvtwo_burner(void *v, u_int on, u_int flags)
353: {
354: struct tvtwo_softc *sc = v;
355: u_int32_t dispkludge;
356:
357: if (on)
358: dispkludge = DISPKLUDGE_DEFAULT & ~DISPKLUDGE_BLANK;
359: else {
360: dispkludge = DISPKLUDGE_DEFAULT | DISPKLUDGE_BLANK;
361: if (flags & WSDISPLAY_BURN_VBLANK)
362: dispkludge |= DISPKLUDGE_SYNC;
363: }
364:
365: *(volatile u_int32_t *)(sc->sc_regs + PX_REG_DISPKLUDGE) =
366: dispkludge;
367: }
368:
369: void
370: tvtwo_reset(struct tvtwo_softc *sc, u_int depth)
371: {
372: if (depth == 32) {
373: /* Initialize a direct color map. */
374: tvtwo_directcmap(sc);
375: } else {
376: fbwscons_setcolormap(&sc->sc_sunfb, tvtwo_setcolor);
377: }
378: }
379:
380: /*
381: * Simple Bt463 programming routines.
382: */
383:
384: static __inline__ void
385: tvtwo_ramdac_wraddr(struct tvtwo_softc *sc, u_int32_t addr)
386: {
387: volatile u_int32_t *dac = (u_int32_t *)(sc->sc_regs + PX_REG_BT463_RED);
388:
389: dac[0] = (addr & 0xff); /* lo addr */
390: dac[1] = ((addr >> 8) & 0xff); /* hi addr */
391: }
392:
393: void
394: tvtwo_directcmap(struct tvtwo_softc *sc)
395: {
396: volatile u_int32_t *dac = (u_int32_t *)(sc->sc_regs + PX_REG_BT463_RED);
397: u_int32_t c;
398:
399: tvtwo_ramdac_wraddr(sc, 0);
400: for (c = 0; c < 256; c++) {
401: dac[3] = c; /* R */
402: dac[3] = c; /* G */
403: dac[3] = c; /* B */
404: }
405: }
406:
407: void
408: tvtwo_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
409: {
410: struct tvtwo_softc *sc = v;
411: volatile u_int32_t *dac = (u_int32_t *)(sc->sc_regs + PX_REG_BT463_RED);
412:
413: tvtwo_ramdac_wraddr(sc, index);
414: dac[3] = r;
415: dac[3] = g;
416: dac[3] = b;
417: }
CVSweb