123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 |
- /*
- * ATI Radeon [789]XXX vga driver
- * see /sys/src/cmd/aux/vga/radeon.c
- */
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "io.h"
- #include "../port/error.h"
- #define Image IMAGE
- #include <draw.h>
- #include <memdraw.h>
- #include <cursor.h>
- #include "screen.h"
- #include "/sys/src/cmd/aux/vga/radeon.h" /* ugh */
- /* #define HW_ACCEL */
- enum {
- Kilo = 1024,
- Meg = Kilo * Kilo,
- };
- static Pcidev*
- radeonpci(void)
- {
- static Pcidev *p = nil;
- struct pciids *ids;
- while ((p = pcimatch(p, ATI_PCIVID, 0)) != nil)
- for (ids = radeon_pciids; ids->did; ids++)
- if (ids->did == p->did)
- return p;
- return nil;
- }
- /* mmio access */
- static void
- OUTREG8(ulong mmio, ulong offset, uchar val)
- {
- ((uchar*)KADDR((mmio + offset)))[0] = val;
- }
- static void
- OUTREG(ulong mmio, ulong offset, ulong val)
- {
- ((ulong*)KADDR((mmio + offset)))[0] = val;
- }
- static ulong
- INREG(ulong mmio, ulong offset)
- {
- return ((ulong*)KADDR((mmio + offset)))[0];
- }
- static void
- OUTREGP(ulong mmio, ulong offset, ulong val, ulong mask)
- {
- OUTREG(mmio, offset, (INREG(mmio, offset) & mask) | val);
- }
- static void
- OUTPLL(ulong mmio, ulong offset, ulong val)
- {
- OUTREG8(mmio, CLOCK_CNTL_INDEX, (offset & 0x3f) | PLL_WR_EN);
- OUTREG(mmio, CLOCK_CNTL_DATA, val);
- }
- static ulong
- INPLL(ulong mmio, ulong offset)
- {
- OUTREG8(mmio, CLOCK_CNTL_INDEX, offset & 0x3f);
- return INREG(mmio, CLOCK_CNTL_DATA);
- }
- static void
- OUTPLLP(ulong mmio, ulong offset, ulong val, ulong mask)
- {
- OUTPLL(mmio, offset, (INPLL(mmio, offset) & mask) | val);
- }
- static void
- radeonlinear(VGAscr *, int, int)
- {
- }
- static void
- radeonenable(VGAscr *scr)
- {
- Pcidev *p;
- if (scr->mmio)
- return;
- p = radeonpci();
- if (p == nil)
- return;
- scr->id = p->did;
- scr->pci = p;
- scr->mmio = vmap(p->mem[2].bar & ~0x0f, p->mem[2].size);
- if(scr->mmio == 0)
- return;
- addvgaseg("radeonmmio", p->mem[2].bar & ~0x0f, p->mem[2].size);
- vgalinearpci(scr);
- if(scr->apsize) {
- addvgaseg("radeonscreen", scr->paddr, scr->apsize);
- mtrr(scr->paddr, scr->apsize, "wc");
- }
- }
- static void
- radeoncurload(VGAscr *scr, Cursor *curs)
- {
- int x, y;
- ulong *p;
- if(scr->mmio == nil)
- return;
- p = (ulong*)KADDR(scr->storage);
- for(y = 0; y < 64; y++){
- int cv, sv;
- if (y < 16) {
- cv = curs->clr[2*y] << 8 | curs->clr[2*y+1];
- sv = curs->set[2*y] << 8 | curs->set[2*y+1];
- } else
- cv = sv = 0;
- for(x = 0; x < 64; x++){
- ulong col = 0;
- int c, s;
- if (x < 16) {
- c = (cv >> (15 - x)) & 1;
- s = (sv >> (15 - x)) & 1;
- } else
- c = s = 0;
- switch(c | s<<1) {
- case 0:
- col = 0;
- break;
- case 1:
- col = ~0ul; /* white */
- break;
- case 2:
- case 3:
- col = 0xff000000; /* black */
- break;
- }
- *p++ = col;
- }
- }
- scr->offset.x = curs->offset.x;
- scr->offset.y = curs->offset.y;
- }
- static int
- radeoncurmove(VGAscr *scr, Point p)
- {
- int x, y, ox, oy;
- static ulong storage = 0;
- if(scr->mmio == nil)
- return 1;
- if (storage == 0)
- storage = scr->apsize - 1*Meg;
- x = p.x + scr->offset.x;
- y = p.y + scr->offset.y;
- ox = oy = 0;
- if (x < 0) {
- ox = -x - 1;
- x = 0;
- }
- if (y < 0) {
- oy = -y - 1;
- y = 0;
- }
- OUTREG((ulong)scr->mmio, CUR_OFFSET, storage + oy * 256);
- OUTREG((ulong)scr->mmio, CUR_HORZ_VERT_OFF,
- (ox & 0x7fff) << 16 | (oy & 0x7fff));
- OUTREG((ulong)scr->mmio, CUR_HORZ_VERT_POSN,
- (x & 0x7fff) << 16 | (y & 0x7fff));
- return 0;
- }
- static void
- radeoncurdisable(VGAscr *scr)
- {
- if(scr->mmio == nil)
- return;
- OUTREGP((ulong)scr->mmio, CRTC_GEN_CNTL, 0, ~CRTC_CUR_EN);
- }
- static void
- radeoncurenable(VGAscr *scr)
- {
- ulong storage;
- if(scr->mmio == 0)
- return;
- radeoncurdisable(scr);
- storage = scr->apsize - 1*Meg;
- scr->storage = (ulong)KADDR(scr->paddr + storage);
- radeoncurload(scr, &arrow);
- radeoncurmove(scr, ZP);
- OUTREGP((ulong)scr->mmio, CRTC_GEN_CNTL, CRTC_CUR_EN | 2<<20,
- ~(CRTC_CUR_EN | 3<<20));
- }
- /* hw blank */
- static void
- radeonblank(VGAscr* scr, int blank)
- {
- ulong mask;
- char *cp;
- if (scr->mmio == 0)
- return;
- // iprint("radeon: hwblank(%d)\n", blank);
- mask = CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS;
- if (blank == 0) {
- OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, 0, ~mask);
- return;
- }
- cp = getconf("*dpms");
- if (cp) {
- if (strcmp(cp, "standby") == 0)
- OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL,
- CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS, ~mask);
- else if (strcmp(cp, "suspend") == 0)
- OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL,
- CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS, ~mask);
- else if (strcmp(cp, "off") == 0)
- OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
- return;
- }
- OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
- }
- /* hw acceleration */
- static void
- radeonwaitfifo(VGAscr *scr, int entries)
- {
- int i;
- for (i = 0; i < 2000000; i++)
- if (INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK >=
- entries)
- return;
- iprint("radeon: fifo timeout\n");
- }
- static void
- radeonwaitidle(VGAscr *scr)
- {
- radeonwaitfifo(scr, 64);
- for (; ; ) {
- int i;
- for (i = 0; i < 2000000; i++)
- if (!(INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_ACTIVE))
- return;
- iprint("radeon: idle timed out: %uld entries, stat=0x%.8ulx\n",
- INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK,
- INREG((ulong)scr->mmio, RBBM_STATUS));
- }
- }
- static ulong dp_gui_master_cntl = 0;
- static int
- radeonfill(VGAscr *scr, Rectangle r, ulong color)
- {
- if (scr->mmio == nil)
- return 0;
- radeonwaitfifo(scr, 6);
- OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL,
- dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR |
- GMC_SRC_DATATYPE_COLOR | ROP3_P);
- OUTREG((ulong)scr->mmio, DP_BRUSH_FRGD_CLR, color);
- OUTREG((ulong)scr->mmio, DP_WRITE_MASK, ~0ul);
- OUTREG((ulong)scr->mmio, DP_CNTL,
- DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
- OUTREG((ulong)scr->mmio, DST_Y_X, r.min.y << 16 | r.min.x);
- OUTREG((ulong)scr->mmio, DST_WIDTH_HEIGHT, Dx(r) << 16 | Dy(r));
- radeonwaitidle(scr);
- return 1;
- }
- static int
- radeonscroll(VGAscr*scr, Rectangle dst, Rectangle src)
- {
- int xs, ys, xd, yd, w, h;
- ulong dp_cntl = 0x20;
- if (scr->mmio == nil)
- return 0;
- // iprint("radeon: hwscroll(dst:%R, src:%R)\n", dst, src);
- xd = dst.min.x;
- yd = dst.min.y;
- xs = src.min.x;
- ys = src.min.y;
- w = Dx(dst);
- h = Dy(dst);
- if (ys < yd) {
- ys += h - 1;
- yd += h - 1;
- } else
- dp_cntl |= DST_Y_TOP_TO_BOTTOM;
- if (xs < xd) {
- xs += w - 1;
- xd += w - 1;
- } else
- dp_cntl |= DST_X_LEFT_TO_RIGHT;
- radeonwaitfifo(scr, 6);
- OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL, dp_gui_master_cntl |
- GMC_BRUSH_NONE | GMC_SRC_DATATYPE_COLOR | DP_SRC_SOURCE_MEMORY |
- ROP3_S);
- OUTREG((ulong)scr->mmio, DP_WRITE_MASK, ~0ul);
- OUTREG((ulong)scr->mmio, DP_CNTL, dp_cntl);
- OUTREG((ulong)scr->mmio, SRC_Y_X, ys << 16 | xs);
- OUTREG((ulong)scr->mmio, DST_Y_X, yd << 16 | xd);
- OUTREG((ulong)scr->mmio, DST_WIDTH_HEIGHT, w << 16 | h);
- radeonwaitidle(scr);
- // iprint("radeon: hwscroll(xs=%d ys=%d xd=%d yd=%d w=%d h=%d)\n",
- // xs, ys, xd, yd, w, h);
- return 1;
- }
- static void
- radeondrawinit(VGAscr*scr)
- {
- ulong bpp, dtype, i, pitch, clock_cntl_index, mclk_cntl, rbbm_soft_reset;
- if (scr->mmio == 0)
- return;
- switch (scr->gscreen->depth) {
- case 6:
- case 8:
- dtype = 2;
- bpp = 1;
- break;
- case 15:
- dtype = 3;
- bpp = 2;
- break;
- case 16:
- dtype = 4;
- bpp = 2;
- break;
- case 32:
- dtype = 6;
- bpp = 4;
- break;
- default:
- return;
- }
- /* disable 3D */
- OUTREG((ulong)scr->mmio, RB3D_CNTL, 0);
- /* flush engine */
- OUTREGP((ulong)scr->mmio, RB2D_DSTCACHE_CTLSTAT,
- RB2D_DC_FLUSH_ALL, ~RB2D_DC_FLUSH_ALL);
- for (i = 0; i < 2000000; i++)
- if (!(INREG((ulong)scr->mmio, RB2D_DSTCACHE_CTLSTAT) &
- RB2D_DC_BUSY))
- break;
- /* reset 2D engine */
- clock_cntl_index = INREG((ulong)scr->mmio, CLOCK_CNTL_INDEX);
- mclk_cntl = INPLL((ulong)scr->mmio, MCLK_CNTL);
- OUTPLL((ulong)scr->mmio, MCLK_CNTL, mclk_cntl | FORCEON_MCLKA |
- FORCEON_MCLKB | FORCEON_YCLKA | FORCEON_YCLKB | FORCEON_MC |
- FORCEON_AIC);
- rbbm_soft_reset = INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
- OUTREG((ulong)scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset |
- SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
- SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB);
- INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
- OUTREG((ulong)scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset &
- ~(SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
- SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB));
- INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
- OUTPLL((ulong)scr->mmio, MCLK_CNTL, mclk_cntl);
- OUTREG((ulong)scr->mmio, CLOCK_CNTL_INDEX, clock_cntl_index);
- /* init 2D engine */
- radeonwaitfifo(scr, 1);
- OUTREG((ulong)scr->mmio, RB2D_DSTCACHE_MODE, 0);
- pitch = Dx(scr->gscreen->r) * bpp;
- radeonwaitfifo(scr, 4);
- OUTREG((ulong)scr->mmio, DEFAULT_PITCH, pitch);
- OUTREG((ulong)scr->mmio, DST_PITCH, pitch);
- OUTREG((ulong)scr->mmio, SRC_PITCH, pitch);
- OUTREG((ulong)scr->mmio, DST_PITCH_OFFSET_C, 0);
- radeonwaitfifo(scr, 3);
- OUTREG((ulong)scr->mmio, DEFAULT_OFFSET, 0);
- OUTREG((ulong)scr->mmio, DST_OFFSET, 0);
- OUTREG((ulong)scr->mmio, SRC_OFFSET, 0);
- radeonwaitfifo(scr, 1);
- OUTREGP((ulong)scr->mmio, DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
- radeonwaitfifo(scr, 1);
- OUTREG((ulong)scr->mmio, DEFAULT_SC_BOTTOM_RIGHT,
- DEFAULT_SC_RIGHT_MAX | DEFAULT_SC_BOTTOM_MAX);
- dp_gui_master_cntl = dtype << GMC_DST_DATATYPE_SHIFT |
- GMC_SRC_PITCH_OFFSET_CNTL | GMC_DST_PITCH_OFFSET_CNTL |
- GMC_CLR_CMP_CNTL_DIS;
- radeonwaitfifo(scr, 1);
- OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL,
- dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR | GMC_SRC_DATATYPE_COLOR);
- radeonwaitfifo(scr, 7);
- OUTREG((ulong)scr->mmio, DST_LINE_START, 0);
- OUTREG((ulong)scr->mmio, DST_LINE_END, 0);
- OUTREG((ulong)scr->mmio, DP_BRUSH_FRGD_CLR, ~0ul);
- OUTREG((ulong)scr->mmio, DP_BRUSH_BKGD_CLR, 0);
- OUTREG((ulong)scr->mmio, DP_SRC_FRGD_CLR, ~0ul);
- OUTREG((ulong)scr->mmio, DP_SRC_BKGD_CLR, 0);
- OUTREG((ulong)scr->mmio, DP_WRITE_MASK, ~0ul);
- radeonwaitidle(scr);
- scr->fill = radeonfill;
- scr->scroll = radeonscroll;
- hwaccel = 1;
- scr->blank = radeonblank;
- hwblank = 1;
- }
- /* hw overlay */
- static void
- radeonovlctl(VGAscr *scr, Chan *c, void *data, int len)
- {
- USED(scr, c, data, len);
- }
- static int
- radeonovlwrite(VGAscr *scr, void *data, int len, vlong opt)
- {
- USED(scr, data, len, opt);
- return -1;
- }
- static void
- radeonflush(VGAscr *scr, Rectangle r)
- {
- USED(scr, r);
- }
- /* Export */
- VGAdev vgaradeondev = {
- "radeon",
- radeonenable,
- 0, /* disable */
- 0, /* page */
- radeonlinear,
- radeondrawinit,
- #ifdef HW_ACCEL
- radeonfill,
- radeonovlctl,
- radeonovlwrite,
- radeonflush,
- #endif
- };
- VGAcur vgaradeoncur = {
- "radeonhwgc",
- radeoncurenable,
- radeoncurdisable,
- radeoncurload,
- radeoncurmove,
- 0 /* doespanning */
- };
|