radeon: Use request_firmware()
[safe/jmp/linux-2.6] / drivers / gpu / drm / radeon / r600_cp.c
index 6f2cc74..8327912 100644 (file)
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 
-#include "r600_microcode.h"
+#define PFP_UCODE_SIZE 576
+#define PM4_UCODE_SIZE 1792
+#define R700_PFP_UCODE_SIZE 848
+#define R700_PM4_UCODE_SIZE 1360
+
+/* Firmware Names */
+MODULE_FIRMWARE("radeon/R600_pfp.bin");
+MODULE_FIRMWARE("radeon/R600_me.bin");
+MODULE_FIRMWARE("radeon/RV610_pfp.bin");
+MODULE_FIRMWARE("radeon/RV610_me.bin");
+MODULE_FIRMWARE("radeon/RV630_pfp.bin");
+MODULE_FIRMWARE("radeon/RV630_me.bin");
+MODULE_FIRMWARE("radeon/RV620_pfp.bin");
+MODULE_FIRMWARE("radeon/RV620_me.bin");
+MODULE_FIRMWARE("radeon/RV635_pfp.bin");
+MODULE_FIRMWARE("radeon/RV635_me.bin");
+MODULE_FIRMWARE("radeon/RV670_pfp.bin");
+MODULE_FIRMWARE("radeon/RV670_me.bin");
+MODULE_FIRMWARE("radeon/RS780_pfp.bin");
+MODULE_FIRMWARE("radeon/RS780_me.bin");
+MODULE_FIRMWARE("radeon/RV770_pfp.bin");
+MODULE_FIRMWARE("radeon/RV770_me.bin");
+MODULE_FIRMWARE("radeon/RV730_pfp.bin");
+MODULE_FIRMWARE("radeon/RV730_me.bin");
+MODULE_FIRMWARE("radeon/RV710_pfp.bin");
+MODULE_FIRMWARE("radeon/RV710_me.bin");
 
 # define ATI_PCIGART_PAGE_SIZE         4096    /**< PCI GART page size */
 # define ATI_PCIGART_PAGE_MASK         (~(ATI_PCIGART_PAGE_SIZE-1))
@@ -125,7 +150,7 @@ void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
                return;
 
        if (gart_info->bus_addr) {
-               max_pages = (gart_info->table_size / sizeof(u32));
+               max_pages = (gart_info->table_size / sizeof(u64));
                pages = (entry->pages <= max_pages)
                  ? entry->pages : max_pages;
 
@@ -172,7 +197,6 @@ int r600_page_table_init(struct drm_device *dev)
                if (entry->busaddr[i] == 0) {
                        DRM_ERROR("unable to map PCIGART pages!\n");
                        r600_page_table_cleanup(dev, gart_info);
-                       ret = -EINVAL;
                        goto done;
                }
                entry_addr = entry->busaddr[i];
@@ -191,6 +215,7 @@ int r600_page_table_init(struct drm_device *dev)
                        entry_addr += ATI_PCIGART_PAGE_SIZE;
                }
        }
+       ret = 1;
 done:
        return ret;
 }
@@ -275,11 +300,93 @@ static void r600_vm_init(struct drm_device *dev)
        r600_vm_flush_gart_range(dev);
 }
 
