1#include "radeonfb.h" 2 3/* the accelerated functions here are patterned after the 4 * "ACCEL_MMIO" ifdef branches in XFree86 5 * --dte 6 */ 7 8static void radeon_fixup_offset(struct radeonfb_info *rinfo) 9{ 10 u32 local_base; 11 12 13 radeon_fifo_wait (1); 14 local_base = INREG(MC_FB_LOCATION) << 16; 15 if (local_base == rinfo->fb_local_base) 16 return; 17 18 rinfo->fb_local_base = local_base; 19 20 radeon_fifo_wait (3); 21 OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) | 22 (rinfo->fb_local_base >> 10)); 23 OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 24 OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 25} 26 27static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, 28 const struct fb_fillrect *region) 29{ 30 radeon_fifo_wait(4); 31 32 OUTREG(DP_GUI_MASTER_CNTL, 33 rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */ 34 | GMC_BRUSH_SOLID_COLOR 35 | ROP3_P); 36 if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP) 37 OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]); 38 else 39 OUTREG(DP_BRUSH_FRGD_CLR, region->color); 40 OUTREG(DP_WRITE_MSK, 0xffffffff); 41 OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); 42 43 radeon_fifo_wait(2); 44 OUTREG(DST_Y_X, (region->dy << 16) | region->dx); 45 OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height); 46} 47 48void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) 49{ 50 struct radeonfb_info *rinfo = info->par; 51 struct fb_fillrect modded; 52 int vxres, vyres; 53 54 if (info->state != FBINFO_STATE_RUNNING) 55 return; 56 if (info->flags & FBINFO_HWACCEL_DISABLED) { 57 cfb_fillrect(info, region); 58 return; 59 } 60 61 radeon_fixup_offset(rinfo); 62 63 vxres = info->var.xres_virtual; 64 vyres = info->var.yres_virtual; 65 66 memcpy(&modded, region, sizeof(struct fb_fillrect)); 67 68 if(!modded.width || !modded.height || 69 modded.dx >= vxres || modded.dy >= vyres) 70 return; 71 72 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; 73 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; 74 75 radeonfb_prim_fillrect(rinfo, &modded); 76} 77 78static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, 79 const struct fb_copyarea *area) 80{ 81 int xdir, ydir; 82 u32 sx, sy, dx, dy, w, h; 83 84 w = area->width; h = area->height; 85 dx = area->dx; dy = area->dy; 86 sx = area->sx; sy = area->sy; 87 xdir = sx - dx; 88 ydir = sy - dy; 89 90 if ( xdir < 0 ) { sx += w-1; dx += w-1; } 91 if ( ydir < 0 ) { sy += h-1; dy += h-1; } 92 93 radeon_fifo_wait(3); 94 OUTREG(DP_GUI_MASTER_CNTL, 95 rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */ 96 | GMC_BRUSH_NONE 97 | GMC_SRC_DSTCOLOR 98 | ROP3_S 99 | DP_SRC_SOURCE_MEMORY ); 100 OUTREG(DP_WRITE_MSK, 0xffffffff); 101 OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) 102 | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); 103 104 radeon_fifo_wait(3); 105 OUTREG(SRC_Y_X, (sy << 16) | sx); 106 OUTREG(DST_Y_X, (dy << 16) | dx); 107 OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w); 108} 109 110 111void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 112{ 113 struct radeonfb_info *rinfo = info->par; 114 struct fb_copyarea modded; 115 u32 vxres, vyres; 116 modded.sx = area->sx; 117 modded.sy = area->sy; 118 modded.dx = area->dx; 119 modded.dy = area->dy; 120 modded.width = area->width; 121 modded.height = area->height; 122 123 if (info->state != FBINFO_STATE_RUNNING) 124 return; 125 if (info->flags & FBINFO_HWACCEL_DISABLED) { 126 cfb_copyarea(info, area); 127 return; 128 } 129 130 radeon_fixup_offset(rinfo); 131 132 vxres = info->var.xres_virtual; 133 vyres = info->var.yres_virtual; 134 135 if(!modded.width || !modded.height || 136 modded.sx >= vxres || modded.sy >= vyres || 137 modded.dx >= vxres || modded.dy >= vyres) 138 return; 139 140 if(modded.sx + modded.width > vxres) modded.width = vxres - modded.sx; 141 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; 142 if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy; 143 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; 144 145 radeonfb_prim_copyarea(rinfo, &modded); 146} 147 148void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image) 149{ 150 struct radeonfb_info *rinfo = info->par; 151 152 if (info->state != FBINFO_STATE_RUNNING) 153 return; 154 radeon_engine_idle(); 155 156 cfb_imageblit(info, image); 157} 158 159int radeonfb_sync(struct fb_info *info) 160{ 161 struct radeonfb_info *rinfo = info->par; 162 163 if (info->state != FBINFO_STATE_RUNNING) 164 return 0; 165 radeon_engine_idle(); 166 167 return 0; 168} 169 170void radeonfb_engine_reset(struct radeonfb_info *rinfo) 171{ 172 u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset; 173 u32 host_path_cntl; 174 175 radeon_engine_flush (rinfo); 176 177 clock_cntl_index = INREG(CLOCK_CNTL_INDEX); 178 mclk_cntl = INPLL(MCLK_CNTL); 179 180 OUTPLL(MCLK_CNTL, (mclk_cntl | 181 FORCEON_MCLKA | 182 FORCEON_MCLKB | 183 FORCEON_YCLKA | 184 FORCEON_YCLKB | 185 FORCEON_MC | 186 FORCEON_AIC)); 187 188 host_path_cntl = INREG(HOST_PATH_CNTL); 189 rbbm_soft_reset = INREG(RBBM_SOFT_RESET); 190 191 if (rinfo->family == CHIP_FAMILY_R300 || 192 rinfo->family == CHIP_FAMILY_R350 || 193 rinfo->family == CHIP_FAMILY_RV350) { 194 u32 tmp; 195 196 OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset | 197 SOFT_RESET_CP | 198 SOFT_RESET_HI | 199 SOFT_RESET_E2)); 200 INREG(RBBM_SOFT_RESET); 201 OUTREG(RBBM_SOFT_RESET, 0); 202 tmp = INREG(RB2D_DSTCACHE_MODE); 203 OUTREG(RB2D_DSTCACHE_MODE, tmp | (1 << 17)); 204 } else { 205 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset | 206 SOFT_RESET_CP | 207 SOFT_RESET_HI | 208 SOFT_RESET_SE | 209 SOFT_RESET_RE | 210 SOFT_RESET_PP | 211 SOFT_RESET_E2 | 212 SOFT_RESET_RB); 213 INREG(RBBM_SOFT_RESET); 214 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32) 215 ~(SOFT_RESET_CP | 216 SOFT_RESET_HI | 217 SOFT_RESET_SE | 218 SOFT_RESET_RE | 219 SOFT_RESET_PP | 220 SOFT_RESET_E2 | 221 SOFT_RESET_RB)); 222 INREG(RBBM_SOFT_RESET); 223 } 224 225 OUTREG(HOST_PATH_CNTL, host_path_cntl | HDP_SOFT_RESET); 226 INREG(HOST_PATH_CNTL); 227 OUTREG(HOST_PATH_CNTL, host_path_cntl); 228 229 if (rinfo->family != CHIP_FAMILY_R300 || 230 rinfo->family != CHIP_FAMILY_R350 || 231 rinfo->family != CHIP_FAMILY_RV350) 232 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); 233 234 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); 235 OUTPLL(MCLK_CNTL, mclk_cntl); 236} 237 238void radeonfb_engine_init (struct radeonfb_info *rinfo) 239{ 240 unsigned long temp; 241 242 /* disable 3D engine */ 243 OUTREG(RB3D_CNTL, 0); 244 245 radeonfb_engine_reset(rinfo); 246 247 radeon_fifo_wait (1); 248 if ((rinfo->family != CHIP_FAMILY_R300) && 249 (rinfo->family != CHIP_FAMILY_R350) && 250 (rinfo->family != CHIP_FAMILY_RV350)) 251 OUTREG(RB2D_DSTCACHE_MODE, 0); 252 253 radeon_fifo_wait (3); 254 /* We re-read MC_FB_LOCATION from card as it can have been 255 * modified by XFree drivers (ouch !) 256 */ 257 rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16; 258 259 OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) | 260 (rinfo->fb_local_base >> 10)); 261 OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 262 OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); 263 264 radeon_fifo_wait (1); 265#if defined(__BIG_ENDIAN) 266 OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); 267#else 268 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); 269#endif 270 radeon_fifo_wait (2); 271 OUTREG(DEFAULT_SC_TOP_LEFT, 0); 272 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | 273 DEFAULT_SC_BOTTOM_MAX)); 274 275 temp = radeon_get_dstbpp(rinfo->depth); 276 rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); 277 278 radeon_fifo_wait (1); 279 OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | 280 GMC_BRUSH_SOLID_COLOR | 281 GMC_SRC_DATATYPE_COLOR)); 282 283 radeon_fifo_wait (7); 284 285 /* clear line drawing regs */ 286 OUTREG(DST_LINE_START, 0); 287 OUTREG(DST_LINE_END, 0); 288 289 /* set brush color regs */ 290 OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); 291 OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); 292 293 /* set source color regs */ 294 OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); 295 OUTREG(DP_SRC_BKGD_CLR, 0x00000000); 296 297 /* default write mask */ 298 OUTREG(DP_WRITE_MSK, 0xffffffff); 299 300 radeon_engine_idle (); 301} 302