Permalink
Browse files

radeon: Use request_firmware()

Loosely based on a patch by
Jaswinder Singh Rajput <jaswinderlinux@gmail.com>.

KMS support by Dave Airlie <airlied@redhat.com>.

For Radeon 100- to 500-series, firmware blobs look like:
    struct {
        __be32 datah;
        __be32 datal;
    } cp_ucode[256];

For Radeon 600-series, there are two separate firmware blobs:
    __be32 me_ucode[PM4_UCODE_SIZE * 3];
    __be32 pfp_ucode[PFP_UCODE_SIZE];

For Radeon 700-series, likewise:
    __be32 me_ucode[R700_PM4_UCODE_SIZE];
    __be32 pfp_ucode[R700_PFP_UCODE_SIZE];

Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information...
bwhacks authored and Dave Airlie committed Aug 29, 2009
1 parent 1ae7007 commit 70967ab9c0c9017645d167d33675eab996633631
Showing with 13,388 additions and 25,371 deletions.
  1. +1 −0 drivers/gpu/drm/Kconfig
  2. +84 −35 drivers/gpu/drm/radeon/r100.c
  3. +140 −149 drivers/gpu/drm/radeon/r600_cp.c
  4. +0 −23,297 drivers/gpu/drm/radeon/r600_microcode.h
  5. +1 −0 drivers/gpu/drm/radeon/radeon.h
  6. +83 −45 drivers/gpu/drm/radeon/radeon_cp.c
  7. +5 −0 drivers/gpu/drm/radeon/radeon_drv.h
  8. +0 −1 drivers/gpu/drm/radeon/radeon_irq_kms.c
  9. +0 −1,844 drivers/gpu/drm/radeon/radeon_microcode.h
  10. +14 −0 firmware/Makefile
  11. +58 −0 firmware/WHENCE
  12. +130 −0 firmware/radeon/R100_cp.bin.ihex
  13. +130 −0 firmware/radeon/R200_cp.bin.ihex
  14. +130 −0 firmware/radeon/R300_cp.bin.ihex
  15. +130 −0 firmware/radeon/R420_cp.bin.ihex
  16. +130 −0 firmware/radeon/R520_cp.bin.ihex
  17. +1,345 −0 firmware/radeon/R600_me.bin.ihex
  18. +145 −0 firmware/radeon/R600_pfp.bin.ihex
  19. +130 −0 firmware/radeon/RS600_cp.bin.ihex
  20. +130 −0 firmware/radeon/RS690_cp.bin.ihex
  21. +1,345 −0 firmware/radeon/RS780_me.bin.ihex
  22. +145 −0 firmware/radeon/RS780_pfp.bin.ihex
  23. +1,345 −0 firmware/radeon/RV610_me.bin.ihex
  24. +145 −0 firmware/radeon/RV610_pfp.bin.ihex
  25. +1,345 −0 firmware/radeon/RV620_me.bin.ihex
  26. +145 −0 firmware/radeon/RV620_pfp.bin.ihex
  27. +1,345 −0 firmware/radeon/RV630_me.bin.ihex
  28. +145 −0 firmware/radeon/RV630_pfp.bin.ihex
  29. +1,345 −0 firmware/radeon/RV635_me.bin.ihex
  30. +145 −0 firmware/radeon/RV635_pfp.bin.ihex
  31. +1,345 −0 firmware/radeon/RV670_me.bin.ihex
  32. +145 −0 firmware/radeon/RV670_pfp.bin.ihex
  33. +341 −0 firmware/radeon/RV710_me.bin.ihex
  34. +213 −0 firmware/radeon/RV710_pfp.bin.ihex
  35. +341 −0 firmware/radeon/RV730_me.bin.ihex
  36. +213 −0 firmware/radeon/RV730_pfp.bin.ihex
  37. +341 −0 firmware/radeon/RV770_me.bin.ihex
  38. +213 −0 firmware/radeon/RV770_pfp.bin.ihex