-/* load r600 microcode */
+static int r600_cp_init_microcode(drm_radeon_private_t *dev_priv)
+{
+       struct platform_device *pdev;
+       const char *chip_name;
+       size_t pfp_req_size, me_req_size;
+       char fw_name[30];
+       int err;
+
+       pdev = platform_device_register_simple("r600_cp", 0, NULL, 0);
+       err = IS_ERR(pdev);
+       if (err) {
+               printk(KERN_ERR "r600_cp: Failed to register firmware\n");
+               return -EINVAL;
+       }
+
+       switch (dev_priv->flags & RADEON_FAMILY_MASK) {
+       case CHIP_R600:  chip_name = "R600";  break;
+       case CHIP_RV610: chip_name = "RV610"; break;
+       case CHIP_RV630: chip_name = "RV630"; break;
+       case CHIP_RV620: chip_name = "RV620"; break;
+       case CHIP_RV635: chip_name = "RV635"; break;
+       case CHIP_RV670: chip_name = "RV670"; break;
+       case CHIP_RS780:
+       case CHIP_RS880: chip_name = "RS780"; break;
+       case CHIP_RV770: chip_name = "RV770"; break;
+       case CHIP_RV730:
+       case CHIP_RV740: chip_name = "RV730"; break;
+       case CHIP_RV710: chip_name = "RV710"; break;
+       default:         BUG();
+       }
+
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) {
+               pfp_req_size = R700_PFP_UCODE_SIZE * 4;
+               me_req_size = R700_PM4_UCODE_SIZE * 4;
+       } else {
+               pfp_req_size = PFP_UCODE_SIZE * 4;
+               me_req_size = PM4_UCODE_SIZE * 12;
+       }
+
+       DRM_INFO("Loading %s CP Microcode\n", chip_name);
+
+       snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
+       err = request_firmware(&dev_priv->pfp_fw, fw_name, &pdev->dev);
+       if (err)
+               goto out;
+       if (dev_priv->pfp_fw->size != pfp_req_size) {
+               printk(KERN_ERR
+                      "r600_cp: Bogus length %zu in firmware \"%s\"\n",
+                      dev_priv->pfp_fw->size, fw_name);
+               err = -EINVAL;
+               goto out;
+       }
+
+       snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
+       err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev);
+       if (err)
+               goto out;
+       if (dev_priv->me_fw->size != me_req_size) {
+               printk(KERN_ERR
+                      "r600_cp: Bogus length %zu in firmware \"%s\"\n",
+                      dev_priv->me_fw->size, fw_name);
+               err = -EINVAL;
+       }
+out:
+       platform_device_unregister(pdev);
+
+       if (err) {
+               if (err != -EINVAL)
+                       printk(KERN_ERR
+                              "r600_cp: Failed to load firmware \"%s\"\n",
+                              fw_name);
+               release_firmware(dev_priv->pfp_fw);
+               dev_priv->pfp_fw = NULL;
+               release_firmware(dev_priv->me_fw);
+               dev_priv->me_fw = NULL;
+       }
+       return err;
+}
+
 static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
 {
+       const __be32 *fw_data;
        int i;
 
+       if (!dev_priv->me_fw || !dev_priv->pfp_fw)
+               return;
+
        r600_do_cp_stop(dev_priv);
 
        RADEON_WRITE(R600_CP_RB_CNTL,
@@ -292,114 +399,18 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
        DRM_UDELAY(15000);
        RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
 
+       fw_data = (const __be32 *)dev_priv->me_fw->data;
        RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
+       for (i = 0; i < PM4_UCODE_SIZE * 3; i++)
+               RADEON_WRITE(R600_CP_ME_RAM_DATA,
+                            be32_to_cpup(fw_data++));
 
-       if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600)) {
-               DRM_INFO("Loading R600 CP Microcode\n");
-               for (i = 0; i < PM4_UCODE_SIZE; i++) {
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    R600_cp_microcode[i][0]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    R600_cp_microcode[i][1]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    R600_cp_microcode[i][2]);
-               }
-
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-               DRM_INFO("Loading R600 PFP Microcode\n");
-               for (i = 0; i < PFP_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_PFP_UCODE_DATA, R600_pfp_microcode[i]);
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610)) {
-               DRM_INFO("Loading RV610 CP Microcode\n");
-               for (i = 0; i < PM4_UCODE_SIZE; i++) {
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV610_cp_microcode[i][0]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV610_cp_microcode[i][1]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV610_cp_microcode[i][2]);
-               }
-
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-               DRM_INFO("Loading RV610 PFP Microcode\n");
-               for (i = 0; i < PFP_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV610_pfp_microcode[i]);
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630)) {
-               DRM_INFO("Loading RV630 CP Microcode\n");
-               for (i = 0; i < PM4_UCODE_SIZE; i++) {
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV630_cp_microcode[i][0]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV630_cp_microcode[i][1]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV630_cp_microcode[i][2]);
-               }
-
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-               DRM_INFO("Loading RV630 PFP Microcode\n");
-               for (i = 0; i < PFP_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV630_pfp_microcode[i]);
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620)) {
-               DRM_INFO("Loading RV620 CP Microcode\n");
-               for (i = 0; i < PM4_UCODE_SIZE; i++) {
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV620_cp_microcode[i][0]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV620_cp_microcode[i][1]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV620_cp_microcode[i][2]);
-               }
-
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-               DRM_INFO("Loading RV620 PFP Microcode\n");
-               for (i = 0; i < PFP_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV620_pfp_microcode[i]);
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV635)) {
-               DRM_INFO("Loading RV635 CP Microcode\n");
-               for (i = 0; i < PM4_UCODE_SIZE; i++) {
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV635_cp_microcode[i][0]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV635_cp_microcode[i][1]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV635_cp_microcode[i][2]);
-               }
-
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-               DRM_INFO("Loading RV635 PFP Microcode\n");
-               for (i = 0; i < PFP_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV635_pfp_microcode[i]);
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670)) {
-               DRM_INFO("Loading RV670 CP Microcode\n");
-               for (i = 0; i < PM4_UCODE_SIZE; i++) {
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV670_cp_microcode[i][0]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV670_cp_microcode[i][1]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV670_cp_microcode[i][2]);
-               }
-
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-               DRM_INFO("Loading RV670 PFP Microcode\n");
-               for (i = 0; i < PFP_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV670_pfp_microcode[i]);
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
-               DRM_INFO("Loading RS780 CP Microcode\n");
-               for (i = 0; i < PM4_UCODE_SIZE; i++) {
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV670_cp_microcode[i][0]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV670_cp_microcode[i][1]);
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA,
-                                    RV670_cp_microcode[i][2]);
-               }
+       fw_data = (const __be32 *)dev_priv->pfp_fw->data;
+       RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
+       for (i = 0; i < PFP_UCODE_SIZE; i++)
+               RADEON_WRITE(R600_CP_PFP_UCODE_DATA,
+                            be32_to_cpup(fw_data++));
 
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-               DRM_INFO("Loading RS780 PFP Microcode\n");
-               for (i = 0; i < PFP_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV670_pfp_microcode[i]);
-       }
        RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
        RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
        RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
