11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "radeonfb.h" 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* the accelerated functions here are patterned after the 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * "ACCEL_MMIO" ifdef branches in XFree86 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --dte 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 86c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvaldsstatic void radeon_fixup_offset(struct radeonfb_info *rinfo) 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 106c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds u32 local_base; 116c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds 126c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds /* *** Ugly workaround *** */ 136c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds /* 146c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * On some platforms, the video memory is mapped at 0 in radeon chip space 156c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * (like PPCs) by the firmware. X will always move it up so that it's seen 166c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * by the chip to be at the same address as the PCI BAR. 176c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * That means that when switching back from X, there is a mismatch between 186c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * the offsets programmed into the engine. This means that potentially, 196c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * accel operations done before radeonfb has a chance to re-init the engine 206c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * will have incorrect offsets, and potentially trash system memory ! 216c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * 226c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * The correct fix is for fbcon to never call any accel op before the engine 236c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * has properly been re-initialized (by a call to set_var), but this is a 246c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * complex fix. This workaround in the meantime, called before every accel 256c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds * operation, makes sure the offsets are in sync. 266c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds */ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 286c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait (1); 296c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds local_base = INREG(MC_FB_LOCATION) << 16; 306c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds if (local_base == rinfo->fb_local_base) 316c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds return; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 336c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds rinfo->fb_local_base = local_base; 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 356c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait (3); 366c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) | 376c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds (rinfo->fb_local_base >> 10)); 386c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 396c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct fb_fillrect *region) 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 456c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait(4); 466c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds 476c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_GUI_MASTER_CNTL, 486c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */ 496c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds | GMC_BRUSH_SOLID_COLOR 506c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds | ROP3_P); 516c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP) 526c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]); 536c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds else 546c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_BRUSH_FRGD_CLR, region->color); 556c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_WRITE_MSK, 0xffffffff); 566c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); 576c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds 586c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait(2); 59969830b2fedf8336c41d6195f49d250b1e166ff8David Miller OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); 60969830b2fedf8336c41d6195f49d250b1e166ff8David Miller OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); 616c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds 626c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait(2); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(DST_Y_X, (region->dy << 16) | region->dx); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct radeonfb_info *rinfo = info->par; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fb_fillrect modded; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int vxres, vyres; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 736c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds if (info->state != FBINFO_STATE_RUNNING) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (info->flags & FBINFO_HWACCEL_DISABLED) { 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfb_fillrect(info, region); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 806c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fixup_offset(rinfo); 816c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vxres = info->var.xres_virtual; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vyres = info->var.yres_virtual; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(&modded, region, sizeof(struct fb_fillrect)); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!modded.width || !modded.height || 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modded.dx >= vxres || modded.dy >= vyres) 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds radeonfb_prim_fillrect(rinfo, &modded); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct fb_copyarea *area) 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int xdir, ydir; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 sx, sy, dx, dy, w, h; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds w = area->width; h = area->height; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dx = area->dx; dy = area->dy; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sx = area->sx; sy = area->sy; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds xdir = sx - dx; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ydir = sy - dy; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( xdir < 0 ) { sx += w-1; dx += w-1; } 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( ydir < 0 ) { sy += h-1; dy += h-1; } 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1126c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait(3); 1136c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_GUI_MASTER_CNTL, 1146c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */ 1156c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds | GMC_BRUSH_NONE 1166c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds | GMC_SRC_DSTCOLOR 1176c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds | ROP3_S 1186c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds | DP_SRC_SOURCE_MEMORY ); 1196c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_WRITE_MSK, 0xffffffff); 1206c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) 1216c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); 1226c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds 1236c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait(2); 124969830b2fedf8336c41d6195f49d250b1e166ff8David Miller OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); 125969830b2fedf8336c41d6195f49d250b1e166ff8David Miller OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); 1266c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds 1276c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait(3); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(SRC_Y_X, (sy << 16) | sx); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(DST_Y_X, (dy << 16) | dx); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct radeonfb_info *rinfo = info->par; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fb_copyarea modded; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 vxres, vyres; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modded.sx = area->sx; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modded.sy = area->sy; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modded.dx = area->dx; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modded.dy = area->dy; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modded.width = area->width; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modded.height = area->height; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1466c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds if (info->state != FBINFO_STATE_RUNNING) 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (info->flags & FBINFO_HWACCEL_DISABLED) { 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfb_copyarea(info, area); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1536c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fixup_offset(rinfo); 1546c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vxres = info->var.xres_virtual; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vyres = info->var.yres_virtual; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!modded.width || !modded.height || 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modded.sx >= vxres || modded.sy >= vyres || 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds modded.dx >= vxres || modded.dy >= vyres) 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(modded.sx + modded.width > vxres) modded.width = vxres - modded.sx; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds radeonfb_prim_copyarea(rinfo, &modded); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid radeonfb_imageblit(struct fb_info *info, const struct fb_image *image) 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct radeonfb_info *rinfo = info->par; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1756c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds if (info->state != FBINFO_STATE_RUNNING) 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 1776c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_engine_idle(); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfb_imageblit(info, image); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint radeonfb_sync(struct fb_info *info) 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct radeonfb_info *rinfo = info->par; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (info->state != FBINFO_STATE_RUNNING) 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1886c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_engine_idle(); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid radeonfb_engine_reset(struct radeonfb_info *rinfo) 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 host_path_cntl; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds radeon_engine_flush (rinfo); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clock_cntl_index = INREG(CLOCK_CNTL_INDEX); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mclk_cntl = INPLL(MCLK_CNTL); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTPLL(MCLK_CNTL, (mclk_cntl | 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FORCEON_MCLKA | 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FORCEON_MCLKB | 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FORCEON_YCLKA | 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FORCEON_YCLKB | 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FORCEON_MC | 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FORCEON_AIC)); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host_path_cntl = INREG(HOST_PATH_CNTL); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rbbm_soft_reset = INREG(RBBM_SOFT_RESET); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 214a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt if (IS_R300_VARIANT(rinfo)) { 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tmp; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset | 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_CP | 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_HI | 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_E2)); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INREG(RBBM_SOFT_RESET); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(RBBM_SOFT_RESET, 0); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = INREG(RB2D_DSTCACHE_MODE); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(RB2D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */ 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset | 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_CP | 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_HI | 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_SE | 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_RE | 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_PP | 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_E2 | 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_RB); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INREG(RBBM_SOFT_RESET); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32) 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ~(SOFT_RESET_CP | 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_HI | 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_SE | 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_RE | 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_PP | 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_E2 | 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SOFT_RESET_RB)); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INREG(RBBM_SOFT_RESET); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(HOST_PATH_CNTL, host_path_cntl | HDP_SOFT_RESET); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INREG(HOST_PATH_CNTL); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(HOST_PATH_CNTL, host_path_cntl); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 250a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt if (!IS_R300_VARIANT(rinfo)) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTPLL(MCLK_CNTL, mclk_cntl); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid radeonfb_engine_init (struct radeonfb_info *rinfo) 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long temp; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* disable 3D engine */ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(RB3D_CNTL, 0); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds radeonfb_engine_reset(rinfo); 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2666c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait (1); 267a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt if (IS_R300_VARIANT(rinfo)) { 268a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) | 269a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt RB2D_DC_AUTOFLUSH_ENABLE | 270a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt RB2D_DC_DC_DISABLE_IGNORE_PE); 271a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt } else { 272a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt /* This needs to be double checked with ATI. Latest X driver 273a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt * completely "forgets" to set this register on < r3xx, and 274a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt * we used to just write 0 there... I'll keep the 0 and update 275a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt * that when we have sorted things out on X side. 276a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt */ 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(RB2D_DSTCACHE_MODE, 0); 278a6c0c37db654444dfce91cd75ad8a56bb15a0d25Benjamin Herrenschmidt } 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2806c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait (3); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We re-read MC_FB_LOCATION from card as it can have been 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modified by XFree drivers (ouch !) 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) | 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (rinfo->fb_local_base >> 10)); 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2916c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait (1); 2926c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds#if defined(__BIG_ENDIAN) 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2976c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait (2); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(DEFAULT_SC_TOP_LEFT, 0); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEFAULT_SC_BOTTOM_MAX)); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds temp = radeon_get_dstbpp(rinfo->depth); 3036c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3056c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait (1); 3066c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | 3076c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds GMC_BRUSH_SOLID_COLOR | 3086c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds GMC_SRC_DATATYPE_COLOR)); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3106c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_fifo_wait (7); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* clear line drawing regs */ 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(DST_LINE_START, 0); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(DST_LINE_END, 0); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3166c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds /* set brush color regs */ 3176c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); 3186c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); 3196c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds 3206c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds /* set source color regs */ 3216c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); 3226c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds OUTREG(DP_SRC_BKGD_CLR, 0x00000000); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* default write mask */ 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUTREG(DP_WRITE_MSK, 0xffffffff); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3276c34bc2976b30dc8b56392c020e25bae1f363cabLinus Torvalds radeon_engine_idle (); 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 329