1 2/* 3 * ATI Mach64 Hardware Acceleration 4 */ 5 6#include <linux/sched.h> 7#include <linux/delay.h> 8#include <linux/fb.h> 9 10#include <video/fbcon.h> 11#include <video/fbcon-cfb8.h> 12#include <video/fbcon-cfb16.h> 13#include <video/fbcon-cfb24.h> 14#include <video/fbcon-cfb32.h> 15 16#include "mach64.h" 17#include "atyfb.h" 18 19 /* 20 * Text console acceleration 21 */ 22 23static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx, 24 int height, int width); 25static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy, 26 int sx, int height, int width); 27 28 29 /* 30 * Generic Mach64 routines 31 */ 32 33void aty_reset_engine(const struct fb_info_aty *info) 34{ 35 /* reset engine */ 36 aty_st_le32(GEN_TEST_CNTL, 37 aty_ld_le32(GEN_TEST_CNTL, info) & ~GUI_ENGINE_ENABLE, info); 38 /* enable engine */ 39 aty_st_le32(GEN_TEST_CNTL, 40 aty_ld_le32(GEN_TEST_CNTL, info) | GUI_ENGINE_ENABLE, info); 41 /* ensure engine is not locked up by clearing any FIFO or */ 42 /* HOST errors */ 43 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, info) | BUS_HOST_ERR_ACK | 44 BUS_FIFO_ERR_ACK, info); 45} 46 47static void reset_GTC_3D_engine(const struct fb_info_aty *info) 48{ 49 aty_st_le32(SCALE_3D_CNTL, 0xc0, info); 50 mdelay(GTC_3D_RESET_DELAY); 51 aty_st_le32(SETUP_CNTL, 0x00, info); 52 mdelay(GTC_3D_RESET_DELAY); 53 aty_st_le32(SCALE_3D_CNTL, 0x00, info); 54 mdelay(GTC_3D_RESET_DELAY); 55} 56 57void aty_init_engine(const struct atyfb_par *par, struct fb_info_aty *info) 58{ 59 u32 pitch_value; 60 61 /* determine modal information from global mode structure */ 62 pitch_value = par->crtc.vxres; 63 64 if (par->crtc.bpp == 24) { 65 /* In 24 bpp, the engine is in 8 bpp - this requires that all */ 66 /* horizontal coordinates and widths must be adjusted */ 67 pitch_value = pitch_value * 3; 68 } 69 70 /* On GTC (RagePro), we need to reset the 3D engine before */ 71 if (M64_HAS(RESET_3D)) 72 reset_GTC_3D_engine(info); 73 74 /* Reset engine, enable, and clear any engine errors */ 75 aty_reset_engine(info); 76 /* Ensure that vga page pointers are set to zero - the upper */ 77 /* page pointers are set to 1 to handle overflows in the */ 78 /* lower page */ 79 aty_st_le32(MEM_VGA_WP_SEL, 0x00010000, info); 80 aty_st_le32(MEM_VGA_RP_SEL, 0x00010000, info); 81 82 /* ---- Setup standard engine context ---- */ 83 84 /* All GUI registers here are FIFOed - therefore, wait for */ 85 /* the appropriate number of empty FIFO entries */ 86 wait_for_fifo(14, info); 87 88 /* enable all registers to be loaded for context loads */ 89 aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF, info); 90 91 /* set destination pitch to modal pitch, set offset to zero */ 92 aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22, info); 93 94 /* zero these registers (set them to a known state) */ 95 aty_st_le32(DST_Y_X, 0, info); 96 aty_st_le32(DST_HEIGHT, 0, info); 97 aty_st_le32(DST_BRES_ERR, 0, info); 98 aty_st_le32(DST_BRES_INC, 0, info); 99 aty_st_le32(DST_BRES_DEC, 0, info); 100 101 /* set destination drawing attributes */ 102 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM | 103 DST_X_LEFT_TO_RIGHT, info); 104 105 /* set source pitch to modal pitch, set offset to zero */ 106 aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, info); 107 108 /* set these registers to a known state */ 109 aty_st_le32(SRC_Y_X, 0, info); 110 aty_st_le32(SRC_HEIGHT1_WIDTH1, 1, info); 111 aty_st_le32(SRC_Y_X_START, 0, info); 112 aty_st_le32(SRC_HEIGHT2_WIDTH2, 1, info); 113 114 /* set source pixel retrieving attributes */ 115 aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT, info); 116 117 /* set host attributes */ 118 wait_for_fifo(13, info); 119 aty_st_le32(HOST_CNTL, 0, info); 120 121 /* set pattern attributes */ 122 aty_st_le32(PAT_REG0, 0, info); 123 aty_st_le32(PAT_REG1, 0, info); 124 aty_st_le32(PAT_CNTL, 0, info); 125 126 /* set scissors to modal size */ 127 aty_st_le32(SC_LEFT, 0, info); 128 aty_st_le32(SC_TOP, 0, info); 129 aty_st_le32(SC_BOTTOM, par->crtc.vyres-1, info); 130 aty_st_le32(SC_RIGHT, pitch_value-1, info); 131 132 /* set background color to minimum value (usually BLACK) */ 133 aty_st_le32(DP_BKGD_CLR, 0, info); 134 135 /* set foreground color to maximum value (usually WHITE) */ 136 aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF, info); 137 138 /* set write mask to effect all pixel bits */ 139 aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, info); 140 141 /* set foreground mix to overpaint and background mix to */ 142 /* no-effect */ 143 aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D, info); 144 145 /* set primary source pixel channel to foreground color */ 146 /* register */ 147 aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR, info); 148 149 /* set compare functionality to false (no-effect on */ 150 /* destination) */ 151 wait_for_fifo(3, info); 152 aty_st_le32(CLR_CMP_CLR, 0, info); 153 aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF, info); 154 aty_st_le32(CLR_CMP_CNTL, 0, info); 155 156 /* set pixel depth */ 157 wait_for_fifo(2, info); 158 aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, info); 159 aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, info); 160 161 wait_for_fifo(5, info); 162 aty_st_le32(SCALE_3D_CNTL, 0, info); 163 aty_st_le32(Z_CNTL, 0, info); 164 aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, info) & ~0x20, info); 165 aty_st_le32(GUI_TRAJ_CNTL, 0x100023, info); 166 167 /* insure engine is idle before leaving */ 168 wait_for_idle(info); 169} 170 171 172 /* 173 * Accelerated functions 174 */ 175 176static inline void draw_rect(s16 x, s16 y, u16 width, u16 height, 177 struct fb_info_aty *info) 178{ 179 /* perform rectangle fill */ 180 wait_for_fifo(2, info); 181 aty_st_le32(DST_Y_X, (x << 16) | y, info); 182 aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, info); 183 info->blitter_may_be_busy = 1; 184} 185 186static inline void aty_rectcopy(int srcx, int srcy, int dstx, int dsty, 187 u_int width, u_int height, 188 struct fb_info_aty *info) 189{ 190 u32 direction = DST_LAST_PEL; 191 u32 pitch_value; 192 193 if (!width || !height) 194 return; 195 196 pitch_value = info->current_par.crtc.vxres; 197 if (info->current_par.crtc.bpp == 24) { 198 /* In 24 bpp, the engine is in 8 bpp - this requires that all */ 199 /* horizontal coordinates and widths must be adjusted */ 200 pitch_value *= 3; 201 srcx *= 3; 202 dstx *= 3; 203 width *= 3; 204 } 205 206 if (srcy < dsty) { 207 dsty += height - 1; 208 srcy += height - 1; 209 } else 210 direction |= DST_Y_TOP_TO_BOTTOM; 211 212 if (srcx < dstx) { 213 dstx += width - 1; 214 srcx += width - 1; 215 } else 216 direction |= DST_X_LEFT_TO_RIGHT; 217 218 wait_for_fifo(4, info); 219 aty_st_le32(DP_SRC, FRGD_SRC_BLIT, info); 220 aty_st_le32(SRC_Y_X, (srcx << 16) | srcy, info); 221 aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | height, info); 222 aty_st_le32(DST_CNTL, direction, info); 223 draw_rect(dstx, dsty, width, height, info); 224} 225 226void aty_rectfill(int dstx, int dsty, u_int width, u_int height, u_int color, 227 struct fb_info_aty *info) 228{ 229 if (!width || !height) 230 return; 231 232 if (info->current_par.crtc.bpp == 24) { 233 /* In 24 bpp, the engine is in 8 bpp - this requires that all */ 234 /* horizontal coordinates and widths must be adjusted */ 235 dstx *= 3; 236 width *= 3; 237 } 238 239 wait_for_fifo(3, info); 240 aty_st_le32(DP_FRGD_CLR, color, info); 241 aty_st_le32(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE, 242 info); 243 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM | 244 DST_X_LEFT_TO_RIGHT, info); 245 draw_rect(dstx, dsty, width, height, info); 246} 247 248 249 /* 250 * Text console acceleration 251 */ 252 253static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx, 254 int height, int width) 255{ 256#ifdef __sparc__ 257 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); 258 259 if (fb->mmaped && (!fb->fb_info.display_fg 260 || fb->fb_info.display_fg->vc_num == fb->vtconsole)) 261 return; 262#endif 263 264 sx *= fontwidth(p); 265 sy *= fontheight(p); 266 dx *= fontwidth(p); 267 dy *= fontheight(p); 268 width *= fontwidth(p); 269 height *= fontheight(p); 270 271 aty_rectcopy(sx, sy, dx, dy, width, height, 272 (struct fb_info_aty *)p->fb_info); 273} 274 275static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy, 276 int sx, int height, int width) 277{ 278 u32 bgx; 279#ifdef __sparc__ 280 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); 281 282 if (fb->mmaped && (!fb->fb_info.display_fg 283 || fb->fb_info.display_fg->vc_num == fb->vtconsole)) 284 return; 285#endif 286 287 bgx = attr_bgcol_ec(p, conp); 288 bgx |= (bgx << 8); 289 bgx |= (bgx << 16); 290 291 sx *= fontwidth(p); 292 sy *= fontheight(p); 293 width *= fontwidth(p); 294 height *= fontheight(p); 295 296 aty_rectfill(sx, sy, width, height, bgx, 297 (struct fb_info_aty *)p->fb_info); 298} 299 300#ifdef __sparc__ 301#define check_access \ 302 if (fb->mmaped && (!fb->fb_info.display_fg \ 303 || fb->fb_info.display_fg->vc_num == fb->vtconsole)) \ 304 return; 305#else 306#define check_access do { } while (0) 307#endif 308 309#define DEF_FBCON_ATY_OP(name, call, args...) \ 310static void name(struct vc_data *conp, struct display *p, args) \ 311{ \ 312 struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); \ 313 check_access; \ 314 if (fb->blitter_may_be_busy) \ 315 wait_for_idle((struct fb_info_aty *)p->fb_info); \ 316 call; \ 317} 318 319#define DEF_FBCON_ATY(width) \ 320 DEF_FBCON_ATY_OP(fbcon_aty##width##_putc, \ 321 fbcon_cfb##width##_putc(conp, p, c, yy, xx), \ 322 int c, int yy, int xx) \ 323 DEF_FBCON_ATY_OP(fbcon_aty##width##_putcs, \ 324 fbcon_cfb##width##_putcs(conp, p, s, count, yy, xx), \ 325 const unsigned short *s, int count, int yy, int xx) \ 326 DEF_FBCON_ATY_OP(fbcon_aty##width##_clear_margins, \ 327 fbcon_cfb##width##_clear_margins(conp, p, bottom_only), \ 328 int bottom_only) \ 329 \ 330const struct display_switch fbcon_aty##width = { \ 331 setup: fbcon_cfb##width##_setup, \ 332 bmove: fbcon_aty_bmove, \ 333 clear: fbcon_aty_clear, \ 334 putc: fbcon_aty##width##_putc, \ 335 putcs: fbcon_aty##width##_putcs, \ 336 revc: fbcon_cfb##width##_revc, \ 337 clear_margins: fbcon_aty##width##_clear_margins, \ 338 fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) \ 339}; 340 341#ifdef FBCON_HAS_CFB8 342DEF_FBCON_ATY(8) 343#endif 344#ifdef FBCON_HAS_CFB16 345DEF_FBCON_ATY(16) 346#endif 347#ifdef FBCON_HAS_CFB24 348DEF_FBCON_ATY(24) 349#endif 350#ifdef FBCON_HAS_CFB32 351DEF_FBCON_ATY(32) 352#endif 353 354