@@ -458,11 +469,14 @@ static void r700_vm_init(struct drm_device *dev)
        r600_vm_flush_gart_range(dev);
 }
 
-/* load r600 microcode */
 static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
 {
+       const __be32 *fw_data;
        int i;
 
+       if (!dev_priv->me_fw || !dev_priv->pfp_fw)
+               return;
+
        r600_do_cp_stop(dev_priv);
 
        RADEON_WRITE(R600_CP_RB_CNTL,
@@ -475,47 +489,18 @@ static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
        DRM_UDELAY(15000);
        RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
 
+       fw_data = (const __be32 *)dev_priv->pfp_fw->data;
+       RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
+       for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
+               RADEON_WRITE(R600_CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
+       RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
 
-       if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)) {
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-               DRM_INFO("Loading RV770 PFP Microcode\n");
-               for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV770_pfp_microcode[i]);
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-
-               RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-               DRM_INFO("Loading RV770 CP Microcode\n");
-               for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA, RV770_cp_microcode[i]);
-               RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV730)) {
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-               DRM_INFO("Loading RV730 PFP Microcode\n");
-               for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV730_pfp_microcode[i]);
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-
-               RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-               DRM_INFO("Loading RV730 CP Microcode\n");
-               for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA, RV730_cp_microcode[i]);
-               RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)) {
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-               DRM_INFO("Loading RV710 PFP Microcode\n");
-               for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV710_pfp_microcode[i]);
-               RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-
-               RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-               DRM_INFO("Loading RV710 CP Microcode\n");
-               for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
-                       RADEON_WRITE(R600_CP_ME_RAM_DATA, RV710_cp_microcode[i]);
-               RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
+       fw_data = (const __be32 *)dev_priv->me_fw->data;
+       RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
+       for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
+               RADEON_WRITE(R600_CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
+       RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
 
-       }
        RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
        RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
        RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
