OSDN Git Service

Merge commit 'origin/master' into modesetting-gem
[android-x86/external-libdrm.git] / shared-core / radeon_cp.c
index ae31e96..6fbcfea 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "drmP.h"
 #include "drm.h"
+#include "drm_sarea.h"
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 #include "r300_reg.h"
@@ -76,6 +77,23 @@ static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
            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)
 {
 
@@ -138,12 +156,57 @@ static void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base)
        }
 }
 
-static int RADEON_READ_PLL(struct drm_device * dev, int addr)
+
+void radeon_pll_errata_after_index(struct drm_radeon_private *dev_priv)
 {
-       drm_radeon_private_t *dev_priv = dev->dev_private;
+       if (!(dev_priv->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS))
+               return;
 
-       RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f);
-       return RADEON_READ(RADEON_CLOCK_CNTL_DATA);
+       (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);
+       }
+}
+
+int RADEON_READ_PLL(struct drm_radeon_private *dev_priv, int addr)
+{
+       uint32_t 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)
@@ -152,6 +215,39 @@ static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr)
        return RADEON_READ(RADEON_PCIE_DATA);
 }
 
+/* ATOM accessor methods */
+static uint32_t cail_mc_read(struct card_info *info, uint32_t reg)
+{
+       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;
+}
+
 #if RADEON_FIFO_DEBUG
 static void radeon_status(drm_radeon_private_t * dev_priv)
 {
@@ -294,7 +390,7 @@ static void radeon_init_pipes(drm_radeon_private_t * dev_priv)
        }
 
        if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
-               RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
+               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);
@@ -494,15 +590,15 @@ static int radeon_do_engine_reset(struct drm_device * dev)
        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));
+               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);
@@ -527,7 +623,7 @@ static int radeon_do_engine_reset(struct drm_device * dev)
        RADEON_READ(RADEON_RBBM_SOFT_RESET);
 
        if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) {
-               RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);
+               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);
        }
@@ -543,7 +639,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;
 }
@@ -561,9 +658,13 @@ 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) {
+               ring_start = dev_priv->mm.ring->offset +
+                       dev_priv->gart_vm_start;
+       } else
 #if __OS_HAS_AGP
        if (dev_priv->flags & RADEON_IS_AGP) {
                radeon_write_agp_base(dev_priv, dev->agp->base);
@@ -593,6 +694,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_ptr) {
+               RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,
+                            dev_priv->mm.ring_read_ptr->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,
@@ -641,9 +748,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_ptr)
+               dev_priv->scratch = ((__volatile__ u32 *)
+                                    dev_priv->mm.ring_read_ptr_map.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);
 
@@ -651,15 +763,14 @@ 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);
 
@@ -675,15 +786,21 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
 static void radeon_test_writeback(drm_radeon_private_t * dev_priv)
 {
        u32 tmp;
+       void *ring_read_ptr;
+
+       if (dev_priv->mm.ring_read_ptr)
+               ring_read_ptr = dev_priv->mm.ring_read_ptr_map.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);
@@ -809,7 +926,7 @@ 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;
 
@@ -850,9 +967,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");
 
@@ -968,8 +1087,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;
@@ -1005,10 +1124,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);
@@ -1139,28 +1254,40 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
                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_wc(&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
@@ -1169,12 +1296,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)) {
@@ -1237,8 +1359,10 @@ static int radeon_do_cleanup_cp(struct drm_device * dev)
 
                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;
+                       }
                }
        }
        /* only clear to the start of flags */
@@ -1290,6 +1414,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);
 
@@ -1300,7 +1428,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);
        }
@@ -1313,6 +1441,9 @@ 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) {
@@ -1340,6 +1471,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)
@@ -1378,6 +1512,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 */
@@ -1416,6 +1553,9 @@ void radeon_do_release(struct drm_device * dev)
                radeon_mem_takedown(&(dev_priv->gart_heap));
                radeon_mem_takedown(&(dev_priv->fb_heap));
 
+
+               radeon_gem_mm_fini(dev);
+
                /* deallocate kernel resources */
                radeon_do_cleanup_cp(dev);
        }
@@ -1428,6 +1568,9 @@ 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) {
@@ -1448,7 +1591,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);
 }
@@ -1458,6 +1603,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);
 }
 
@@ -1465,6 +1613,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);
@@ -1687,6 +1838,541 @@ 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;
+
+       /* 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_map.virtual;
+       dev_priv->ring.end = (u32 *)(void *)(unsigned long)dev_priv->mm.ring_map.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 = 1;
+
+       radeon_cp_load_microcode(dev_priv);
+       
+       DRM_DEBUG("ring offset is %x %x\n", dev_priv->mm.ring->offset, dev_priv->mm.ring_read_ptr->offset);
+
+       radeon_cp_init_ring_buffer(dev, dev_priv);
+
+       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;
@@ -1727,11 +2413,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(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.
  */
@@ -1743,13 +2540,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);
@@ -1763,9 +2556,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 {
+
+
+       }
+       
+}