1 /* $OpenBSD: radeonfb.c,v 1.8 2022/07/15 17:57:26 kettenis Exp $ */
2
3 /*
4 * Copyright (c) 2009 Mark Kettenis.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/param.h>
20 #include <sys/device.h>
21 #include <sys/pciio.h>
22 #include <sys/systm.h>
23
24 #include <machine/autoconf.h>
25 #include <machine/bus.h>
26 #include <machine/openfirm.h>
27
28 #include <dev/pci/pcireg.h>
29 #include <dev/pci/pcivar.h>
30 #include <dev/pci/pcidevs.h>
31
32 #include <dev/wscons/wsconsio.h>
33 #include <dev/wscons/wsdisplayvar.h>
34
35 #include <dev/rasops/rasops.h>
36
37 #include <machine/fbvar.h>
38
39 #define RADEON_PCI_MEM 0x10
40 #define RADEON_PCI_MMIO 0x18
41
42 #define RADEON_PALETTE_INDEX 0x00b0
43 #define RADEON_PALETTE_DATA 0x00b4
44
45 #define RADEON_CRTC_OFFSET 0x0224
46
47 #define RADEON_SURFACE_CNTL 0x0b00
48 #define RADEON_NONSURF_AP0_SWP_16BPP 0x00100000
49 #define RADEON_NONSURF_AP0_SWP_32BPP 0x00200000
50 #define RADEON_NONSURF_AP1_SWP_16BPP 0x00400000
51 #define RADEON_NONSURF_AP1_SWP_32BPP 0x00800000
52
53 #define RADEON_RBBM_STATUS 0x0e40
54 #define RADEON_RBBM_FIFOCNT_MASK 0x0000007f
55 #define RADEON_RBBM_ACTIVE 0x80000000
56
57 #define RADEON_SRC_Y_X 0x1434
58 #define RADEON_DST_Y_X 0x1438
59 #define RADEON_DST_HEIGHT_WIDTH 0x143c
60
61 #define RADEON_DP_GUI_MASTER_CNTL 0x146c
62 #define RADEON_GMC_DST_8BPP 0x00000200
63 #define RADEON_GMC_DST_32BPP 0x00000600
64 #define RADEON_GMC_BRUSH_NONE 0x000000e0
65 #define RADEON_GMC_BRUSH_SOLID_COLOR 0x000000d0
66 #define RADEON_GMC_SRC_DATATYPE_COLOR 0x00003000
67 #define RADEON_GMC_SRC_SOURCE_MEMORY 0x02000000
68 #define RADEON_ROP3_S 0x00cc0000
69 #define RADEON_ROP3_P 0x00f00000
70 #define RADEON_GMC_CLR_CMP_CNTL_DIS 0x10000000
71
72 #define RADEON_DP_BRUSH_BKGD_CLR 0x1478
73 #define RADEON_DP_BRUSH_FRGD_CLR 0x147c
74
75 #define RADEON_DP_CNTL 0x16c0
76 #define RADEON_DST_X_LEFT_TO_RIGHT 0x00000001
77 #define RADEON_DST_Y_TOP_TO_BOTTOM 0x00000002
78 #define RADEON_DP_WRITE_MASK 0x16cc
79
80 #define RADEON_DEFAULT_PITCH_OFFSET 0x16e0
81 #define RADEON_DEFAULT_SC_BOTTOM_RIGHT 0x16e8
82
83 #define RADEON_WAIT_UNTIL 0x1720
84 #define RADEON_WAIT_2D_IDLECLEAN 0x00010000
85 #define RADEON_WAIT_3D_IDLECLEAN 0x00020000
86 #define RADEON_WAIT_HOST_IDLECLEAN 0x00040000
87
88 #define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c
89 #define RADEON_RB3D_DC_FLUSH_ALL 0x0000000f
90 #define RADEON_RB3D_DC_BUSY 0x80000000
91
92 #define RADEON_COORDS(x, y) ((y << 16) | (x))
93
94 #ifdef APERTURE
95 extern int allowaperture;
96 #endif
97
98 struct radeonfb_softc {
99 struct sunfb sc_sunfb;
100
101 bus_space_tag_t sc_memt;
102 bus_space_handle_t sc_memh;
103 bus_addr_t sc_membase;
104 bus_size_t sc_memsize;
105 bus_size_t sc_memoff;
106
107 bus_space_tag_t sc_mmiot;
108 bus_space_handle_t sc_mmioh;
109 bus_addr_t sc_mmiobase;
110 bus_size_t sc_mmiosize;
111
112 pcitag_t sc_pcitag;
113
114 int sc_mode;
115 u_int8_t sc_cmap_red[256];
116 u_int8_t sc_cmap_green[256];
117 u_int8_t sc_cmap_blue[256];
118 };
119
120 int radeonfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
121 paddr_t radeonfb_mmap(void *, off_t, int);
122
123 struct wsdisplay_accessops radeonfb_accessops = {
124 .ioctl = radeonfb_ioctl,
125 .mmap = radeonfb_mmap
126 };
127
128 int radeonfb_match(struct device *, void *, void *);
129 void radeonfb_attach(struct device *, struct device *, void *);
130
131 const struct cfattach radeonfb_ca = {
132 sizeof(struct radeonfb_softc), radeonfb_match, radeonfb_attach
133 };
134
135 struct cfdriver radeonfb_cd = {
136 NULL, "radeonfb", DV_DULL
137 };
138
139 int radeonfb_is_console(int);
140 int radeonfb_getcmap(struct radeonfb_softc *, struct wsdisplay_cmap *);
141 int radeonfb_putcmap(struct radeonfb_softc *, struct wsdisplay_cmap *);
142 void radeonfb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
143
144 int radeonfb_copycols(void *, int, int, int, int);
145 int radeonfb_erasecols(void *, int, int, int, uint32_t);
146 int radeonfb_copyrows(void *, int, int, int);
147 int radeonfb_eraserows(void *, int, int, uint32_t);
148
149 void radeonfb_init(struct radeonfb_softc *);
150 void radeonfb_wait_fifo(struct radeonfb_softc *, int);
151 void radeonfb_wait(struct radeonfb_softc *);
152 void radeonfb_copyrect(struct radeonfb_softc *, int, int, int, int, int, int);
153 void radeonfb_fillrect(struct radeonfb_softc *, int, int, int, int, int);
154
155 int
radeonfb_match(struct device * parent,void * cf,void * aux)156 radeonfb_match(struct device *parent, void *cf, void *aux)
157 {
158 struct pci_attach_args *pa = aux;
159 char buf[32];
160 int node;
161
162 node = PCITAG_NODE(pa->pa_tag);
163 OF_getprop(node, "name", buf, sizeof(buf));
164 if (strcmp(buf, "SUNW,XVR-100") == 0 ||
165 strcmp(buf, "SUNW,XVR-300") == 0)
166 return (10);
167
168 return (0);
169 }
170
171 void
radeonfb_attach(struct device * parent,struct device * self,void * aux)172 radeonfb_attach(struct device *parent, struct device *self, void *aux)
173 {
174 struct radeonfb_softc *sc = (struct radeonfb_softc *)self;
175 struct pci_attach_args *pa = aux;
176 struct rasops_info *ri;
177 int node, console, flags;
178 char *model;
179
180 sc->sc_pcitag = pa->pa_tag;
181
182 node = PCITAG_NODE(pa->pa_tag);
183 console = radeonfb_is_console(node);
184
185 printf("\n");
186
187 model = getpropstring(node, "model");
188 printf("%s: %s", self->dv_xname, model);
189
190 if (pci_mapreg_map(pa, RADEON_PCI_MEM, PCI_MAPREG_TYPE_MEM,
191 BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh,
192 &sc->sc_membase, &sc->sc_memsize, 0)) {
193 printf("\n%s: can't map video memory\n", self->dv_xname);
194 return;
195 }
196
197 if (pci_mapreg_map(pa, RADEON_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0,
198 &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase,
199 &sc->sc_mmiosize, 0)) {
200 printf("\n%s: can't map registers\n", self->dv_xname);
201 return;
202 }
203
204 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
205
206 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
207
208 /*
209 * The firmware sets up the framebuffer such that at starts at
210 * an offset from the start of video memory.
211 */
212 sc->sc_memoff =
213 bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, RADEON_CRTC_OFFSET);
214
215 ri = &sc->sc_sunfb.sf_ro;
216 ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh);
217 ri->ri_bits += sc->sc_memoff;
218 ri->ri_hw = sc;
219
220 if (sc->sc_sunfb.sf_depth == 32)
221 flags = 0;
222 else
223 flags = RI_BSWAP;
224
225 fbwscons_init(&sc->sc_sunfb, flags, console);
226 fbwscons_setcolormap(&sc->sc_sunfb, radeonfb_setcolor);
227 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
228
229 radeonfb_init(sc);
230 ri->ri_ops.copyrows = radeonfb_copyrows;
231 ri->ri_ops.copycols = radeonfb_copycols;
232 ri->ri_ops.eraserows = radeonfb_eraserows;
233 ri->ri_ops.erasecols = radeonfb_erasecols;
234
235 if (console)
236 fbwscons_console_init(&sc->sc_sunfb, -1);
237 fbwscons_attach(&sc->sc_sunfb, &radeonfb_accessops, console);
238 }
239
240 int
radeonfb_ioctl(void * v,u_long cmd,caddr_t data,int flags,struct proc * p)241 radeonfb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
242 {
243 struct radeonfb_softc *sc = v;
244 struct wsdisplay_fbinfo *wdf;
245 struct pcisel *sel;
246
247 switch (cmd) {
248 case WSDISPLAYIO_GTYPE:
249 *(u_int *)data = WSDISPLAY_TYPE_RADEONFB;
250 break;
251 case WSDISPLAYIO_SMODE:
252 sc->sc_mode = *(u_int *)data;
253 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
254 struct rasops_info *ri = &sc->sc_sunfb.sf_ro;
255
256 /* Restore colormap. */
257 fbwscons_setcolormap(&sc->sc_sunfb, radeonfb_setcolor);
258
259 /* Clear screen. */
260 radeonfb_init(sc);
261 radeonfb_fillrect(sc, 0, 0, ri->ri_width,
262 ri->ri_height, ri->ri_devcmap[WSCOL_WHITE]);
263 }
264 break;
265
266 case WSDISPLAYIO_GINFO:
267 wdf = (void *)data;
268 wdf->height = sc->sc_sunfb.sf_height;
269 wdf->width = sc->sc_sunfb.sf_width;
270 wdf->depth = sc->sc_sunfb.sf_depth;
271 wdf->stride = sc->sc_sunfb.sf_linebytes;
272 wdf->offset = 0;
273 if (sc->sc_sunfb.sf_depth == 32)
274 wdf->cmsize = 0;
275 else
276 wdf->cmsize = 256;
277 break;
278 case WSDISPLAYIO_GETSUPPORTEDDEPTH:
279 if (sc->sc_sunfb.sf_depth == 32)
280 *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
281 else
282 return (-1);
283 break;
284 case WSDISPLAYIO_LINEBYTES:
285 *(u_int *)data = sc->sc_sunfb.sf_linebytes;
286 break;
287
288 case WSDISPLAYIO_GETCMAP:
289 return radeonfb_getcmap(sc, (struct wsdisplay_cmap *)data);
290 case WSDISPLAYIO_PUTCMAP:
291 return radeonfb_putcmap(sc, (struct wsdisplay_cmap *)data);
292
293 case WSDISPLAYIO_GPCIID:
294 sel = (struct pcisel *)data;
295 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag);
296 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag);
297 sel->pc_func = PCITAG_FUN(sc->sc_pcitag);
298 break;
299
300 case WSDISPLAYIO_SVIDEO:
301 case WSDISPLAYIO_GVIDEO:
302 break;
303
304 case WSDISPLAYIO_GCURPOS:
305 case WSDISPLAYIO_SCURPOS:
306 case WSDISPLAYIO_GCURMAX:
307 case WSDISPLAYIO_GCURSOR:
308 case WSDISPLAYIO_SCURSOR:
309 default:
310 return -1; /* not supported yet */
311 }
312
313 return (0);
314 }
315
316 paddr_t
radeonfb_mmap(void * v,off_t off,int prot)317 radeonfb_mmap(void *v, off_t off, int prot)
318 {
319 struct radeonfb_softc *sc = v;
320
321 if (off & PGOFSET)
322 return (-1);
323
324 switch (sc->sc_mode) {
325 case WSDISPLAYIO_MODE_MAPPED:
326 #ifdef APERTURE
327 if (allowaperture == 0)
328 return (-1);
329 #endif
330
331 if (sc->sc_mmiosize == 0)
332 return (-1);
333
334 if (off >= sc->sc_membase &&
335 off < (sc->sc_membase + sc->sc_memsize))
336 return (bus_space_mmap(sc->sc_memt,
337 sc->sc_membase, off - sc->sc_membase,
338 prot, BUS_SPACE_MAP_LINEAR));
339
340 if (off >= sc->sc_mmiobase &&
341 off < (sc->sc_mmiobase + sc->sc_mmiosize))
342 return (bus_space_mmap(sc->sc_mmiot,
343 sc->sc_mmiobase, off - sc->sc_mmiobase,
344 prot, BUS_SPACE_MAP_LINEAR));
345 break;
346
347 case WSDISPLAYIO_MODE_DUMBFB:
348 if ((sc->sc_memoff % PAGE_SIZE) != 0)
349 return (-1);
350
351 if (off >= 0 && off < sc->sc_memsize / 2) {
352 bus_addr_t base = sc->sc_membase + sc->sc_memoff;
353
354 /*
355 * In 32bpp mode, use the second aperture,
356 * which has been set up by the firmware to do
357 * proper byte swapping.
358 */
359 if (sc->sc_sunfb.sf_depth == 32)
360 base += sc->sc_memsize / 2;
361
362 return (bus_space_mmap(sc->sc_memt, base, off,
363 prot, BUS_SPACE_MAP_LINEAR));
364 }
365 break;
366 }
367
368 return (-1);
369 }
370
371 int
radeonfb_is_console(int node)372 radeonfb_is_console(int node)
373 {
374 extern int fbnode;
375
376 return (fbnode == node);
377 }
378
379 int
radeonfb_getcmap(struct radeonfb_softc * sc,struct wsdisplay_cmap * cm)380 radeonfb_getcmap(struct radeonfb_softc *sc, struct wsdisplay_cmap *cm)
381 {
382 u_int index = cm->index;
383 u_int count = cm->count;
384 int error;
385
386 if (index >= 256 || count > 256 - index)
387 return (EINVAL);
388
389 error = copyout(&sc->sc_cmap_red[index], cm->red, count);
390 if (error)
391 return (error);
392 error = copyout(&sc->sc_cmap_green[index], cm->green, count);
393 if (error)
394 return (error);
395 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
396 if (error)
397 return (error);
398 return (0);
399 }
400
401 int
radeonfb_putcmap(struct radeonfb_softc * sc,struct wsdisplay_cmap * cm)402 radeonfb_putcmap(struct radeonfb_softc *sc, struct wsdisplay_cmap *cm)
403 {
404 u_int index = cm->index;
405 u_int count = cm->count;
406 u_int i;
407 int error;
408 u_char *r, *g, *b;
409
410 if (index >= 256 || count > 256 - index)
411 return (EINVAL);
412
413 if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0)
414 return (error);
415 if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0)
416 return (error);
417 if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0)
418 return (error);
419
420 r = &sc->sc_cmap_red[index];
421 g = &sc->sc_cmap_green[index];
422 b = &sc->sc_cmap_blue[index];
423
424 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
425 RADEON_PALETTE_INDEX, index);
426 for (i = 0; i < count; i++) {
427 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
428 RADEON_PALETTE_DATA, (*r << 16) | (*g << 8) | *b);
429 r++, g++, b++;
430 }
431 return (0);
432 }
433
434 void
radeonfb_setcolor(void * v,u_int index,u_int8_t r,u_int8_t g,u_int8_t b)435 radeonfb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
436 {
437 struct radeonfb_softc *sc = v;
438
439 sc->sc_cmap_red[index] = r;
440 sc->sc_cmap_green[index] = g;
441 sc->sc_cmap_blue[index] = b;
442
443 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
444 RADEON_PALETTE_INDEX, index);
445 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
446 RADEON_PALETTE_DATA, (r << 16) | (g << 8) | b);
447 }
448
449 /*
450 * Accelerated routines.
451 */
452
453 int
radeonfb_copycols(void * cookie,int row,int src,int dst,int num)454 radeonfb_copycols(void *cookie, int row, int src, int dst, int num)
455 {
456 struct rasops_info *ri = cookie;
457 struct radeonfb_softc *sc = ri->ri_hw;
458
459 num *= ri->ri_font->fontwidth;
460 src *= ri->ri_font->fontwidth;
461 dst *= ri->ri_font->fontwidth;
462 row *= ri->ri_font->fontheight;
463
464 radeonfb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row,
465 ri->ri_xorigin + dst, ri->ri_yorigin + row,
466 num, ri->ri_font->fontheight);
467
468 return 0;
469 }
470
471 int
radeonfb_erasecols(void * cookie,int row,int col,int num,uint32_t attr)472 radeonfb_erasecols(void *cookie, int row, int col, int num, uint32_t attr)
473 {
474 struct rasops_info *ri = cookie;
475 struct radeonfb_softc *sc = ri->ri_hw;
476 int bg, fg;
477
478 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
479
480 row *= ri->ri_font->fontheight;
481 col *= ri->ri_font->fontwidth;
482 num *= ri->ri_font->fontwidth;
483
484 radeonfb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row,
485 num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
486
487 return 0;
488 }
489
490 int
radeonfb_copyrows(void * cookie,int src,int dst,int num)491 radeonfb_copyrows(void *cookie, int src, int dst, int num)
492 {
493 struct rasops_info *ri = cookie;
494 struct radeonfb_softc *sc = ri->ri_hw;
495
496 num *= ri->ri_font->fontheight;
497 src *= ri->ri_font->fontheight;
498 dst *= ri->ri_font->fontheight;
499
500 radeonfb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src,
501 ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
502
503 return 0;
504 }
505
506 int
radeonfb_eraserows(void * cookie,int row,int num,uint32_t attr)507 radeonfb_eraserows(void *cookie, int row, int num, uint32_t attr)
508 {
509 struct rasops_info *ri = cookie;
510 struct radeonfb_softc *sc = ri->ri_hw;
511 int bg, fg;
512 int x, y, w;
513
514 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
515
516 if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
517 num = ri->ri_height;
518 x = y = 0;
519 w = ri->ri_width;
520 } else {
521 num *= ri->ri_font->fontheight;
522 x = ri->ri_xorigin;
523 y = ri->ri_yorigin + row * ri->ri_font->fontheight;
524 w = ri->ri_emuwidth;
525 }
526 radeonfb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]);
527
528 return 0;
529 }
530
531 void
radeonfb_init(struct radeonfb_softc * sc)532 radeonfb_init(struct radeonfb_softc *sc)
533 {
534 radeonfb_wait_fifo(sc, 2);
535 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
536 RADEON_DEFAULT_PITCH_OFFSET,
537 ((sc->sc_sunfb.sf_linebytes >> 6) << 22) | (sc->sc_memoff >> 10));
538 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
539 RADEON_DEFAULT_SC_BOTTOM_RIGHT, 0x1fff1fff);
540 }
541
542 void
radeonfb_wait_fifo(struct radeonfb_softc * sc,int n)543 radeonfb_wait_fifo(struct radeonfb_softc *sc, int n)
544 {
545 int i;
546
547 for (i = 1000000; i != 0; i--) {
548 if ((bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
549 RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK) >= n)
550 break;
551 DELAY(1);
552 }
553 }
554
555 void
radeonfb_wait(struct radeonfb_softc * sc)556 radeonfb_wait(struct radeonfb_softc *sc)
557 {
558 int i;
559
560 radeonfb_wait_fifo(sc, 64);
561
562 for (i = 1000000; i != 0; i--) {
563 if ((bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
564 RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) == 0)
565 break;
566 DELAY(1);
567 }
568
569 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
570 RADEON_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_DC_FLUSH_ALL);
571
572 for (i = 1000000; i != 0; i--) {
573 if ((bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
574 RADEON_RB3D_DSTCACHE_CTLSTAT) & RADEON_RB3D_DC_BUSY) == 0)
575 break;
576 DELAY(1);
577 }
578 }
579
580 void
radeonfb_copyrect(struct radeonfb_softc * sc,int sx,int sy,int dx,int dy,int w,int h)581 radeonfb_copyrect(struct radeonfb_softc *sc, int sx, int sy, int dx, int dy,
582 int w, int h)
583 {
584 uint32_t gmc;
585 uint32_t dir;
586
587 radeonfb_wait_fifo(sc, 1);
588 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, RADEON_WAIT_UNTIL,
589 RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN);
590
591 if (dy < sy) {
592 dir = RADEON_DST_Y_TOP_TO_BOTTOM;
593 } else {
594 sy += h - 1;
595 dy += h - 1;
596 dir = 0;
597 }
598 if (dx < sx) {
599 dir |= RADEON_DST_X_LEFT_TO_RIGHT;
600 } else {
601 sx += w - 1;
602 dx += w - 1;
603 }
604
605 radeonfb_wait_fifo(sc, 6);
606
607 if (sc->sc_sunfb.sf_depth == 32)
608 gmc = RADEON_GMC_DST_32BPP;
609 else
610 gmc = RADEON_GMC_DST_8BPP;
611 gmc |= RADEON_GMC_BRUSH_NONE;
612 gmc |= RADEON_GMC_SRC_DATATYPE_COLOR;
613 gmc |= RADEON_GMC_SRC_SOURCE_MEMORY;
614 gmc |= RADEON_ROP3_S;
615 gmc |= RADEON_GMC_CLR_CMP_CNTL_DIS;
616 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
617 RADEON_DP_GUI_MASTER_CNTL, gmc);
618 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
619 RADEON_DP_WRITE_MASK, 0xffffffff);
620 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
621 RADEON_DP_CNTL, dir);
622
623 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
624 RADEON_SRC_Y_X, RADEON_COORDS(sx, sy));
625 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
626 RADEON_DST_Y_X, RADEON_COORDS(dx, dy));
627 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
628 RADEON_DST_HEIGHT_WIDTH, RADEON_COORDS(w, h));
629
630 radeonfb_wait(sc);
631 }
632
633 void
radeonfb_fillrect(struct radeonfb_softc * sc,int x,int y,int w,int h,int color)634 radeonfb_fillrect(struct radeonfb_softc *sc, int x, int y, int w, int h,
635 int color)
636 {
637 uint32_t gmc;
638
639 radeonfb_wait_fifo(sc, 1);
640 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, RADEON_WAIT_UNTIL,
641 RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN);
642
643 radeonfb_wait_fifo(sc, 6);
644
645 if (sc->sc_sunfb.sf_depth == 32)
646 gmc = RADEON_GMC_DST_32BPP;
647 else
648 gmc = RADEON_GMC_DST_8BPP;
649 gmc |= RADEON_GMC_BRUSH_SOLID_COLOR;
650 gmc |= RADEON_GMC_SRC_DATATYPE_COLOR;
651 gmc |= RADEON_ROP3_P;
652 gmc |= RADEON_GMC_CLR_CMP_CNTL_DIS;
653 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
654 RADEON_DP_GUI_MASTER_CNTL, gmc);
655 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
656 RADEON_DP_BRUSH_FRGD_CLR, color);
657 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
658 RADEON_DP_WRITE_MASK, 0xffffffff);
659 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, RADEON_DP_CNTL,
660 RADEON_DST_Y_TOP_TO_BOTTOM | RADEON_DST_X_LEFT_TO_RIGHT);
661
662 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
663 RADEON_DST_Y_X, RADEON_COORDS(x, y));
664 bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
665 RADEON_DST_HEIGHT_WIDTH, RADEON_COORDS(w, h));
666
667 radeonfb_wait(sc);
668 }
669