0001
0002 #include "radeonfb.h"
0003
0004
0005
0006
0007
0008
0009 static void radeon_fixup_offset(struct radeonfb_info *rinfo)
0010 {
0011 u32 local_base;
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 radeon_fifo_wait (1);
0030 local_base = INREG(MC_FB_LOCATION) << 16;
0031 if (local_base == rinfo->fb_local_base)
0032 return;
0033
0034 rinfo->fb_local_base = local_base;
0035
0036 radeon_fifo_wait (3);
0037 OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
0038 (rinfo->fb_local_base >> 10));
0039 OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
0040 OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
0041 }
0042
0043 static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo,
0044 const struct fb_fillrect *region)
0045 {
0046 radeon_fifo_wait(4);
0047
0048 OUTREG(DP_GUI_MASTER_CNTL,
0049 rinfo->dp_gui_master_cntl
0050 | GMC_BRUSH_SOLID_COLOR
0051 | ROP3_P);
0052 if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP)
0053 OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]);
0054 else
0055 OUTREG(DP_BRUSH_FRGD_CLR, region->color);
0056 OUTREG(DP_WRITE_MSK, 0xffffffff);
0057 OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
0058
0059 radeon_fifo_wait(2);
0060 OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
0061 OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
0062
0063 radeon_fifo_wait(2);
0064 OUTREG(DST_Y_X, (region->dy << 16) | region->dx);
0065 OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height);
0066 }
0067
0068 void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
0069 {
0070 struct radeonfb_info *rinfo = info->par;
0071 struct fb_fillrect modded;
0072 int vxres, vyres;
0073
0074 if (info->state != FBINFO_STATE_RUNNING)
0075 return;
0076 if (info->flags & FBINFO_HWACCEL_DISABLED) {
0077 cfb_fillrect(info, region);
0078 return;
0079 }
0080
0081 radeon_fixup_offset(rinfo);
0082
0083 vxres = info->var.xres_virtual;
0084 vyres = info->var.yres_virtual;
0085
0086 memcpy(&modded, region, sizeof(struct fb_fillrect));
0087
0088 if(!modded.width || !modded.height ||
0089 modded.dx >= vxres || modded.dy >= vyres)
0090 return;
0091
0092 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
0093 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
0094
0095 radeonfb_prim_fillrect(rinfo, &modded);
0096 }
0097
0098 static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo,
0099 const struct fb_copyarea *area)
0100 {
0101 int xdir, ydir;
0102 u32 sx, sy, dx, dy, w, h;
0103
0104 w = area->width; h = area->height;
0105 dx = area->dx; dy = area->dy;
0106 sx = area->sx; sy = area->sy;
0107 xdir = sx - dx;
0108 ydir = sy - dy;
0109
0110 if ( xdir < 0 ) { sx += w-1; dx += w-1; }
0111 if ( ydir < 0 ) { sy += h-1; dy += h-1; }
0112
0113 radeon_fifo_wait(3);
0114 OUTREG(DP_GUI_MASTER_CNTL,
0115 rinfo->dp_gui_master_cntl
0116 | GMC_BRUSH_NONE
0117 | GMC_SRC_DSTCOLOR
0118 | ROP3_S
0119 | DP_SRC_SOURCE_MEMORY );
0120 OUTREG(DP_WRITE_MSK, 0xffffffff);
0121 OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0)
0122 | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
0123
0124 radeon_fifo_wait(2);
0125 OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
0126 OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
0127
0128 radeon_fifo_wait(3);
0129 OUTREG(SRC_Y_X, (sy << 16) | sx);
0130 OUTREG(DST_Y_X, (dy << 16) | dx);
0131 OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w);
0132 }
0133
0134
0135 void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
0136 {
0137 struct radeonfb_info *rinfo = info->par;
0138 struct fb_copyarea modded;
0139 u32 vxres, vyres;
0140 modded.sx = area->sx;
0141 modded.sy = area->sy;
0142 modded.dx = area->dx;
0143 modded.dy = area->dy;
0144 modded.width = area->width;
0145 modded.height = area->height;
0146
0147 if (info->state != FBINFO_STATE_RUNNING)
0148 return;
0149 if (info->flags & FBINFO_HWACCEL_DISABLED) {
0150 cfb_copyarea(info, area);
0151 return;
0152 }
0153
0154 radeon_fixup_offset(rinfo);
0155
0156 vxres = info->var.xres_virtual;
0157 vyres = info->var.yres_virtual;
0158
0159 if(!modded.width || !modded.height ||
0160 modded.sx >= vxres || modded.sy >= vyres ||
0161 modded.dx >= vxres || modded.dy >= vyres)
0162 return;
0163
0164 if(modded.sx + modded.width > vxres) modded.width = vxres - modded.sx;
0165 if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx;
0166 if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy;
0167 if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
0168
0169 radeonfb_prim_copyarea(rinfo, &modded);
0170 }
0171
0172 void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
0173 {
0174 struct radeonfb_info *rinfo = info->par;
0175
0176 if (info->state != FBINFO_STATE_RUNNING)
0177 return;
0178 radeon_engine_idle();
0179
0180 cfb_imageblit(info, image);
0181 }
0182
0183 int radeonfb_sync(struct fb_info *info)
0184 {
0185 struct radeonfb_info *rinfo = info->par;
0186
0187 if (info->state != FBINFO_STATE_RUNNING)
0188 return 0;
0189 radeon_engine_idle();
0190
0191 return 0;
0192 }
0193
0194 void radeonfb_engine_reset(struct radeonfb_info *rinfo)
0195 {
0196 u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
0197 u32 host_path_cntl;
0198
0199 radeon_engine_flush (rinfo);
0200
0201 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
0202 mclk_cntl = INPLL(MCLK_CNTL);
0203
0204 OUTPLL(MCLK_CNTL, (mclk_cntl |
0205 FORCEON_MCLKA |
0206 FORCEON_MCLKB |
0207 FORCEON_YCLKA |
0208 FORCEON_YCLKB |
0209 FORCEON_MC |
0210 FORCEON_AIC));
0211
0212 host_path_cntl = INREG(HOST_PATH_CNTL);
0213 rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
0214
0215 if (IS_R300_VARIANT(rinfo)) {
0216 u32 tmp;
0217
0218 OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset |
0219 SOFT_RESET_CP |
0220 SOFT_RESET_HI |
0221 SOFT_RESET_E2));
0222 INREG(RBBM_SOFT_RESET);
0223 OUTREG(RBBM_SOFT_RESET, 0);
0224 tmp = INREG(RB2D_DSTCACHE_MODE);
0225 OUTREG(RB2D_DSTCACHE_MODE, tmp | (1 << 17));
0226 } else {
0227 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
0228 SOFT_RESET_CP |
0229 SOFT_RESET_HI |
0230 SOFT_RESET_SE |
0231 SOFT_RESET_RE |
0232 SOFT_RESET_PP |
0233 SOFT_RESET_E2 |
0234 SOFT_RESET_RB);
0235 INREG(RBBM_SOFT_RESET);
0236 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32)
0237 ~(SOFT_RESET_CP |
0238 SOFT_RESET_HI |
0239 SOFT_RESET_SE |
0240 SOFT_RESET_RE |
0241 SOFT_RESET_PP |
0242 SOFT_RESET_E2 |
0243 SOFT_RESET_RB));
0244 INREG(RBBM_SOFT_RESET);
0245 }
0246
0247 OUTREG(HOST_PATH_CNTL, host_path_cntl | HDP_SOFT_RESET);
0248 INREG(HOST_PATH_CNTL);
0249 OUTREG(HOST_PATH_CNTL, host_path_cntl);
0250
0251 if (!IS_R300_VARIANT(rinfo))
0252 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
0253
0254 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
0255 OUTPLL(MCLK_CNTL, mclk_cntl);
0256 }
0257
0258 void radeonfb_engine_init (struct radeonfb_info *rinfo)
0259 {
0260 unsigned long temp;
0261
0262
0263 OUTREG(RB3D_CNTL, 0);
0264
0265 radeonfb_engine_reset(rinfo);
0266
0267 radeon_fifo_wait (1);
0268 if (IS_R300_VARIANT(rinfo)) {
0269 OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) |
0270 RB2D_DC_AUTOFLUSH_ENABLE |
0271 RB2D_DC_DC_DISABLE_IGNORE_PE);
0272 } else {
0273
0274
0275
0276
0277
0278 OUTREG(RB2D_DSTCACHE_MODE, 0);
0279 }
0280
0281 radeon_fifo_wait (3);
0282
0283
0284
0285 rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
0286
0287 OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
0288 (rinfo->fb_local_base >> 10));
0289 OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
0290 OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
0291
0292 radeon_fifo_wait (1);
0293 #if defined(__BIG_ENDIAN)
0294 OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
0295 #else
0296 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
0297 #endif
0298 radeon_fifo_wait (2);
0299 OUTREG(DEFAULT_SC_TOP_LEFT, 0);
0300 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
0301 DEFAULT_SC_BOTTOM_MAX));
0302
0303 temp = radeon_get_dstbpp(rinfo->depth);
0304 rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
0305
0306 radeon_fifo_wait (1);
0307 OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
0308 GMC_BRUSH_SOLID_COLOR |
0309 GMC_SRC_DATATYPE_COLOR));
0310
0311 radeon_fifo_wait (7);
0312
0313
0314 OUTREG(DST_LINE_START, 0);
0315 OUTREG(DST_LINE_END, 0);
0316
0317
0318 OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
0319 OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
0320
0321
0322 OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
0323 OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
0324
0325
0326 OUTREG(DP_WRITE_MSK, 0xffffffff);
0327
0328 radeon_engine_idle ();
0329 }