View
@@ -50,6 +50,7 @@ config DRM_RADEON
select FB_CFB_IMAGEBLIT
select FB
select FRAMEBUFFER_CONSOLE if !EMBEDDED
+ select FW_LOADER
help
Choose this option if you have an ATI Radeon graphics card. There
are both PCI and AGP versions. You don't need to choose this to
@@ -29,9 +29,27 @@
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
-#include "radeon_microcode.h"
#include "radeon_reg.h"
#include "radeon.h"
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+
+/* 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);
/* This files gather functions specifics to:
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
@@ -478,75 +496,97 @@ void r100_ring_start(struct radeon_device *rdev)
radeon_ring_unlock_commit(rdev);
}
-static void r100_cp_load_microcode(struct radeon_device *rdev)
+
+/* Load the microcode for the CP */
+static int r100_cp_init_microcode(struct radeon_device *rdev)
{
- int i;
+ struct platform_device *pdev;
+ const char *fw_name = NULL;
+ int err;
- if (r100_gui_wait_for_idle(rdev)) {
- printk(KERN_WARNING "Failed to wait GUI idle while "
- "programming pipes. Bad things might happen.\n");
- }
+ DRM_DEBUG("\n");
- WREG32(RADEON_CP_ME_RAM_ADDR, 0);
+ 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;
+ }
if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) ||
(rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) ||
(rdev->family == CHIP_RS200)) {
DRM_INFO("Loading R100 Microcode\n");
- for (i = 0; i < 256; i++) {
- WREG32(RADEON_CP_ME_RAM_DATAH, R100_cp_microcode[i][1]);
- WREG32(RADEON_CP_ME_RAM_DATAL, R100_cp_microcode[i][0]);
- }
+ fw_name = FIRMWARE_R100;
} else if ((rdev->family == CHIP_R200) ||
(rdev->family == CHIP_RV250) ||
(rdev->family == CHIP_RV280) ||
(rdev->family == CHIP_RS300)) {
DRM_INFO("Loading R200 Microcode\n");
- for (i = 0; i < 256; i++) {
- WREG32(RADEON_CP_ME_RAM_DATAH, R200_cp_microcode[i][1]);
- WREG32(RADEON_CP_ME_RAM_DATAL, R200_cp_microcode[i][0]);
- }
+ fw_name = FIRMWARE_R200;
} else if ((rdev->family == CHIP_R300) ||
(rdev->family == CHIP_R350) ||
(rdev->family == CHIP_RV350) ||
(rdev->family == CHIP_RV380) ||
(rdev->family == CHIP_RS400) ||
(rdev->family == CHIP_RS480)) {
DRM_INFO("Loading R300 Microcode\n");
- for (i = 0; i < 256; i++) {
- WREG32(RADEON_CP_ME_RAM_DATAH, R300_cp_microcode[i][1]);
- WREG32(RADEON_CP_ME_RAM_DATAL, R300_cp_microcode[i][0]);
- }
+ fw_name = FIRMWARE_R300;
} else if ((rdev->family == CHIP_R420) ||
(rdev->family == CHIP_R423) ||
(rdev->family == CHIP_RV410)) {
DRM_INFO("Loading R400 Microcode\n");
- for (i = 0; i < 256; i++) {
- WREG32(RADEON_CP_ME_RAM_DATAH, R420_cp_microcode[i][1]);
- WREG32(RADEON_CP_ME_RAM_DATAL, R420_cp_microcode[i][0]);
- }
+ fw_name = FIRMWARE_R420;
} else if ((rdev->family == CHIP_RS690) ||
(rdev->family == CHIP_RS740)) {
DRM_INFO("Loading RS690/RS740 Microcode\n");
- for (i = 0; i < 256; i++) {
- WREG32(RADEON_CP_ME_RAM_DATAH, RS690_cp_microcode[i][1]);
- WREG32(RADEON_CP_ME_RAM_DATAL, RS690_cp_microcode[i][0]);
- }
+ fw_name = FIRMWARE_RS690;
} else if (rdev->family == CHIP_RS600) {
DRM_INFO("Loading RS600 Microcode\n");
- for (i = 0; i < 256; i++) {
- WREG32(RADEON_CP_ME_RAM_DATAH, RS600_cp_microcode[i][1]);
- WREG32(RADEON_CP_ME_RAM_DATAL, RS600_cp_microcode[i][0]);
- }
+ fw_name = FIRMWARE_RS600;
} else if ((rdev->family == CHIP_RV515) ||
(rdev->family == CHIP_R520) ||
(rdev->family == CHIP_RV530) ||
(rdev->family == CHIP_R580) ||
(rdev->family == CHIP_RV560) ||
(rdev->family == CHIP_RV570)) {
DRM_INFO("Loading R500 Microcode\n");
- for (i = 0; i < 256; i++) {
- WREG32(RADEON_CP_ME_RAM_DATAH, R520_cp_microcode[i][1]);
- WREG32(RADEON_CP_ME_RAM_DATAL, R520_cp_microcode[i][0]);
+ fw_name = FIRMWARE_R520;
+ }
+
+ err = request_firmware(&rdev->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 (rdev->fw->size % 8) {
+ printk(KERN_ERR
+ "radeon_cp: Bogus length %zu in firmware \"%s\"\n",
+ rdev->fw->size, fw_name);
+ err = -EINVAL;
+ release_firmware(rdev->fw);
+ rdev->fw = NULL;
+ }
+ return err;
+}
+static void r100_cp_load_microcode(struct radeon_device *rdev)
+{
+ const __be32 *fw_data;
+ int i, size;
+
+ if (r100_gui_wait_for_idle(rdev)) {
+ printk(KERN_WARNING "Failed to wait GUI idle while "
+ "programming pipes. Bad things might happen.\n");
+ }
+
+ if (rdev->fw) {
+ size = rdev->fw->size / 4;
+ fw_data = (const __be32 *)&rdev->fw->data[0];
+ WREG32(RADEON_CP_ME_RAM_ADDR, 0);
+ for (i = 0; i < size; i += 2) {
+ WREG32(RADEON_CP_ME_RAM_DATAH,
+ be32_to_cpup(&fw_data[i]));
+ WREG32(RADEON_CP_ME_RAM_DATAL,
+ be32_to_cpup(&fw_data[i + 1]));
}
}
}
@@ -585,6 +625,15 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
} else {
DRM_INFO("radeon: cp idle (0x%08X)\n", tmp);
}
+
+ if (!rdev->fw) {
+ r = r100_cp_init_microcode(rdev);
+ if (r) {
+ DRM_ERROR("Failed to load firmware!\n");
+ return r;
+ }
+ }
+
/* Align ring size */
rb_bufsz = drm_order(ring_size / 8);
ring_size = (1 << (rb_bufsz + 1)) * 4;
Oops, something went wrong.

0 comments on commit 70967ab

Please sign in to comment.