OSDN Git Service

Brute force port of legacy crtc/encoder code
[android-x86/external-libdrm.git] / shared-core / radeon_cp.c
index 9ea98a8..53177bb 100644 (file)
@@ -2,6 +2,7 @@
 /*
  * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
+ * Copyright 2007 Advanced Micro Devices, Inc.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
 
 #include "drmP.h"
 #include "drm.h"
+#include "drm_sarea.h"
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 #include "r300_reg.h"
 
+#include "radeon_microcode.h"
 #define RADEON_FIFO_DEBUG      0
 
 static int radeon_do_cleanup_cp(struct drm_device * dev);
 
-/* CP microcode (from ATI) */
-static const u32 R200_cp_microcode[][2] = {
-       {0x21007000, 0000000000},
-       {0x20007000, 0000000000},
-       {0x000000ab, 0x00000004},
-       {0x000000af, 0x00000004},
-       {0x66544a49, 0000000000},
-       {0x49494174, 0000000000},
-       {0x54517d83, 0000000000},
-       {0x498d8b64, 0000000000},
-       {0x49494949, 0000000000},
-       {0x49da493c, 0000000000},
-       {0x49989898, 0000000000},
-       {0xd34949d5, 0000000000},
-       {0x9dc90e11, 0000000000},
-       {0xce9b9b9b, 0000000000},
-       {0x000f0000, 0x00000016},
-       {0x352e232c, 0000000000},
-       {0x00000013, 0x00000004},
-       {0x000f0000, 0x00000016},
-       {0x352e272c, 0000000000},
-       {0x000f0001, 0x00000016},
-       {0x3239362f, 0000000000},
-       {0x000077ef, 0x00000002},
-       {0x00061000, 0x00000002},
-       {0x00000020, 0x0000001a},
-       {0x00004000, 0x0000001e},
-       {0x00061000, 0x00000002},
-       {0x00000020, 0x0000001a},
-       {0x00004000, 0x0000001e},
-       {0x00061000, 0x00000002},
-       {0x00000020, 0x0000001a},
-       {0x00004000, 0x0000001e},
-       {0x00000016, 0x00000004},
-       {0x0003802a, 0x00000002},
-       {0x040067e0, 0x00000002},
-       {0x00000016, 0x00000004},
-       {0x000077e0, 0x00000002},
-       {0x00065000, 0x00000002},
-       {0x000037e1, 0x00000002},
-       {0x040067e1, 0x00000006},
-       {0x000077e0, 0x00000002},
-       {0x000077e1, 0x00000002},
-       {0x000077e1, 0x00000006},
-       {0xffffffff, 0000000000},
-       {0x10000000, 0000000000},
-       {0x0003802a, 0x00000002},
-       {0x040067e0, 0x00000006},
-       {0x00007675, 0x00000002},
-       {0x00007676, 0x00000002},
-       {0x00007677, 0x00000002},
-       {0x00007678, 0x00000006},
-       {0x0003802b, 0x00000002},
-       {0x04002676, 0x00000002},
-       {0x00007677, 0x00000002},
-       {0x00007678, 0x00000006},
-       {0x0000002e, 0x00000018},
-       {0x0000002e, 0x00000018},
-       {0000000000, 0x00000006},
-       {0x0000002f, 0x00000018},
-       {0x0000002f, 0x00000018},
-       {0000000000, 0x00000006},
-       {0x01605000, 0x00000002},
-       {0x00065000, 0x00000002},
-       {0x00098000, 0x00000002},
-       {0x00061000, 0x00000002},
-       {0x64c0603d, 0x00000004},
-       {0x00080000, 0x00000016},
-       {0000000000, 0000000000},
-       {0x0400251d, 0x00000002},
-       {0x00007580, 0x00000002},
-       {0x00067581, 0x00000002},
-       {0x04002580, 0x00000002},
-       {0x00067581, 0x00000002},
-       {0x00000046, 0x00000004},
-       {0x00005000, 0000000000},
-       {0x00061000, 0x00000002},
-       {0x0000750e, 0x00000002},
-       {0x00019000, 0x00000002},
-       {0x00011055, 0x00000014},
-       {0x00000055, 0x00000012},
-       {0x0400250f, 0x00000002},
-       {0x0000504a, 0x00000004},
-       {0x00007565, 0x00000002},
-       {0x00007566, 0x00000002},
-       {0x00000051, 0x00000004},
-       {0x01e655b4, 0x00000002},
-       {0x4401b0dc, 0x00000002},
-       {0x01c110dc, 0x00000002},
-       {0x2666705d, 0x00000018},
-       {0x040c2565, 0x00000002},
-       {0x0000005d, 0x00000018},
-       {0x04002564, 0x00000002},
-       {0x00007566, 0x00000002},
-       {0x00000054, 0x00000004},
-       {0x00401060, 0x00000008},
-       {0x00101000, 0x00000002},
-       {0x000d80ff, 0x00000002},
-       {0x00800063, 0x00000008},
-       {0x000f9000, 0x00000002},
-       {0x000e00ff, 0x00000002},
-       {0000000000, 0x00000006},
-       {0x00000080, 0x00000018},
-       {0x00000054, 0x00000004},
-       {0x00007576, 0x00000002},
-       {0x00065000, 0x00000002},
-       {0x00009000, 0x00000002},
-       {0x00041000, 0x00000002},
-       {0x0c00350e, 0x00000002},
-       {0x00049000, 0x00000002},
-       {0x00051000, 0x00000002},
-       {0x01e785f8, 0x00000002},
-       {0x00200000, 0x00000002},
-       {0x00600073, 0x0000000c},
-       {0x00007563, 0x00000002},
-       {0x006075f0, 0x00000021},
-       {0x20007068, 0x00000004},
-       {0x00005068, 0x00000004},
-       {0x00007576, 0x00000002},
-       {0x00007577, 0x00000002},
-       {0x0000750e, 0x00000002},
-       {0x0000750f, 0x00000002},
-       {0x00a05000, 0x00000002},
-       {0x00600076, 0x0000000c},
-       {0x006075f0, 0x00000021},
-       {0x000075f8, 0x00000002},
-       {0x00000076, 0x00000004},
-       {0x000a750e, 0x00000002},
-       {0x0020750f, 0x00000002},
-       {0x00600079, 0x00000004},
-       {0x00007570, 0x00000002},
-       {0x00007571, 0x00000002},
-       {0x00007572, 0x00000006},
-       {0x00005000, 0x00000002},
-       {0x00a05000, 0x00000002},
-       {0x00007568, 0x00000002},
-       {0x00061000, 0x00000002},
-       {0x00000084, 0x0000000c},
-       {0x00058000, 0x00000002},
-       {0x0c607562, 0x00000002},
-       {0x00000086, 0x00000004},
-       {0x00600085, 0x00000004},
-       {0x400070dd, 0000000000},
-       {0x000380dd, 0x00000002},
-       {0x00000093, 0x0000001c},
-       {0x00065095, 0x00000018},
-       {0x040025bb, 0x00000002},
-       {0x00061096, 0x00000018},
-       {0x040075bc, 0000000000},
-       {0x000075bb, 0x00000002},
-       {0x000075bc, 0000000000},
-       {0x00090000, 0x00000006},
-       {0x00090000, 0x00000002},
-       {0x000d8002, 0x00000006},
-       {0x00005000, 0x00000002},
-       {0x00007821, 0x00000002},
-       {0x00007800, 0000000000},
-       {0x00007821, 0x00000002},
-       {0x00007800, 0000000000},
-       {0x01665000, 0x00000002},
-       {0x000a0000, 0x00000002},
-       {0x000671cc, 0x00000002},
-       {0x0286f1cd, 0x00000002},
-       {0x000000a3, 0x00000010},
-       {0x21007000, 0000000000},
-       {0x000000aa, 0x0000001c},
-       {0x00065000, 0x00000002},
-       {0x000a0000, 0x00000002},
-       {0x00061000, 0x00000002},
-       {0x000b0000, 0x00000002},
-       {0x38067000, 0x00000002},
-       {0x000a00a6, 0x00000004},
-       {0x20007000, 0000000000},
-       {0x01200000, 0x00000002},
-       {0x20077000, 0x00000002},
-       {0x01200000, 0x00000002},
-       {0x20007000, 0000000000},
-       {0x00061000, 0x00000002},
-       {0x0120751b, 0x00000002},
-       {0x8040750a, 0x00000002},
-       {0x8040750b, 0x00000002},
-       {0x00110000, 0x00000002},
-       {0x000380dd, 0x00000002},
-       {0x000000bd, 0x0000001c},
-       {0x00061096, 0x00000018},
-       {0x844075bd, 0x00000002},
-       {0x00061095, 0x00000018},
-       {0x840075bb, 0x00000002},
-       {0x00061096, 0x00000018},
-       {0x844075bc, 0x00000002},
-       {0x000000c0, 0x00000004},
-       {0x804075bd, 0x00000002},
-       {0x800075bb, 0x00000002},
-       {0x804075bc, 0x00000002},
-       {0x00108000, 0x00000002},
-       {0x01400000, 0x00000002},
-       {0x006000c4, 0x0000000c},
-       {0x20c07000, 0x00000020},
-       {0x000000c6, 0x00000012},
-       {0x00800000, 0x00000006},
-       {0x0080751d, 0x00000006},
-       {0x000025bb, 0x00000002},
-       {0x000040c0, 0x00000004},
-       {0x0000775c, 0x00000002},
-       {0x00a05000, 0x00000002},
-       {0x00661000, 0x00000002},
-       {0x0460275d, 0x00000020},
-       {0x00004000, 0000000000},
-       {0x00007999, 0x00000002},
-       {0x00a05000, 0x00000002},
-       {0x00661000, 0x00000002},
-       {0x0460299b, 0x00000020},
-       {0x00004000, 0000000000},
-       {0x01e00830, 0x00000002},
-       {0x21007000, 0000000000},
-       {0x00005000, 0x00000002},
-       {0x00038042, 0x00000002},
-       {0x040025e0, 0x00000002},
-       {0x000075e1, 0000000000},
-       {0x00000001, 0000000000},
-       {0x000380d9, 0x00000002},
-       {0x04007394, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-};
-
-static const u32 radeon_cp_microcode[][2] = {
-       {0x21007000, 0000000000},
-       {0x20007000, 0000000000},
-       {0x000000b4, 0x00000004},
-       {0x000000b8, 0x00000004},
-       {0x6f5b4d4c, 0000000000},
-       {0x4c4c427f, 0000000000},
-       {0x5b568a92, 0000000000},
-       {0x4ca09c6d, 0000000000},
-       {0xad4c4c4c, 0000000000},
-       {0x4ce1af3d, 0000000000},
-       {0xd8afafaf, 0000000000},
-       {0xd64c4cdc, 0000000000},
-       {0x4cd10d10, 0000000000},
-       {0x000f0000, 0x00000016},
-       {0x362f242d, 0000000000},
-       {0x00000012, 0x00000004},
-       {0x000f0000, 0x00000016},
-       {0x362f282d, 0000000000},
-       {0x000380e7, 0x00000002},
-       {0x04002c97, 0x00000002},
-       {0x000f0001, 0x00000016},
-       {0x333a3730, 0000000000},
-       {0x000077ef, 0x00000002},
-       {0x00061000, 0x00000002},
-       {0x00000021, 0x0000001a},
-       {0x00004000, 0x0000001e},
-       {0x00061000, 0x00000002},
-       {0x00000021, 0x0000001a},
-       {0x00004000, 0x0000001e},
-       {0x00061000, 0x00000002},
-       {0x00000021, 0x0000001a},
-       {0x00004000, 0x0000001e},
-       {0x00000017, 0x00000004},
-       {0x0003802b, 0x00000002},
-       {0x040067e0, 0x00000002},
-       {0x00000017, 0x00000004},
-       {0x000077e0, 0x00000002},
-       {0x00065000, 0x00000002},
-       {0x000037e1, 0x00000002},
-       {0x040067e1, 0x00000006},
-       {0x000077e0, 0x00000002},
-       {0x000077e1, 0x00000002},
-       {0x000077e1, 0x00000006},
-       {0xffffffff, 0000000000},
-       {0x10000000, 0000000000},
-       {0x0003802b, 0x00000002},
-       {0x040067e0, 0x00000006},
-       {0x00007675, 0x00000002},
-       {0x00007676, 0x00000002},
-       {0x00007677, 0x00000002},
-       {0x00007678, 0x00000006},
-       {0x0003802c, 0x00000002},
-       {0x04002676, 0x00000002},
-       {0x00007677, 0x00000002},
-       {0x00007678, 0x00000006},
-       {0x0000002f, 0x00000018},
-       {0x0000002f, 0x00000018},
-       {0000000000, 0x00000006},
-       {0x00000030, 0x00000018},
-       {0x00000030, 0x00000018},
-       {0000000000, 0x00000006},
-       {0x01605000, 0x00000002},
-       {0x00065000, 0x00000002},
-       {0x00098000, 0x00000002},
-       {0x00061000, 0x00000002},
-       {0x64c0603e, 0x00000004},
-       {0x000380e6, 0x00000002},
-       {0x040025c5, 0x00000002},
-       {0x00080000, 0x00000016},
-       {0000000000, 0000000000},
-       {0x0400251d, 0x00000002},
-       {0x00007580, 0x00000002},
-       {0x00067581, 0x00000002},
-       {0x04002580, 0x00000002},
-       {0x00067581, 0x00000002},
-       {0x00000049, 0x00000004},
-       {0x00005000, 0000000000},
-       {0x000380e6, 0x00000002},
-       {0x040025c5, 0x00000002},
-       {0x00061000, 0x00000002},
-       {0x0000750e, 0x00000002},
-       {0x00019000, 0x00000002},
-       {0x00011055, 0x00000014},
-       {0x00000055, 0x00000012},
-       {0x0400250f, 0x00000002},
-       {0x0000504f, 0x00000004},
-       {0x000380e6, 0x00000002},
-       {0x040025c5, 0x00000002},
-       {0x00007565, 0x00000002},
-       {0x00007566, 0x00000002},
-       {0x00000058, 0x00000004},
-       {0x000380e6, 0x00000002},
-       {0x040025c5, 0x00000002},
-       {0x01e655b4, 0x00000002},
-       {0x4401b0e4, 0x00000002},
-       {0x01c110e4, 0x00000002},
-       {0x26667066, 0x00000018},
-       {0x040c2565, 0x00000002},
-       {0x00000066, 0x00000018},
-       {0x04002564, 0x00000002},
-       {0x00007566, 0x00000002},
-       {0x0000005d, 0x00000004},
-       {0x00401069, 0x00000008},
-       {0x00101000, 0x00000002},
-       {0x000d80ff, 0x00000002},
-       {0x0080006c, 0x00000008},
-       {0x000f9000, 0x00000002},
-       {0x000e00ff, 0x00000002},
-       {0000000000, 0x00000006},
-       {0x0000008f, 0x00000018},
-       {0x0000005b, 0x00000004},
-       {0x000380e6, 0x00000002},
-       {0x040025c5, 0x00000002},
-       {0x00007576, 0x00000002},
-       {0x00065000, 0x00000002},
-       {0x00009000, 0x00000002},
-       {0x00041000, 0x00000002},
-       {0x0c00350e, 0x00000002},
-       {0x00049000, 0x00000002},
-       {0x00051000, 0x00000002},
-       {0x01e785f8, 0x00000002},
-       {0x00200000, 0x00000002},
-       {0x0060007e, 0x0000000c},
-       {0x00007563, 0x00000002},
-       {0x006075f0, 0x00000021},
-       {0x20007073, 0x00000004},
-       {0x00005073, 0x00000004},
-       {0x000380e6, 0x00000002},
-       {0x040025c5, 0x00000002},
-       {0x00007576, 0x00000002},
-       {0x00007577, 0x00000002},
-       {0x0000750e, 0x00000002},
-       {0x0000750f, 0x00000002},
-       {0x00a05000, 0x00000002},
-       {0x00600083, 0x0000000c},
-       {0x006075f0, 0x00000021},
-       {0x000075f8, 0x00000002},
-       {0x00000083, 0x00000004},
-       {0x000a750e, 0x00000002},
-       {0x000380e6, 0x00000002},
-       {0x040025c5, 0x00000002},
-       {0x0020750f, 0x00000002},
-       {0x00600086, 0x00000004},
-       {0x00007570, 0x00000002},
-       {0x00007571, 0x00000002},
-       {0x00007572, 0x00000006},
-       {0x000380e6, 0x00000002},
-       {0x040025c5, 0x00000002},
-       {0x00005000, 0x00000002},
-       {0x00a05000, 0x00000002},
-       {0x00007568, 0x00000002},
-       {0x00061000, 0x00000002},
-       {0x00000095, 0x0000000c},
-       {0x00058000, 0x00000002},
-       {0x0c607562, 0x00000002},
-       {0x00000097, 0x00000004},
-       {0x000380e6, 0x00000002},
-       {0x040025c5, 0x00000002},
-       {0x00600096, 0x00000004},
-       {0x400070e5, 0000000000},
-       {0x000380e6, 0x00000002},
-       {0x040025c5, 0x00000002},
-       {0x000380e5, 0x00000002},
-       {0x000000a8, 0x0000001c},
-       {0x000650aa, 0x00000018},
-       {0x040025bb, 0x00000002},
-       {0x000610ab, 0x00000018},
-       {0x040075bc, 0000000000},
-       {0x000075bb, 0x00000002},
-       {0x000075bc, 0000000000},
-       {0x00090000, 0x00000006},
-       {0x00090000, 0x00000002},
-       {0x000d8002, 0x00000006},
-       {0x00007832, 0x00000002},
-       {0x00005000, 0x00000002},
-       {0x000380e7, 0x00000002},
-       {0x04002c97, 0x00000002},
-       {0x00007820, 0x00000002},
-       {0x00007821, 0x00000002},
-       {0x00007800, 0000000000},
-       {0x01200000, 0x00000002},
-       {0x20077000, 0x00000002},
-       {0x01200000, 0x00000002},
-       {0x20007000, 0x00000002},
-       {0x00061000, 0x00000002},
-       {0x0120751b, 0x00000002},
-       {0x8040750a, 0x00000002},
-       {0x8040750b, 0x00000002},
-       {0x00110000, 0x00000002},
-       {0x000380e5, 0x00000002},
-       {0x000000c6, 0x0000001c},
-       {0x000610ab, 0x00000018},
-       {0x844075bd, 0x00000002},
-       {0x000610aa, 0x00000018},
-       {0x840075bb, 0x00000002},
-       {0x000610ab, 0x00000018},
-       {0x844075bc, 0x00000002},
-       {0x000000c9, 0x00000004},
-       {0x804075bd, 0x00000002},
-       {0x800075bb, 0x00000002},
-       {0x804075bc, 0x00000002},
-       {0x00108000, 0x00000002},
-       {0x01400000, 0x00000002},
-       {0x006000cd, 0x0000000c},
-       {0x20c07000, 0x00000020},
-       {0x000000cf, 0x00000012},
-       {0x00800000, 0x00000006},
-       {0x0080751d, 0x00000006},
-       {0000000000, 0000000000},
-       {0x0000775c, 0x00000002},
-       {0x00a05000, 0x00000002},
-       {0x00661000, 0x00000002},
-       {0x0460275d, 0x00000020},
-       {0x00004000, 0000000000},
-       {0x01e00830, 0x00000002},
-       {0x21007000, 0000000000},
-       {0x6464614d, 0000000000},
-       {0x69687420, 0000000000},
-       {0x00000073, 0000000000},
-       {0000000000, 0000000000},
-       {0x00005000, 0x00000002},
-       {0x000380d0, 0x00000002},
-       {0x040025e0, 0x00000002},
-       {0x000075e1, 0000000000},
-       {0x00000001, 0000000000},
-       {0x000380e0, 0x00000002},
-       {0x04002394, 0x00000002},
-       {0x00005000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0x00000008, 0000000000},
-       {0x00000004, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-       {0000000000, 0000000000},
-};
-
-static const u32 R300_cp_microcode[][2] = {
-       { 0x4200e000, 0000000000 },
-       { 0x4000e000, 0000000000 },
-       { 0x000000af, 0x00000008 },
-       { 0x000000b3, 0x00000008 },
-       { 0x6c5a504f, 0000000000 },
-       { 0x4f4f497a, 0000000000 },
-       { 0x5a578288, 0000000000 },
-       { 0x4f91906a, 0000000000 },
-       { 0x4f4f4f4f, 0000000000 },
-       { 0x4fe24f44, 0000000000 },
-       { 0x4f9c9c9c, 0000000000 },
-       { 0xdc4f4fde, 0000000000 },
-       { 0xa1cd4f4f, 0000000000 },
-       { 0xd29d9d9d, 0000000000 },
-       { 0x4f0f9fd7, 0000000000 },
-       { 0x000ca000, 0x00000004 },
-       { 0x000d0012, 0x00000038 },
-       { 0x0000e8b4, 0x00000004 },
-       { 0x000d0014, 0x00000038 },
-       { 0x0000e8b6, 0x00000004 },
-       { 0x000d0016, 0x00000038 },
-       { 0x0000e854, 0x00000004 },
-       { 0x000d0018, 0x00000038 },
-       { 0x0000e855, 0x00000004 },
-       { 0x000d001a, 0x00000038 },
-       { 0x0000e856, 0x00000004 },
-       { 0x000d001c, 0x00000038 },
-       { 0x0000e857, 0x00000004 },
-       { 0x000d001e, 0x00000038 },
-       { 0x0000e824, 0x00000004 },
-       { 0x000d0020, 0x00000038 },
-       { 0x0000e825, 0x00000004 },
-       { 0x000d0022, 0x00000038 },
-       { 0x0000e830, 0x00000004 },
-       { 0x000d0024, 0x00000038 },
-       { 0x0000f0c0, 0x00000004 },
-       { 0x000d0026, 0x00000038 },
-       { 0x0000f0c1, 0x00000004 },
-       { 0x000d0028, 0x00000038 },
-       { 0x0000f041, 0x00000004 },
-       { 0x000d002a, 0x00000038 },
-       { 0x0000f184, 0x00000004 },
-       { 0x000d002c, 0x00000038 },
-       { 0x0000f185, 0x00000004 },
-       { 0x000d002e, 0x00000038 },
-       { 0x0000f186, 0x00000004 },
-       { 0x000d0030, 0x00000038 },
-       { 0x0000f187, 0x00000004 },
-       { 0x000d0032, 0x00000038 },
-       { 0x0000f180, 0x00000004 },
-       { 0x000d0034, 0x00000038 },
-       { 0x0000f393, 0x00000004 },
-       { 0x000d0036, 0x00000038 },
-       { 0x0000f38a, 0x00000004 },
-       { 0x000d0038, 0x00000038 },
-       { 0x0000f38e, 0x00000004 },
-       { 0x0000e821, 0x00000004 },
-       { 0x0140a000, 0x00000004 },
-       { 0x00000043, 0x00000018 },
-       { 0x00cce800, 0x00000004 },
-       { 0x001b0001, 0x00000004 },
-       { 0x08004800, 0x00000004 },
-       { 0x001b0001, 0x00000004 },
-       { 0x08004800, 0x00000004 },
-       { 0x001b0001, 0x00000004 },
-       { 0x08004800, 0x00000004 },
-       { 0x0000003a, 0x00000008 },
-       { 0x0000a000, 0000000000 },
-       { 0x02c0a000, 0x00000004 },
-       { 0x000ca000, 0x00000004 },
-       { 0x00130000, 0x00000004 },
-       { 0x000c2000, 0x00000004 },
-       { 0xc980c045, 0x00000008 },
-       { 0x2000451d, 0x00000004 },
-       { 0x0000e580, 0x00000004 },
-       { 0x000ce581, 0x00000004 },
-       { 0x08004580, 0x00000004 },
-       { 0x000ce581, 0x00000004 },
-       { 0x0000004c, 0x00000008 },
-       { 0x0000a000, 0000000000 },
-       { 0x000c2000, 0x00000004 },
-       { 0x0000e50e, 0x00000004 },
-       { 0x00032000, 0x00000004 },
-       { 0x00022056, 0x00000028 },
-       { 0x00000056, 0x00000024 },
-       { 0x0800450f, 0x00000004 },
-       { 0x0000a050, 0x00000008 },
-       { 0x0000e565, 0x00000004 },
-       { 0x0000e566, 0x00000004 },
-       { 0x00000057, 0x00000008 },
-       { 0x03cca5b4, 0x00000004 },
-       { 0x05432000, 0x00000004 },
-       { 0x00022000, 0x00000004 },
-       { 0x4ccce063, 0x00000030 },
-       { 0x08274565, 0x00000004 },
-       { 0x00000063, 0x00000030 },
-       { 0x08004564, 0x00000004 },
-       { 0x0000e566, 0x00000004 },
-       { 0x0000005a, 0x00000008 },
-       { 0x00802066, 0x00000010 },
-       { 0x00202000, 0x00000004 },
-       { 0x001b00ff, 0x00000004 },
-       { 0x01000069, 0x00000010 },
-       { 0x001f2000, 0x00000004 },
-       { 0x001c00ff, 0x00000004 },
-       { 0000000000, 0x0000000c },
-       { 0x00000085, 0x00000030 },
-       { 0x0000005a, 0x00000008 },
-       { 0x0000e576, 0x00000004 },
-       { 0x000ca000, 0x00000004 },
-       { 0x00012000, 0x00000004 },
-       { 0x00082000, 0x00000004 },
-       { 0x1800650e, 0x00000004 },
-       { 0x00092000, 0x00000004 },
-       { 0x000a2000, 0x00000004 },
-       { 0x000f0000, 0x00000004 },
-       { 0x00400000, 0x00000004 },
-       { 0x00000079, 0x00000018 },
-       { 0x0000e563, 0x00000004 },
-       { 0x00c0e5f9, 0x000000c2 },
-       { 0x0000006e, 0x00000008 },
-       { 0x0000a06e, 0x00000008 },
-       { 0x0000e576, 0x00000004 },
-       { 0x0000e577, 0x00000004 },
-       { 0x0000e50e, 0x00000004 },
-       { 0x0000e50f, 0x00000004 },
-       { 0x0140a000, 0x00000004 },
-       { 0x0000007c, 0x00000018 },
-       { 0x00c0e5f9, 0x000000c2 },
-       { 0x0000007c, 0x00000008 },
-       { 0x0014e50e, 0x00000004 },
-       { 0x0040e50f, 0x00000004 },
-       { 0x00c0007f, 0x00000008 },
-       { 0x0000e570, 0x00000004 },
-       { 0x0000e571, 0x00000004 },
-       { 0x0000e572, 0x0000000c },
-       { 0x0000a000, 0x00000004 },
-       { 0x0140a000, 0x00000004 },
-       { 0x0000e568, 0x00000004 },
-       { 0x000c2000, 0x00000004 },
-       { 0x00000089, 0x00000018 },
-       { 0x000b0000, 0x00000004 },
-       { 0x18c0e562, 0x00000004 },
-       { 0x0000008b, 0x00000008 },
-       { 0x00c0008a, 0x00000008 },
-       { 0x000700e4, 0x00000004 },
-       { 0x00000097, 0x00000038 },
-       { 0x000ca099, 0x00000030 },
-       { 0x080045bb, 0x00000004 },
-       { 0x000c209a, 0x00000030 },
-       { 0x0800e5bc, 0000000000 },
-       { 0x0000e5bb, 0x00000004 },
-       { 0x0000e5bc, 0000000000 },
-       { 0x00120000, 0x0000000c },
-       { 0x00120000, 0x00000004 },
-       { 0x001b0002, 0x0000000c },
-       { 0x0000a000, 0x00000004 },
-       { 0x0000e821, 0x00000004 },
-       { 0x0000e800, 0000000000 },
-       { 0x0000e821, 0x00000004 },
-       { 0x0000e82e, 0000000000 },
-       { 0x02cca000, 0x00000004 },
-       { 0x00140000, 0x00000004 },
-       { 0x000ce1cc, 0x00000004 },
-       { 0x050de1cd, 0x00000004 },
-       { 0x000000a7, 0x00000020 },
-       { 0x4200e000, 0000000000 },
-       { 0x000000ae, 0x00000038 },
-       { 0x000ca000, 0x00000004 },
-       { 0x00140000, 0x00000004 },
-       { 0x000c2000, 0x00000004 },
-       { 0x00160000, 0x00000004 },
-       { 0x700ce000, 0x00000004 },
-       { 0x001400aa, 0x00000008 },
-       { 0x4000e000, 0000000000 },
-       { 0x02400000, 0x00000004 },
-       { 0x400ee000, 0x00000004 },
-       { 0x02400000, 0x00000004 },
-       { 0x4000e000, 0000000000 },
-       { 0x000c2000, 0x00000004 },
-       { 0x0240e51b, 0x00000004 },
-       { 0x0080e50a, 0x00000005 },
-       { 0x0080e50b, 0x00000005 },
-       { 0x00220000, 0x00000004 },
-       { 0x000700e4, 0x00000004 },
-       { 0x000000c1, 0x00000038 },
-       { 0x000c209a, 0x00000030 },
-       { 0x0880e5bd, 0x00000005 },
-       { 0x000c2099, 0x00000030 },
-       { 0x0800e5bb, 0x00000005 },
-       { 0x000c209a, 0x00000030 },
-       { 0x0880e5bc, 0x00000005 },
-       { 0x000000c4, 0x00000008 },
-       { 0x0080e5bd, 0x00000005 },
-       { 0x0000e5bb, 0x00000005 },
-       { 0x0080e5bc, 0x00000005 },
-       { 0x00210000, 0x00000004 },
-       { 0x02800000, 0x00000004 },
-       { 0x00c000c8, 0x00000018 },
-       { 0x4180e000, 0x00000040 },
-       { 0x000000ca, 0x00000024 },
-       { 0x01000000, 0x0000000c },
-       { 0x0100e51d, 0x0000000c },
-       { 0x000045bb, 0x00000004 },
-       { 0x000080c4, 0x00000008 },
-       { 0x0000f3ce, 0x00000004 },
-       { 0x0140a000, 0x00000004 },
-       { 0x00cc2000, 0x00000004 },
-       { 0x08c053cf, 0x00000040 },
-       { 0x00008000, 0000000000 },
-       { 0x0000f3d2, 0x00000004 },
-       { 0x0140a000, 0x00000004 },
-       { 0x00cc2000, 0x00000004 },
-       { 0x08c053d3, 0x00000040 },
-       { 0x00008000, 0000000000 },
-       { 0x0000f39d, 0x00000004 },
-       { 0x0140a000, 0x00000004 },
-       { 0x00cc2000, 0x00000004 },
-       { 0x08c0539e, 0x00000040 },
-       { 0x00008000, 0000000000 },
-       { 0x03c00830, 0x00000004 },
-       { 0x4200e000, 0000000000 },
-       { 0x0000a000, 0x00000004 },
-       { 0x200045e0, 0x00000004 },
-       { 0x0000e5e1, 0000000000 },
-       { 0x00000001, 0000000000 },
-       { 0x000700e1, 0x00000004 },
-       { 0x0800e394, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-       { 0000000000, 0000000000 },
-};
-
-static u32 RADEON_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
 {
        u32 ret;
        RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff));
@@ -825,13 +50,58 @@ static u32 RADEON_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
        return ret;
 }
 
+static u32 RS480_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+       u32 ret;
+       RADEON_WRITE(RS480_NB_MC_INDEX, addr & 0xff);
+       ret = RADEON_READ(RS480_NB_MC_DATA);
+       RADEON_WRITE(RS480_NB_MC_INDEX, 0xff);
+       return ret;
+}
+
+static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+       u32 ret;
+       RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK));
+       ret = RADEON_READ(RS690_MC_DATA);
+       RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_MASK);
+       return ret;
+}
+
+static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+{
+        if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+           return RS690_READ_MCIND(dev_priv, addr);
+       else
+           return RS480_READ_MCIND(dev_priv, addr);
+}
+
+u32 radeon_read_mc_reg(drm_radeon_private_t *dev_priv, int addr)
+{
+        if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               return IGP_READ_MCIND(dev_priv, addr);
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515)
+               return R500_READ_MCIND(dev_priv, addr);
+       return 0;
+}
+
+void radeon_write_mc_reg(drm_radeon_private_t *dev_priv, u32 addr, u32 val)
+{
+        if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               IGP_WRITE_MCIND(addr, val);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515)
+               R500_WRITE_MCIND(addr, val);
+}
+
 u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv)
 {
-       
+
        if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-               return RADEON_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
+               return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION);
        else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-               return RADEON_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
