2 * ATI Radeon [789]XXX vga driver
3 * see /sys/src/cmd/aux/vga/radeon.c
6 #include "../port/lib.h"
11 #include "../port/error.h"
19 #include "/sys/src/cmd/aux/vga/radeon.h" /* ugh */
21 /* #define HW_ACCEL */
31 static Pcidev *p = nil;
34 while ((p = pcimatch(p, ATI_PCIVID, 0)) != nil)
35 for (ids = radeon_pciids; ids->did; ids++)
36 if (ids->did == p->did)
44 OUTREG8(ulong mmio, ulong offset, uchar val)
46 ((uchar*)KADDR((mmio + offset)))[0] = val;
50 OUTREG(ulong mmio, ulong offset, ulong val)
52 ((ulong*)KADDR((mmio + offset)))[0] = val;
56 INREG(ulong mmio, ulong offset)
58 return ((ulong*)KADDR((mmio + offset)))[0];
62 OUTREGP(ulong mmio, ulong offset, ulong val, ulong mask)
64 OUTREG(mmio, offset, (INREG(mmio, offset) & mask) | val);
68 OUTPLL(ulong mmio, ulong offset, ulong val)
70 OUTREG8(mmio, CLOCK_CNTL_INDEX, (offset & 0x3f) | PLL_WR_EN);
71 OUTREG(mmio, CLOCK_CNTL_DATA, val);
75 INPLL(ulong mmio, ulong offset)
77 OUTREG8(mmio, CLOCK_CNTL_INDEX, offset & 0x3f);
78 return INREG(mmio, CLOCK_CNTL_DATA);
82 OUTPLLP(ulong mmio, ulong offset, ulong val, ulong mask)
84 OUTPLL(mmio, offset, (INPLL(mmio, offset) & mask) | val);
88 radeonlinear(VGAscr *, int, int)
93 radeonenable(VGAscr *scr)
105 scr->mmio = vmap(p->mem[2].bar & ~0x0f, p->mem[2].size);
108 addvgaseg("radeonmmio", p->mem[2].bar & ~0x0f, p->mem[2].size);
112 addvgaseg("radeonscreen", scr->paddr, scr->apsize);
116 radeoncurload(VGAscr *scr, Cursor *curs)
124 p = (ulong*)KADDR(scr->storage);
126 for(y = 0; y < 64; y++){
130 cv = curs->clr[2*y] << 8 | curs->clr[2*y+1];
131 sv = curs->set[2*y] << 8 | curs->set[2*y+1];
135 for(x = 0; x < 64; x++){
140 c = (cv >> (15 - x)) & 1;
141 s = (sv >> (15 - x)) & 1;
150 col = ~0ul; /* white */
154 col = 0xff000000; /* black */
162 scr->offset.x = curs->offset.x;
163 scr->offset.y = curs->offset.y;
167 radeoncurmove(VGAscr *scr, Point p)
170 static ulong storage = 0;
176 storage = scr->apsize - 1*Meg;
178 x = p.x + scr->offset.x;
179 y = p.y + scr->offset.y;
191 OUTREG((ulong)scr->mmio, CUR_OFFSET, storage + oy * 256);
192 OUTREG((ulong)scr->mmio, CUR_HORZ_VERT_OFF,
193 (ox & 0x7fff) << 16 | (oy & 0x7fff));
194 OUTREG((ulong)scr->mmio, CUR_HORZ_VERT_POSN,
195 (x & 0x7fff) << 16 | (y & 0x7fff));
200 radeoncurdisable(VGAscr *scr)
204 OUTREGP((ulong)scr->mmio, CRTC_GEN_CNTL, 0, ~CRTC_CUR_EN);
208 radeoncurenable(VGAscr *scr)
215 radeoncurdisable(scr);
216 storage = scr->apsize - 1*Meg;
217 scr->storage = (ulong)KADDR(scr->paddr + storage);
218 radeoncurload(scr, &arrow);
219 radeoncurmove(scr, ZP);
221 OUTREGP((ulong)scr->mmio, CRTC_GEN_CNTL, CRTC_CUR_EN | 2<<20,
222 ~(CRTC_CUR_EN | 3<<20));
228 radeonblank(VGAscr* scr, int blank)
236 // iprint("radeon: hwblank(%d)\n", blank);
238 mask = CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS;
240 OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, 0, ~mask);
244 cp = getconf("*dpms");
246 if (strcmp(cp, "standby") == 0)
247 OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL,
248 CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS, ~mask);
249 else if (strcmp(cp, "suspend") == 0)
250 OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL,
251 CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS, ~mask);
252 else if (strcmp(cp, "off") == 0)
253 OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
257 OUTREGP((ulong)scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
260 /* hw acceleration */
263 radeonwaitfifo(VGAscr *scr, int entries)
267 for (i = 0; i < 2000000; i++)
268 if (INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK >=
271 iprint("radeon: fifo timeout\n");
275 radeonwaitidle(VGAscr *scr)
277 radeonwaitfifo(scr, 64);
282 for (i = 0; i < 2000000; i++)
283 if (!(INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_ACTIVE))
286 iprint("radeon: idle timed out: %uld entries, stat=0x%.8ulx\n",
287 INREG((ulong)scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK,
288 INREG((ulong)scr->mmio, RBBM_STATUS));
292 static ulong dp_gui_master_cntl = 0;
295 radeonfill(VGAscr *scr, Rectangle r, ulong color)
297 if (scr->mmio == nil)
300 radeonwaitfifo(scr, 6);
301 OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL,
302 dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR |
303 GMC_SRC_DATATYPE_COLOR | ROP3_P);
304 OUTREG((ulong)scr->mmio, DP_BRUSH_FRGD_CLR, color);
305 OUTREG((ulong)scr->mmio, DP_WRITE_MASK, ~0ul);
306 OUTREG((ulong)scr->mmio, DP_CNTL,
307 DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
308 OUTREG((ulong)scr->mmio, DST_Y_X, r.min.y << 16 | r.min.x);
309 OUTREG((ulong)scr->mmio, DST_WIDTH_HEIGHT, Dx(r) << 16 | Dy(r));
316 radeonscroll(VGAscr*scr, Rectangle dst, Rectangle src)
318 int xs, ys, xd, yd, w, h;
319 ulong dp_cntl = 0x20;
321 if (scr->mmio == nil)
324 // iprint("radeon: hwscroll(dst:%R, src:%R)\n", dst, src);
337 dp_cntl |= DST_Y_TOP_TO_BOTTOM;
343 dp_cntl |= DST_X_LEFT_TO_RIGHT;
345 radeonwaitfifo(scr, 6);
346 OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL, dp_gui_master_cntl |
347 GMC_BRUSH_NONE | GMC_SRC_DATATYPE_COLOR | DP_SRC_SOURCE_MEMORY |
349 OUTREG((ulong)scr->mmio, DP_WRITE_MASK, ~0ul);
350 OUTREG((ulong)scr->mmio, DP_CNTL, dp_cntl);
351 OUTREG((ulong)scr->mmio, SRC_Y_X, ys << 16 | xs);
352 OUTREG((ulong)scr->mmio, DST_Y_X, yd << 16 | xd);
353 OUTREG((ulong)scr->mmio, DST_WIDTH_HEIGHT, w << 16 | h);
357 // iprint("radeon: hwscroll(xs=%d ys=%d xd=%d yd=%d w=%d h=%d)\n",
358 // xs, ys, xd, yd, w, h);
363 radeondrawinit(VGAscr*scr)
365 ulong bpp, dtype, i, pitch, clock_cntl_index, mclk_cntl, rbbm_soft_reset;
370 switch (scr->gscreen->depth) {
393 OUTREG((ulong)scr->mmio, RB3D_CNTL, 0);
396 OUTREGP((ulong)scr->mmio, RB2D_DSTCACHE_CTLSTAT,
397 RB2D_DC_FLUSH_ALL, ~RB2D_DC_FLUSH_ALL);
398 for (i = 0; i < 2000000; i++)
399 if (!(INREG((ulong)scr->mmio, RB2D_DSTCACHE_CTLSTAT) &
403 /* reset 2D engine */
404 clock_cntl_index = INREG((ulong)scr->mmio, CLOCK_CNTL_INDEX);
406 mclk_cntl = INPLL((ulong)scr->mmio, MCLK_CNTL);
407 OUTPLL((ulong)scr->mmio, MCLK_CNTL, mclk_cntl | FORCEON_MCLKA |
408 FORCEON_MCLKB | FORCEON_YCLKA | FORCEON_YCLKB | FORCEON_MC |
410 rbbm_soft_reset = INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
412 OUTREG((ulong)scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset |
413 SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
414 SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB);
415 INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
416 OUTREG((ulong)scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset &
417 ~(SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
418 SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB));
419 INREG((ulong)scr->mmio, RBBM_SOFT_RESET);
421 OUTPLL((ulong)scr->mmio, MCLK_CNTL, mclk_cntl);
422 OUTREG((ulong)scr->mmio, CLOCK_CNTL_INDEX, clock_cntl_index);
425 radeonwaitfifo(scr, 1);
426 OUTREG((ulong)scr->mmio, RB2D_DSTCACHE_MODE, 0);
428 pitch = Dx(scr->gscreen->r) * bpp;
429 radeonwaitfifo(scr, 4);
430 OUTREG((ulong)scr->mmio, DEFAULT_PITCH, pitch);
431 OUTREG((ulong)scr->mmio, DST_PITCH, pitch);
432 OUTREG((ulong)scr->mmio, SRC_PITCH, pitch);
433 OUTREG((ulong)scr->mmio, DST_PITCH_OFFSET_C, 0);
435 radeonwaitfifo(scr, 3);
436 OUTREG((ulong)scr->mmio, DEFAULT_OFFSET, 0);
437 OUTREG((ulong)scr->mmio, DST_OFFSET, 0);
438 OUTREG((ulong)scr->mmio, SRC_OFFSET, 0);
440 radeonwaitfifo(scr, 1);
441 OUTREGP((ulong)scr->mmio, DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
443 radeonwaitfifo(scr, 1);
444 OUTREG((ulong)scr->mmio, DEFAULT_SC_BOTTOM_RIGHT,
445 DEFAULT_SC_RIGHT_MAX | DEFAULT_SC_BOTTOM_MAX);
447 dp_gui_master_cntl = dtype << GMC_DST_DATATYPE_SHIFT |
448 GMC_SRC_PITCH_OFFSET_CNTL | GMC_DST_PITCH_OFFSET_CNTL |
449 GMC_CLR_CMP_CNTL_DIS;
450 radeonwaitfifo(scr, 1);
451 OUTREG((ulong)scr->mmio, DP_GUI_MASTER_CNTL,
452 dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR | GMC_SRC_DATATYPE_COLOR);
454 radeonwaitfifo(scr, 7);
455 OUTREG((ulong)scr->mmio, DST_LINE_START, 0);
456 OUTREG((ulong)scr->mmio, DST_LINE_END, 0);
457 OUTREG((ulong)scr->mmio, DP_BRUSH_FRGD_CLR, ~0ul);
458 OUTREG((ulong)scr->mmio, DP_BRUSH_BKGD_CLR, 0);
459 OUTREG((ulong)scr->mmio, DP_SRC_FRGD_CLR, ~0ul);
460 OUTREG((ulong)scr->mmio, DP_SRC_BKGD_CLR, 0);
461 OUTREG((ulong)scr->mmio, DP_WRITE_MASK, ~0ul);
465 scr->fill = radeonfill;
466 scr->scroll = radeonscroll;
469 scr->blank = radeonblank;
476 radeonovlctl(VGAscr *scr, Chan *c, void *data, int len)
478 USED(scr, c, data, len);
482 radeonovlwrite(VGAscr *scr, void *data, int len, vlong opt)
484 USED(scr, data, len, opt);
489 radeonflush(VGAscr *scr, Rectangle r)
496 VGAdev vgaradeondev = {
513 VGAcur vgaradeoncur = {