FreeBSD/Linux Kernel Cross Reference
sys/dev/fb/creator.c
1 /*-
2 * Copyright (c) 2003 Jake Burkholder.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: releng/5.2/sys/dev/fb/creator.c 122471 2003-11-11 07:34:08Z jake $
27 */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/bus.h>
32 #include <sys/kernel.h>
33 #include <sys/conf.h>
34 #include <sys/cons.h>
35 #include <sys/proc.h>
36 #include <sys/fcntl.h>
37 #include <sys/malloc.h>
38 #include <sys/fbio.h>
39 #include <sys/consio.h>
40
41 #include <machine/bus.h>
42 #include <machine/ofw_upa.h>
43
44 #include <sys/rman.h>
45
46 #include <dev/fb/fbreg.h>
47 #include <dev/fb/gallant12x22.h>
48 #include <dev/syscons/syscons.h>
49
50 #include <dev/ofw/openfirm.h>
51
52 #include <sparc64/creator/creator.h>
53
54 static int creator_configure(int flags);
55
56 static vi_probe_t creator_probe;
57 static vi_init_t creator_init;
58 static vi_get_info_t creator_get_info;
59 static vi_query_mode_t creator_query_mode;
60 static vi_set_mode_t creator_set_mode;
61 static vi_save_font_t creator_save_font;
62 static vi_load_font_t creator_load_font;
63 static vi_show_font_t creator_show_font;
64 static vi_save_palette_t creator_save_palette;
65 static vi_load_palette_t creator_load_palette;
66 static vi_set_border_t creator_set_border;
67 static vi_save_state_t creator_save_state;
68 static vi_load_state_t creator_load_state;
69 static vi_set_win_org_t creator_set_win_org;
70 static vi_read_hw_cursor_t creator_read_hw_cursor;
71 static vi_set_hw_cursor_t creator_set_hw_cursor;
72 static vi_set_hw_cursor_shape_t creator_set_hw_cursor_shape;
73 static vi_blank_display_t creator_blank_display;
74 static vi_mmap_t creator_mmap;
75 static vi_ioctl_t creator_ioctl;
76 static vi_clear_t creator_clear;
77 static vi_fill_rect_t creator_fill_rect;
78 static vi_bitblt_t creator_bitblt;
79 static vi_diag_t creator_diag;
80 static vi_save_cursor_palette_t creator_save_cursor_palette;
81 static vi_load_cursor_palette_t creator_load_cursor_palette;
82 static vi_copy_t creator_copy;
83 static vi_putp_t creator_putp;
84 static vi_putc_t creator_putc;
85 static vi_puts_t creator_puts;
86 static vi_putm_t creator_putm;
87
88 static void creator_ras_fifo_wait(struct creator_softc *sc, int n);
89 static void creator_ras_setbg(struct creator_softc *sc, int bg);
90 static void creator_ras_setfg(struct creator_softc *sc, int fg);
91 static void creator_ras_wait(struct creator_softc *sc);
92
93 static video_switch_t creatorvidsw = {
94 .probe = creator_probe,
95 .init = creator_init,
96 .get_info = creator_get_info,
97 .query_mode = creator_query_mode,
98 .set_mode = creator_set_mode,
99 .save_font = creator_save_font,
100 .load_font = creator_load_font,
101 .show_font = creator_show_font,
102 .save_palette = creator_save_palette,
103 .load_palette = creator_load_palette,
104 .set_border = creator_set_border,
105 .save_state = creator_save_state,
106 .load_state = creator_load_state,
107 .set_win_org = creator_set_win_org,
108 .read_hw_cursor = creator_read_hw_cursor,
109 .set_hw_cursor = creator_set_hw_cursor,
110 .set_hw_cursor_shape = creator_set_hw_cursor_shape,
111 .blank_display = creator_blank_display,
112 .mmap = creator_mmap,
113 .ioctl = creator_ioctl,
114 .clear = creator_clear,
115 .fill_rect = creator_fill_rect,
116 .bitblt = creator_bitblt,
117 NULL, /* XXX brain damage */
118 NULL, /* XXX brain damage */
119 .diag = creator_diag,
120 .save_cursor_palette = creator_save_cursor_palette,
121 .load_cursor_palette = creator_load_cursor_palette,
122 .copy = creator_copy,
123 .putp = creator_putp,
124 .putc = creator_putc,
125 .puts = creator_puts,
126 .putm = creator_putm
127 };
128
129 VIDEO_DRIVER(creator, creatorvidsw, creator_configure);
130
131 extern sc_rndr_sw_t txtrndrsw;
132 RENDERER(creator, 0, txtrndrsw, gfb_set);
133
134 RENDERER_MODULE(creator, gfb_set);
135
136 extern struct bus_space_tag nexus_bustag;
137
138 #define C(r, g, b) ((b << 16) | (g << 8) | (r))
139 static int cmap[] = {
140 C(0x00, 0x00, 0x00), /* black */
141 C(0x00, 0x00, 0xff), /* blue */
142 C(0x00, 0xff, 0x00), /* green */
143 C(0x00, 0xc0, 0xc0), /* cyan */
144 C(0xff, 0x00, 0x00), /* red */
145 C(0xc0, 0x00, 0xc0), /* magenta */
146 C(0xc0, 0xc0, 0x00), /* brown */
147 C(0xc0, 0xc0, 0xc0), /* light grey */
148 C(0x80, 0x80, 0x80), /* dark grey */
149 C(0x80, 0x80, 0xff), /* light blue */
150 C(0x80, 0xff, 0x80), /* light green */
151 C(0x80, 0xff, 0xff), /* light cyan */
152 C(0xff, 0x80, 0x80), /* light red */
153 C(0xff, 0x80, 0xff), /* light magenta */
154 C(0xff, 0xff, 0x80), /* yellow */
155 C(0xff, 0xff, 0xff), /* white */
156 };
157
158 #define TODO printf("%s: unimplemented\n", __func__)
159
160 static struct creator_softc creator_softc;
161
162 static int
163 creator_configure(int flags)
164 {
165 struct upa_regs reg[FFB_NREG];
166 struct creator_softc *sc;
167 phandle_t chosen;
168 phandle_t stdout;
169 phandle_t child;
170 char buf[32];
171 int i;
172
173 sc = &creator_softc;
174 for (child = OF_child(OF_peer(0)); child != 0;
175 child = OF_peer(child)) {
176 OF_getprop(child, "name", buf, sizeof(buf));
177 if (strcmp(buf, "SUNW,ffb") == 0 ||
178 strcmp(buf, "SUNW,afb") == 0)
179 break;
180 }
181 if (child == 0)
182 return (0);
183
184 chosen = OF_finddevice("/chosen");
185 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
186 if (child == stdout)
187 sc->sc_console = 1;
188
189 OF_getprop(child, "reg", reg, sizeof(reg));
190 for (i = 0; i < FFB_NREG; i++) {
191 sc->sc_bt[i] = &nexus_bustag;
192 sc->sc_bh[i] = UPA_REG_PHYS(reg + i);
193 }
194 OF_getprop(child, "height", &sc->sc_height, sizeof(sc->sc_height));
195 OF_getprop(child, "width", &sc->sc_width, sizeof(sc->sc_width));
196
197 creator_init(0, &sc->sc_va, 0);
198
199 return (0);
200 }
201
202 static int
203 creator_probe(int unit, video_adapter_t **adp, void *arg, int flags)
204 {
205 TODO;
206 return (0);
207 }
208
209 static u_char creator_mouse_pointer[64][8] __aligned(8) = {
210 { 0x00, 0x00, }, /* ............ */
211 { 0x80, 0x00, }, /* *........... */
212 { 0xc0, 0x00, }, /* **.......... */
213 { 0xe0, 0x00, }, /* ***......... */
214 { 0xf0, 0x00, }, /* ****........ */
215 { 0xf8, 0x00, }, /* *****....... */
216 { 0xfc, 0x00, }, /* ******...... */
217 { 0xfe, 0x00, }, /* *******..... */
218 { 0xff, 0x00, }, /* ********.... */
219 { 0xff, 0x80, }, /* *********... */
220 { 0xfc, 0xc0, }, /* ******..**.. */
221 { 0xdc, 0x00, }, /* **.***...... */
222 { 0x8e, 0x00, }, /* *...***..... */
223 { 0x0e, 0x00, }, /* ....***..... */
224 { 0x07, 0x00, }, /* .....***.... */
225 { 0x04, 0x00, }, /* .....*...... */
226 { 0x00, 0x00, }, /* ............ */
227 { 0x00, 0x00, }, /* ............ */
228 { 0x00, 0x00, }, /* ............ */
229 { 0x00, 0x00, }, /* ............ */
230 { 0x00, 0x00, }, /* ............ */
231 { 0x00, 0x00, }, /* ............ */
232 };
233
234 static int
235 creator_init(int unit, video_adapter_t *adp, int flags)
236 {
237 struct creator_softc *sc;
238 phandle_t options;
239 video_info_t *vi;
240 char buf[32];
241 cell_t col;
242 cell_t row;
243 int i, j;
244
245 sc = (struct creator_softc *)adp;
246 vi = &adp->va_info;
247
248 vid_init_struct(adp, "creator", -1, unit);
249
250 options = OF_finddevice("/options");
251 OF_getprop(options, "screen-#rows", buf, sizeof(buf));
252 vi->vi_height = strtol(buf, NULL, 10);
253 OF_getprop(options, "screen-#columns", buf, sizeof(buf));
254 vi->vi_width = strtol(buf, NULL, 10);
255 vi->vi_cwidth = 12;
256 vi->vi_cheight = 22;
257
258 sc->sc_font = gallant12x22_data;
259 sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2;
260 sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight)) / 2;
261
262 sc->sc_bg_cache = -1;
263 sc->sc_fg_cache = -1;
264
265 creator_ras_wait(sc);
266 sc->sc_fifo_cache = 0;
267 creator_ras_fifo_wait(sc, 2);
268
269 FFB_WRITE(sc, FFB_FBC, FFB_FBC_PPC, FBC_PPC_VCE_DIS |
270 FBC_PPC_TBE_OPAQUE | FBC_PPC_APE_DIS | FBC_PPC_CS_CONST);
271 FFB_WRITE(sc, FFB_FBC, FFB_FBC_FBC, FFB_FBC_WB_A | FFB_FBC_RB_A |
272 FFB_FBC_SB_BOTH | FFB_FBC_XE_OFF | FFB_FBC_RGBE_MASK);
273
274 FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE, 0x8000);
275 sc->sc_dac = (FFB_READ(sc, FFB_DAC, FFB_DAC_VALUE) >> 0x1c);
276
277 FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, 0x102);
278 FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, 0xffffff);
279 FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, 0x0);
280
281 for (i = 0; i < 2; i++) {
282 FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, i ? 0x0 : 0x80);
283 for (j = 0; j < 64; j++) {
284 FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2,
285 *(uint32_t *)(&creator_mouse_pointer[j][0]));
286 FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2,
287 *(uint32_t *)(&creator_mouse_pointer[j][4]));
288 }
289 }
290
291 FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, 0x100);
292 FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2, 0x0);
293
294 if (sc->sc_console) {
295 col = NULL;
296 row = NULL;
297 OF_interpret("stdout @ is my-self addr line# addr column# ",
298 2, &col, &row);
299 if (col != NULL && row != NULL) {
300 sc->sc_colp = (int *)(col + 4);
301 sc->sc_rowp = (int *)(row + 4);
302 }
303 } else {
304 creator_blank_display(&sc->sc_va, V_DISPLAY_ON);
305 }
306
307 creator_set_mode(&sc->sc_va, 0);
308
309 vid_register(&sc->sc_va);
310
311 return (0);
312 }
313
314 static int
315 creator_get_info(video_adapter_t *adp, int mode, video_info_t *info)
316 {
317 bcopy(&adp->va_info, info, sizeof(*info));
318 return (0);
319 }
320
321 static int
322 creator_query_mode(video_adapter_t *adp, video_info_t *info)
323 {
324 TODO;
325 return (0);
326 }
327
328 static int
329 creator_set_mode(video_adapter_t *adp, int mode)
330 {
331 struct creator_softc *sc;
332
333 sc = (struct creator_softc *)adp;
334 creator_ras_fifo_wait(sc, 4);
335 FFB_WRITE(sc, FFB_FBC, FFB_FBC_ROP, FBC_ROP_NEW);
336 FFB_WRITE(sc, FFB_FBC, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE);
337 FFB_WRITE(sc, FFB_FBC, FFB_FBC_PMASK, 0xffffffff);
338 FFB_WRITE(sc, FFB_FBC, FFB_FBC_FONTINC, 0x10000);
339
340 creator_ras_setbg(sc, 0x0);
341 creator_ras_setfg(sc, 0xffffff);
342
343 creator_ras_fifo_wait(sc, 4);
344 FFB_WRITE(sc, FFB_FBC, FFB_FBC_BX, 0);
345 FFB_WRITE(sc, FFB_FBC, FFB_FBC_BY, 0);
346 FFB_WRITE(sc, FFB_FBC, FFB_FBC_BH, sc->sc_height);
347 FFB_WRITE(sc, FFB_FBC, FFB_FBC_BW, sc->sc_width);
348
349 creator_ras_wait(sc);
350
351 return (0);
352 }
353
354 static int
355 creator_save_font(video_adapter_t *adp, int page, int size, u_char *data,
356 int c, int count)
357 {
358 TODO;
359 return (0);
360 }
361
362 static int
363 creator_load_font(video_adapter_t *adp, int page, int size, u_char *data,
364 int c, int count)
365 {
366 TODO;
367 return (0);
368 }
369
370 static int
371 creator_show_font(video_adapter_t *adp, int page)
372 {
373 TODO;
374 return (0);
375 }
376
377 static int
378 creator_save_palette(video_adapter_t *adp, u_char *palette)
379 {
380 /* TODO; */
381 return (0);
382 }
383
384 static int
385 creator_load_palette(video_adapter_t *adp, u_char *palette)
386 {
387 /* TODO; */
388 return (0);
389 }
390
391 static int
392 creator_set_border(video_adapter_t *adp, int border)
393 {
394 /* TODO; */
395 return (0);
396 }
397
398 static int
399 creator_save_state(video_adapter_t *adp, void *p, size_t size)
400 {
401 TODO;
402 return (0);
403 }
404
405 static int
406 creator_load_state(video_adapter_t *adp, void *p)
407 {
408 TODO;
409 return (0);
410 }
411
412 static int
413 creator_set_win_org(video_adapter_t *adp, off_t offset)
414 {
415 TODO;
416 return (0);
417 }
418
419 static int
420 creator_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
421 {
422 struct creator_softc *sc;
423
424 sc = (struct creator_softc *)adp;
425 if (sc->sc_colp != NULL && sc->sc_rowp != NULL) {
426 *col = *sc->sc_colp;
427 *row = *sc->sc_rowp;
428 } else {
429 *col = 0;
430 *row = 0;
431 }
432 return (0);
433 }
434
435 static int
436 creator_set_hw_cursor(video_adapter_t *adp, int col, int row)
437 {
438 struct creator_softc *sc;
439
440 sc = (struct creator_softc *)adp;
441 if (sc->sc_colp != NULL && sc->sc_rowp != NULL) {
442 *sc->sc_colp = col;
443 *sc->sc_rowp = row;
444 }
445 return (0);
446 }
447
448 static int
449 creator_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
450 int celsize, int blink)
451 {
452 return (0);
453 }
454
455 static int
456 creator_blank_display(video_adapter_t *adp, int mode)
457 {
458 struct creator_softc *sc;
459 int v;
460
461 sc = (struct creator_softc *)adp;
462 FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE, 0x6000);
463 v = FFB_READ(sc, FFB_DAC, FFB_DAC_VALUE);
464 FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE, 0x6000);
465 if (mode == V_DISPLAY_ON)
466 v |= 0x1;
467 else
468 v &= ~0x1;
469 FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE, v);
470 return (0);
471 }
472
473 static int
474 creator_mmap(video_adapter_t *adp, vm_offset_t offset, vm_paddr_t *paddr,
475 int prot)
476 {
477 TODO;
478 return (0);
479 }
480
481 static int
482 creator_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
483 {
484 TODO;
485 return (0);
486 }
487
488 static int
489 creator_clear(video_adapter_t *adp)
490 {
491 TODO;
492 return (0);
493 }
494
495 static int
496 creator_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
497 {
498 TODO;
499 return (0);
500 }
501
502 static int
503 creator_bitblt(video_adapter_t *adp, ...)
504 {
505 TODO;
506 return (0);
507 }
508
509 static int
510 creator_diag(video_adapter_t *adp, int level)
511 {
512 TODO;
513 return (0);
514 }
515
516 static int
517 creator_save_cursor_palette(video_adapter_t *adp, u_char *palette)
518 {
519 TODO;
520 return (0);
521 }
522
523 static int
524 creator_load_cursor_palette(video_adapter_t *adp, u_char *palette)
525 {
526 TODO;
527 return (0);
528 }
529
530 static int
531 creator_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
532 {
533 TODO;
534 return (0);
535 }
536
537 static int
538 creator_putp(video_adapter_t *adp, vm_offset_t off, u_int32_t p, u_int32_t a,
539 int size, int bpp, int bit_ltor, int byte_ltor)
540 {
541 TODO;
542 return (0);
543 }
544
545 static int
546 creator_putc(video_adapter_t *adp, vm_offset_t off, u_int8_t c, u_int8_t a)
547 {
548 struct creator_softc *sc;
549 uint16_t *p;
550 int row;
551 int col;
552 int i;
553
554 sc = (struct creator_softc *)adp;
555 row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
556 col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
557 p = (uint16_t *)sc->sc_font + (c * adp->va_info.vi_cheight);
558 creator_ras_setfg(sc, cmap[a & 0xf]);
559 creator_ras_setbg(sc, cmap[(a >> 4) & 0xf]);
560 creator_ras_fifo_wait(sc, 2 + adp->va_info.vi_cheight);
561 FFB_WRITE(sc, FFB_FBC, FFB_FBC_FONTXY,
562 ((row + sc->sc_ymargin) << 16) | (col + sc->sc_xmargin));
563 FFB_WRITE(sc, FFB_FBC, FFB_FBC_FONTW, adp->va_info.vi_cwidth);
564 for (i = 0; i < adp->va_info.vi_cheight; i++) {
565 FFB_WRITE(sc, FFB_FBC, FFB_FBC_FONT, *p++ << 16);
566 }
567 return (0);
568 }
569
570 static int
571 creator_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
572 {
573 int i;
574
575 for (i = 0; i < len; i++) {
576 (*vidsw[adp->va_index]->putc)(adp, off + i, s[i] & 0xff,
577 (s[i] & 0xff00) >> 8);
578 }
579 return (0);
580 }
581
582 static int
583 creator_putm(video_adapter_t *adp, int x, int y, u_int8_t *pixel_image,
584 u_int32_t pixel_mask, int size)
585 {
586 struct creator_softc *sc;
587
588 sc = (struct creator_softc *)adp;
589 FFB_WRITE(sc, FFB_DAC, FFB_DAC_TYPE2, 0x104);
590 FFB_WRITE(sc, FFB_DAC, FFB_DAC_VALUE2,
591 ((y + sc->sc_ymargin) << 16) | (x + sc->sc_xmargin));
592 return (0);
593 }
594
595 static void
596 creator_ras_fifo_wait(struct creator_softc *sc, int n)
597 {
598 int cache;
599
600 cache = sc->sc_fifo_cache;
601 while (cache < n) {
602 cache = (FFB_READ(sc, FFB_FBC, FFB_FBC_UCSR) &
603 FBC_UCSR_FIFO_MASK) - 8;
604 }
605 sc->sc_fifo_cache = cache - n;
606 }
607
608 static void
609 creator_ras_setbg(struct creator_softc *sc, int bg)
610 {
611
612 if (bg == sc->sc_bg_cache)
613 return;
614 sc->sc_bg_cache = bg;
615 creator_ras_fifo_wait(sc, 1);
616 FFB_WRITE(sc, FFB_FBC, FFB_FBC_BG, bg);
617 creator_ras_wait(sc);
618 }
619
620 static void
621 creator_ras_setfg(struct creator_softc *sc, int fg)
622 {
623
624 if (fg == sc->sc_fg_cache)
625 return;
626 sc->sc_fg_cache = fg;
627 creator_ras_fifo_wait(sc, 1);
628 FFB_WRITE(sc, FFB_FBC, FFB_FBC_FG, fg);
629 creator_ras_wait(sc);
630 }
631
632 static void
633 creator_ras_wait(struct creator_softc *sc)
634 {
635 int ucsr;
636 int r;
637
638 for (;;) {
639 ucsr = FFB_READ(sc, FFB_FBC, FFB_FBC_UCSR);
640 if ((ucsr & (FBC_UCSR_FB_BUSY|FBC_UCSR_RP_BUSY)) == 0)
641 break;
642 r = ucsr & (FBC_UCSR_READ_ERR | FBC_UCSR_FIFO_OVFL);
643 if (r != 0) {
644 FFB_WRITE(sc, FFB_FBC, FFB_FBC_UCSR, r);
645 }
646 }
647 }
Cache object: 752f8de265db5beb912b3fabeecfd854
|