+               return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION);
        else
                return RADEON_READ(RADEON_MC_FB_LOCATION);
 }
@@ -839,9 +109,11 @@ u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv)
 static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc)
 {
        if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-               RADEON_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
+               R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc);
        else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-               RADEON_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
+               R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc);
        else
                RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc);
 }
@@ -849,19 +121,87 @@ static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc)
 static void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc)
 {
        if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515)
-               RADEON_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
+               R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc);
+       else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+               RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc);
        else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515)
-               RADEON_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
+               R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc);
        else
                RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc);
 }
 
-static int RADEON_READ_PLL(struct drm_device * dev, int addr)
+static void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base)
 {
-       drm_radeon_private_t *dev_priv = dev->dev_private;
+       u32 agp_base_hi = upper_32_bits(agp_base);
+       u32 agp_base_lo = agp_base & 0xffffffff;
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) {
+               R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo);
+               R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi);
+       } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
+               RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo);
+               RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi);
+       } else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) {
+               R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo);
+               R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi);
+       } else {
+               RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_base_lo);
+               if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200)
+                       RADEON_WRITE(RADEON_AGP_BASE_2, agp_base_hi);
+       }
+}
+
+
+void radeon_pll_errata_after_index(struct drm_radeon_private *dev_priv)
+{
+       if (!(dev_priv->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS))
+               return;
+
+       (void)RADEON_READ(RADEON_CLOCK_CNTL_DATA);
+       (void)RADEON_READ(RADEON_CRTC_GEN_CNTL);
+}
+
+void radeon_pll_errata_after_data(struct drm_radeon_private *dev_priv)
+{
+       /* This workarounds is necessary on RV100, RS100 and RS200 chips
+        * or the chip could hang on a subsequent access
+        */
+       if (dev_priv->pll_errata & CHIP_ERRATA_PLL_DELAY)
+               udelay(5000);
+
+       /* This function is required to workaround a hardware bug in some (all?)
+        * revisions of the R300.  This workaround should be called after every
+        * CLOCK_CNTL_INDEX register access.  If not, register reads afterward
+        * may not be correct.
+        */
+       if (dev_priv->pll_errata & CHIP_ERRATA_R300_CG) {
+               uint32_t save, tmp;
+
+               save = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
+               tmp = save & ~(0x3f | RADEON_PLL_WR_EN);
+               RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, tmp);
+               tmp = RADEON_READ(RADEON_CLOCK_CNTL_DATA);
+               RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, save);
+       }
+}
+
+u32 RADEON_READ_PLL(struct drm_radeon_private *dev_priv, int addr)
+{
+       uint32_t data;
 
-       RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
-       return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
+       RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x3f);
+       radeon_pll_errata_after_index(dev_priv);
+       data = RADEON_READ(RADEON_CLOCK_CNTL_DATA);
+       radeon_pll_errata_after_data(dev_priv);
+       return data;
+}
+
+void RADEON_WRITE_PLL(struct drm_radeon_private *dev_priv, int addr, uint32_t data)
+{
+       RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, ((addr & 0x3f) | RADEON_PLL_WR_EN));
+       radeon_pll_errata_after_index(dev_priv);
+       RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, data);
+       radeon_pll_errata_after_data(dev_priv);
 }
 
 static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
