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