1 /* $OpenBSD: cgthree.c,v 1.32 2006/12/03 16:38:13 miod Exp $ */
2 /* $NetBSD: cgthree.c,v 1.33 1997/05/24 20:16:11 pk Exp $ */
3
4 /*
5 * Copyright (c) 2002 Miodrag Vallat. All rights reserved.
6 * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Effort sponsored in part by the Defense Advanced Research Projects
31 * Agency (DARPA) and Air Force Research Laboratory, Air Force
32 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
33 *
34 *
35 * Copyright (c) 1992, 1993
36 * The Regents of the University of California. All rights reserved.
37 *
38 * This software was developed by the Computer Systems Engineering group
39 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
40 * contributed to Berkeley.
41 *
42 * All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed by the University of
45 * California, Lawrence Berkeley Laboratory.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * @(#)cgthree.c 8.2 (Berkeley) 10/30/93
72 */
73
74 /*
75 * Color display (cgthree) driver.
76 * Works with the real Sun hardware, as well as various clones from Tatung,
77 * Integrix (S20), and the Vigra VS10-EK.
78 */
79
80 #include <sys/param.h>
81 #include <sys/systm.h>
82 #include <sys/buf.h>
83 #include <sys/device.h>
84 #include <sys/ioctl.h>
85 #include <sys/malloc.h>
86 #include <sys/mman.h>
87 #include <sys/tty.h>
88 #include <sys/conf.h>
89
90 #include <uvm/uvm_extern.h>
91
92 #include <machine/autoconf.h>
93 #include <machine/pmap.h>
94 #include <machine/cpu.h>
95 #include <machine/conf.h>
96
97 #include <dev/wscons/wsconsio.h>
98 #include <dev/wscons/wsdisplayvar.h>
99 #include <dev/rasops/rasops.h>
100 #include <machine/fbvar.h>
101
102 #include <sparc/dev/btreg.h>
103 #include <sparc/dev/btvar.h>
104 #include <sparc/dev/cgthreereg.h>
105 #include <sparc/dev/sbusvar.h>
106
107 /* per-display variables */
108 struct cgthree_softc {
109 struct sunfb sc_sunfb; /* common base part */
110 struct rom_reg sc_phys; /* phys address description */
111 volatile struct fbcontrol *sc_fbc; /* Brooktree registers */
112 union bt_cmap sc_cmap; /* Brooktree color map */
113 struct intrhand sc_ih;
114 };
115
116 void cgthree_burner(void *, u_int, u_int);
117 int cgthree_intr(void *);
118 int cgthree_ioctl(void *, u_long, caddr_t, int, struct proc *);
119 static __inline__
120 void cgthree_loadcmap_deferred(struct cgthree_softc *, u_int, u_int);
121 paddr_t cgthree_mmap(void *, off_t, int);
122 void cgthree_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
123
124 struct wsdisplay_accessops cgthree_accessops = {
125 cgthree_ioctl,
126 cgthree_mmap,
127 NULL, /* alloc_screen */
128 NULL, /* free_screen */
129 NULL, /* show_screen */
130 NULL, /* load_font */
131 NULL, /* scrollback */
132 NULL, /* getchar */
133 cgthree_burner,
134 NULL /* pollc */
135 };
136
137 int cgthreematch(struct device *, void *, void *);
138 void cgthreeattach(struct device *, struct device *, void *);
139
140 struct cfattach cgthree_ca = {
141 sizeof (struct cgthree_softc), cgthreematch, cgthreeattach
142 };
143
144 struct cfdriver cgthree_cd = {
145 NULL, "cgthree", DV_DULL
146 };
147
148 /* Video control parameters */
149 struct cg3_videoctrl {
150 u_int8_t sense;
151 u_int8_t vctrl[12];
152 } cg3_videoctrl[] = {
153 { /* cpd-1790 */
154 0x31,
155 { 0xbb, 0x2b, 0x04, 0x14, 0xae, 0x03,
156 0xa8, 0x24, 0x01, 0x05, 0xff, 0x01 },
157 },
158 { /* gdm-20e20 */
159 0x41,
160 { 0xb7, 0x27, 0x03, 0x0f, 0xae, 0x03,
161 0xae, 0x2a, 0x01, 0x09, 0xff, 0x01 },
162 },
163 { /* defaults, should be last */
164 0xff,
165 { 0xbb, 0x2b, 0x03, 0x0b, 0xb3, 0x03,
166 0xaf, 0x2b, 0x02, 0x0a, 0xff, 0x01 },
167 },
168 };
169
170 int
cgthreematch(struct device * parent,void * vcf,void * aux)171 cgthreematch(struct device *parent, void *vcf, void *aux)
172 {
173 struct cfdata *cf = vcf;
174 struct confargs *ca = aux;
175 struct romaux *ra = &ca->ca_ra;
176
177 if (strcmp(cf->cf_driver->cd_name, ra->ra_name) &&
178 strcmp("cgRDI", ra->ra_name))
179 return (0);
180
181 if (ca->ca_bustype != BUS_SBUS)
182 return (0);
183
184 return (1);
185 }
186
187 void
cgthreeattach(struct device * parent,struct device * self,void * args)188 cgthreeattach(struct device *parent, struct device *self, void *args)
189 {
190 struct cgthree_softc *sc = (struct cgthree_softc *)self;
191 struct confargs *ca = args;
192 int node, isrdi = 0, i;
193 volatile struct bt_regs *bt;
194 int isconsole = 0;
195 char *nam;
196
197 printf(": ");
198
199 node = ca->ca_ra.ra_node;
200
201 if (strcmp(ca->ca_ra.ra_name, "cgRDI") == 0) {
202 isrdi = 1;
203 nam = "cgRDI";
204 } else
205 nam = getpropstring(node, "model");
206
207 if (nam != NULL && *nam != '\0')
208 printf("%s, ", nam);
209
210 isconsole = node == fbnode;
211
212 sc->sc_fbc = (volatile struct fbcontrol *)
213 mapiodev(ca->ca_ra.ra_reg, CG3REG_REG,
214 sizeof(struct fbcontrol));
215
216 /* Transfer video magic to board, if it's not running */
217 if (isrdi == 0 && (sc->sc_fbc->fbc_ctrl & FBC_TIMING) == 0)
218 for (i = 0; i < sizeof(cg3_videoctrl)/sizeof(cg3_videoctrl[0]);
219 i++) {
220 volatile struct fbcontrol *fbc = sc->sc_fbc;
221 if (cg3_videoctrl[i].sense == 0xff ||
222 (fbc->fbc_status & FBS_MSENSE) ==
223 cg3_videoctrl[i].sense) {
224 int j;
225 #ifdef DEBUG
226 printf(" (setting video ctrl)");
227 #endif
228 for (j = 0; j < 12; j++)
229 fbc->fbc_vcontrol[j] =
230 cg3_videoctrl[i].vctrl[j];
231 fbc->fbc_ctrl |= FBC_TIMING;
232 break;
233 }
234 }
235
236 sc->sc_phys = ca->ca_ra.ra_reg[0];
237
238 sc->sc_ih.ih_fun = cgthree_intr;
239 sc->sc_ih.ih_arg = sc;
240 intr_establish(ca->ca_ra.ra_intr[0].int_pri, &sc->sc_ih, IPL_FB);
241
242 /* enable video */
243 cgthree_burner(sc, 1, 0);
244 bt = &sc->sc_fbc->fbc_dac;
245 BT_INIT(bt, 0);
246
247 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
248 sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg, CG3REG_MEM,
249 round_page(sc->sc_sunfb.sf_fbsize));
250 sc->sc_sunfb.sf_ro.ri_hw = sc;
251
252 printf("%dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
253
254 /*
255 * If the framebuffer width is under 1024x768, which is the case for
256 * some clones on laptops, as well as with the VS10-EK, switch from
257 * the PROM font to the more adequate 8x16 font here.
258 * However, we need to adjust two things in this case:
259 * - the display row should be overrided from the current PROM metrics,
260 * to prevent us from overwriting the last few lines of text.
261 * - if the 80x34 screen would make a large margin appear around it,
262 * choose to clear the screen rather than keeping old prom output in
263 * the margins.
264 * XXX there should be a rasops "clear margins" feature
265 */
266 fbwscons_init(&sc->sc_sunfb, isconsole &&
267 (sc->sc_sunfb.sf_width >= 1024) ? 0 : RI_CLEAR);
268 fbwscons_setcolormap(&sc->sc_sunfb, cgthree_setcolor);
269
270 if (isconsole) {
271 fbwscons_console_init(&sc->sc_sunfb,
272 sc->sc_sunfb.sf_width >= 1024 ? -1 : 0);
273 }
274
275 fbwscons_attach(&sc->sc_sunfb, &cgthree_accessops, isconsole);
276 }
277
278 int
cgthree_ioctl(void * v,u_long cmd,caddr_t data,int flags,struct proc * p)279 cgthree_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
280 {
281 struct cgthree_softc *sc = v;
282 struct wsdisplay_fbinfo *wdf;
283 struct wsdisplay_cmap *cm;
284 int error;
285
286 switch (cmd) {
287 case WSDISPLAYIO_GTYPE:
288 *(u_int *)data = WSDISPLAY_TYPE_SUNCG3;
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 = sc->sc_sunfb.sf_depth;
295 wdf->cmsize = 256;
296 break;
297 case WSDISPLAYIO_LINEBYTES:
298 *(u_int *)data = sc->sc_sunfb.sf_linebytes;
299 break;
300
301 case WSDISPLAYIO_GETCMAP:
302 cm = (struct wsdisplay_cmap *)data;
303 error = bt_getcmap(&sc->sc_cmap, cm);
304 if (error)
305 return (error);
306 break;
307
308 case WSDISPLAYIO_PUTCMAP:
309 cm = (struct wsdisplay_cmap *)data;
310 error = bt_putcmap(&sc->sc_cmap, cm);
311 if (error)
312 return (error);
313 cgthree_loadcmap_deferred(sc, cm->index, cm->count);
314 break;
315
316 case WSDISPLAYIO_SVIDEO:
317 case WSDISPLAYIO_GVIDEO:
318 break;
319
320 case WSDISPLAYIO_GCURPOS:
321 case WSDISPLAYIO_SCURPOS:
322 case WSDISPLAYIO_GCURMAX:
323 case WSDISPLAYIO_GCURSOR:
324 case WSDISPLAYIO_SCURSOR:
325 default:
326 return (-1); /* not supported yet */
327 }
328
329 return (0);
330 }
331
332 paddr_t
cgthree_mmap(void * v,off_t offset,int prot)333 cgthree_mmap(void *v, off_t offset, int prot)
334 {
335 struct cgthree_softc *sc = v;
336
337 if (offset & PGOFSET)
338 return (-1);
339
340 if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
341 return (REG2PHYS(&sc->sc_phys,
342 CG3REG_MEM + offset) | PMAP_NC);
343 }
344
345 return (-1);
346 }
347
348 void
cgthree_setcolor(void * v,u_int index,u_int8_t r,u_int8_t g,u_int8_t b)349 cgthree_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
350 {
351 struct cgthree_softc *sc = v;
352
353 bt_setcolor(&sc->sc_cmap, &sc->sc_fbc->fbc_dac, index, r, g, b, 0);
354 }
355
356 static __inline__ void
cgthree_loadcmap_deferred(struct cgthree_softc * sc,u_int start,u_int ncolors)357 cgthree_loadcmap_deferred(struct cgthree_softc *sc, u_int start, u_int ncolors)
358 {
359
360 sc->sc_fbc->fbc_ctrl |= FBC_IENAB;
361 }
362
363 void
cgthree_burner(void * v,u_int on,u_int flags)364 cgthree_burner(void *v, u_int on, u_int flags)
365 {
366 struct cgthree_softc *sc = v;
367 int s;
368
369 s = splhigh();
370 if (on)
371 sc->sc_fbc->fbc_ctrl |= FBC_VENAB | FBC_TIMING;
372 else {
373 sc->sc_fbc->fbc_ctrl &= ~FBC_VENAB;
374 if (flags & WSDISPLAY_BURN_VBLANK)
375 sc->sc_fbc->fbc_ctrl &= ~FBC_TIMING;
376 }
377 splx(s);
378 }
379
380 int
cgthree_intr(void * v)381 cgthree_intr(void *v)
382 {
383 struct cgthree_softc *sc = v;
384
385 if (!ISSET(sc->sc_fbc->fbc_ctrl, FBC_IENAB) ||
386 !ISSET(sc->sc_fbc->fbc_status, FBS_INTR)) {
387 /* Not expecting an interrupt, it's not for us. */
388 return (0);
389 }
390
391 /* Acknowledge the interrupt and disable it. */
392 sc->sc_fbc->fbc_ctrl &= ~FBC_IENAB;
393
394 bt_loadcmap(&sc->sc_cmap, &sc->sc_fbc->fbc_dac, 0, 256, 0);
395 return (1);
396 }
397