@@ -782,6 +767,7 @@ static void r600_gfx_init(struct drm_device *dev,
                break;
        case CHIP_RV610:
        case CHIP_RS780:
+       case CHIP_RS880:
        case CHIP_RV620:
                dev_priv->r600_max_pipes = 1;
                dev_priv->r600_max_tile_pipes = 1;
@@ -916,7 +902,8 @@ static void r600_gfx_init(struct drm_device *dev,
            ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) ||
            ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
            ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780))
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
                RADEON_WRITE(R600_DB_DEBUG, R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE);
        else
                RADEON_WRITE(R600_DB_DEBUG, 0);
@@ -934,7 +921,8 @@ static void r600_gfx_init(struct drm_device *dev,
        sq_ms_fifo_sizes = RADEON_READ(R600_SQ_MS_FIFO_SIZES);
        if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
            ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
                sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(0xa) |
                                    R600_FETCH_FIFO_HIWATER(0xa) |
                                    R600_DONE_FIFO_HIWATER(0xe0) |
@@ -977,7 +965,8 @@ static void r600_gfx_init(struct drm_device *dev,
                                            R600_NUM_ES_STACK_ENTRIES(0));
        } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
                   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
                /* no vertex cache */
                sq_config &= ~R600_VC_ENABLE;
 
@@ -1034,7 +1023,8 @@ static void r600_gfx_init(struct drm_device *dev,
 
        if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
            ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780))
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
                RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_TC_ONLY));
        else
                RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_VC_AND_TC));
