This source file includes following definitions.
- cgthreematch
- cgthreeattach
- cgthree_ioctl
- cgthree_alloc_screen
- cgthree_free_screen
- cgthree_show_screen
- cgthree_mmap
- cgthree_is_console
- cgthree_setcolor
- cgthree_loadcmap
- cg3_bt_getcmap
- cg3_bt_putcmap
- cgthree_reset
- cgthree_burner
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 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/errno.h>
38 #include <sys/device.h>
39 #include <sys/ioctl.h>
40 #include <sys/malloc.h>
41
42 #include <machine/bus.h>
43 #include <machine/intr.h>
44 #include <machine/autoconf.h>
45 #include <machine/openfirm.h>
46
47 #include <dev/sbus/sbusvar.h>
48 #include <dev/wscons/wsconsio.h>
49 #include <dev/wscons/wsdisplayvar.h>
50 #include <dev/rasops/rasops.h>
51 #include <machine/fbvar.h>
52
53 #include <dev/ic/bt458reg.h>
54
55 #define CGTHREE_CTRL_OFFSET 0x400000
56 #define CGTHREE_CTRL_SIZE (sizeof(u_int32_t) * 8)
57 #define CGTHREE_VID_OFFSET 0x800000
58 #define CGTHREE_VID_SIZE (1024 * 1024)
59
60 union bt_cmap {
61 u_int8_t cm_map[256][3];
62 u_int32_t cm_chip[256 * 3 / 4];
63 };
64
65 #define BT_ADDR 0x00
66 #define BT_CMAP 0x04
67 #define BT_CTRL 0x08
68 #define BT_OMAP 0x0c
69 #define CG3_FBC_CTRL 0x10
70 #define CG3_FBC_STAT 0x11
71 #define CG3_FBC_START 0x12
72 #define CG3_FBC_END 0x13
73 #define CG3_FBC_VCTRL 0x14
74
75 #define BT_WRITE(sc, reg, val) \
76 bus_space_write_4((sc)->sc_bustag, (sc)->sc_ctrl_regs, (reg), (val))
77 #define BT_READ(sc, reg) \
78 bus_space_read_4((sc)->sc_bustag, (sc)->sc_ctrl_regs, (reg))
79 #define BT_BARRIER(sc,reg,flags) \
80 bus_space_barrier((sc)->sc_bustag, (sc)->sc_ctrl_regs, (reg), \
81 sizeof(u_int32_t), (flags))
82
83 #define BT_D4M3(x) ((((x) >> 2) << 1) + ((x) >> 2))
84 #define BT_D4M4(x) ((x) & ~3)
85
86 #define FBC_CTRL_IENAB 0x80
87 #define FBC_CTRL_VENAB 0x40
88 #define FBC_CTRL_TIME 0x20
89 #define FBC_CTRL_CURS 0x10
90 #define FBC_CTRL_XTAL 0x0c
91 #define FBC_CTRL_XTAL_0 0x00
92 #define FBC_CTRL_XTAL_1 0x04
93 #define FBC_CTRL_XTAL_2 0x08
94 #define FBC_CTRL_XTAL_TEST 0x0c
95 #define FBC_CTRL_DIV 0x03
96 #define FBC_CTRL_DIV_1 0x00
97 #define FBC_CTRL_DIV_2 0x01
98 #define FBC_CTRL_DIV_3 0x02
99 #define FBC_CTRL_DIV_4 0x03
100
101 #define FBC_STAT_INTR 0x80
102 #define FBC_STAT_RES 0x70
103 #define FBC_STAT_RES_1024 0x10
104 #define FBC_STAT_RES_1280 0x40
105 #define FBC_STAT_RES_1152 0x30
106 #define FBC_STAT_RES_1152A 0x40
107 #define FBC_STAT_RES_1600 0x50
108 #define FBC_STAT_RES_1152B 0x60
109 #define FBC_STAT_ID 0x0f
110 #define FBC_STAT_ID_COLOR 0x01
111 #define FBC_STAT_ID_MONO 0x02
112 #define FBC_STAT_ID_MONOECL 0x03
113
114 #define FBC_READ(sc, reg) \
115 bus_space_read_1((sc)->sc_bustag, (sc)->sc_ctrl_regs, (reg))
116 #define FBC_WRITE(sc, reg, val) \
117 bus_space_write_1((sc)->sc_bustag, (sc)->sc_ctrl_regs, (reg), (val))
118
119 struct cgthree_softc {
120 struct sunfb sc_sunfb;
121 bus_space_tag_t sc_bustag;
122 bus_addr_t sc_paddr;
123 bus_space_handle_t sc_ctrl_regs;
124 bus_space_handle_t sc_vid_regs;
125 int sc_nscreens;
126 union bt_cmap sc_cmap;
127 u_int sc_mode;
128 };
129
130 int cgthree_ioctl(void *, u_long, caddr_t, int, struct proc *);
131 int cgthree_alloc_screen(void *, const struct wsscreen_descr *, void **,
132 int *, int *, long *);
133 void cgthree_free_screen(void *, void *);
134 int cgthree_show_screen(void *, void *, int, void (*cb)(void *, int, int),
135 void *);
136 paddr_t cgthree_mmap(void *, off_t, int);
137 int cgthree_is_console(int);
138 void cgthree_loadcmap(struct cgthree_softc *, u_int, u_int);
139 int cg3_bt_putcmap(union bt_cmap *, struct wsdisplay_cmap *);
140 int cg3_bt_getcmap(union bt_cmap *, struct wsdisplay_cmap *);
141 void cgthree_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
142 void cgthree_burner(void *, u_int, u_int);
143 void cgthree_reset(struct cgthree_softc *);
144
145 struct wsdisplay_accessops cgthree_accessops = {
146 cgthree_ioctl,
147 cgthree_mmap,
148 cgthree_alloc_screen,
149 cgthree_free_screen,
150 cgthree_show_screen,
151 NULL,
152 NULL,
153 NULL,
154 cgthree_burner,
155 };
156
157 int cgthreematch(struct device *, void *, void *);
158 void cgthreeattach(struct device *, struct device *, void *);
159
160 struct cfattach cgthree_ca = {
161 sizeof (struct cgthree_softc), cgthreematch, cgthreeattach
162 };
163
164 struct cfdriver cgthree_cd = {
165 NULL, "cgthree", DV_DULL
166 };
167
168 #define CG3_TYPE_DEFAULT 0
169 #define CG3_TYPE_76HZ 1
170 #define CG3_TYPE_SMALL 2
171
172 struct cg3_videoctrl {
173 u_int8_t sense;
174 u_int8_t vctrl[12];
175 u_int8_t ctrl;
176 } cg3_videoctrl[] = {
177 {
178 0x31,
179 { 0xbb, 0x2b, 0x04, 0x14, 0xae, 0x03,
180 0xa8, 0x24, 0x01, 0x05, 0xff, 0x01 },
181 FBC_CTRL_XTAL_0 | FBC_CTRL_DIV_1
182 },
183 {
184 0x41,
185 { 0xb7, 0x27, 0x03, 0x0f, 0xae, 0x03,
186 0xae, 0x2a, 0x01, 0x09, 0xff, 0x01 },
187 FBC_CTRL_XTAL_1 | FBC_CTRL_DIV_1
188 },
189 {
190 0xff,
191 { 0xbb, 0x2b, 0x03, 0x0b, 0xb3, 0x03,
192 0xaf, 0x2b, 0x02, 0x0a, 0xff, 0x01 },
193 0,
194 },
195 };
196
197 int
198 cgthreematch(struct device *parent, void *vcf, void *aux)
199 {
200 struct cfdata *cf = vcf;
201 struct sbus_attach_args *sa = aux;
202
203 return (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0);
204 }
205
206 void
207 cgthreeattach(struct device *parent, struct device *self, void *aux)
208 {
209 struct cgthree_softc *sc = (struct cgthree_softc *)self;
210 struct sbus_attach_args *sa = aux;
211 int node, console;
212 const char *nam;
213
214 node = sa->sa_node;
215 sc->sc_bustag = sa->sa_bustag;
216 sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset);
217
218 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
219
220 if (sa->sa_nreg != 1) {
221 printf(": expected %d registers, got %d\n", 1, sa->sa_nreg);
222 goto fail;
223 }
224
225
226
227
228 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
229 sa->sa_reg[0].sbr_offset + CGTHREE_CTRL_OFFSET,
230 CGTHREE_CTRL_SIZE, 0, 0, &sc->sc_ctrl_regs) != 0) {
231 printf(": cannot map ctrl registers\n");
232 goto fail_ctrl;
233 }
234
235 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
236 sa->sa_reg[0].sbr_offset + CGTHREE_VID_OFFSET,
237 sc->sc_sunfb.sf_fbsize, BUS_SPACE_MAP_LINEAR,
238 0, &sc->sc_vid_regs) != 0) {
239 printf(": cannot map vid registers\n");
240 goto fail_vid;
241 }
242
243 nam = getpropstring(node, "model");
244 if (*nam == '\0')
245 nam = sa->sa_name;
246 printf(": %s", nam);
247
248 console = cgthree_is_console(node);
249
250 cgthree_reset(sc);
251 cgthree_burner(sc, 1, 0);
252
253 sc->sc_sunfb.sf_ro.ri_bits = (void *)bus_space_vaddr(sc->sc_bustag,
254 sc->sc_vid_regs);
255 sc->sc_sunfb.sf_ro.ri_hw = sc;
256
257 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
258
259
260
261
262
263
264
265
266
267
268
269
270
271 fbwscons_init(&sc->sc_sunfb, console &&
272 (sc->sc_sunfb.sf_width >= 1024) ? 0 : RI_CLEAR);
273
274 fbwscons_setcolormap(&sc->sc_sunfb, cgthree_setcolor);
275
276 if (console) {
277 fbwscons_console_init(&sc->sc_sunfb,
278 sc->sc_sunfb.sf_width >= 1024 ? -1 : 0);
279 }
280
281 fbwscons_attach(&sc->sc_sunfb, &cgthree_accessops, console);
282
283 return;
284
285 fail_vid:
286 bus_space_unmap(sa->sa_bustag, sc->sc_ctrl_regs, CGTHREE_CTRL_SIZE);
287 fail_ctrl:
288 fail:
289 ;
290 }
291
292 int
293 cgthree_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
294 {
295 struct cgthree_softc *sc = v;
296 struct wsdisplay_fbinfo *wdf;
297 struct wsdisplay_cmap *cm;
298 int error;
299
300 switch (cmd) {
301 case WSDISPLAYIO_GTYPE:
302 *(u_int *)data = WSDISPLAY_TYPE_SUNCG3;
303 break;
304 case WSDISPLAYIO_SMODE:
305 sc->sc_mode = *(u_int *)data;
306 break;
307 case WSDISPLAYIO_GINFO:
308 wdf = (void *)data;
309 wdf->height = sc->sc_sunfb.sf_height;
310 wdf->width = sc->sc_sunfb.sf_width;
311 wdf->depth = sc->sc_sunfb.sf_depth;
312 wdf->cmsize = 256;
313 break;
314 case WSDISPLAYIO_LINEBYTES:
315 *(u_int *)data = sc->sc_sunfb.sf_linebytes;
316 break;
317
318 case WSDISPLAYIO_GETCMAP:
319 cm = (struct wsdisplay_cmap *)data;
320 error = cg3_bt_getcmap(&sc->sc_cmap, cm);
321 if (error)
322 return (error);
323 break;
324
325 case WSDISPLAYIO_PUTCMAP:
326 cm = (struct wsdisplay_cmap *)data;
327 error = cg3_bt_putcmap(&sc->sc_cmap, cm);
328 if (error)
329 return (error);
330 cgthree_loadcmap(sc, cm->index, cm->count);
331 break;
332
333 case WSDISPLAYIO_SVIDEO:
334 case WSDISPLAYIO_GVIDEO:
335 break;
336
337 case WSDISPLAYIO_GCURPOS:
338 case WSDISPLAYIO_SCURPOS:
339 case WSDISPLAYIO_GCURMAX:
340 case WSDISPLAYIO_GCURSOR:
341 case WSDISPLAYIO_SCURSOR:
342 default:
343 return -1;
344 }
345
346 return (0);
347 }
348
349 int
350 cgthree_alloc_screen(void *v, const struct wsscreen_descr *type,
351 void **cookiep, int *curxp, int *curyp, long *attrp)
352 {
353 struct cgthree_softc *sc = v;
354
355 if (sc->sc_nscreens > 0)
356 return (ENOMEM);
357
358 *cookiep = &sc->sc_sunfb.sf_ro;
359 *curyp = 0;
360 *curxp = 0;
361 sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro,
362 WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp);
363 sc->sc_nscreens++;
364 return (0);
365 }
366
367 void
368 cgthree_free_screen(void *v, void *cookie)
369 {
370 struct cgthree_softc *sc = v;
371
372 sc->sc_nscreens--;
373 }
374
375 int
376 cgthree_show_screen(void *v, void *cookie, int waitok,
377 void (*cb)(void *, int, int), void *cbarg)
378 {
379 return (0);
380 }
381
382 #define START (128 * 1024 + 128 * 1024)
383 #define NOOVERLAY (0x04000000)
384
385 paddr_t
386 cgthree_mmap(void *v, off_t offset, int prot)
387 {
388 struct cgthree_softc *sc = v;
389
390 if (offset & PGOFSET || offset < 0)
391 return (-1);
392
393 switch (sc->sc_mode) {
394 case WSDISPLAYIO_MODE_MAPPED:
395 if (offset >= NOOVERLAY)
396 offset -= NOOVERLAY;
397 else if (offset >= START)
398 offset -= START;
399 else
400 offset = 0;
401 if (offset >= sc->sc_sunfb.sf_fbsize)
402 return (-1);
403 return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
404 CGTHREE_VID_OFFSET + offset, prot, BUS_SPACE_MAP_LINEAR));
405 case WSDISPLAYIO_MODE_DUMBFB:
406 if (offset < sc->sc_sunfb.sf_fbsize)
407 return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
408 CGTHREE_VID_OFFSET + offset, prot,
409 BUS_SPACE_MAP_LINEAR));
410 break;
411 }
412 return (-1);
413 }
414
415 int
416 cgthree_is_console(int node)
417 {
418 extern int fbnode;
419
420 return (fbnode == node);
421 }
422
423 void
424 cgthree_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
425 {
426 struct cgthree_softc *sc = v;
427 union bt_cmap *bcm = &sc->sc_cmap;
428
429 bcm->cm_map[index][0] = r;
430 bcm->cm_map[index][1] = g;
431 bcm->cm_map[index][2] = b;
432 cgthree_loadcmap(sc, index, 1);
433 }
434
435 void
436 cgthree_loadcmap(struct cgthree_softc *sc, u_int start, u_int ncolors)
437 {
438 u_int cstart;
439 int count;
440
441 cstart = BT_D4M3(start);
442 count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3;
443 BT_WRITE(sc, BT_ADDR, BT_D4M4(start));
444 while (--count >= 0) {
445 BT_WRITE(sc, BT_CMAP, sc->sc_cmap.cm_chip[cstart]);
446 cstart++;
447 }
448 }
449
450 int
451 cg3_bt_getcmap(union bt_cmap *bcm, struct wsdisplay_cmap *rcm)
452 {
453 u_int index = rcm->index, count = rcm->count, i;
454 int error;
455
456 if (index >= 256 || count > 256 - index)
457 return (EINVAL);
458 for (i = 0; i < count; i++) {
459 if ((error = copyout(&bcm->cm_map[index + i][0],
460 &rcm->red[i], 1)) != 0)
461 return (error);
462 if ((error = copyout(&bcm->cm_map[index + i][1],
463 &rcm->green[i], 1)) != 0)
464 return (error);
465 if ((error = copyout(&bcm->cm_map[index + i][2],
466 &rcm->blue[i], 1)) != 0)
467 return (error);
468 }
469 return (0);
470 }
471
472 int
473 cg3_bt_putcmap(union bt_cmap *bcm, struct wsdisplay_cmap *rcm)
474 {
475 u_int index = rcm->index, count = rcm->count, i;
476 int error;
477
478 if (index >= 256 || count > 256 - index)
479 return (EINVAL);
480 for (i = 0; i < count; i++) {
481 if ((error = copyin(&rcm->red[i],
482 &bcm->cm_map[index + i][0], 1)) != 0)
483 return (error);
484 if ((error = copyin(&rcm->green[i],
485 &bcm->cm_map[index + i][1], 1)) != 0)
486 return (error);
487 if ((error = copyin(&rcm->blue[i],
488 &bcm->cm_map[index + i][2], 1)) != 0)
489 return (error);
490 }
491 return (0);
492 }
493
494 void
495 cgthree_reset(struct cgthree_softc *sc)
496 {
497 int i, j;
498 u_int8_t sts, ctrl;
499
500 sts = FBC_READ(sc, CG3_FBC_STAT);
501 ctrl = FBC_READ(sc, CG3_FBC_CTRL);
502
503 if (ctrl & FBC_CTRL_TIME) {
504
505 return;
506 }
507
508 for (i = 0; i < sizeof(cg3_videoctrl)/sizeof(cg3_videoctrl[0]); i++) {
509 if (cg3_videoctrl[i].sense == 0xff ||
510 (cg3_videoctrl[i].sense ==
511 (sts & (FBC_STAT_RES | FBC_STAT_ID)))) {
512 for (j = 0; j < 12; j++)
513 FBC_WRITE(sc, CG3_FBC_VCTRL + j,
514 cg3_videoctrl[i].vctrl[j]);
515 ctrl &= ~(FBC_CTRL_XTAL | FBC_CTRL_DIV);
516 ctrl |= cg3_videoctrl[i].ctrl |
517 FBC_CTRL_TIME;
518 FBC_WRITE(sc, CG3_FBC_CTRL, ctrl);
519 break;
520 }
521 }
522
523
524 BT_WRITE(sc, BT_ADDR, BT_RMR);
525 BT_BARRIER(sc, BT_ADDR, BUS_SPACE_BARRIER_WRITE);
526 BT_WRITE(sc, BT_CTRL, 0xff);
527 BT_BARRIER(sc, BT_CTRL, BUS_SPACE_BARRIER_WRITE);
528
529
530 BT_WRITE(sc, BT_ADDR, BT_BMR);
531 BT_BARRIER(sc, BT_ADDR, BUS_SPACE_BARRIER_WRITE);
532 BT_WRITE(sc, BT_CTRL, 0x00);
533 BT_BARRIER(sc, BT_CTRL, BUS_SPACE_BARRIER_WRITE);
534
535
536
537
538
539 BT_WRITE(sc, BT_ADDR, BT_CR);
540 BT_BARRIER(sc, BT_ADDR, BUS_SPACE_BARRIER_WRITE);
541 BT_WRITE(sc, BT_CTRL,
542 (BTCR_MPLX_4 | BTCR_RAMENA | BTCR_BLINK_6464));
543 BT_BARRIER(sc, BT_CTRL, BUS_SPACE_BARRIER_WRITE);
544
545
546 BT_WRITE(sc, BT_ADDR, BT_CTR);
547 BT_BARRIER(sc, BT_ADDR, BUS_SPACE_BARRIER_WRITE);
548 BT_WRITE(sc, BT_CTRL, 0x00);
549 BT_BARRIER(sc, BT_CTRL, BUS_SPACE_BARRIER_WRITE);
550 }
551
552 void
553 cgthree_burner(void *vsc, u_int on, u_int flags)
554 {
555 struct cgthree_softc *sc = vsc;
556 int s;
557 u_int8_t fbc;
558
559 s = splhigh();
560 fbc = FBC_READ(sc, CG3_FBC_CTRL);
561 if (on)
562 fbc |= FBC_CTRL_VENAB | FBC_CTRL_TIME;
563 else {
564 fbc &= ~FBC_CTRL_VENAB;
565 if (flags & WSDISPLAY_BURN_VBLANK)
566 fbc &= ~FBC_CTRL_TIME;
567 }
568 FBC_WRITE(sc, CG3_FBC_CTRL, fbc);
569 splx(s);
570 }