radeon: Use request_firmware()
[linux-2.6.git] / drivers / gpu / drm / radeon / radeon_cp.c
index d835682..6b6cc84 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);
 
@@ -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;
+               }
        }
 }