upgrade to fedora-2.6.12-1.1398.FC4 + vserver 2.0.rc7
[linux-2.6.git] / drivers / video / aty / radeon_accel.c
index e3883cf..3ca27cb 100644 (file)
@@ -4,6 +4,41 @@
  * "ACCEL_MMIO" ifdef branches in XFree86
  * --dte
  */
+
+static void radeon_fixup_offset(struct radeonfb_info *rinfo)
+{
+       u32 local_base;
+
+       /* *** Ugly workaround *** */
+       /*
+        * On some platforms, the video memory is mapped at 0 in radeon chip space
+        * (like PPCs) by the firmware. X will always move it up so that it's seen
+        * by the chip to be at the same address as the PCI BAR.
+        * That means that when switching back from X, there is a mismatch between
+        * the offsets programmed into the engine. This means that potentially,
+        * accel operations done before radeonfb has a chance to re-init the engine
+        * will have incorrect offsets, and potentially trash system memory !
+        *
+        * The correct fix is for fbcon to never call any accel op before the engine
+        * has properly been re-initialized (by a call to set_var), but this is a
+        * complex fix. This workaround in the meantime, called before every accel
+        * operation, makes sure the offsets are in sync.
+        */
+
+       radeon_fifo_wait (1);
+       local_base = INREG(MC_FB_LOCATION) << 16;
+       if (local_base == rinfo->fb_local_base)
+               return;
+
+       rinfo->fb_local_base = local_base;
+
+       radeon_fifo_wait (3);
+       OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) |
+                                    (rinfo->fb_local_base >> 10));
+       OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
+       OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10));
+}
+
 static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, 
                                   const struct fb_fillrect *region)
 {
@@ -38,6 +73,8 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region)
                return;
        }
 
+       radeon_fixup_offset(rinfo);
+
        vxres = info->var.xres_virtual;
        vyres = info->var.yres_virtual;
 
@@ -105,6 +142,8 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
                return;
        }
 
+       radeon_fixup_offset(rinfo);
+
        vxres = info->var.xres_virtual;
        vyres = info->var.yres_virtual;
 
@@ -150,32 +189,6 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
 
        radeon_engine_flush (rinfo);
 
-       /* Some ASICs have bugs with dynamic-on feature, which are  
-        * ASIC-version dependent, so we force all blocks on for now
-        * -- from XFree86
-        * We don't do that on macs, things just work here with dynamic
-        * clocking... --BenH
-        */
-#ifdef CONFIG_ALL_PPC
-       if (_machine != _MACH_Pmac && rinfo->hasCRTC2)
-#else
-       if (rinfo->has_CRTC2)
-#endif 
-       {
-               u32 tmp;
-
-               tmp = INPLL(SCLK_CNTL);
-               OUTPLL(SCLK_CNTL, ((tmp & ~DYN_STOP_LAT_MASK) |
-                                  CP_MAX_DYN_STOP_LAT |
-                                  SCLK_FORCEON_MASK));
-
-               if (rinfo->family == CHIP_FAMILY_RV200)
-               {
-                       tmp = INPLL(SCLK_MORE_CNTL);
-                       OUTPLL(SCLK_MORE_CNTL, tmp | SCLK_MORE_FORCEON);
-               }
-       }
-
        clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
        mclk_cntl = INPLL(MCLK_CNTL);
 
@@ -235,8 +248,6 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
 
        OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
        OUTPLL(MCLK_CNTL, mclk_cntl);
-       if (rinfo->R300_cg_workaround)
-               R300_cg_workardound(rinfo);
 }
 
 void radeonfb_engine_init (struct radeonfb_info *rinfo)