@@ -870,12 +210,36 @@ static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
        return RADEON_READ(RADEON_PCIE_DATA);
 }
 
-static u32 RADEON_READ_IGPGART(drm_radeon_private_t *dev_priv, int addr)
+/* ATOM accessor methods */
+static uint32_t cail_mc_read(struct card_info *info, uint32_t reg)
 {
-       u32 ret;
-       RADEON_WRITE(RADEON_IGPGART_INDEX, addr & 0x7f);
-       ret = RADEON_READ(RADEON_IGPGART_DATA);
-       RADEON_WRITE(RADEON_IGPGART_INDEX, 0x7f);
+       uint32_t ret = radeon_read_mc_reg(info->dev->dev_private, reg);
+
+       //      DRM_DEBUG("(%x) = %x\n", reg, ret);
+       return ret;
+}
+
+static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val)
+{
+  //   DRM_DEBUG("(%x,  %x)\n", reg, val);
+       radeon_write_mc_reg(info->dev->dev_private, reg, val);
+}
+
+static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val)
+{
+       drm_radeon_private_t *dev_priv = info->dev->dev_private;
+       
+       //      DRM_DEBUG("(%x,  %x)\n", reg*4, val);
+       RADEON_WRITE(reg*4, val);
+}
+
+static uint32_t cail_reg_read(struct card_info *info, uint32_t reg)
+{
+       uint32_t ret;
+       drm_radeon_private_t *dev_priv = info->dev->dev_private;
+
+       ret = RADEON_READ(reg*4);
+       //      DRM_DEBUG("(%x) = %x\n", reg*4, ret);
        return ret;
 }
 