@@ -1077,6 +1067,7 @@ static void r600_gfx_init(struct drm_device *dev,
                break;
        case CHIP_RV610:
        case CHIP_RS780:
+       case CHIP_RS880:
        case CHIP_RV620:
                gs_prim_buffer_depth = 32;
                break;
@@ -1122,6 +1113,7 @@ static void r600_gfx_init(struct drm_device *dev,
        switch (dev_priv->flags & RADEON_FAMILY_MASK) {
        case CHIP_RV610:
        case CHIP_RS780:
+       case CHIP_RS880:
        case CHIP_RV620:
                tc_cntl = R600_TC_L2_SIZE(8);
                break;
@@ -1324,6 +1316,10 @@ static void r700_gfx_init(struct drm_device *dev,
                dev_priv->r700_sc_prim_fifo_size = 0xf9;
                dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
                dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
+               if (dev_priv->r600_sx_max_export_pos_size > 16) {
+                       dev_priv->r600_sx_max_export_pos_size -= 16;
+                       dev_priv->r600_sx_max_export_smx_size += 16;
+               }
                break;
        case CHIP_RV710:
                dev_priv->r600_max_pipes = 2;
@@ -1345,6 +1341,31 @@ static void r700_gfx_init(struct drm_device *dev,
                dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
                dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
                break;
+       case CHIP_RV740:
+               dev_priv->r600_max_pipes = 4;
+               dev_priv->r600_max_tile_pipes = 4;
+               dev_priv->r600_max_simds = 8;
+               dev_priv->r600_max_backends = 4;
+               dev_priv->r600_max_gprs = 256;
+               dev_priv->r600_max_threads = 248;
+               dev_priv->r600_max_stack_entries = 512;
+               dev_priv->r600_max_hw_contexts = 8;
+               dev_priv->r600_max_gs_threads = 16 * 2;
+               dev_priv->r600_sx_max_export_size = 256;
+               dev_priv->r600_sx_max_export_pos_size = 32;
+               dev_priv->r600_sx_max_export_smx_size = 224;
+               dev_priv->r600_sq_num_cf_insts = 2;
+
+               dev_priv->r700_sx_num_of_sets = 7;
+               dev_priv->r700_sc_prim_fifo_size = 0x100;
+               dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
+               dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
+
+               if (dev_priv->r600_sx_max_export_pos_size > 16) {
+                       dev_priv->r600_sx_max_export_pos_size -= 16;
+                       dev_priv->r600_sx_max_export_smx_size += 16;
+               }
+               break;
        default:
                break;
        }
@@ -1493,6 +1514,7 @@ static void r700_gfx_init(struct drm_device *dev,
                break;
        case CHIP_RV730:
        case CHIP_RV710:
+       case CHIP_RV740:
        default:
                sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4);
                break;
@@ -1569,6 +1591,7 @@ static void r700_gfx_init(struct drm_device *dev,
        switch (dev_priv->flags & RADEON_FAMILY_MASK) {
        case CHIP_RV770:
        case CHIP_RV730:
+       case CHIP_RV740:
                gs_prim_buffer_depth = 384;
                break;
        case CHIP_RV710:
@@ -1630,6 +1653,7 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
 {
        struct drm_radeon_master_private *master_priv;
        u32 ring_start;
+       u64 rptr_addr;
 
        if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
                r700_gfx_init(dev, dev_priv);
@@ -1684,21 +1708,20 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
 
 #if __OS_HAS_AGP
        if (dev_priv->flags & RADEON_IS_AGP) {
-               /* XXX */
-               RADEON_WRITE(R600_CP_RB_RPTR_ADDR,
-                            (dev_priv->ring_rptr->offset
-                            - dev->agp->base + dev_priv->gart_vm_start) >> 8);
-               RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI, 0);
+               rptr_addr = dev_priv->ring_rptr->offset
+                       - dev->agp->base +
+                       dev_priv->gart_vm_start;
        } else
 #endif
        {
-               RADEON_WRITE(R600_CP_RB_RPTR_ADDR,
-                            dev_priv->ring_rptr->offset
-                            - ((unsigned long) dev->sg->virtual)
-                            + dev_priv->gart_vm_start);
-
-               RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI, 0);
+               rptr_addr = dev_priv->ring_rptr->offset
+                       - ((unsigned long) dev->sg->virtual)
+                       + dev_priv->gart_vm_start;
        }
+       RADEON_WRITE(R600_CP_RB_RPTR_ADDR,
+                    rptr_addr & 0xffffffff);
+       RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI,
+                    upper_32_bits(rptr_addr));
 
 #ifdef __BIG_ENDIAN
        RADEON_WRITE(R600_CP_RB_CNTL,
@@ -1737,9 +1760,6 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
 
        RADEON_WRITE(R600_CP_DEBUG, (1 << 27) | (1 << 28));
 
-       /* Start with assuming that writeback doesn't work */
-       dev_priv->writeback_works = 0;
-
        /* Initialize the scratch register pointer.  This will cause
         * the scratch register values to be written out to memory
         * whenever they are updated.
@@ -1747,8 +1767,17 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
         * We simply put this behind the ring read pointer, this works
         * with PCI GART as well as (whatever kind of) AGP GART
         */
-       RADEON_WRITE(R600_SCRATCH_ADDR, ((RADEON_READ(R600_CP_RB_RPTR_ADDR) << 8)
-                                        + R600_SCRATCH_REG_OFFSET) >> 8);
+       {
+               u64 scratch_addr;
+
+               scratch_addr = RADEON_READ(R600_CP_RB_RPTR_ADDR);
+               scratch_addr |= ((u64)RADEON_READ(R600_CP_RB_RPTR_ADDR_HI)) << 32;
+               scratch_addr += R600_SCRATCH_REG_OFFSET;
+               scratch_addr >>= 8;
+               scratch_addr &= 0xffffffff;
+
+               RADEON_WRITE(R600_SCRATCH_ADDR, (uint32_t)scratch_addr);
+       }
 
        RADEON_WRITE(R600_SCRATCH_UMSK, 0x7);
 
@@ -2089,7 +2118,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
                          dev_priv->gart_info.addr,
                          dev_priv->pcigart_offset);
 
-               if (r600_page_table_init(dev)) {
+               if (!r600_page_table_init(dev)) {
                        DRM_ERROR("Failed to init GART table\n");
                        r600_do_cleanup_cp(dev);
                        return -EINVAL;
@@ -2101,6 +2130,14 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
                        r600_vm_init(dev);
        }
 
+       if (!dev_priv->me_fw || !dev_priv->pfp_fw) {
+               int err = r600_cp_init_microcode(dev_priv);
+               if (err) {
+                       DRM_ERROR("Failed to load firmware!\n");
+                       r600_do_cleanup_cp(dev);
+                       return err;
+               }
+       }
        if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
                r700_cp_load_microcode(dev_priv);
        else