Here's a patch to radeon to make it use request_firmware. This is compile-tested only, but I have hardware I can test on shortly. The firmware files can be produced by writing the arrays as 32-bit little-endian values. They should be suitable for inclusion in firmware-nonfree, so I am including a patch for that as well.
Ben. diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig index ea26dfd..17edd8a 100644 --- a/drivers/char/drm/Kconfig +++ b/drivers/char/drm/Kconfig @@ -35,6 +35,7 @@ config DRM_R128 config DRM_RADEON tristate "ATI Radeon" depends on DRM && PCI + 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 diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index e53158f..8408e34 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -29,14 +29,14 @@ * Gareth Hughes <[EMAIL PROTECTED]> */ +#include <linux/firmware.h> + #include "drmP.h" #include "drm.h" #include "radeon_drm.h" #include "radeon_drv.h" #include "r300_reg.h" -#include "radeon_microcode.h" - #define RADEON_FIFO_DEBUG 0 static int radeon_do_cleanup_cp(struct drm_device * dev); @@ -319,83 +319,71 @@ static void radeon_init_pipes(drm_radeon_private_t *dev_priv) * CP control, initialization */ +static const char *radeon_cp_family_name(drm_radeon_private_t * dev_priv) +{ + switch (dev_priv->flags & RADEON_FAMILY_MASK) { + case CHIP_R100: case CHIP_RV100: case CHIP_RV200: case CHIP_RS100: + case CHIP_RS200: + return "R100"; + case CHIP_R200: case CHIP_RV250: case CHIP_RV280: case CHIP_RS300: + return "R200"; + case CHIP_R300: case CHIP_R350: case CHIP_RV350: case CHIP_RV380: + case CHIP_RS480: + return "R300"; + case CHIP_R420: case CHIP_RV410: + return "R400"; + case CHIP_RS690: + return "RS690"; + case CHIP_RV515: case CHIP_R520: case CHIP_RV530: case CHIP_R580: + case CHIP_RV560: case CHIP_RV570: + return "R500"; + default: + WARN_ON(1); /* new chip needs a name */ + return ""; + } +} + /* Load the microcode for the CP */ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv) { + const __le32 *microcode; int i; DRM_DEBUG("\n"); radeon_do_wait_for_idle(dev_priv); + DRM_INFO("Loading %s Microcode\n", radeon_cp_family_name(dev_priv)); + microcode = (const __le32 *)dev_priv->microcode->data; 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]); - } - } 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]); - } - } 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) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) || - ((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]); - } - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) || - ((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]); - } - } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) { - DRM_INFO("Loading RS690 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]); - } - } 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) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) || - ((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++) { - RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, - R520_cp_microcode[i][1]); - RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, - R520_cp_microcode[i][0]); - } + for (i = 0; i < 256; i++) { + RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, + le32_to_cpu(microcode[2 * i + 1])); + RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, + le32_to_cpu(microcode[2 * i + 0])); } } +static int radeon_cp_load_microcode_init(struct drm_device *dev, + drm_radeon_private_t *dev_priv) +{ + char fw_name[40]; + int rc; + + snprintf(fw_name, sizeof(fw_name), "radeon/%s_cp_ucode.bin", + radeon_cp_family_name(dev_priv)); + rc = request_firmware(&dev_priv->microcode, fw_name, &dev->pdev->dev); + if (rc) + return rc; + if (dev_priv->microcode->size != 256 * 8) { + release_firmware(dev_priv->microcode); + dev_priv->microcode = NULL; + return -EINVAL; + } + + radeon_cp_load_microcode(dev_priv); + return 0; +} + /* Flush any pending commands to the CP. This should only be used just * prior to a wait for idle, as it informs the engine that the command * stream is ending. @@ -853,6 +841,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) { drm_radeon_private_t *dev_priv = dev->dev_private; + int rc; DRM_DEBUG("\n"); @@ -1195,7 +1184,13 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) radeon_set_pcigart(dev_priv, 1); } - radeon_cp_load_microcode(dev_priv); + rc = radeon_cp_load_microcode_init(dev, dev_priv); + if (rc) { + DRM_ERROR("failed to load microcode\n"); + radeon_do_cleanup_cp(dev); + return rc; + } + radeon_cp_init_ring_buffer(dev, dev_priv); dev_priv->last_buf = 0; @@ -1218,6 +1213,11 @@ static int radeon_do_cleanup_cp(struct drm_device * dev) if (dev->irq_enabled) drm_irq_uninstall(dev); + if (dev_priv->microcode) { + release_firmware(dev_priv->microcode); + dev_priv->microcode = NULL; + } + #if __OS_HAS_AGP if (dev_priv->flags & RADEON_IS_AGP) { if (dev_priv->cp_ring != NULL) { diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c index 349ac3d..3414109 100644 --- a/drivers/char/drm/radeon_drv.c +++ b/drivers/char/drm/radeon_drv.c @@ -124,3 +124,9 @@ module_exit(radeon_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL and additional rights"); +MODULE_FIRMWARE("radeon/R100_cp_ucode.bin"); +MODULE_FIRMWARE("radeon/R200_cp_ucode.bin"); +MODULE_FIRMWARE("radeon/R300_cp_ucode.bin"); +MODULE_FIRMWARE("radeon/R400_cp_ucode.bin"); +MODULE_FIRMWARE("radeon/R500_cp_ucode.bin"); +MODULE_FIRMWARE("radeon/RS690_cp_ucode.bin"); diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 3f0eca9..1f2c329 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -244,6 +244,7 @@ typedef struct drm_radeon_private { int usec_timeout; int microcode_version; + const struct firmware *microcode; struct { u32 boxes; --- END --- Patch for firmware-nonfree: Index: defines =================================================================== --- defines (revision 12301) +++ defines (working copy) @@ -1,5 +1,6 @@ [base] packages: + ati bnx2 iwlwifi qlogic Index: ati/LICENSE =================================================================== --- ati/LICENSE (revision 0) +++ ati/LICENSE (revision 0) @@ -0,0 +1,21 @@ +Copyright 2007 Advanced Micro Devices, Inc. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Index: ati/defines =================================================================== --- ati/defines (revision 0) +++ ati/defines (revision 0) @@ -0,0 +1,29 @@ +[base] +desc: ATI Radeon graphics cards +files: + radeon/R100_cp_ucode.bin + radeon/R200_cp_ucode.bin + radeon/R300_cp_ucode.bin + radeon/R400_cp_ucode.bin + radeon/R500_cp_ucode.bin + radeon/RS690_cp_ucode.bin +longdesc: ATI Radeon graphics cards supported by the radeon driver +uri: http://ftp.debian.org/debian/pool/non-free/f/firmware-nonfree + +[R100_cp_ucode.bin_base] +desc: ATI Radeon R100-family CP microcode + +[R200_cp_ucode.bin_base] +desc: ATI Radeon R200-family CP microcode + +[R300_cp_ucode.bin_base] +desc: ATI Radeon R300-family CP microcode + +[R400_cp_ucode.bin_base] +desc: ATI Radeon R400-family CP microcode + +[R500_cp_ucode.bin_base] +desc: ATI Radeon R500-family CP microcode + +[RS690_cp_ucode.bin_base] +desc: ATI Radeon RS690 CP microcode --- END ---
signature.asc
Description: This is a digitally signed message part