2 * ATI Radeon [789]XXX vga driver
3 * see /sys/src/cmd/aux/vga/radeon.c
6 #include "../port/lib.h"
11 #include "../port/pci.h"
12 #include "../port/error.h"
20 #include "/sys/src/cmd/aux/vga/radeon.h" /* ugh */
22 /* #define HW_ACCEL */
32 OUTREG8(ulong *mmio, ulong offset, uchar val)
34 ((uchar*)KADDR((((uintptr)mmio) + offset)))[0] = val;
38 OUTREG(ulong *mmio, ulong offset, ulong val)
40 ((ulong*)KADDR((((uintptr)mmio) + offset)))[0] = val;
44 INREG(ulong *mmio, ulong offset)
46 return ((ulong*)KADDR((((uintptr)mmio) + offset)))[0];
50 OUTREGP(ulong *mmio, ulong offset, ulong val, ulong mask)
52 OUTREG(mmio, offset, (INREG(mmio, offset) & mask) | val);
56 OUTPLL(ulong *mmio, ulong offset, ulong val)
58 OUTREG8(mmio, CLOCK_CNTL_INDEX, (offset & 0x3f) | PLL_WR_EN);
59 OUTREG(mmio, CLOCK_CNTL_DATA, val);
63 INPLL(ulong *mmio, ulong offset)
65 OUTREG8(mmio, CLOCK_CNTL_INDEX, offset & 0x3f);
66 return INREG(mmio, CLOCK_CNTL_DATA);
70 OUTPLLP(ulong *mmio, ulong offset, ulong val, ulong mask)
72 OUTPLL(mmio, offset, (INPLL(mmio, offset) & mask) | val);
76 radeonlinear(VGAscr *, int, int)
81 radeonenable(VGAscr *scr)
93 scr->mmio = vmap(p->mem[2].bar & ~0x0f, p->mem[2].size);
96 addvgaseg("radeonmmio", p->mem[2].bar & ~0x0f, p->mem[2].size);
100 addvgaseg("radeonscreen", scr->paddr, scr->apsize);
104 radeoncurload(VGAscr *scr, Cursor *curs)
112 p = (ulong*)KADDR(scr->storage);
114 for(y = 0; y < 64; y++){
118 cv = curs->clr[2*y] << 8 | curs->clr[2*y+1];
119 sv = curs->set[2*y] << 8 | curs->set[2*y+1];
123 for(x = 0; x < 64; x++){
128 c = (cv >> (15 - x)) & 1;
129 s = (sv >> (15 - x)) & 1;
138 col = ~0ul; /* white */
142 col = 0xff000000; /* black */
150 scr->offset.x = curs->offset.x;
151 scr->offset.y = curs->offset.y;
155 radeoncurmove(VGAscr *scr, Point p)
158 static ulong storage = 0;
164 storage = scr->apsize - 1*Meg;
166 x = p.x + scr->offset.x;
167 y = p.y + scr->offset.y;
179 OUTREG(scr->mmio, CUR_OFFSET, storage + oy * 256);
180 OUTREG(scr->mmio, CUR_HORZ_VERT_OFF,
181 (ox & 0x7fff) << 16 | (oy & 0x7fff));
182 OUTREG(scr->mmio, CUR_HORZ_VERT_POSN,
183 (x & 0x7fff) << 16 | (y & 0x7fff));
188 radeoncurdisable(VGAscr *scr)
192 OUTREGP(scr->mmio, CRTC_GEN_CNTL, 0, ~CRTC_CUR_EN);
196 radeoncurenable(VGAscr *scr)
203 radeoncurdisable(scr);
204 storage = scr->apsize - 1*Meg;
205 scr->storage = (uintptr)KADDR(scr->paddr + storage);
206 radeoncurload(scr, &cursor);
207 radeoncurmove(scr, ZP);
209 OUTREGP(scr->mmio, CRTC_GEN_CNTL, CRTC_CUR_EN | 2<<20,
210 ~(CRTC_CUR_EN | 3<<20));
216 radeonblank(VGAscr* scr, int blank)
224 // iprint("radeon: hwblank(%d)\n", blank);
226 mask = CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS;
228 OUTREGP(scr->mmio, CRTC_EXT_CNTL, 0, ~mask);
232 cp = getconf("*dpms");
234 if (strcmp(cp, "standby") == 0)
235 OUTREGP(scr->mmio, CRTC_EXT_CNTL,
236 CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS, ~mask);
237 else if (strcmp(cp, "suspend") == 0)
238 OUTREGP(scr->mmio, CRTC_EXT_CNTL,
239 CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS, ~mask);
240 else if (strcmp(cp, "off") == 0)
241 OUTREGP(scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
245 OUTREGP(scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
248 /* hw acceleration */
251 radeonwaitfifo(VGAscr *scr, int entries)
255 for (i = 0; i < 2000000; i++)
256 if (INREG(scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK >=
259 iprint("radeon: fifo timeout\n");
263 radeonwaitidle(VGAscr *scr)
265 radeonwaitfifo(scr, 64);
270 for (i = 0; i < 2000000; i++)
271 if (!(INREG(scr->mmio, RBBM_STATUS) & RBBM_ACTIVE))
274 iprint("radeon: idle timed out: %uld entries, stat=0x%.8ulx\n",
275 INREG(scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK,
276 INREG(scr->mmio, RBBM_STATUS));
280 static ulong dp_gui_master_cntl = 0;
283 radeonfill(VGAscr *scr, Rectangle r, ulong color)
285 if (scr->mmio == nil)
288 radeonwaitfifo(scr, 6);
289 OUTREG(scr->mmio, DP_GUI_MASTER_CNTL,
290 dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR |
291 GMC_SRC_DATATYPE_COLOR | ROP3_P);
292 OUTREG(scr->mmio, DP_BRUSH_FRGD_CLR, color);
293 OUTREG(scr->mmio, DP_WRITE_MASK, ~0ul);
294 OUTREG(scr->mmio, DP_CNTL,
295 DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
296 OUTREG(scr->mmio, DST_Y_X, r.min.y << 16 | r.min.x);
297 OUTREG(scr->mmio, DST_WIDTH_HEIGHT, Dx(r) << 16 | Dy(r));
304 radeonscroll(VGAscr*scr, Rectangle dst, Rectangle src)
306 int xs, ys, xd, yd, w, h;
307 ulong dp_cntl = 0x20;
309 if (scr->mmio == nil)
312 // iprint("radeon: hwscroll(dst:%R, src:%R)\n", dst, src);
325 dp_cntl |= DST_Y_TOP_TO_BOTTOM;
331 dp_cntl |= DST_X_LEFT_TO_RIGHT;
333 radeonwaitfifo(scr, 6);
334 OUTREG(scr->mmio, DP_GUI_MASTER_CNTL, dp_gui_master_cntl |
335 GMC_BRUSH_NONE | GMC_SRC_DATATYPE_COLOR | DP_SRC_SOURCE_MEMORY |
337 OUTREG(scr->mmio, DP_WRITE_MASK, ~0ul);
338 OUTREG(scr->mmio, DP_CNTL, dp_cntl);
339 OUTREG(scr->mmio, SRC_Y_X, ys << 16 | xs);
340 OUTREG(scr->mmio, DST_Y_X, yd << 16 | xd);
341 OUTREG(scr->mmio, DST_WIDTH_HEIGHT, w << 16 | h);
345 // iprint("radeon: hwscroll(xs=%d ys=%d xd=%d yd=%d w=%d h=%d)\n",
346 // xs, ys, xd, yd, w, h);
351 radeondrawinit(VGAscr*scr)
353 ulong dtype, i, clock_cntl_index, mclk_cntl, rbbm_soft_reset;
358 switch (scr->gscreen->depth) {
377 OUTREG(scr->mmio, RB3D_CNTL, 0);
380 OUTREGP(scr->mmio, RB2D_DSTCACHE_CTLSTAT,
381 RB2D_DC_FLUSH_ALL, ~RB2D_DC_FLUSH_ALL);
382 for (i = 0; i < 2000000; i++)
383 if (!(INREG(scr->mmio, RB2D_DSTCACHE_CTLSTAT) &
387 /* reset 2D engine */
388 clock_cntl_index = INREG(scr->mmio, CLOCK_CNTL_INDEX);
390 mclk_cntl = INPLL(scr->mmio, MCLK_CNTL);
391 OUTPLL(scr->mmio, MCLK_CNTL, mclk_cntl | FORCEON_MCLKA |
392 FORCEON_MCLKB | FORCEON_YCLKA | FORCEON_YCLKB | FORCEON_MC |
394 rbbm_soft_reset = INREG(scr->mmio, RBBM_SOFT_RESET);
396 OUTREG(scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset |
397 SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
398 SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB);
399 INREG(scr->mmio, RBBM_SOFT_RESET);
400 OUTREG(scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset &
401 ~(SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
402 SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB));
403 INREG(scr->mmio, RBBM_SOFT_RESET);
405 OUTPLL(scr->mmio, MCLK_CNTL, mclk_cntl);
406 OUTREG(scr->mmio, CLOCK_CNTL_INDEX, clock_cntl_index);
409 radeonwaitfifo(scr, 1);
410 OUTREG(scr->mmio, RB2D_DSTCACHE_MODE, 0);
412 radeonwaitfifo(scr, 4);
413 OUTREG(scr->mmio, DEFAULT_PITCH, scr->pitch);
414 OUTREG(scr->mmio, DST_PITCH, scr->pitch);
415 OUTREG(scr->mmio, SRC_PITCH, scr->pitch);
416 OUTREG(scr->mmio, DST_PITCH_OFFSET_C, 0);
418 radeonwaitfifo(scr, 3);
419 OUTREG(scr->mmio, DEFAULT_OFFSET, 0);
420 OUTREG(scr->mmio, DST_OFFSET, 0);
421 OUTREG(scr->mmio, SRC_OFFSET, 0);
423 radeonwaitfifo(scr, 1);
424 OUTREGP(scr->mmio, DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
426 radeonwaitfifo(scr, 1);
427 OUTREG(scr->mmio, DEFAULT_SC_BOTTOM_RIGHT,
428 DEFAULT_SC_RIGHT_MAX | DEFAULT_SC_BOTTOM_MAX);
430 dp_gui_master_cntl = dtype << GMC_DST_DATATYPE_SHIFT |
431 GMC_SRC_PITCH_OFFSET_CNTL | GMC_DST_PITCH_OFFSET_CNTL |
432 GMC_CLR_CMP_CNTL_DIS;
433 radeonwaitfifo(scr, 1);
434 OUTREG(scr->mmio, DP_GUI_MASTER_CNTL,
435 dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR | GMC_SRC_DATATYPE_COLOR);
437 radeonwaitfifo(scr, 7);
438 OUTREG(scr->mmio, DST_LINE_START, 0);
439 OUTREG(scr->mmio, DST_LINE_END, 0);
440 OUTREG(scr->mmio, DP_BRUSH_FRGD_CLR, ~0ul);
441 OUTREG(scr->mmio, DP_BRUSH_BKGD_CLR, 0);
442 OUTREG(scr->mmio, DP_SRC_FRGD_CLR, ~0ul);
443 OUTREG(scr->mmio, DP_SRC_BKGD_CLR, 0);
444 OUTREG(scr->mmio, DP_WRITE_MASK, ~0ul);
448 scr->fill = radeonfill;
449 scr->scroll = radeonscroll;
450 scr->blank = radeonblank;
456 radeonovlctl(VGAscr *scr, Chan *c, void *data, int len)
458 USED(scr, c, data, len);
462 radeonovlwrite(VGAscr *scr, void *data, int len, vlong opt)
464 USED(scr, data, len, opt);
469 radeonflush(VGAscr *scr, Rectangle r)
476 VGAdev vgaradeondev = {
493 VGAcur vgaradeoncur = {