@@ -913,16 +277,36 @@ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv)
 
        dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 
-       tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
-       tmp |= RADEON_RB3D_DC_FLUSH_ALL;
-       RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) {
+               tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT);
+               tmp |= RADEON_RB3D_DC_FLUSH_ALL;
+               RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
 
-       for (i = 0; i < dev_priv->usec_timeout; i++) {
-               if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
-                     & RADEON_RB3D_DC_BUSY)) {
-                       return 0;
+               for (i = 0; i < dev_priv->usec_timeout; i++) {
+                       if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT)
+                             & RADEON_RB3D_DC_BUSY)) {
+                               return 0;
+                       }
+                       DRM_UDELAY(1);
+               }
+       } else {
+               /* 3D */
+               tmp = RADEON_READ(R300_RB3D_DSTCACHE_CTLSTAT);
+               tmp |= RADEON_RB3D_DC_FLUSH_ALL;
+               RADEON_WRITE(R300_RB3D_DSTCACHE_CTLSTAT, tmp);
+
+               /* 2D */
+               tmp = RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT);
+               tmp |= RADEON_RB3D_DC_FLUSH_ALL;
+               RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp);
+
+               for (i = 0; i < dev_priv->usec_timeout; i++) {
+                       if (!(RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT)
+                         & RADEON_RB3D_DC_BUSY)) {
+                               return 0;
+                       }
+                       DRM_UDELAY(1);
                }
-               DRM_UDELAY(1);
        }
 
 #if RADEON_FIFO_DEBUG
@@ -979,6 +363,50 @@ static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)
        return -EBUSY;
 }
 
+static void radeon_init_pipes(drm_radeon_private_t * dev_priv)
+{
+       uint32_t gb_tile_config, gb_pipe_sel = 0;
+
+       /* RS4xx/RS6xx/R4xx/R5xx */
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {
+               gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);
+               dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
+       } else {
+               /* R3xx */
+               if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
+                   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350)) {
+                       dev_priv->num_gb_pipes = 2;
+               } else {
+                       /* R3Vxx */
+                       dev_priv->num_gb_pipes = 1;
+               }
+       }
+       DRM_INFO("Num pipes: %d\n", dev_priv->num_gb_pipes);
+
+       gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 /*| R300_SUBPIXEL_1_16*/);
+
+       switch(dev_priv->num_gb_pipes) {
+       case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
+       case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
+       case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
+       default:
+       case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
+       }
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
+               RADEON_WRITE_PLL(dev_priv, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
+               RADEON_WRITE(R500_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1));
+       }
+       RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config);
+       radeon_do_wait_for_idle(dev_priv);
+       RADEON_WRITE(R300_DST_PIPE_CONFIG, RADEON_READ(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG);
+       RADEON_WRITE(R300_RB2D_DSTCACHE_MODE, (RADEON_READ(R300_RB2D_DSTCACHE_MODE) |
+                                              R300_DC_AUTOFLUSH_ENABLE |
+                                              R300_DC_DC_DISABLE_IGNORE_PE));
+
+
+}
+
 /* ================================================================
  * CP control, initialization
  */
@@ -993,7 +421,22 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
 
        RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
 
-       if (dev_priv->microcode_version == UCODE_R200) {
+       if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) {
+               DRM_INFO("Loading R100 Microcode\n");
+               for (i = 0; i < 256; i++) {
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+                                    R100_cp_microcode[i][1]);
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+                                    R100_cp_microcode[i][0]);
+               }
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) {
                DRM_INFO("Loading R200 Microcode\n");
                for (i = 0; i < 256; i++) {
                        RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
@@ -1001,7 +444,11 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
                        RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
                                     R200_cp_microcode[i][0]);
                }
-       } else if (dev_priv->microcode_version == UCODE_R300) {
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
                DRM_INFO("Loading R300 Microcode\n");
                for (i = 0; i < 256; i++) {
                        RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
@@ -1009,12 +456,35 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
                        RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
                                     R300_cp_microcode[i][0]);
                }
-       } else {
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
+               DRM_INFO("Loading R400 Microcode\n");
                for (i = 0; i < 256; i++) {
                        RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
-                                    radeon_cp_microcode[i][1]);
+                                    R420_cp_microcode[i][1]);
                        RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    radeon_cp_microcode[i][0]);
+                                    R420_cp_microcode[i][0]);
+               }
+       } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
+               DRM_INFO("Loading RS690 Microcode\n");
+               for (i = 0; i < 256; i++) {
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+                                    RS690_cp_microcode[i][1]);
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+                                    RS690_cp_microcode[i][0]);
+               }
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) {
+               DRM_INFO("Loading R500 Microcode\n");
+               for (i = 0; i < 256; i++) {
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+                                    R520_cp_microcode[i][1]);
+                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+                                    R520_cp_microcode[i][0]);
                }
        }
 }
@@ -1109,49 +579,56 @@ static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
 static int radeon_do_engine_reset(struct drm_device * dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
-       u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
+       u32 clock_cntl_index = 0, mclk_cntl = 0, rbbm_soft_reset;
        DRM_DEBUG("\n");
 
        radeon_do_pixcache_flush(dev_priv);
 
-       if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) {
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
+               /* may need something similar for newer chips */
                clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX);
-               mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL);
-               
-               RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl |
-                                                   RADEON_FORCEON_MCLKA |
-                                                   RADEON_FORCEON_MCLKB |
-                                                   RADEON_FORCEON_YCLKA |
-                                                   RADEON_FORCEON_YCLKB |
-                                                   RADEON_FORCEON_MC |
-                                                   RADEON_FORCEON_AIC));
-               
-               rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
-               
-               RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
-                                                     RADEON_SOFT_RESET_CP |
-                                                     RADEON_SOFT_RESET_HI |
-                                                     RADEON_SOFT_RESET_SE |
-                                                     RADEON_SOFT_RESET_RE |
-                                                     RADEON_SOFT_RESET_PP |
-                                                     RADEON_SOFT_RESET_E2 |
-                                                     RADEON_SOFT_RESET_RB));
-               RADEON_READ(RADEON_RBBM_SOFT_RESET);
-               RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
-                                                     ~(RADEON_SOFT_RESET_CP |
-                                                       RADEON_SOFT_RESET_HI |
-                                                       RADEON_SOFT_RESET_SE |
-                                                       RADEON_SOFT_RESET_RE |
-                                                       RADEON_SOFT_RESET_PP |
-                                                       RADEON_SOFT_RESET_E2 |
-                                                       RADEON_SOFT_RESET_RB)));
-               RADEON_READ(RADEON_RBBM_SOFT_RESET);
-               
-               RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
+               mclk_cntl = RADEON_READ_PLL(dev_priv, RADEON_MCLK_CNTL);
+
+               RADEON_WRITE_PLL(dev_priv, RADEON_MCLK_CNTL, (mclk_cntl |
+                                                             RADEON_FORCEON_MCLKA |
+                                                             RADEON_FORCEON_MCLKB |
+                                                             RADEON_FORCEON_YCLKA |
+                                                             RADEON_FORCEON_YCLKB |
+                                                             RADEON_FORCEON_MC |
+                                                             RADEON_FORCEON_AIC));
+       }
+
+       rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+       RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
+                                             RADEON_SOFT_RESET_CP |
+                                             RADEON_SOFT_RESET_HI |
+                                             RADEON_SOFT_RESET_SE |
+                                             RADEON_SOFT_RESET_RE |
+                                             RADEON_SOFT_RESET_PP |
+                                             RADEON_SOFT_RESET_E2 |
+                                             RADEON_SOFT_RESET_RB));
+       RADEON_READ(RADEON_RBBM_SOFT_RESET);
+       RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
+                                             ~(RADEON_SOFT_RESET_CP |
+                                               RADEON_SOFT_RESET_HI |
+                                               RADEON_SOFT_RESET_SE |
+                                               RADEON_SOFT_RESET_RE |
+                                               RADEON_SOFT_RESET_PP |
+                                               RADEON_SOFT_RESET_E2 |
+                                               RADEON_SOFT_RESET_RB)));
+       RADEON_READ(RADEON_RBBM_SOFT_RESET);
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
+               RADEON_WRITE_PLL(dev_priv, RADEON_MCLK_CNTL, mclk_cntl);
                RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
                RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
        }
 
+       /* setup the raster pipes */
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300)
+           radeon_init_pipes(dev_priv);
+
        /* Reset the CP ring */
        radeon_do_cp_reset(dev_priv);
 
@@ -1159,7 +636,8 @@ static int radeon_do_engine_reset(struct drm_device * dev)
        dev_priv->cp_running = 0;
 
        /* Reset any pending vertex, indirect buffers */
-       radeon_freelist_reset(dev);
+       if (dev->dma)
+               radeon_freelist_reset(dev);
 
        return 0;
 }
@@ -1177,12 +655,17 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
         */
        if (!dev_priv->new_memmap)
                radeon_write_fb_location(dev_priv,
-                            ((dev_priv->gart_vm_start - 1) & 0xffff0000)
-                            | (dev_priv->fb_location >> 16));
-
+                                        ((dev_priv->gart_vm_start - 1) & 0xffff0000)
+                                        | (dev_priv->fb_location >> 16));
+       
+       if (dev_priv->mm.ring.bo) {
+               ring_start = dev_priv->mm.ring.bo->offset +
+                       dev_priv->gart_vm_start;
+       } else
 #if __OS_HAS_AGP
        if (dev_priv->flags & RADEON_IS_AGP) {
-               RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);
+               radeon_write_agp_base(dev_priv, dev->agp->base);
+
                radeon_write_agp_location(dev_priv,
                             (((dev_priv->gart_vm_start - 1 +
                                dev_priv->gart_size) & 0xffff0000) |
@@ -1208,6 +691,12 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
        SET_RING_HEAD(dev_priv, cur_read_ptr);
        dev_priv->ring.tail = cur_read_ptr;
 
+
+       if (dev_priv->mm.ring_read.bo) {
+               RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
+                            dev_priv->mm.ring_read.bo->offset +
+                            dev_priv->gart_vm_start);
+       } else
 #if __OS_HAS_AGP
        if (dev_priv->flags & RADEON_IS_AGP) {
                RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
@@ -1256,9 +745,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
        RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)
                     + RADEON_SCRATCH_REG_OFFSET);
 
