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 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 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 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 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 372 radeonfb_is_console(int node) 373 { 374 extern int fbnode; 375 376 return (fbnode == node); 377 } 378 379 int 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 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 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 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 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 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 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 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 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 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 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 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