3 /* the accelerated functions here are patterned after the 
 
   4  * "ACCEL_MMIO" ifdef branches in XFree86
 
   8 static void radeon_fixup_offset(struct radeonfb_info *rinfo)
 
  12         /* *** Ugly workaround *** */
 
  14          * On some platforms, the video memory is mapped at 0 in radeon chip space
 
  15          * (like PPCs) by the firmware. X will always move it up so that it's seen
 
  16          * by the chip to be at the same address as the PCI BAR.
 
  17          * That means that when switching back from X, there is a mismatch between
 
  18          * the offsets programmed into the engine. This means that potentially,
 
  19          * accel operations done before radeonfb has a chance to re-init the engine
 
  20          * will have incorrect offsets, and potentially trash system memory !
 
  22          * The correct fix is for fbcon to never call any accel op before the engine
 
  23          * has properly been re-initialized (by a call to set_var), but this is a
 
  24          * complex fix. This workaround in the meantime, called before every accel
 
  25          * operation, makes sure the offsets are in sync.
 
  29         local_base = INREG(MC_FB_LOCATION) << 16;
 
  30         if (local_base == rinfo->fb_local_base)
 
  33         rinfo->fb_local_base = local_base;
 
  36         OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
 
  37                                      (rinfo->fb_local_base >> 10));
 
  38         OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
 
  39         OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
 
  42 static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, 
 
  43                                    const struct fb_fillrect *region)
 
  47         OUTREG(DP_GUI_MASTER_CNTL,  
 
  48                 rinfo->dp_gui_master_cntl  /* contains, like GMC_DST_32BPP */
 
  49                 | GMC_BRUSH_SOLID_COLOR
 
  51         if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP)
 
  52                 OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]);
 
  54                 OUTREG(DP_BRUSH_FRGD_CLR, region->color);
 
  55         OUTREG(DP_WRITE_MSK, 0xffffffff);
 
  56         OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
 
  59         OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
 
  60         OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
 
  63         OUTREG(DST_Y_X, (region->dy << 16) | region->dx);
 
  64         OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height);
 
  67 void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
 
  69         struct radeonfb_info *rinfo = info->par;
 
  70         struct fb_fillrect modded;
 
  73         if (info->state != FBINFO_STATE_RUNNING)
 
  75         if (info->flags & FBINFO_HWACCEL_DISABLED) {
 
  76                 cfb_fillrect(info, region);
 
  80         radeon_fixup_offset(rinfo);
 
  82         vxres = info->var.xres_virtual;
 
  83         vyres = info->var.yres_virtual;
 
  85         memcpy(&modded, region, sizeof(struct fb_fillrect));
 
  87         if(!modded.width || !modded.height ||
 
  88            modded.dx >= vxres || modded.dy >= vyres)
 
  91         if(modded.dx + modded.width  > vxres) modded.width  = vxres - modded.dx;
 
  92         if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
 
  94         radeonfb_prim_fillrect(rinfo, &modded);
 
  97 static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, 
 
  98                                    const struct fb_copyarea *area)
 
 101         u32 sx, sy, dx, dy, w, h;
 
 103         w = area->width; h = area->height;
 
 104         dx = area->dx; dy = area->dy;
 
 105         sx = area->sx; sy = area->sy;
 
 109         if ( xdir < 0 ) { sx += w-1; dx += w-1; }
 
 110         if ( ydir < 0 ) { sy += h-1; dy += h-1; }
 
 113         OUTREG(DP_GUI_MASTER_CNTL,
 
 114                 rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */
 
 118                 | DP_SRC_SOURCE_MEMORY );
 
 119         OUTREG(DP_WRITE_MSK, 0xffffffff);
 
 120         OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0)
 
 121                         | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
 
 124         OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL);
 
 125         OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE));
 
 128         OUTREG(SRC_Y_X, (sy << 16) | sx);
 
 129         OUTREG(DST_Y_X, (dy << 16) | dx);
 
 130         OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w);
 
 134 void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 
 136         struct radeonfb_info *rinfo = info->par;
 
 137         struct fb_copyarea modded;
 
 139         modded.sx = area->sx;
 
 140         modded.sy = area->sy;
 
 141         modded.dx = area->dx;
 
 142         modded.dy = area->dy;
 
 143         modded.width  = area->width;
 
 144         modded.height = area->height;
 
 146         if (info->state != FBINFO_STATE_RUNNING)
 
 148         if (info->flags & FBINFO_HWACCEL_DISABLED) {
 
 149                 cfb_copyarea(info, area);
 
 153         radeon_fixup_offset(rinfo);
 
 155         vxres = info->var.xres_virtual;
 
 156         vyres = info->var.yres_virtual;
 
 158         if(!modded.width || !modded.height ||
 
 159            modded.sx >= vxres || modded.sy >= vyres ||
 
 160            modded.dx >= vxres || modded.dy >= vyres)
 
 163         if(modded.sx + modded.width > vxres)  modded.width = vxres - modded.sx;
 
 164         if(modded.dx + modded.width > vxres)  modded.width = vxres - modded.dx;
 
 165         if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy;
 
 166         if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy;
 
 168         radeonfb_prim_copyarea(rinfo, &modded);
 
 171 void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image)
 
 173         struct radeonfb_info *rinfo = info->par;
 
 175         if (info->state != FBINFO_STATE_RUNNING)
 
 177         radeon_engine_idle();
 
 179         cfb_imageblit(info, image);
 
 182 int radeonfb_sync(struct fb_info *info)
 
 184         struct radeonfb_info *rinfo = info->par;
 
 186         if (info->state != FBINFO_STATE_RUNNING)
 
 188         radeon_engine_idle();
 
 193 void radeonfb_engine_reset(struct radeonfb_info *rinfo)
 
 195         u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
 
 198         radeon_engine_flush (rinfo);
 
 200         clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
 
 201         mclk_cntl = INPLL(MCLK_CNTL);
 
 203         OUTPLL(MCLK_CNTL, (mclk_cntl |
 
 211         host_path_cntl = INREG(HOST_PATH_CNTL);
 
 212         rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
 
 214         if (IS_R300_VARIANT(rinfo)) {
 
 217                 OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset |
 
 221                 INREG(RBBM_SOFT_RESET);
 
 222                 OUTREG(RBBM_SOFT_RESET, 0);
 
 223                 tmp = INREG(RB2D_DSTCACHE_MODE);
 
 224                 OUTREG(RB2D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */
 
 226                 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
 
 234                 INREG(RBBM_SOFT_RESET);
 
 235                 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32)
 
 243                 INREG(RBBM_SOFT_RESET);
 
 246         OUTREG(HOST_PATH_CNTL, host_path_cntl | HDP_SOFT_RESET);
 
 247         INREG(HOST_PATH_CNTL);
 
 248         OUTREG(HOST_PATH_CNTL, host_path_cntl);
 
 250         if (!IS_R300_VARIANT(rinfo))
 
 251                 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
 
 253         OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
 
 254         OUTPLL(MCLK_CNTL, mclk_cntl);
 
 257 void radeonfb_engine_init (struct radeonfb_info *rinfo)
 
 261         /* disable 3D engine */
 
 262         OUTREG(RB3D_CNTL, 0);
 
 264         radeonfb_engine_reset(rinfo);
 
 266         radeon_fifo_wait (1);
 
 267         if (IS_R300_VARIANT(rinfo)) {
 
 268                 OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) |
 
 269                        RB2D_DC_AUTOFLUSH_ENABLE |
 
 270                        RB2D_DC_DC_DISABLE_IGNORE_PE);
 
 272                 /* This needs to be double checked with ATI. Latest X driver
 
 273                  * completely "forgets" to set this register on < r3xx, and
 
 274                  * we used to just write 0 there... I'll keep the 0 and update
 
 275                  * that when we have sorted things out on X side.
 
 277                 OUTREG(RB2D_DSTCACHE_MODE, 0);
 
 280         radeon_fifo_wait (3);
 
 281         /* We re-read MC_FB_LOCATION from card as it can have been
 
 282          * modified by XFree drivers (ouch !)
 
 284         rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
 
 286         OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
 
 287                                      (rinfo->fb_local_base >> 10));
 
 288         OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
 
 289         OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
 
 291         radeon_fifo_wait (1);
 
 292 #if defined(__BIG_ENDIAN)
 
 293         OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
 
 295         OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
 
 297         radeon_fifo_wait (2);
 
 298         OUTREG(DEFAULT_SC_TOP_LEFT, 0);
 
 299         OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
 
 300                                          DEFAULT_SC_BOTTOM_MAX));
 
 302         temp = radeon_get_dstbpp(rinfo->depth);
 
 303         rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);
 
 305         radeon_fifo_wait (1);
 
 306         OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
 
 307                                     GMC_BRUSH_SOLID_COLOR |
 
 308                                     GMC_SRC_DATATYPE_COLOR));
 
 310         radeon_fifo_wait (7);
 
 312         /* clear line drawing regs */
 
 313         OUTREG(DST_LINE_START, 0);
 
 314         OUTREG(DST_LINE_END, 0);
 
 316         /* set brush color regs */
 
 317         OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
 
 318         OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
 
 320         /* set source color regs */
 
 321         OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
 
 322         OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
 
 324         /* default write mask */
 
 325         OUTREG(DP_WRITE_MSK, 0xffffffff);
 
 327         radeon_engine_idle ();