-       dev_priv->scratch = ((__volatile__ u32 *)
-                            dev_priv->ring_rptr->handle +
-                            (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
+       if (dev_priv->mm.ring_read.bo)
+               dev_priv->scratch = ((__volatile__ u32 *)
+                                    dev_priv->mm.ring_read.kmap.virtual +
+                                    (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
+       else
+               dev_priv->scratch = ((__volatile__ u32 *)
+                                    dev_priv->ring_rptr->handle +
+                                    (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));
 
        RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
 
@@ -1266,39 +760,50 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
        tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
        RADEON_WRITE(RADEON_BUS_CNTL, tmp);
 
-       dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;
-       RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
+       dev_priv->scratch[0] = 0;
+       RADEON_WRITE(RADEON_LAST_FRAME_REG, 0);
 
-       dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;
-       RADEON_WRITE(RADEON_LAST_DISPATCH_REG,
-                    dev_priv->sarea_priv->last_dispatch);
+       dev_priv->scratch[1] = 0;
+       RADEON_WRITE(RADEON_LAST_DISPATCH_REG, 0);
 
-       dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;
-       RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);
+       dev_priv->scratch[2] = 0;
+       RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);
 
        radeon_do_wait_for_idle(dev_priv);
 
        /* Sync everything up */
+       if (dev_priv->chip_family > CHIP_RV280) {
        RADEON_WRITE(RADEON_ISYNC_CNTL,
                     (RADEON_ISYNC_ANY2D_IDLE3D |
                      RADEON_ISYNC_ANY3D_IDLE2D |
                      RADEON_ISYNC_WAIT_IDLEGUI |
                      RADEON_ISYNC_CPSCRATCH_IDLEGUI));
-
+       } else {
+       RADEON_WRITE(RADEON_ISYNC_CNTL,
+                    (RADEON_ISYNC_ANY2D_IDLE3D |
+                     RADEON_ISYNC_ANY3D_IDLE2D |
+                     RADEON_ISYNC_WAIT_IDLEGUI));
+       }
 }
 
 static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
 {
        u32 tmp;
+       void *ring_read_ptr;
+
+       if (dev_priv->mm.ring_read.bo)
+               ring_read_ptr = dev_priv->mm.ring_read.kmap.virtual;
+       else
+               ring_read_ptr = dev_priv->ring_rptr->handle;
 
        /* Writeback doesn't seem to work everywhere, test it here and possibly
         * enable it if it appears to work
         */
-       DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);
+       writel(0, ring_read_ptr + RADEON_SCRATCHOFF(1));
        RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);
 
        for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
-               if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==
+               if (readl(ring_read_ptr + RADEON_SCRATCHOFF(1)) ==
                    0xdeadbeef)
                        break;
                DRM_UDELAY(1);
@@ -1326,40 +831,79 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
 /* Enable or disable IGP GART on the chip */
 static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on)
 {
-       u32 temp, tmp;
+       u32 temp;
 
-       tmp = RADEON_READ(RADEON_AIC_CNTL);
-       DRM_DEBUG("setting igpgart AIC CNTL is %08X\n", tmp);
        if (on) {
-               DRM_DEBUG("programming igpgart %08X %08lX %08X\n",
+               DRM_DEBUG("programming igp gart %08X %08lX %08X\n",
                         dev_priv->gart_vm_start,
                         (long)dev_priv->gart_info.bus_addr,
                         dev_priv->gart_size);
 
-               RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_18, 0x1000);
-               RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, 0x1);
-               RADEON_WRITE_IGPGART(RADEON_IGPGART_CTRL, 0x42040800);
-               RADEON_WRITE_IGPGART(RADEON_IGPGART_BASE_ADDR,
-                                    dev_priv->gart_info.bus_addr);
+               temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL);
+
+               if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690)
+                       IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN |
+                                                            RS690_BLOCK_GFX_D3_EN));
+               else
+                       IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN);
+
+               IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
+                                                              RS480_VA_SIZE_32MB));
+
+               temp = IGP_READ_MCIND(dev_priv, RS480_GART_FEATURE_ID);
+               IGP_WRITE_MCIND(RS480_GART_FEATURE_ID, (RS480_HANG_EN |
+                                                       RS480_TLB_ENABLE |
+                                                       RS480_GTW_LAC_EN |
+                                                       RS480_1LEVEL_GART));
+
+               temp = dev_priv->gart_info.bus_addr & 0xfffff000;
+               temp |= (upper_32_bits(dev_priv->gart_info.bus_addr) & 0xff) << 4;
+               IGP_WRITE_MCIND(RS480_GART_BASE, temp);
 
-               temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_UNK_39);
-               RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_39, temp);
+               temp = IGP_READ_MCIND(dev_priv, RS480_AGP_MODE_CNTL);
+               IGP_WRITE_MCIND(RS480_AGP_MODE_CNTL, ((1 << RS480_REQ_TYPE_SNOOP_SHIFT) |
+                                                     RS480_REQ_TYPE_SNOOP_DIS));
+
+               if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
+                       IGP_WRITE_MCIND(RS690_MC_AGP_BASE,
+                                       (unsigned int)dev_priv->gart_vm_start);
+                       IGP_WRITE_MCIND(RS690_MC_AGP_BASE_2, 0);
+               } else {
+                       RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev_priv->gart_vm_start);
+                       RADEON_WRITE(RS480_AGP_BASE_2, 0);
+               }
 
-               RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev_priv->gart_vm_start);
                dev_priv->gart_size = 32*1024*1024;
-               radeon_write_agp_location(dev_priv,
-                            (((dev_priv->gart_vm_start - 1 +
-                              dev_priv->gart_size) & 0xffff0000) |
-                            (dev_priv->gart_vm_start >> 16)));
+               temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & 
+                       0xffff0000) | (dev_priv->gart_vm_start >> 16));
+
+               radeon_write_agp_location(dev_priv, temp);
 
-               temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_ENABLE);
-               RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, temp);
+               temp = IGP_READ_MCIND(dev_priv, RS480_AGP_ADDRESS_SPACE_SIZE);
+               IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN |
+                                                              RS480_VA_SIZE_32MB));
+
+               do {
+                       temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
+                       if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
+                               break;
+                       DRM_UDELAY(1);
+               } while(1);
+
+               IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL,
+                               RS480_GART_CACHE_INVALIDATE);
+
+               do {
+                       temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
+                       if ((temp & RS480_GART_CACHE_INVALIDATE) == 0)
+                               break;
+                       DRM_UDELAY(1);
+               } while(1);
 
-               RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH);
-               RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x1);
-               RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH);
-               RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x0);
-       }
+               IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 0);
+       } else {
+               IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, 0);
+       }
 }
 
 static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
@@ -1392,11 +936,12 @@ static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on)
 }
 
 /* Enable or disable PCI GART on the chip */
-static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
+void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
 {
        u32 tmp;
 
-       if (dev_priv->flags & RADEON_IS_IGPGART) {
+       if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+           (dev_priv->flags & RADEON_IS_IGPGART)) {
                radeon_set_igpgart(dev_priv, on);
                return;
        }
@@ -1432,9 +977,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
        }
 }
 
-static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
+static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
+                            struct drm_file *file_priv)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
+       struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
 
        DRM_DEBUG("\n");
 
@@ -1475,17 +1022,6 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
         */
        dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
 
-       switch(init->func) {
-       case RADEON_INIT_R200_CP:
-               dev_priv->microcode_version = UCODE_R200;
-               break;
-       case RADEON_INIT_R300_CP:
-               dev_priv->microcode_version = UCODE_R300;
-               break;
-       default:
-               dev_priv->microcode_version = UCODE_R100;
-       }
-
        dev_priv->do_boxes = 0;
        dev_priv->cp_mode = init->cp_mode;
 
@@ -1533,9 +1069,8 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
         */
        dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |
                                           (dev_priv->color_fmt << 10) |
-                                          (dev_priv->microcode_version ==
-                                           UCODE_R100 ? RADEON_ZBLOCK16 : 0));
-
+                                          (dev_priv->chip_family < CHIP_R200 ? RADEON_ZBLOCK16 : 0));
+       
        dev_priv->depth_clear.rb3d_zstencilcntl =
            (dev_priv->depth_fmt |
             RADEON_Z_TEST_ALWAYS |
@@ -1562,8 +1097,8 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
        dev_priv->buffers_offset = init->buffers_offset;
        dev_priv->gart_textures_offset = init->gart_textures_offset;
 
-       dev_priv->sarea = drm_getsarea(dev);
-       if (!dev_priv->sarea) {
+       master_priv->sarea = drm_getsarea(dev);
+       if (!master_priv->sarea) {
                DRM_ERROR("could not find sarea!\n");
                radeon_do_cleanup_cp(dev);
                return -EINVAL;
@@ -1599,10 +1134,6 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
                }
        }
 
-       dev_priv->sarea_priv =
-           (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle +
-                                   init->sarea_priv_offset);
-
 #if __OS_HAS_AGP
        if (dev_priv->flags & RADEON_IS_AGP) {
                drm_core_ioremap(dev_priv->cp_ring, dev);
@@ -1730,30 +1261,44 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
        } else
 #endif
        {
+               dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
                /* if we have an offset set from userspace */
                if (dev_priv->pcigart_offset_set) {
-                       dev_priv->gart_info.bus_addr =
-                           dev_priv->pcigart_offset + dev_priv->fb_location;
-                       dev_priv->gart_info.mapping.offset =
-                           dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
-                       dev_priv->gart_info.mapping.size =
-                           dev_priv->gart_info.table_size;
-
-                       drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
-                       dev_priv->gart_info.addr =
-                           dev_priv->gart_info.mapping.handle;
-
-                       if (dev_priv->flags & RADEON_IS_PCIE)
-                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
-                       else
-                               dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
-                       dev_priv->gart_info.gart_table_location =
-                           DRM_ATI_GART_FB;
 
-                       DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
-                                 dev_priv->gart_info.addr,
-                                 dev_priv->pcigart_offset);
+                       /* if it came from userspace - remap it */
+                       if (dev_priv->pcigart_offset_set == 1) {
+                               dev_priv->gart_info.bus_addr =
+                                       dev_priv->pcigart_offset + dev_priv->fb_location;
+                               dev_priv->gart_info.mapping.offset =
+                                       dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
+                               dev_priv->gart_info.mapping.size =
+                                       dev_priv->gart_info.table_size;
+                               
+                               /* this is done by the mm now */
+                               drm_core_ioremap(&dev_priv->gart_info.mapping, dev);
+                               dev_priv->gart_info.addr =
+                                       dev_priv->gart_info.mapping.handle;
+                               
+                               memset(dev_priv->gart_info.addr, 0, dev_priv->gart_info.table_size);
+                               if (dev_priv->flags & RADEON_IS_PCIE)
+                                       dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
+                               else
+                                       dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
+                               dev_priv->gart_info.gart_table_location =
+                                       DRM_ATI_GART_FB;
+                               
+                               DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
+                                         dev_priv->gart_info.addr,
+                                         dev_priv->pcigart_offset);
+                       }
                } else {
+
+                       if (dev_priv->flags & RADEON_IS_PCIE) {
+                               DRM_ERROR
+                                   ("Cannot use PCI Express without GART in FB memory\n");
+                               radeon_do_cleanup_cp(dev);
+                               return -EINVAL;
+                       }
                        if (dev_priv->flags & RADEON_IS_IGPGART)
                                dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP;
                        else
@@ -1762,12 +1307,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
                            DRM_ATI_GART_MAIN;
                        dev_priv->gart_info.addr = NULL;
                        dev_priv->gart_info.bus_addr = 0;
-                       if (dev_priv->flags & RADEON_IS_PCIE) {
-                               DRM_ERROR
-                                   ("Cannot use PCI Express without GART in FB memory\n");
-                               radeon_do_cleanup_cp(dev);
-                               return -EINVAL;
-                       }
+
                }
 
                if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
@@ -1824,14 +1364,16 @@ static int radeon_do_cleanup_cp(struct drm_device * dev)
                if (dev_priv->gart_info.bus_addr) {
                        /* Turn off PCI GART */
                        radeon_set_pcigart(dev_priv, 0);
-                       if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info))
-                               DRM_ERROR("failed to cleanup PCI GART!\n");
+                       drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info);
                }
 
                if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
                {
-                       drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
-                       dev_priv->gart_info.addr = 0;
+                       if (dev_priv->pcigart_offset_set == 1) {
+                               drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
+                               dev_priv->gart_info.addr = NULL;
+                               dev_priv->pcigart_offset_set = 0;
+                       }
                }
        }
        /* only clear to the start of flags */
@@ -1882,6 +1424,10 @@ static int radeon_do_resume_cp(struct drm_device * dev)
 int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
        drm_radeon_init_t *init = data;
