This source file includes following definitions.
- tvtwomatch
- tvtwoattach
- tvtwo_ioctl
- tvtwo_mmap
- tvtwo_alloc_screen
- tvtwo_free_screen
- tvtwo_show_screen
- tvtwo_burner
- tvtwo_reset
- tvtwo_ramdac_wraddr
- tvtwo_directcmap
- tvtwo_setcolor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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/bus.h>
63 #include <machine/pmap.h>
64 #include <machine/cpu.h>
65 #include <machine/conf.h>
66
67 #include <dev/wscons/wsconsio.h>
68 #include <dev/wscons/wsdisplayvar.h>
69 #include <dev/rasops/rasops.h>
70 #include <machine/fbvar.h>
71
72 #include <dev/sbus/sbusvar.h>
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 #define PX_PROM0_OFFSET 0x000000
97 #define PX_OVERLAY_OFFSET 0x010000
98 #define PX_REG_OFFSET 0x040000
99 #define PX_CCUBE_OFFSET 0x050000
100 #define PX_PLANE8_OFFSET 0x080000
101 #define PX_PLANE24_OFFSET 0x200000
102 #define PX_PROM1_OFFSET 0x7f0000
103
104
105
106
107
108 #define PX_REG_DISPKLUDGE 0x00b8
109 #define DISPKLUDGE_DEFAULT 0xc41f
110 #define DISPKLUDGE_BLANK (1 << 12)
111 #define DISPKLUDGE_SYNC (1 << 13)
112
113 #define PX_REG_BT463_RED 0x0480
114 #define PX_REG_BT463_GREEN 0x0490
115 #define PX_REG_BT463_BLUE 0x04a0
116 #define PX_REG_BT463_ALL 0x04b0
117
118 #define PX_REG_SIZE 0x04d0
119
120
121
122 struct tvtwo_softc {
123 struct sunfb sc_sunfb;
124
125 bus_space_tag_t sc_bustag;
126 bus_addr_t sc_paddr;
127
128 volatile u_int8_t *sc_m8;
129 volatile u_int8_t *sc_m24;
130 volatile u_int8_t *sc_regs;
131
132 int sc_nscreens;
133 };
134
135 int tvtwo_ioctl(void *, u_long, caddr_t, int, struct proc *);
136 int tvtwo_alloc_screen(void *, const struct wsscreen_descr *, void **,
137 int *, int *, long *);
138 void tvtwo_free_screen(void *, void *);
139 int tvtwo_show_screen(void *, void *, int, void (*cb)(void *, int, int),
140 void *);
141 paddr_t tvtwo_mmap(void *, off_t, int);
142 void tvtwo_burner(void *, u_int, u_int);
143
144 struct wsdisplay_accessops tvtwo_accessops = {
145 tvtwo_ioctl,
146 tvtwo_mmap,
147 tvtwo_alloc_screen,
148 tvtwo_free_screen,
149 tvtwo_show_screen,
150 NULL,
151 NULL,
152 NULL,
153 tvtwo_burner,
154 };
155
156 void tvtwo_directcmap(struct tvtwo_softc *);
157 static __inline__
158 void tvtwo_ramdac_wraddr(struct tvtwo_softc *, u_int32_t);
159 void tvtwo_reset(struct tvtwo_softc *, u_int);
160 void tvtwo_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
161
162 int tvtwomatch(struct device *, void *, void *);
163 void tvtwoattach(struct device *, struct device *, void *);
164
165 struct cfattach tvtwo_ca = {
166 sizeof(struct tvtwo_softc), tvtwomatch, tvtwoattach
167 };
168
169 struct cfdriver tvtwo_cd = {
170 NULL, "tvtwo", DV_DULL
171 };
172
173
174
175
176 #define NFREQCODE 5
177 const int defwidth[NFREQCODE] = { 1152, 1152, 1152, 1024, 640 };
178 const int defheight[NFREQCODE] = { 900, 900, 900, 768, 480 };
179
180
181
182
183 int
184 tvtwomatch(struct device *parent, void *vcf, void *aux)
185 {
186 struct sbus_attach_args *sa = aux;
187
188 if (strcmp(sa->sa_name, "PGI,tvtwo") == 0 ||
189 strcmp(sa->sa_name, "PGI,tvthree") == 0)
190 return (1);
191
192 return (0);
193 }
194
195
196
197
198 void
199 tvtwoattach(struct device *parent, struct device *self, void *args)
200 {
201 struct tvtwo_softc *sc = (struct tvtwo_softc *)self;
202 struct sbus_attach_args *sa = args;
203 bus_space_tag_t bt;
204 bus_space_handle_t bh;
205 int node, width, height, freqcode;
206 int isconsole;
207 char *freqstring;
208
209 bt = sa->sa_bustag;
210 node = sa->sa_node;
211
212 printf(": %s", getpropstring(node, "model"));
213 printf(", revision %s\n", getpropstring(node, "revision"));
214
215
216 if (sa->sa_nreg != 1) {
217 printf("%s: old-style boards with %d registers are not supported\n"
218 "%s: please report this to <sparc@openbsd.org>\n",
219 self->dv_xname, sa->sa_nreg,
220 self->dv_xname);
221 return;
222 }
223
224 isconsole = node == fbnode;
225
226
227 sc->sc_bustag = bt;
228 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + PX_REG_OFFSET,
229 PX_REG_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
230 printf("%s: couldn't map registers\n", self->dv_xname);
231 return;
232 }
233 sc->sc_regs = bus_space_vaddr(bt, bh);
234
235
236 freqstring = getpropstring(node, "freqcode");
237 freqcode = (int)*freqstring;
238 if (freqcode == 'g') {
239 width = height = 1024;
240 } else {
241 if (freqcode < '1' || freqcode > '6')
242 freqcode = 0;
243 else
244 freqcode -= '1';
245 width = defwidth[freqcode];
246 height = defheight[freqcode];
247 }
248
249 width = getpropint(node, "hres", width);
250 height = getpropint(node, "vres", height);
251
252
253
254
255
256
257
258 sc->sc_sunfb.sf_depth = 8;
259 sc->sc_sunfb.sf_width = width;
260 sc->sc_sunfb.sf_height = height;
261 sc->sc_sunfb.sf_linebytes = width >= 1024 ? width : 1024;
262 sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_linebytes * height;
263
264
265 sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);
266 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + PX_PLANE8_OFFSET,
267 round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR, 0,
268 &bh) != 0) {
269 printf("%s: couldn't map 8-bit video plane\n", self->dv_xname);
270 return;
271 }
272 sc->sc_m8 = bus_space_vaddr(bt, bh);
273 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + PX_PLANE24_OFFSET,
274 round_page(4 * sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR, 0,
275 &bh) != 0) {
276 printf("%s: couldn't map 32-bit video plane\n", self->dv_xname);
277 return;
278 }
279 sc->sc_m24 = bus_space_vaddr(bt, bh);
280
281
282 tvtwo_burner(sc, 1, 0);
283
284 sc->sc_sunfb.sf_ro.ri_hw = sc;
285 sc->sc_sunfb.sf_ro.ri_bits = (u_char *)sc->sc_m8;
286
287
288
289
290
291 fbwscons_init(&sc->sc_sunfb,
292 isconsole && (width >= 1024) ? RI_CLEARMARGINS : RI_CLEAR);
293 fbwscons_setcolormap(&sc->sc_sunfb, tvtwo_setcolor);
294
295 if (isconsole) {
296 fbwscons_console_init(&sc->sc_sunfb,
297 width >= 1024 ? -1 : 0);
298 }
299
300 printf("%s: %dx%d\n", self->dv_xname,
301 sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
302
303 fbwscons_attach(&sc->sc_sunfb, &tvtwo_accessops, isconsole);
304 }
305
306 int
307 tvtwo_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
308 {
309 struct tvtwo_softc *sc = dev;
310 struct wsdisplay_fbinfo *wdf;
311
312
313
314
315
316 switch (cmd) {
317 case WSDISPLAYIO_GTYPE:
318 *(u_int *)data = WSDISPLAY_TYPE_SUN24;
319 break;
320 case WSDISPLAYIO_GINFO:
321 wdf = (struct wsdisplay_fbinfo *)data;
322 wdf->height = sc->sc_sunfb.sf_height;
323 wdf->width = sc->sc_sunfb.sf_width;
324 wdf->depth = 32;
325 wdf->cmsize = 0;
326 break;
327 case WSDISPLAYIO_GETSUPPORTEDDEPTH:
328 *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
329 break;
330 case WSDISPLAYIO_LINEBYTES:
331 *(u_int *)data = sc->sc_sunfb.sf_linebytes * 4;
332 break;
333
334 case WSDISPLAYIO_GETCMAP:
335 case WSDISPLAYIO_PUTCMAP:
336 break;
337
338 case WSDISPLAYIO_SMODE:
339 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
340
341 tvtwo_reset(sc, 8);
342 } else {
343
344 tvtwo_reset(sc, 32);
345 }
346 break;
347
348 case WSDISPLAYIO_SVIDEO:
349 case WSDISPLAYIO_GVIDEO:
350 break;
351
352 case WSDISPLAYIO_GCURPOS:
353 case WSDISPLAYIO_SCURPOS:
354 case WSDISPLAYIO_GCURMAX:
355 case WSDISPLAYIO_GCURSOR:
356 case WSDISPLAYIO_SCURSOR:
357 default:
358 return (-1);
359 }
360
361 return (0);
362 }
363
364
365
366
367
368 paddr_t
369 tvtwo_mmap(void *v, off_t offset, int prot)
370 {
371 struct tvtwo_softc *sc = v;
372
373 if (offset & PGOFSET)
374 return (-1);
375
376
377 if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize * 4) {
378 return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
379 PX_PLANE24_OFFSET + offset, prot, BUS_SPACE_MAP_LINEAR));
380 }
381
382 return (-1);
383 }
384
385 int
386 tvtwo_alloc_screen(void *v, const struct wsscreen_descr *type,
387 void **cookiep, int *curxp, int *curyp, long *attrp)
388 {
389 struct tvtwo_softc *sc = v;
390
391 if (sc->sc_nscreens > 0)
392 return (ENOMEM);
393
394 *cookiep = &sc->sc_sunfb.sf_ro;
395 *curyp = 0;
396 *curxp = 0;
397 sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro,
398 0, 0, 0, attrp);
399 sc->sc_nscreens++;
400 return (0);
401 }
402
403 void
404 tvtwo_free_screen(void *v, void *cookie)
405 {
406 struct tvtwo_softc *sc = v;
407
408 sc->sc_nscreens--;
409 }
410
411 int
412 tvtwo_show_screen(void *v, void *cookie, int waitok,
413 void (*cb)(void *, int, int), void *cbarg)
414 {
415 return (0);
416 }
417
418 void
419 tvtwo_burner(void *v, u_int on, u_int flags)
420 {
421 struct tvtwo_softc *sc = v;
422 u_int32_t dispkludge;
423
424 if (on)
425 dispkludge = DISPKLUDGE_DEFAULT & ~DISPKLUDGE_BLANK;
426 else {
427 dispkludge = DISPKLUDGE_DEFAULT | DISPKLUDGE_BLANK;
428 if (flags & WSDISPLAY_BURN_VBLANK)
429 dispkludge |= DISPKLUDGE_SYNC;
430 }
431
432 *(volatile u_int32_t *)(sc->sc_regs + PX_REG_DISPKLUDGE) =
433 dispkludge;
434 }
435
436 void
437 tvtwo_reset(struct tvtwo_softc *sc, u_int depth)
438 {
439 if (depth == 32) {
440
441 tvtwo_directcmap(sc);
442 } else {
443 fbwscons_setcolormap(&sc->sc_sunfb, tvtwo_setcolor);
444 }
445 }
446
447
448
449
450
451 static __inline__ void
452 tvtwo_ramdac_wraddr(struct tvtwo_softc *sc, u_int32_t addr)
453 {
454 volatile u_int32_t *dac = (u_int32_t *)(sc->sc_regs + PX_REG_BT463_RED);
455
456 dac[0] = (addr & 0xff);
457 dac[1] = ((addr >> 8) & 0xff);
458 }
459
460 void
461 tvtwo_directcmap(struct tvtwo_softc *sc)
462 {
463 volatile u_int32_t *dac = (u_int32_t *)(sc->sc_regs + PX_REG_BT463_RED);
464 u_int32_t c;
465
466 tvtwo_ramdac_wraddr(sc, 0);
467 for (c = 0; c < 256; c++) {
468 dac[3] = c;
469 dac[3] = c;
470 dac[3] = c;
471 }
472 }
473
474 void
475 tvtwo_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
476 {
477 struct tvtwo_softc *sc = v;
478 volatile u_int32_t *dac = (u_int32_t *)(sc->sc_regs + PX_REG_BT463_RED);
479
480 tvtwo_ramdac_wraddr(sc, index);
481 dac[3] = r;
482 dac[3] = g;
483 dac[3] = b;
484 }