]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - drivers/gpu/drm/radeon/radeon_cp.c
radeon: Use request_firmware()
[linux-2.6.git] / drivers / gpu / drm / radeon / radeon_cp.c
index 6f579a8e5349253ed9037c1862be3bd7c54e23c1..6b6cc8434d3c8bfb0b077dd06039b57d9d54df78 100644 (file)
 #include "radeon_drv.h"
 #include "r300_reg.h"
 
-#include "radeon_microcode.h"
-
 #define RADEON_FIFO_DEBUG      0
 
+/* Firmware Names */
+#define FIRMWARE_R100          "radeon/R100_cp.bin"
+#define FIRMWARE_R200          "radeon/R200_cp.bin"
+#define FIRMWARE_R300          "radeon/R300_cp.bin"
+#define FIRMWARE_R420          "radeon/R420_cp.bin"
+#define FIRMWARE_RS690         "radeon/RS690_cp.bin"
+#define FIRMWARE_RS600         "radeon/RS600_cp.bin"
+#define FIRMWARE_R520          "radeon/R520_cp.bin"
+
+MODULE_FIRMWARE(FIRMWARE_R100);
+MODULE_FIRMWARE(FIRMWARE_R200);
+MODULE_FIRMWARE(FIRMWARE_R300);
+MODULE_FIRMWARE(FIRMWARE_R420);
+MODULE_FIRMWARE(FIRMWARE_RS690);
+MODULE_FIRMWARE(FIRMWARE_RS600);
+MODULE_FIRMWARE(FIRMWARE_R520);
+
 static int radeon_do_cleanup_cp(struct drm_device * dev);
 static void radeon_do_cp_start(drm_radeon_private_t * dev_priv);
 
@@ -434,7 +449,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(R500_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1));
+               RADEON_WRITE(R300_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);
@@ -451,37 +466,34 @@ static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
  */
 
 /* Load the microcode for the CP */
-static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
+static int radeon_cp_init_microcode(drm_radeon_private_t *dev_priv)
 {
-       int i;
+       struct platform_device *pdev;
+       const char *fw_name = NULL;
+       int err;
+
        DRM_DEBUG("\n");
 
-       radeon_do_wait_for_idle(dev_priv);
+       pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0);
+       err = IS_ERR(pdev);
+       if (err) {
+               printk(KERN_ERR "radeon_cp: Failed to register firmware\n");
+               return -EINVAL;
+       }
 
-       RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
        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]);
-               }
+               fw_name = FIRMWARE_R100;
        } 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,
-                                    R200_cp_microcode[i][1]);
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    R200_cp_microcode[i][0]);
-               }
+               fw_name = FIRMWARE_R200;
        } 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) ||
@@ -489,39 +501,19 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
                   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
                   ((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,
-                                    R300_cp_microcode[i][1]);
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    R300_cp_microcode[i][0]);
-               }
+               fw_name = FIRMWARE_R300;
        } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
                   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) ||
                   ((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,
-                                    R420_cp_microcode[i][1]);
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    R420_cp_microcode[i][0]);
-               }
+               fw_name = FIRMWARE_R420;
        } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
                   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
                DRM_INFO("Loading RS690/RS740 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]);
-               }
+               fw_name = FIRMWARE_RS690;
        } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) {
                DRM_INFO("Loading RS600 Microcode\n");
-               for (i = 0; i < 256; i++) {
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
-                                    RS600_cp_microcode[i][1]);
-                       RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    RS600_cp_microcode[i][0]);
-               }
+               fw_name = FIRMWARE_RS600;
        } 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) ||
