xref: /openbsd/sys/arch/sparc64/dev/radeonfb.c (revision 3d8817e4)
1 /*	$OpenBSD: radeonfb.c,v 1.4 2011/02/21 07:54:47 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 	radeonfb_ioctl,
125 	radeonfb_mmap,
126 	NULL,	/* alloc_screen */
127 	NULL,	/* free_screen */
128 	NULL,	/* show_screen */
129 	NULL,	/* load_font */
130 	NULL,	/* scrollback */
131 	NULL,	/* getchar */
132 	NULL,	/* burner */
133 	NULL	/* pollc */
134 };
135 
136 int	radeonfb_match(struct device *, void *, void *);
137 void	radeonfb_attach(struct device *, struct device *, void *);
138 
139 struct cfattach radeonfb_ca = {
140 	sizeof(struct radeonfb_softc), radeonfb_match, radeonfb_attach
141 };
142 
143 struct cfdriver radeonfb_cd = {
144 	NULL, "radeonfb", DV_DULL
145 };
146 
147 int	radeonfb_is_console(int);
148 int	radeonfb_getcmap(struct radeonfb_softc *, struct wsdisplay_cmap *);
149 int	radeonfb_putcmap(struct radeonfb_softc *, struct wsdisplay_cmap *);
150 void	radeonfb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
151 
152 int	radeonfb_copycols(void *, int, int, int, int);
153 int	radeonfb_erasecols(void *, int, int, int, long);
154 int	radeonfb_copyrows(void *, int, int, int);
155 int	radeonfb_eraserows(void *, int, int, long);
156 
157 void	radeonfb_init(struct radeonfb_softc *);
158 void	radeonfb_wait_fifo(struct radeonfb_softc *, int);
159 void	radeonfb_wait(struct radeonfb_softc *);
160 void	radeonfb_copyrect(struct radeonfb_softc *, int, int, int, int, int, int);
161 void	radeonfb_fillrect(struct radeonfb_softc *, int, int, int, int, int);
162 
163 int
164 radeonfb_match(struct device *parent, void *cf, void *aux)
165 {
166 	struct pci_attach_args *pa = aux;
167 	char buf[32];
168 	int node;
169 
170 	node = PCITAG_NODE(pa->pa_tag);
171 	OF_getprop(node, "name", buf, sizeof(buf));
172 	if (strcmp(buf, "SUNW,XVR-100") == 0 ||
173 	    strcmp(buf, "SUNW,XVR-300") == 0)
174 		return (10);
175 
176 	return (0);
177 }
178 
179 void
180 radeonfb_attach(struct device *parent, struct device *self, void *aux)
181 {
182 	struct radeonfb_softc *sc = (struct radeonfb_softc *)self;
183 	struct pci_attach_args *pa = aux;
184 	struct rasops_info *ri;
185 	int node, console, flags;
186 	char *model;
187 
188 	sc->sc_pcitag = pa->pa_tag;
189 
190 	node = PCITAG_NODE(pa->pa_tag);
191 	console = radeonfb_is_console(node);
192 
193 	printf("\n");
194 
195 	model = getpropstring(node, "model");
196 	printf("%s: %s", self->dv_xname, model);
197 
198 	if (pci_mapreg_map(pa, RADEON_PCI_MEM, PCI_MAPREG_TYPE_MEM,
199 	    BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh,
200 	    &sc->sc_membase, &sc->sc_memsize, 0)) {
201 		printf("\n%s: can't map video memory\n", self->dv_xname);
202 		return;
203 	}
204 
205 	if (pci_mapreg_map(pa, RADEON_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0,
206 	    &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase,
207 	    &sc->sc_mmiosize, 0)) {
208 		printf("\n%s: can't map registers\n", self->dv_xname);
209 		return;
210 	}
211 
212 	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
213 
214 	printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
215 
216 	/*
217 	 * The firmware sets up the framebuffer such that at starts at
218 	 * an offset from the start of video memory.
219 	 */
220 	sc->sc_memoff =
221 	    bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, RADEON_CRTC_OFFSET);
222 
223 	ri = &sc->sc_sunfb.sf_ro;
224 	ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh);
225 	ri->ri_bits += sc->sc_memoff;
226 	ri->ri_hw = sc;
227 
228 	if (sc->sc_sunfb.sf_depth == 32)
229 		flags = 0;
230 	else
231 		flags = RI_BSWAP;
232 
233 	fbwscons_init(&sc->sc_sunfb, flags, console);
234 	fbwscons_setcolormap(&sc->sc_sunfb, radeonfb_setcolor);
235 	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
236 
237 	radeonfb_init(sc);
238 	ri->ri_ops.copyrows = radeonfb_copyrows;
239 	ri->ri_ops.copycols = radeonfb_copycols;
240 	ri->ri_ops.eraserows = radeonfb_eraserows;
241 	ri->ri_ops.erasecols = radeonfb_erasecols;
242 
243 	if (console)
244 		fbwscons_console_init(&sc->sc_sunfb, -1);
245 	fbwscons_attach(&sc->sc_sunfb, &radeonfb_accessops, console);
246 }
247 
248 int
249 radeonfb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
250 {
251 	struct radeonfb_softc *sc = v;
252 	struct wsdisplay_fbinfo *wdf;
253 	struct pcisel *sel;
254 
255 	switch (cmd) {
256 	case WSDISPLAYIO_GTYPE:
257 		*(u_int *)data = WSDISPLAY_TYPE_RADEONFB;
258 		break;
259 	case WSDISPLAYIO_SMODE:
260 		sc->sc_mode = *(u_int *)data;
261 		if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
262 			struct rasops_info *ri = &sc->sc_sunfb.sf_ro;
263 
264 			/* Restore colormap. */
265 			fbwscons_setcolormap(&sc->sc_sunfb, radeonfb_setcolor);
266 
267 			/* Clear screen. */
268 			radeonfb_init(sc);
269 			radeonfb_fillrect(sc, 0, 0, ri->ri_width,
270 			    ri->ri_height, ri->ri_devcmap[WSCOL_WHITE]);
271 		}
272 		break;
273 
274 	case WSDISPLAYIO_GINFO:
275 		wdf = (void *)data;
276 		wdf->height = sc->sc_sunfb.sf_height;
277 		wdf->width  = sc->sc_sunfb.sf_width;
278 		wdf->depth  = sc->sc_sunfb.sf_depth;
279 		if (sc->sc_sunfb.sf_depth == 32)
280 			wdf->cmsize = 0;
281 		else
282 			wdf->cmsize = 256;
283 		break;
284 	case WSDISPLAYIO_GETSUPPORTEDDEPTH:
285 		if (sc->sc_sunfb.sf_depth == 32)
286 			*(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
287 		else
288 			return (-1);
289 		break;
290 	case WSDISPLAYIO_LINEBYTES:
291 		*(u_int *)data = sc->sc_sunfb.sf_linebytes;
292 		break;
293 
294 	case WSDISPLAYIO_GETCMAP:
295 		return radeonfb_getcmap(sc, (struct wsdisplay_cmap *)data);
296 	case WSDISPLAYIO_PUTCMAP:
297 		return radeonfb_putcmap(sc, (struct wsdisplay_cmap *)data);
298 
299 	case WSDISPLAYIO_GPCIID:
300 		sel = (struct pcisel *)data;
301 		sel->pc_bus = PCITAG_BUS(sc->sc_pcitag);
302 		sel->pc_dev = PCITAG_DEV(sc->sc_pcitag);
303 		sel->pc_func = PCITAG_FUN(sc->sc_pcitag);
304 		break;
305 
306 	case WSDISPLAYIO_SVIDEO:
307 	case WSDISPLAYIO_GVIDEO:
308 		break;
309 
310 	case WSDISPLAYIO_GCURPOS:
311 	case WSDISPLAYIO_SCURPOS:
312 	case WSDISPLAYIO_GCURMAX:
313 	case WSDISPLAYIO_GCURSOR:
314 	case WSDISPLAYIO_SCURSOR:
315 	default:
316 		return -1; /* not supported yet */
317         }
318 
319 	return (0);
320 }
321 
322 paddr_t
323 radeonfb_mmap(void *v, off_t off, int prot)
324 {
325 	struct radeonfb_softc *sc = v;
326 
327 	if (off & PGOFSET)
328 		return (-1);
329 
330 	switch (sc->sc_mode) {
331 	case WSDISPLAYIO_MODE_MAPPED:
332 #ifdef APERTURE
333 		if (allowaperture == 0)
334 			return (-1);
335 #endif
336 
337 		if (sc->sc_mmiosize == 0)
338 			return (-1);
339 
340 		if (off >= sc->sc_membase &&
341 		    off < (sc->sc_membase + sc->sc_memsize))
342 			return (bus_space_mmap(sc->sc_memt,
343 			    sc->sc_membase, off - sc->sc_membase,
344 			    prot, BUS_SPACE_MAP_LINEAR));
345 
346 		if (off >= sc->sc_mmiobase &&
347 		    off < (sc->sc_mmiobase + sc->sc_mmiosize))
348 			return (bus_space_mmap(sc->sc_mmiot,
349 			    sc->sc_mmiobase, off - sc->sc_mmiobase,
350 			    prot, BUS_SPACE_MAP_LINEAR));
351 		break;
352 
353 	case WSDISPLAYIO_MODE_DUMBFB:
354 		if ((sc->sc_memoff % PAGE_SIZE) != 0)
355 			return (-1);
356 
357 		if (off >= 0 && off < sc->sc_memsize / 2) {
358 			bus_addr_t base = sc->sc_membase + sc->sc_memoff;
359 
360 			/*
361 			 * In 32bpp mode, use the second aperture,
362 			 * which has been set up by the firmware to do
363 			 * proper byte swapping.
364 			 */
365 			if (sc->sc_sunfb.sf_depth == 32)
366 				base += sc->sc_memsize / 2;
367 
368 			return (bus_space_mmap(sc->sc_memt, base, off,
369 			    prot, BUS_SPACE_MAP_LINEAR));
370 		}
371 		break;
372 	}
373 
374 	return (-1);
375 }
376 
377 int
378 radeonfb_is_console(int node)
379 {
380 	extern int fbnode;
381 
382 	return (fbnode == node);
383 }
384 
385 int
386 radeonfb_getcmap(struct radeonfb_softc *sc, struct wsdisplay_cmap *cm)
387 {
388 	u_int index = cm->index;
389 	u_int count = cm->count;
390 	int error;
391 
392 	if (index >= 256 || count > 256 - index)
393 		return (EINVAL);
394 
395 	error = copyout(&sc->sc_cmap_red[index], cm->red, count);
396 	if (error)
397 		return (error);
398 	error = copyout(&sc->sc_cmap_green[index], cm->green, count);
399 	if (error)
400 		return (error);
401 	error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
402 	if (error)
403 		return (error);
404 	return (0);
405 }
406 
407 int
408 radeonfb_putcmap(struct radeonfb_softc *sc, struct wsdisplay_cmap *cm)
409 {
410 	u_int index = cm->index;
411 	u_int count = cm->count;
412 	u_int i;
413 	int error;
414 	u_char *r, *g, *b;
415 
416 	if (index >= 256 || count > 256 - index)
417 		return (EINVAL);
418 
419 	if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0)
420 		return (error);
421 	if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0)
422 		return (error);
423 	if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0)
424 		return (error);
425 
426 	r = &sc->sc_cmap_red[index];
427 	g = &sc->sc_cmap_green[index];
428 	b = &sc->sc_cmap_blue[index];
429 
430 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
431 	    RADEON_PALETTE_INDEX, index);
432 	for (i = 0; i < count; i++) {
433 		bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
434 		    RADEON_PALETTE_DATA, (*r << 16) | (*g << 8) | *b);
435 		r++, g++, b++;
436 	}
437 	return (0);
438 }
439 
440 void
441 radeonfb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
442 {
443 	struct radeonfb_softc *sc = v;
444 
445 	sc->sc_cmap_red[index] = r;
446 	sc->sc_cmap_green[index] = g;
447 	sc->sc_cmap_blue[index] = b;
448 
449 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
450 	    RADEON_PALETTE_INDEX, index);
451 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
452 	    RADEON_PALETTE_DATA, (r << 16) | (g << 8) | b);
453 }
454 
455 /*
456  * Accelerated routines.
457  */
458 
459 int
460 radeonfb_copycols(void *cookie, int row, int src, int dst, int num)
461 {
462 	struct rasops_info *ri = cookie;
463 	struct radeonfb_softc *sc = ri->ri_hw;
464 
465 	num *= ri->ri_font->fontwidth;
466 	src *= ri->ri_font->fontwidth;
467 	dst *= ri->ri_font->fontwidth;
468 	row *= ri->ri_font->fontheight;
469 
470 	radeonfb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row,
471 	    ri->ri_xorigin + dst, ri->ri_yorigin + row,
472 	    num, ri->ri_font->fontheight);
473 
474 	return 0;
475 }
476 
477 int
478 radeonfb_erasecols(void *cookie, int row, int col, int num, long attr)
479 {
480 	struct rasops_info *ri = cookie;
481 	struct radeonfb_softc *sc = ri->ri_hw;
482 	int bg, fg;
483 
484 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
485 
486 	row *= ri->ri_font->fontheight;
487 	col *= ri->ri_font->fontwidth;
488 	num *= ri->ri_font->fontwidth;
489 
490 	radeonfb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row,
491 	    num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
492 
493 	return 0;
494 }
495 
496 int
497 radeonfb_copyrows(void *cookie, int src, int dst, int num)
498 {
499 	struct rasops_info *ri = cookie;
500 	struct radeonfb_softc *sc = ri->ri_hw;
501 
502 	num *= ri->ri_font->fontheight;
503 	src *= ri->ri_font->fontheight;
504 	dst *= ri->ri_font->fontheight;
505 
506 	radeonfb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src,
507 	    ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
508 
509 	return 0;
510 }
511 
512 int
513 radeonfb_eraserows(void *cookie, int row, int num, long attr)
514 {
515 	struct rasops_info *ri = cookie;
516 	struct radeonfb_softc *sc = ri->ri_hw;
517 	int bg, fg;
518 	int x, y, w;
519 
520 	ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
521 
522 	if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
523 		num = ri->ri_height;
524 		x = y = 0;
525 		w = ri->ri_width;
526 	} else {
527 		num *= ri->ri_font->fontheight;
528 		x = ri->ri_xorigin;
529 		y = ri->ri_yorigin + row * ri->ri_font->fontheight;
530 		w = ri->ri_emuwidth;
531 	}
532 	radeonfb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]);
533 
534 	return 0;
535 }
536 
537 void
538 radeonfb_init(struct radeonfb_softc *sc)
539 {
540 	radeonfb_wait_fifo(sc, 2);
541 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
542 	    RADEON_DEFAULT_PITCH_OFFSET,
543 	    ((sc->sc_sunfb.sf_linebytes >> 6) << 22) | (sc->sc_memoff >> 10));
544 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
545 	    RADEON_DEFAULT_SC_BOTTOM_RIGHT, 0x1fff1fff);
546 }
547 
548 void
549 radeonfb_wait_fifo(struct radeonfb_softc *sc, int n)
550 {
551 	int i;
552 
553 	for (i = 1000000; i != 0; i--) {
554 		if ((bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
555 		    RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK) >= n)
556 			break;
557 		DELAY(1);
558 	}
559 }
560 
561 void
562 radeonfb_wait(struct radeonfb_softc *sc)
563 {
564 	int i;
565 
566 	radeonfb_wait_fifo(sc, 64);
567 
568 	for (i = 1000000; i != 0; i--) {
569 		if ((bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
570 		    RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) == 0)
571 			break;
572 		DELAY(1);
573 	}
574 
575 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
576 	    RADEON_RB3D_DSTCACHE_CTLSTAT, RADEON_RB3D_DC_FLUSH_ALL);
577 
578 	for (i = 1000000; i != 0; i--) {
579 		if ((bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh,
580 		    RADEON_RB3D_DSTCACHE_CTLSTAT) & RADEON_RB3D_DC_BUSY) == 0)
581 			break;
582 		DELAY(1);
583 	}
584 }
585 
586 void
587 radeonfb_copyrect(struct radeonfb_softc *sc, int sx, int sy, int dx, int dy,
588     int w, int h)
589 {
590 	uint32_t gmc;
591 	uint32_t dir;
592 
593 	radeonfb_wait_fifo(sc, 1);
594 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, RADEON_WAIT_UNTIL,
595 	    RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN);
596 
597 	if (dy < sy) {
598 		dir = RADEON_DST_Y_TOP_TO_BOTTOM;
599 	} else {
600 		sy += h - 1;
601 		dy += h - 1;
602 		dir = 0;
603 	}
604 	if (dx < sx) {
605 		dir |= RADEON_DST_X_LEFT_TO_RIGHT;
606 	} else {
607 		sx += w - 1;
608 		dx += w - 1;
609 	}
610 
611 	radeonfb_wait_fifo(sc, 6);
612 
613 	if (sc->sc_sunfb.sf_depth == 32)
614 		gmc = RADEON_GMC_DST_32BPP;
615 	else
616 		gmc = RADEON_GMC_DST_8BPP;
617 	gmc |= RADEON_GMC_BRUSH_NONE;
618 	gmc |= RADEON_GMC_SRC_DATATYPE_COLOR;
619 	gmc |= RADEON_GMC_SRC_SOURCE_MEMORY;
620 	gmc |= RADEON_ROP3_S;
621 	gmc |= RADEON_GMC_CLR_CMP_CNTL_DIS;
622 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
623 	    RADEON_DP_GUI_MASTER_CNTL, gmc);
624 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
625 	    RADEON_DP_WRITE_MASK, 0xffffffff);
626 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
627 	    RADEON_DP_CNTL, dir);
628 
629 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
630 	    RADEON_SRC_Y_X, RADEON_COORDS(sx, sy));
631 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
632 	    RADEON_DST_Y_X, RADEON_COORDS(dx, dy));
633 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
634 	    RADEON_DST_HEIGHT_WIDTH, RADEON_COORDS(w, h));
635 
636 	radeonfb_wait(sc);
637 }
638 
639 void
640 radeonfb_fillrect(struct radeonfb_softc *sc, int x, int y, int w, int h,
641     int color)
642 {
643 	uint32_t gmc;
644 
645 	radeonfb_wait_fifo(sc, 1);
646 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, RADEON_WAIT_UNTIL,
647 	    RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN);
648 
649 	radeonfb_wait_fifo(sc, 6);
650 
651 	if (sc->sc_sunfb.sf_depth == 32)
652 		gmc = RADEON_GMC_DST_32BPP;
653 	else
654 		gmc = RADEON_GMC_DST_8BPP;
655 	gmc |= RADEON_GMC_BRUSH_SOLID_COLOR;
656 	gmc |= RADEON_GMC_SRC_DATATYPE_COLOR;
657 	gmc |= RADEON_ROP3_P;
658 	gmc |= RADEON_GMC_CLR_CMP_CNTL_DIS;
659 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
660 	    RADEON_DP_GUI_MASTER_CNTL, gmc);
661 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
662 	    RADEON_DP_BRUSH_FRGD_CLR, color);
663 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
664 	    RADEON_DP_WRITE_MASK, 0xffffffff);
665 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, RADEON_DP_CNTL,
666 	    RADEON_DST_Y_TOP_TO_BOTTOM | RADEON_DST_X_LEFT_TO_RIGHT);
667 
668 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
669 	    RADEON_DST_Y_X, RADEON_COORDS(x, y));
670 	bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh,
671 	    RADEON_DST_HEIGHT_WIDTH, RADEON_COORDS(w, h));
672 
673         radeonfb_wait(sc);
674 }
675