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
95extern int allowaperture;
96#endif
97
98struct 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
120int	radeonfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
121paddr_t	radeonfb_mmap(void *, off_t, int);
122
123struct wsdisplay_accessops radeonfb_accessops = {
124	.ioctl = radeonfb_ioctl,
125	.mmap = radeonfb_mmap
126};
127
128int	radeonfb_match(struct device *, void *, void *);
129void	radeonfb_attach(struct device *, struct device *, void *);
130
131const struct cfattach radeonfb_ca = {
132	sizeof(struct radeonfb_softc), radeonfb_match, radeonfb_attach
133};
134
135struct cfdriver radeonfb_cd = {
136	NULL, "radeonfb", DV_DULL
137};
138
139int	radeonfb_is_console(int);
140int	radeonfb_getcmap(struct radeonfb_softc *, struct wsdisplay_cmap *);
141int	radeonfb_putcmap(struct radeonfb_softc *, struct wsdisplay_cmap *);
142void	radeonfb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
143
144int	radeonfb_copycols(void *, int, int, int, int);
145int	radeonfb_erasecols(void *, int, int, int, uint32_t);
146int	radeonfb_copyrows(void *, int, int, int);
147int	radeonfb_eraserows(void *, int, int, uint32_t);
148
149void	radeonfb_init(struct radeonfb_softc *);
150void	radeonfb_wait_fifo(struct radeonfb_softc *, int);
151void	radeonfb_wait(struct radeonfb_softc *);
152void	radeonfb_copyrect(struct radeonfb_softc *, int, int, int, int, int, int);
153void	radeonfb_fillrect(struct radeonfb_softc *, int, int, int, int, int);
154
155int
156radeonfb_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
171void
172radeonfb_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
240int
241radeonfb_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
316paddr_t
317radeonfb_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
371int
372radeonfb_is_console(int node)
373{
374	extern int fbnode;
375
376	return (fbnode == node);
377}
378
379int
380radeonfb_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
401int
402radeonfb_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
434void
435radeonfb_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
453int
454radeonfb_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
471int
472radeonfb_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
490int
491radeonfb_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
506int
507radeonfb_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
531void
532radeonfb_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
542void
543radeonfb_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
555void
556radeonfb_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
580void
581radeonfb_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
633void
634radeonfb_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