@@ -529,11 +521,41 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
                   ((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++) {
+               fw_name = FIRMWARE_R520;
+       }
+
+       err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev);
+       platform_device_unregister(pdev);
+       if (err) {
+               printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n",
+                      fw_name);
+       } else if (dev_priv->me_fw->size % 8) {
+               printk(KERN_ERR
+                      "radeon_cp: Bogus length %zu in firmware \"%s\"\n",
+                      dev_priv->me_fw->size, fw_name);
+               err = -EINVAL;
+               release_firmware(dev_priv->me_fw);
+               dev_priv->me_fw = NULL;
+       }
+       return err;
+}
+
+static void radeon_cp_load_microcode(drm_radeon_private_t *dev_priv)
+{
+       const __be32 *fw_data;
+       int i, size;
+
+       radeon_do_wait_for_idle(dev_priv);
+
+       if (dev_priv->me_fw) {
+               size = dev_priv->me_fw->size / 4;
+               fw_data = (const __be32 *)&dev_priv->me_fw->data[0];
+               RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
+               for (i = 0; i < size; i += 2) {
                        RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
-                                    R520_cp_microcode[i][1]);
+                                    be32_to_cpup(&fw_data[i]));
                        RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
-                                    R520_cp_microcode[i][0]);
+                                    be32_to_cpup(&fw_data[i + 1]));
                }
        }
 }
@@ -1486,6 +1508,14 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
                radeon_set_pcigart(dev_priv, 1);
        }
 
+       if (!dev_priv->me_fw) {
+               int err = radeon_cp_init_microcode(dev_priv);
+               if (err) {
+                       DRM_ERROR("Failed to load firmware!\n");
+                       radeon_do_cleanup_cp(dev);
+                       return err;
+               }
+       }
        radeon_cp_load_microcode(dev_priv);
        radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
 
@@ -1755,6 +1785,14 @@ void radeon_do_release(struct drm_device * dev)
                        r600_do_cleanup_cp(dev);
                else
                        radeon_do_cleanup_cp(dev);
+               if (dev_priv->me_fw) {
+                       release_firmware(dev_priv->me_fw);
+                       dev_priv->me_fw = NULL;
+               }
+               if (dev_priv->pfp_fw) {
+                       release_firmware(dev_priv->pfp_fw);
+                       dev_priv->pfp_fw = NULL;
+               }
        }
 }
 
@@ -2045,11 +2083,10 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
        drm_radeon_private_t *dev_priv;
        int ret = 0;
 
-       dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER);
+       dev_priv = kzalloc(sizeof(drm_radeon_private_t), GFP_KERNEL);
        if (dev_priv == NULL)
                return -ENOMEM;
 
-       memset(dev_priv, 0, sizeof(drm_radeon_private_t));
        dev->dev_private = (void *)dev_priv;
        dev_priv->flags = flags;
 
@@ -2103,13 +2140,13 @@ int radeon_master_create(struct drm_device *dev, struct drm_master *master)
        unsigned long sareapage;
        int ret;
 
-       master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
+       master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
        if (!master_priv)
                return -ENOMEM;
 
        /* prebuild the SAREA */
        sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE);
-       ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK|_DRM_DRIVER,
+       ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK,
                         &master_priv->sarea);
        if (ret) {
                DRM_ERROR("SAREA setup failed\n");
@@ -2137,7 +2174,7 @@ void radeon_master_destroy(struct drm_device *dev, struct drm_master *master)
        if (master_priv->sarea)
                drm_rmmap_locked(dev, master_priv->sarea);
 
-       drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
+       kfree(master_priv);
 
        master->driver_priv = NULL;
 }
@@ -2171,7 +2208,7 @@ int radeon_driver_unload(struct drm_device *dev)
 
        drm_rmmap(dev, dev_priv->mmio);
 
-       drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+       kfree(dev_priv);
 
        dev->dev_private = NULL;
        return 0;
@@ -2185,9 +2222,9 @@ void radeon_commit_ring(drm_radeon_private_t *dev_priv)
 
        /* check if the ring is padded out to 16-dword alignment */
 
-       tail_aligned = dev_priv->ring.tail & 0xf;
+       tail_aligned = dev_priv->ring.tail & (RADEON_RING_ALIGN-1);
        if (tail_aligned) {
-               int num_p2 = 16 - tail_aligned;
+               int num_p2 = RADEON_RING_ALIGN - tail_aligned;
 
                ring = dev_priv->ring.start;
                /* pad with some CP_PACKET2 */