+       
+       /* on a modesetting driver ignore this stuff */
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return 0;
 
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
@@ -1892,7 +1438,7 @@ int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_pri
        case RADEON_INIT_CP:
        case RADEON_INIT_R200_CP:
        case RADEON_INIT_R300_CP:
-               return radeon_do_init_cp(dev, init);
+               return radeon_do_init_cp(dev, init, file_priv);
        case RADEON_CLEANUP_CP:
                return radeon_do_cleanup_cp(dev);
        }
@@ -1905,15 +1451,18 @@ int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_pr
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return 0;
+
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (dev_priv->cp_running) {
-               DRM_DEBUG("%s while CP running\n", __FUNCTION__);
+               DRM_DEBUG("while CP running\n");
                return 0;
        }
        if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) {
-               DRM_DEBUG("%s called with bogus CP mode (%d)\n",
-                         __FUNCTION__, dev_priv->cp_mode);
+               DRM_DEBUG("called with bogus CP mode (%d)\n",
+                         dev_priv->cp_mode);
                return 0;
        }
 
@@ -1932,6 +1481,9 @@ int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_pri
        int ret;
        DRM_DEBUG("\n");
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return 0;
+
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv->cp_running)
@@ -1970,6 +1522,9 @@ void radeon_do_release(struct drm_device * dev)
        drm_radeon_private_t *dev_priv = dev->dev_private;
        int i, ret;
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) 
+               return;
+               
        if (dev_priv) {
                if (dev_priv->cp_running) {
                        /* Stop the cp */
@@ -1979,7 +1534,7 @@ void radeon_do_release(struct drm_device * dev)
                                schedule();
 #else
 #if defined(__FreeBSD__) && __FreeBSD_version > 500000
-                               msleep(&ret, &dev->dev_lock, PZERO, "rdnrel",
+                               mtx_sleep(&ret, &dev->dev_lock, PZERO, "rdnrel",
                                       1);
 #else
                                tsleep(&ret, PZERO, "rdnrel", 1);
@@ -2008,6 +1563,11 @@ void radeon_do_release(struct drm_device * dev)
                radeon_mem_takedown(&(dev_priv->gart_heap));
                radeon_mem_takedown(&(dev_priv->fb_heap));
 
+               if (dev_priv->user_mm_enable) {
+                       radeon_gem_mm_fini(dev);
+                       dev_priv->user_mm_enable = false;
+               }
+
                /* deallocate kernel resources */
                radeon_do_cleanup_cp(dev);
        }
@@ -2020,10 +1580,13 @@ int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_pr
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) 
+               return 0;
+
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        if (!dev_priv) {
-               DRM_DEBUG("%s called before init done\n", __FUNCTION__);
+               DRM_DEBUG("called before init done\n");
                return -EINVAL;
        }
 
@@ -2040,7 +1603,9 @@ int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_pri
        drm_radeon_private_t *dev_priv = dev->dev_private;
        DRM_DEBUG("\n");
 
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
+       
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        return radeon_do_cp_idle(dev_priv);
 }
@@ -2050,6 +1615,9 @@ int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_pri
 int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) 
+               return 0;
+
        return radeon_do_resume_cp(dev);
 }
 
@@ -2057,6 +1625,9 @@ int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *fil
 {
        DRM_DEBUG("\n");
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) 
+               return 0;
+
        LOCK_TEST_WITH_RETURN(dev, file_priv);
 
        return radeon_do_engine_reset(dev);
@@ -2279,6 +1850,549 @@ int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_
        return ret;
 }
 
