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