From 70967ab9c0c9017645d167d33675eab996633631 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 29 Aug 2009 14:53:51 +0100 Subject: radeon: Use request_firmware() Loosely based on a patch by Jaswinder Singh Rajput . KMS support by Dave Airlie . 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 Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_cp.c | 128 ++++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 45 deletions(-) (limited to 'drivers/gpu/drm/radeon/radeon_cp.c') diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index d8356827ef17..6b6cc8434d3c 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -36,10 +36,25 @@ #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; + } } } -- cgit v1.2.3