+static void radeon_get_vram_type(struct drm_device *dev)
+{
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+       uint32_t tmp;
+
+       if (dev_priv->flags & RADEON_IS_IGP || (dev_priv->chip_family >= CHIP_R300))
+               dev_priv->is_ddr = true;
+       else if (RADEON_READ(RADEON_MEM_SDRAM_MODE_REG) & RADEON_MEM_CFG_TYPE_DDR)
+               dev_priv->is_ddr = true;
+       else
+               dev_priv->is_ddr = false;
+
+       if ((dev_priv->chip_family >= CHIP_R600) &&
+           (dev_priv->chip_family <= CHIP_RV635)) {
+               int chansize;
+               
+               tmp = RADEON_READ(R600_RAMCFG);
+               if (tmp & R600_CHANSIZE_OVERRIDE)
+                       chansize = 16;
+               else if (tmp & R600_CHANSIZE)
+                       chansize = 64;
+               else
+                       chansize = 32;
+
+               if (dev_priv->chip_family == CHIP_R600)
+                       dev_priv->ram_width = 8 * chansize;
+               else if (dev_priv->chip_family == CHIP_RV670)
+                       dev_priv->ram_width = 4 * chansize;
+               else if ((dev_priv->chip_family == CHIP_RV610) ||
+                        (dev_priv->chip_family == CHIP_RV620))
+                       dev_priv->ram_width = chansize;
+               else if ((dev_priv->chip_family == CHIP_RV630) ||
+                        (dev_priv->chip_family == CHIP_RV635))
+                       dev_priv->ram_width = 2 * chansize;
+       } else if (dev_priv->chip_family == CHIP_RV515) {
+               tmp = radeon_read_mc_reg(dev_priv, RV515_MC_CNTL);
+               tmp &= RV515_MEM_NUM_CHANNELS_MASK;
+               switch (tmp) {
+               case 0: dev_priv->ram_width = 64; break;
+               case 1: dev_priv->ram_width = 128; break;
+               default: dev_priv->ram_width = 128; break;
+               }
+       } else if ((dev_priv->chip_family >= CHIP_R520) &&
+                  (dev_priv->chip_family <= CHIP_RV570)) {
+               tmp = radeon_read_mc_reg(dev_priv, R520_MC_CNTL0);
+               switch ((tmp & R520_MEM_NUM_CHANNELS_MASK) >> R520_MEM_NUM_CHANNELS_SHIFT) {
+               case 0: dev_priv->ram_width = 32; break;
+               case 1: dev_priv->ram_width = 64; break;
+               case 2: dev_priv->ram_width = 128; break;
+               case 3: dev_priv->ram_width = 256; break;
+               default: dev_priv->ram_width = 128; break;
+               }
+       } else if ((dev_priv->chip_family == CHIP_RV100) ||
+                  (dev_priv->chip_family == CHIP_RS100) ||
+                  (dev_priv->chip_family == CHIP_RS200)) {
+               tmp = RADEON_READ(RADEON_MEM_CNTL);
+               if (tmp & RV100_HALF_MODE)
+                       dev_priv->ram_width = 32;
+               else
+                       dev_priv->ram_width = 64;
+
+               if (dev_priv->flags & RADEON_SINGLE_CRTC) {
+                       dev_priv->ram_width /= 4;
+                       dev_priv->is_ddr = true;
+               }
+       } else if (dev_priv->chip_family <= CHIP_RV280) {
+               tmp = RADEON_READ(RADEON_MEM_CNTL);
+               if (tmp & RADEON_MEM_NUM_CHANNELS_MASK)
+                       dev_priv->ram_width = 128;
+               else
+                       dev_priv->ram_width = 64;
+       } else {
+               /* newer IGPs */
+               dev_priv->ram_width = 128;
+       }
+       DRM_DEBUG("RAM width %d bits %cDR\n", dev_priv->ram_width, dev_priv->is_ddr ? 'D' : 'S');
+}   
+
+static void radeon_force_some_clocks(struct drm_device *dev)
+{
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+       uint32_t tmp;
+
+       tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_CNTL);
+       tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP;
+       RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_CNTL, tmp);
+}
+
+static void radeon_set_dynamic_clock(struct drm_device *dev, int mode)
+{
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+       uint32_t tmp;
+
+       switch(mode) {
+       case 0:
+               if (dev_priv->flags & RADEON_SINGLE_CRTC) {
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_CNTL);
+                       tmp |= (RADEON_SCLK_FORCE_CP   | RADEON_SCLK_FORCE_HDP |
+                               RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP |
+                               RADEON_SCLK_FORCE_E2   | RADEON_SCLK_FORCE_SE  |
+                               RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP |
+                               RADEON_SCLK_FORCE_RE   | RADEON_SCLK_FORCE_PB  |
+                               RADEON_SCLK_FORCE_TAM  | RADEON_SCLK_FORCE_TDM |
+                               RADEON_SCLK_FORCE_RB);
+                       RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_CNTL, tmp);
+               } else if (dev_priv->chip_family == CHIP_RV350) {
+                       /* for RV350/M10, no delays are required. */
+                       tmp = RADEON_READ_PLL(dev_priv, R300_SCLK_CNTL2);
+                       tmp |= (R300_SCLK_FORCE_TCL |
+                               R300_SCLK_FORCE_GA |
+                               R300_SCLK_FORCE_CBA);
+                       RADEON_WRITE_PLL(dev_priv, R300_SCLK_CNTL2, tmp);
+
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_CNTL);
+                       tmp &= ~(RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP      |
+                                RADEON_SCLK_FORCE_HDP   | RADEON_SCLK_FORCE_DISP1   |
+                                RADEON_SCLK_FORCE_TOP   | RADEON_SCLK_FORCE_E2      |
+                                R300_SCLK_FORCE_VAP     | RADEON_SCLK_FORCE_IDCT    |
+                                RADEON_SCLK_FORCE_VIP   | R300_SCLK_FORCE_SR        |
+                                R300_SCLK_FORCE_PX      | R300_SCLK_FORCE_TX        |
+                                R300_SCLK_FORCE_US      | RADEON_SCLK_FORCE_TV_SCLK |
+                                R300_SCLK_FORCE_SU      | RADEON_SCLK_FORCE_OV0);
+                       tmp |=  RADEON_DYN_STOP_LAT_MASK;
+                       RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_CNTL, tmp);
+
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_MORE_CNTL);
+                       tmp &= ~RADEON_SCLK_MORE_FORCEON;
+                       tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
+                       RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_MORE_CNTL, tmp);
+
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_VCLK_ECP_CNTL);
+                       tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
+                               RADEON_PIXCLK_DAC_ALWAYS_ONb);
+                       RADEON_WRITE_PLL(dev_priv, RADEON_VCLK_ECP_CNTL, tmp);
+
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_PIXCLKS_CNTL);
+                       tmp |= (RADEON_PIX2CLK_ALWAYS_ONb         |
+                               RADEON_PIX2CLK_DAC_ALWAYS_ONb     |
+                               RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
+                               R300_DVOCLK_ALWAYS_ONb            |   
+                               RADEON_PIXCLK_BLEND_ALWAYS_ONb    |
+                               RADEON_PIXCLK_GV_ALWAYS_ONb       |
+                               R300_PIXCLK_DVO_ALWAYS_ONb        | 
+                               RADEON_PIXCLK_LVDS_ALWAYS_ONb     |
+                               RADEON_PIXCLK_TMDS_ALWAYS_ONb     |
+                               R300_PIXCLK_TRANS_ALWAYS_ONb      |
+                               R300_PIXCLK_TVO_ALWAYS_ONb        |
+                               R300_P2G2CLK_ALWAYS_ONb           |
+                               R300_P2G2CLK_ALWAYS_ONb);
+                       RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, tmp);
+               } else {
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_CNTL);
+                       tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2);
+                       tmp |= RADEON_SCLK_FORCE_SE;
+
+                       if ( dev_priv->flags & RADEON_SINGLE_CRTC ) {
+                               tmp |= ( RADEON_SCLK_FORCE_RB    |
+                                        RADEON_SCLK_FORCE_TDM   |
+                                        RADEON_SCLK_FORCE_TAM   |
+                                        RADEON_SCLK_FORCE_PB    |
+                                        RADEON_SCLK_FORCE_RE    |
+                                        RADEON_SCLK_FORCE_VIP   |
+                                        RADEON_SCLK_FORCE_IDCT  |
+                                        RADEON_SCLK_FORCE_TOP   |
+                                        RADEON_SCLK_FORCE_DISP1 |
+                                        RADEON_SCLK_FORCE_DISP2 |
+                                        RADEON_SCLK_FORCE_HDP    );
+                       } else if ((dev_priv->chip_family == CHIP_R300) ||
+                                  (dev_priv->chip_family == CHIP_R350)) {
+                               tmp |= ( RADEON_SCLK_FORCE_HDP   |
+                                        RADEON_SCLK_FORCE_DISP1 |
+                                        RADEON_SCLK_FORCE_DISP2 |
+                                        RADEON_SCLK_FORCE_TOP   |
+                                        RADEON_SCLK_FORCE_IDCT  |
+                                        RADEON_SCLK_FORCE_VIP);
+                       }
+
+                       RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_CNTL, tmp);
+
+                       udelay(16000);
+                       
+                       if ((dev_priv->chip_family == CHIP_R300) ||
+                           (dev_priv->chip_family == CHIP_R350)) {
+                               tmp = RADEON_READ_PLL(dev_priv, R300_SCLK_CNTL2);
+                               tmp |= ( R300_SCLK_FORCE_TCL |
+                                        R300_SCLK_FORCE_GA  |
+                                        R300_SCLK_FORCE_CBA);
+                               RADEON_WRITE_PLL(dev_priv, R300_SCLK_CNTL2, tmp);
+                               udelay(16000);
+                       }
+                       
+                       if (dev_priv->flags & RADEON_IS_IGP) {
+                               tmp = RADEON_READ_PLL(dev_priv, RADEON_MCLK_CNTL);
+                               tmp &= ~(RADEON_FORCEON_MCLKA |
+                                        RADEON_FORCEON_YCLKA);
+                               RADEON_WRITE_PLL(dev_priv, RADEON_MCLK_CNTL, tmp);
+                               udelay(16000);
+                       }
+                       
+                       if ((dev_priv->chip_family == CHIP_RV200) ||
+                           (dev_priv->chip_family == CHIP_RV250) ||
+                           (dev_priv->chip_family == CHIP_RV280)) {
+                               tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_MORE_CNTL);
+                               tmp |= RADEON_SCLK_MORE_FORCEON;
+                               RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_MORE_CNTL, tmp);
+                               udelay(16000);
+                       }
+                       
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_PIXCLKS_CNTL);
+                       tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb         |
+                                RADEON_PIX2CLK_DAC_ALWAYS_ONb     |
+                                RADEON_PIXCLK_BLEND_ALWAYS_ONb    |
+                                RADEON_PIXCLK_GV_ALWAYS_ONb       |
+                                RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
+                                RADEON_PIXCLK_LVDS_ALWAYS_ONb     |
+                                RADEON_PIXCLK_TMDS_ALWAYS_ONb);
+                       
+                       RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, tmp);
+                       udelay(16000);
+                       
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_VCLK_ECP_CNTL);
+                       tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb  |
+                                RADEON_PIXCLK_DAC_ALWAYS_ONb); 
+                       RADEON_WRITE_PLL(dev_priv, RADEON_VCLK_ECP_CNTL, tmp);
+               }
+               DRM_DEBUG("Dynamic Clock Scaling Disabled\n");
+               break;
+        case 1:
+               if (dev_priv->flags & RADEON_SINGLE_CRTC) {
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_CNTL);
+                       if ((RADEON_READ(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) >
+                           RADEON_CFG_ATI_REV_A13) { 
+                               tmp &= ~(RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_RB);
+                       }
+                       tmp &= ~(RADEON_SCLK_FORCE_HDP  | RADEON_SCLK_FORCE_DISP1 |
+                                RADEON_SCLK_FORCE_TOP  | RADEON_SCLK_FORCE_SE   |
+                                RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE   |
+                                RADEON_SCLK_FORCE_PB   | RADEON_SCLK_FORCE_TAM  |
+                                RADEON_SCLK_FORCE_TDM);
+                       RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_CNTL, tmp);
+               } else if ((dev_priv->chip_family == CHIP_R300) ||
+                          (dev_priv->chip_family == CHIP_R350) ||
+                          (dev_priv->chip_family == CHIP_RV350)) {
+                       if (dev_priv->chip_family == CHIP_RV350) {
+                               tmp = RADEON_READ_PLL(dev_priv, R300_SCLK_CNTL2);
+                               tmp &= ~(R300_SCLK_FORCE_TCL |
+                                        R300_SCLK_FORCE_GA  |
+                                        R300_SCLK_FORCE_CBA);
+                               tmp |=  (R300_SCLK_TCL_MAX_DYN_STOP_LAT |
+                                        R300_SCLK_GA_MAX_DYN_STOP_LAT  |
+                                        R300_SCLK_CBA_MAX_DYN_STOP_LAT);
+                               RADEON_WRITE_PLL(dev_priv, R300_SCLK_CNTL2, tmp);
+                               
+                               tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_CNTL);
+                               tmp &= ~(RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP      |
+                                        RADEON_SCLK_FORCE_HDP   | RADEON_SCLK_FORCE_DISP1   |
+                                        RADEON_SCLK_FORCE_TOP   | RADEON_SCLK_FORCE_E2      |
+                                        R300_SCLK_FORCE_VAP     | RADEON_SCLK_FORCE_IDCT    |
+                                        RADEON_SCLK_FORCE_VIP   | R300_SCLK_FORCE_SR        |
+                                        R300_SCLK_FORCE_PX      | R300_SCLK_FORCE_TX        |
+                                        R300_SCLK_FORCE_US      | RADEON_SCLK_FORCE_TV_SCLK |
+                                        R300_SCLK_FORCE_SU      | RADEON_SCLK_FORCE_OV0);
+                               tmp |=  RADEON_DYN_STOP_LAT_MASK;
+                               RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_CNTL, tmp);
+
+                               tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_MORE_CNTL);
+                               tmp &= ~RADEON_SCLK_MORE_FORCEON;
+                               tmp |=  RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
+                               RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_MORE_CNTL, tmp);
+                               
+                               tmp = RADEON_READ_PLL(dev_priv, RADEON_VCLK_ECP_CNTL);
+                               tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
+                                       RADEON_PIXCLK_DAC_ALWAYS_ONb);   
+                               RADEON_WRITE_PLL(dev_priv, RADEON_VCLK_ECP_CNTL, tmp);
+
+                               tmp = RADEON_READ_PLL(dev_priv, RADEON_PIXCLKS_CNTL);
+                               tmp |= (RADEON_PIX2CLK_ALWAYS_ONb         |
+                                       RADEON_PIX2CLK_DAC_ALWAYS_ONb     |
+                                       RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
+                                       R300_DVOCLK_ALWAYS_ONb            |   
+                                       RADEON_PIXCLK_BLEND_ALWAYS_ONb    |
+                                       RADEON_PIXCLK_GV_ALWAYS_ONb       |
+                                       R300_PIXCLK_DVO_ALWAYS_ONb        | 
+                                       RADEON_PIXCLK_LVDS_ALWAYS_ONb     |
+                                       RADEON_PIXCLK_TMDS_ALWAYS_ONb     |
+                                       R300_PIXCLK_TRANS_ALWAYS_ONb      |
+                                       R300_PIXCLK_TVO_ALWAYS_ONb        |
+                                       R300_P2G2CLK_ALWAYS_ONb           |
+                                       R300_P2G2CLK_ALWAYS_ONb);
+                               RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, tmp);
+
+                               tmp = RADEON_READ_PLL(dev_priv, RADEON_MCLK_MISC);
+                               tmp |= (RADEON_MC_MCLK_DYN_ENABLE |
+                                       RADEON_IO_MCLK_DYN_ENABLE);
+                               RADEON_WRITE_PLL(dev_priv, RADEON_MCLK_MISC, tmp);
+
+                               tmp = RADEON_READ_PLL(dev_priv, RADEON_MCLK_CNTL);
+                               tmp |= (RADEON_FORCEON_MCLKA |
+                                       RADEON_FORCEON_MCLKB);
+
+                               tmp &= ~(RADEON_FORCEON_YCLKA  |
+                                        RADEON_FORCEON_YCLKB  |
+                                        RADEON_FORCEON_MC);
+
+                               /* Some releases of vbios have set DISABLE_MC_MCLKA
+                                  and DISABLE_MC_MCLKB bits in the vbios table.  Setting these
+                                  bits will cause H/W hang when reading video memory with dynamic clocking
+                                  enabled. */
+                               if ((tmp & R300_DISABLE_MC_MCLKA) &&
+                                   (tmp & R300_DISABLE_MC_MCLKB)) {
+                                       /* If both bits are set, then check the active channels */
+                                       tmp = RADEON_READ_PLL(dev_priv, RADEON_MCLK_CNTL);
+                                       if (dev_priv->ram_width == 64) {
+                                               if (RADEON_READ(RADEON_MEM_CNTL) & R300_MEM_USE_CD_CH_ONLY)
+                                                       tmp &= ~R300_DISABLE_MC_MCLKB;
+                                               else
+                                                       tmp &= ~R300_DISABLE_MC_MCLKA;
+                                       } else {
+                                               tmp &= ~(R300_DISABLE_MC_MCLKA |
+                                                        R300_DISABLE_MC_MCLKB);
+                                       }
+                               }
+                               
+                               RADEON_WRITE_PLL(dev_priv, RADEON_MCLK_CNTL, tmp);
+                       } else {
+                               tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_CNTL);
+                               tmp &= ~(R300_SCLK_FORCE_VAP);
+                               tmp |= RADEON_SCLK_FORCE_CP;
+                               RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_CNTL, tmp);
+                               udelay(15000);
+                               
+                               tmp = RADEON_READ_PLL(dev_priv, R300_SCLK_CNTL2);
+                               tmp &= ~(R300_SCLK_FORCE_TCL |
+                                        R300_SCLK_FORCE_GA  |
+                                        R300_SCLK_FORCE_CBA);
+                               RADEON_WRITE_PLL(dev_priv, R300_SCLK_CNTL2, tmp);
+                       }
+               } else {
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_CLK_PWRMGT_CNTL);
+                       tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK     | 
+                                RADEON_DISP_DYN_STOP_LAT_MASK   | 
+                                RADEON_DYN_STOP_MODE_MASK); 
+                       
+                       tmp |= (RADEON_ENGIN_DYNCLK_MODE |
+                               (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT));
+                       RADEON_WRITE_PLL(dev_priv, RADEON_CLK_PWRMGT_CNTL, tmp);
+                       udelay(15000);
+
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_CLK_PIN_CNTL);
+                       tmp |= RADEON_SCLK_DYN_START_CNTL; 
+                       RADEON_WRITE_PLL(dev_priv, RADEON_CLK_PIN_CNTL, tmp);
+                       udelay(15000);
+
+                       /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200 
+                          to lockup randomly, leave them as set by BIOS.
+                       */
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_CNTL);
+                       /*tmp &= RADEON_SCLK_SRC_SEL_MASK;*/
+                       tmp &= ~RADEON_SCLK_FORCEON_MASK;
+
+                       /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
+                       if (((dev_priv->chip_family == CHIP_RV250) &&
+                            ((RADEON_READ(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <
+                             RADEON_CFG_ATI_REV_A13)) || 
+                           ((dev_priv->chip_family == CHIP_RV100) &&
+                            ((RADEON_READ(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <=
+                             RADEON_CFG_ATI_REV_A13))){
+                               tmp |= RADEON_SCLK_FORCE_CP;
+                               tmp |= RADEON_SCLK_FORCE_VIP;
+                       }
+                       
+                       RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_CNTL, tmp);
+
+                       if ((dev_priv->chip_family == CHIP_RV200) ||
+                           (dev_priv->chip_family == CHIP_RV250) ||
+                           (dev_priv->chip_family == CHIP_RV280)) {
+                               tmp = RADEON_READ_PLL(dev_priv, RADEON_SCLK_MORE_CNTL);
+                               tmp &= ~RADEON_SCLK_MORE_FORCEON;
+
+                               /* RV200::A11 A12 RV250::A11 A12 */
+                               if (((dev_priv->chip_family == CHIP_RV200) ||
+                                    (dev_priv->chip_family == CHIP_RV250)) &&
+                                   ((RADEON_READ(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <
+                                    RADEON_CFG_ATI_REV_A13)) {
+                                       tmp |= RADEON_SCLK_MORE_FORCEON;
+                               }
+                               RADEON_WRITE_PLL(dev_priv, RADEON_SCLK_MORE_CNTL, tmp);
+                               udelay(15000);
+                       }
+                       
+                       /* RV200::A11 A12, RV250::A11 A12 */
+                       if (((dev_priv->chip_family == CHIP_RV200) ||
+                            (dev_priv->chip_family == CHIP_RV250)) &&
+                           ((RADEON_READ(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <
+                            RADEON_CFG_ATI_REV_A13)) {
+                               tmp = RADEON_READ_PLL(dev_priv, RADEON_PLL_PWRMGT_CNTL);
+                               tmp |= RADEON_TCL_BYPASS_DISABLE;
+                               RADEON_WRITE_PLL(dev_priv, RADEON_PLL_PWRMGT_CNTL, tmp);
+                       }
+                       udelay(15000);
+                       
+                       /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK)*/
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_PIXCLKS_CNTL);
+                       tmp |=  (RADEON_PIX2CLK_ALWAYS_ONb         |
+                                RADEON_PIX2CLK_DAC_ALWAYS_ONb     |
+                                RADEON_PIXCLK_BLEND_ALWAYS_ONb    |
+                                RADEON_PIXCLK_GV_ALWAYS_ONb       |
+                                RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
+                                RADEON_PIXCLK_LVDS_ALWAYS_ONb     |
+                                RADEON_PIXCLK_TMDS_ALWAYS_ONb);
+                       
+                       RADEON_WRITE_PLL(dev_priv, RADEON_PIXCLKS_CNTL, tmp);
+                       udelay(15000);
+                       
+                       tmp = RADEON_READ_PLL(dev_priv, RADEON_VCLK_ECP_CNTL);
+                       tmp |= (RADEON_PIXCLK_ALWAYS_ONb  |
+                               RADEON_PIXCLK_DAC_ALWAYS_ONb); 
+                       
+                       RADEON_WRITE_PLL(dev_priv, RADEON_VCLK_ECP_CNTL, tmp);
+                       udelay(15000);
+               }    
+               DRM_DEBUG("Dynamic Clock Scaling Enabled\n");
+               break;
+        default:
+               break;
+       }
+       
+}
+
+int radeon_modeset_cp_init(struct drm_device *dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       uint32_t tmp;
+
+       /* allocate a ring and ring rptr bits from GART space */
+       /* these are allocated in GEM files */
+       
+       dev_priv->usec_timeout = RADEON_DEFAULT_CP_TIMEOUT;
+       dev_priv->ring.size = RADEON_DEFAULT_RING_SIZE;
+       dev_priv->cp_mode = RADEON_CSQ_PRIBM_INDBM;
+
+       dev_priv->ring.start = (u32 *)(void *)(unsigned long)dev_priv->mm.ring.kmap.virtual;
+       dev_priv->ring.end = (u32 *)(void *)(unsigned long)dev_priv->mm.ring.kmap.virtual +
+               dev_priv->ring.size / sizeof(u32);
+       dev_priv->ring.size_l2qw = drm_order(dev_priv->ring.size / 8);
+       dev_priv->ring.rptr_update = 4096;
+       dev_priv->ring.rptr_update_l2qw = drm_order(4096 / 8);
+       dev_priv->ring.fetch_size = 32;
+       dev_priv->ring.fetch_size_l2ow = drm_order(32 / 16);
+       dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
+       dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
+
+       dev_priv->new_memmap = true;
+
+       r300_init_reg_flags(dev);
+               
+       radeon_cp_load_microcode(dev_priv);
+       
+       DRM_DEBUG("ring offset is %x %x\n", dev_priv->mm.ring.bo->offset, dev_priv->mm.ring_read.bo->offset);
+
+       radeon_cp_init_ring_buffer(dev, dev_priv);
+
+       /* need to enable BUS mastering in Buscntl */
+       tmp = RADEON_READ(RADEON_BUS_CNTL);
+       tmp &= ~RADEON_BUS_MASTER_DIS;
+       RADEON_WRITE(RADEON_BUS_CNTL, tmp);
+
+       radeon_do_engine_reset(dev);
+       radeon_test_writeback(dev_priv);
+
+       radeon_do_cp_start(dev_priv);
+       return 0;
+}
+
+static bool radeon_get_bios(struct drm_device *dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       u8 __iomem *bios;
+       size_t size;
+       uint16_t tmp;
+
+       bios = pci_map_rom(dev->pdev, &size);
+       if (!bios)
+               return -1;
+
+       dev_priv->bios = kmalloc(size, GFP_KERNEL);
+       if (!dev_priv->bios) {
+               pci_unmap_rom(dev->pdev, bios);
+               return -1;
+       }
+
+       memcpy(dev_priv->bios, bios, size);
+
+       pci_unmap_rom(dev->pdev, bios);
+
+       if (dev_priv->bios[0] != 0x55 || dev_priv->bios[1] != 0xaa)
+               goto free_bios;
+
+       dev_priv->bios_header_start = radeon_bios16(dev_priv, 0x48);
+
+       if (!dev_priv->bios_header_start)
+               goto free_bios;
+
+       tmp = dev_priv->bios_header_start + 4;
+
+       if (!memcmp(dev_priv->bios + tmp, "ATOM", 4) ||
+           !memcmp(dev_priv->bios + tmp, "MOTA", 4))
+               dev_priv->is_atom_bios = true;
+       else
+               dev_priv->is_atom_bios = false;
+
+       DRM_DEBUG("%sBIOS detected\n", dev_priv->is_atom_bios ? "ATOM" : "COM");
+       return true;
+free_bios:
+       kfree(dev_priv->bios);
+       dev_priv->bios = NULL;
+       return false;
+}
+
+int radeon_modeset_preinit(struct drm_device *dev)
+{
+       drm_radeon_private_t *dev_priv = dev->dev_private;
+       static struct card_info card;
+       int ret;
+
+       card.dev = dev;
+       card.reg_read = cail_reg_read;
+       card.reg_write = cail_reg_write;
+       card.mc_read = cail_mc_read;
+       card.mc_write = cail_mc_write;
+
+       ret = radeon_get_bios(dev);
+       if (!ret)
+               return -1;
+
+       if (dev_priv->is_atom_bios) {
+               dev_priv->mode_info.atom_context = atom_parse(&card, dev_priv->bios);
+       }
+       radeon_get_clock_info(dev);
+       return 0;
+}
+
+
 int radeon_driver_load(struct drm_device *dev, unsigned long flags)
 {
        drm_radeon_private_t *dev_priv;
@@ -2311,6 +2425,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
                break;
        }
 
+       dev_priv->chip_family = flags & RADEON_FAMILY_MASK;
        if (drm_device_is_agp(dev))
                dev_priv->flags |= RADEON_IS_AGP;
        else if (drm_device_is_pcie(dev))
@@ -2318,11 +2433,122 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
        else
                dev_priv->flags |= RADEON_IS_PCI;
 
+
+           
        DRM_DEBUG("%s card detected\n",
                  ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI"))));
+
+       ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
+                        drm_get_resource_len(dev, 2), _DRM_REGISTERS,
+                        _DRM_DRIVER | _DRM_READ_ONLY, &dev_priv->mmio);
+       if (ret != 0)
+               return ret;
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               radeon_modeset_preinit(dev);
+
+
+       radeon_get_vram_type(dev);
+
+       dev_priv->pll_errata = 0;
+
+       if (dev_priv->chip_family == CHIP_R300 &&
+           (RADEON_READ(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) == RADEON_CFG_ATI_REV_A11)
+               dev_priv->pll_errata |= CHIP_ERRATA_R300_CG;
+               
+       if (dev_priv->chip_family == CHIP_RV200 ||
+           dev_priv->chip_family == CHIP_RS200)
+               dev_priv->pll_errata |= CHIP_ERRATA_PLL_DUMMYREADS;
+
+
+       if (dev_priv->chip_family == CHIP_RV100 ||
+           dev_priv->chip_family == CHIP_RS100 ||
+           dev_priv->chip_family == CHIP_RS200)
+               dev_priv->pll_errata |= CHIP_ERRATA_PLL_DELAY;
+
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               if ((dev_priv->flags & RADEON_IS_MOBILITY) && !radeon_is_avivo(dev_priv)) {
+                       radeon_set_dynamic_clock(dev, radeon_dynclks);
+               } else if (radeon_is_avivo(dev_priv)) {
+                       if (radeon_dynclks) {
+                               radeon_atom_static_pwrmgt_setup(dev, 1);
+                               radeon_atom_dyn_clk_setup(dev, 1);
+                       }
+               }
+               radeon_force_some_clocks(dev);
+       }
+               
+       /* init memory manager - start with all of VRAM and a 32MB GART aperture for now */
+       dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0);
+
+       drm_bo_driver_init(dev);
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+       
+               dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16;
+               dev_priv->fb_size =
+                       ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000)
+                       - dev_priv->fb_location;
+               radeon_gem_mm_init(dev);
+               radeon_modeset_init(dev);
+
+               radeon_modeset_cp_init(dev);
+               dev->devname = kstrdup(DRIVER_NAME, GFP_KERNEL);
+
+               drm_irq_install(dev);
+       }
+
+
        return ret;
 }
 
+
+int radeon_master_create(struct drm_device *dev, struct drm_master *master)
+{
+       struct drm_radeon_master_private *master_priv;
+       unsigned long sareapage;
+       int ret;
+
+       master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
+       if (!master_priv)
+               return -ENOMEM;
+
+       /* prebuild the SAREA */
+       sareapage = max(SAREA_MAX, PAGE_SIZE);
+       ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK|_DRM_DRIVER,
+                        &master_priv->sarea);
+       if (ret) {
+               DRM_ERROR("SAREA setup failed\n");
+               return ret;
+       }
+       master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
+       master_priv->sarea_priv->pfCurrentPage = 0;
+
+       master->driver_priv = master_priv;
+       return 0;
+}
+
+void radeon_master_destroy(struct drm_device *dev, struct drm_master *master)
+{
+       struct drm_radeon_master_private *master_priv = master->driver_priv;
+       struct drm_radeon_private *dev_priv = dev->dev_private;
+
+       if (!master_priv)
+               return;
+
+       if (master_priv->sarea_priv &&
+           master_priv->sarea_priv->pfCurrentPage != 0)
+               radeon_cp_dispatch_flip(dev, master);
+
+       master_priv->sarea_priv = NULL;
+       if (master_priv->sarea)
+               drm_rmmap_locked(dev, master_priv->sarea);
+               
+       drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
+
+       master->driver_priv = NULL;
+}
 /* Create mappings for registers and framebuffer so userland doesn't necessarily
  * have to find them.
  */
@@ -2334,13 +2560,9 @@ int radeon_driver_firstopen(struct drm_device *dev)
 
        dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE;
 
-       ret = drm_addmap(dev, drm_get_resource_start(dev, 2),
-                        drm_get_resource_len(dev, 2), _DRM_REGISTERS,
-                        _DRM_READ_ONLY, &dev_priv->mmio);
-       if (ret != 0)
-               return ret;
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               radeon_gem_mm_init(dev);
 
-       dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0);
        ret = drm_addmap(dev, dev_priv->fb_aper_offset,
                         drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER,
                         _DRM_WRITE_COMBINING, &map);
@@ -2354,9 +2576,40 @@ int radeon_driver_unload(struct drm_device *dev)
 {
        drm_radeon_private_t *dev_priv = dev->dev_private;
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               drm_irq_uninstall(dev);
+               radeon_modeset_cleanup(dev);
+               radeon_gem_mm_fini(dev);
+       }
+
+       drm_bo_driver_finish(dev);
+       drm_rmmap(dev, dev_priv->mmio);
+
        DRM_DEBUG("\n");
        drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
 
        dev->dev_private = NULL;
        return 0;
 }
+
+void radeon_gart_flush(struct drm_device *dev)
+{
+        drm_radeon_private_t *dev_priv = dev->dev_private;
+        
+        if (dev_priv->flags & RADEON_IS_IGPGART) {
+                IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
+                IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, RS480_GART_CACHE_INVALIDATE);
+                IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL);
+                IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 0);
+        } else if (dev_priv->flags & RADEON_IS_PCIE) {
+                u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);
+                tmp |= RADEON_PCIE_TX_GART_INVALIDATE_TLB;
+                RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
+                tmp &= ~RADEON_PCIE_TX_GART_INVALIDATE_TLB;
+                RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
+        } else {
+
+
+       }
+       
+}