Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70967ab9 authored by Ben Hutchings's avatar Ben Hutchings Committed by Dave Airlie
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: default avatarBen Hutchings <ben@decadent.org.uk>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 1ae70072
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -50,6 +50,7 @@ config DRM_RADEON
	select FB_CFB_IMAGEBLIT
	select FB_CFB_IMAGEBLIT
	select FB
	select FB
	select FRAMEBUFFER_CONSOLE if !EMBEDDED
	select FRAMEBUFFER_CONSOLE if !EMBEDDED
	select FW_LOADER
	help
	help
	  Choose this option if you have an ATI Radeon graphics card.  There
	  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
	  are both PCI and AGP versions.  You don't need to choose this to
+84 −35
Original line number Original line Diff line number Diff line
@@ -29,9 +29,27 @@
#include "drmP.h"
#include "drmP.h"
#include "drm.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drm.h"
#include "radeon_microcode.h"
#include "radeon_reg.h"
#include "radeon_reg.h"
#include "radeon.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:
/* This files gather functions specifics to:
 * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
 * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
@@ -478,33 +496,33 @@ void r100_ring_start(struct radeon_device *rdev)
	radeon_ring_unlock_commit(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)) {
	DRM_DEBUG("\n");
		printk(KERN_WARNING "Failed to wait GUI idle while "
		       "programming pipes. Bad things might happen.\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) ||
	if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) ||
	    (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) ||
	    (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) ||
	    (rdev->family == CHIP_RS200)) {
	    (rdev->family == CHIP_RS200)) {
		DRM_INFO("Loading R100 Microcode\n");
		DRM_INFO("Loading R100 Microcode\n");
		for (i = 0; i < 256; i++) {
		fw_name = FIRMWARE_R100;
			WREG32(RADEON_CP_ME_RAM_DATAH, R100_cp_microcode[i][1]);
			WREG32(RADEON_CP_ME_RAM_DATAL, R100_cp_microcode[i][0]);
		}
	} else if ((rdev->family == CHIP_R200) ||
	} else if ((rdev->family == CHIP_R200) ||
		   (rdev->family == CHIP_RV250) ||
		   (rdev->family == CHIP_RV250) ||
		   (rdev->family == CHIP_RV280) ||
		   (rdev->family == CHIP_RV280) ||
		   (rdev->family == CHIP_RS300)) {
		   (rdev->family == CHIP_RS300)) {
		DRM_INFO("Loading R200 Microcode\n");
		DRM_INFO("Loading R200 Microcode\n");
		for (i = 0; i < 256; i++) {
		fw_name = FIRMWARE_R200;
			WREG32(RADEON_CP_ME_RAM_DATAH, R200_cp_microcode[i][1]);
			WREG32(RADEON_CP_ME_RAM_DATAL, R200_cp_microcode[i][0]);
		}
	} else if ((rdev->family == CHIP_R300) ||
	} else if ((rdev->family == CHIP_R300) ||
		   (rdev->family == CHIP_R350) ||
		   (rdev->family == CHIP_R350) ||
		   (rdev->family == CHIP_RV350) ||
		   (rdev->family == CHIP_RV350) ||
@@ -512,31 +530,19 @@ static void r100_cp_load_microcode(struct radeon_device *rdev)
		   (rdev->family == CHIP_RS400) ||
		   (rdev->family == CHIP_RS400) ||
		   (rdev->family == CHIP_RS480)) {
		   (rdev->family == CHIP_RS480)) {
		DRM_INFO("Loading R300 Microcode\n");
		DRM_INFO("Loading R300 Microcode\n");
		for (i = 0; i < 256; i++) {
		fw_name = FIRMWARE_R300;
			WREG32(RADEON_CP_ME_RAM_DATAH, R300_cp_microcode[i][1]);
			WREG32(RADEON_CP_ME_RAM_DATAL, R300_cp_microcode[i][0]);
		}
	} else if ((rdev->family == CHIP_R420) ||
	} else if ((rdev->family == CHIP_R420) ||
		   (rdev->family == CHIP_R423) ||
		   (rdev->family == CHIP_R423) ||
		   (rdev->family == CHIP_RV410)) {
		   (rdev->family == CHIP_RV410)) {
		DRM_INFO("Loading R400 Microcode\n");
		DRM_INFO("Loading R400 Microcode\n");
		for (i = 0; i < 256; i++) {
		fw_name = FIRMWARE_R420;
			WREG32(RADEON_CP_ME_RAM_DATAH, R420_cp_microcode[i][1]);
			WREG32(RADEON_CP_ME_RAM_DATAL, R420_cp_microcode[i][0]);
		}
	} else if ((rdev->family == CHIP_RS690) ||
	} else if ((rdev->family == CHIP_RS690) ||
		   (rdev->family == CHIP_RS740)) {
		   (rdev->family == CHIP_RS740)) {
		DRM_INFO("Loading RS690/RS740 Microcode\n");
		DRM_INFO("Loading RS690/RS740 Microcode\n");
		for (i = 0; i < 256; i++) {
		fw_name = FIRMWARE_RS690;
			WREG32(RADEON_CP_ME_RAM_DATAH, RS690_cp_microcode[i][1]);
			WREG32(RADEON_CP_ME_RAM_DATAL, RS690_cp_microcode[i][0]);
		}
	} else if (rdev->family == CHIP_RS600) {
	} else if (rdev->family == CHIP_RS600) {
		DRM_INFO("Loading RS600 Microcode\n");
		DRM_INFO("Loading RS600 Microcode\n");
		for (i = 0; i < 256; i++) {
		fw_name = FIRMWARE_RS600;
			WREG32(RADEON_CP_ME_RAM_DATAH, RS600_cp_microcode[i][1]);
			WREG32(RADEON_CP_ME_RAM_DATAL, RS600_cp_microcode[i][0]);
		}
	} else if ((rdev->family == CHIP_RV515) ||
	} else if ((rdev->family == CHIP_RV515) ||
		   (rdev->family == CHIP_R520) ||
		   (rdev->family == CHIP_R520) ||
		   (rdev->family == CHIP_RV530) ||
		   (rdev->family == CHIP_RV530) ||
@@ -544,9 +550,43 @@ static void r100_cp_load_microcode(struct radeon_device *rdev)
		   (rdev->family == CHIP_RV560) ||
		   (rdev->family == CHIP_RV560) ||
		   (rdev->family == CHIP_RV570)) {
		   (rdev->family == CHIP_RV570)) {
		DRM_INFO("Loading R500 Microcode\n");
		DRM_INFO("Loading R500 Microcode\n");
		for (i = 0; i < 256; i++) {
		fw_name = FIRMWARE_R520;
			WREG32(RADEON_CP_ME_RAM_DATAH, R520_cp_microcode[i][1]);
	}
			WREG32(RADEON_CP_ME_RAM_DATAL, R520_cp_microcode[i][0]);

	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 {
	} else {
		DRM_INFO("radeon: cp idle (0x%08X)\n", tmp);
		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 */
	/* Align ring size */
	rb_bufsz = drm_order(ring_size / 8);
	rb_bufsz = drm_order(ring_size / 8);
	ring_size = (1 << (rb_bufsz + 1)) * 4;
	ring_size = (1 << (rb_bufsz + 1)) * 4;
+140 −149
Original line number Original line Diff line number Diff line
@@ -31,7 +31,32 @@
#include "radeon_drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
#include "radeon_drv.h"


#include "r600_microcode.h"
#define PFP_UCODE_SIZE 576
#define PM4_UCODE_SIZE 1792
#define R700_PFP_UCODE_SIZE 848
#define R700_PM4_UCODE_SIZE 1360

/* Firmware Names */
MODULE_FIRMWARE("radeon/R600_pfp.bin");
MODULE_FIRMWARE("radeon/R600_me.bin");
MODULE_FIRMWARE("radeon/RV610_pfp.bin");
MODULE_FIRMWARE("radeon/RV610_me.bin");
MODULE_FIRMWARE("radeon/RV630_pfp.bin");
MODULE_FIRMWARE("radeon/RV630_me.bin");
MODULE_FIRMWARE("radeon/RV620_pfp.bin");
MODULE_FIRMWARE("radeon/RV620_me.bin");
MODULE_FIRMWARE("radeon/RV635_pfp.bin");
MODULE_FIRMWARE("radeon/RV635_me.bin");
MODULE_FIRMWARE("radeon/RV670_pfp.bin");
MODULE_FIRMWARE("radeon/RV670_me.bin");
MODULE_FIRMWARE("radeon/RS780_pfp.bin");
MODULE_FIRMWARE("radeon/RS780_me.bin");
MODULE_FIRMWARE("radeon/RV770_pfp.bin");
MODULE_FIRMWARE("radeon/RV770_me.bin");
MODULE_FIRMWARE("radeon/RV730_pfp.bin");
MODULE_FIRMWARE("radeon/RV730_me.bin");
MODULE_FIRMWARE("radeon/RV710_pfp.bin");
MODULE_FIRMWARE("radeon/RV710_me.bin");


# define ATI_PCIGART_PAGE_SIZE		4096	/**< PCI GART page size */
# define ATI_PCIGART_PAGE_SIZE		4096	/**< PCI GART page size */
# define ATI_PCIGART_PAGE_MASK		(~(ATI_PCIGART_PAGE_SIZE-1))
# define ATI_PCIGART_PAGE_MASK		(~(ATI_PCIGART_PAGE_SIZE-1))
@@ -275,11 +300,93 @@ static void r600_vm_init(struct drm_device *dev)
	r600_vm_flush_gart_range(dev);
	r600_vm_flush_gart_range(dev);
}
}


/* load r600 microcode */
static int r600_cp_init_microcode(drm_radeon_private_t *dev_priv)
{
	struct platform_device *pdev;
	const char *chip_name;
	size_t pfp_req_size, me_req_size;
	char fw_name[30];
	int err;

	pdev = platform_device_register_simple("r600_cp", 0, NULL, 0);
	err = IS_ERR(pdev);
	if (err) {
		printk(KERN_ERR "r600_cp: Failed to register firmware\n");
		return -EINVAL;
	}

	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
	case CHIP_R600:  chip_name = "R600";  break;
	case CHIP_RV610: chip_name = "RV610"; break;
	case CHIP_RV630: chip_name = "RV630"; break;
	case CHIP_RV620: chip_name = "RV620"; break;
	case CHIP_RV635: chip_name = "RV635"; break;
	case CHIP_RV670: chip_name = "RV670"; break;
	case CHIP_RS780:
	case CHIP_RS880: chip_name = "RS780"; break;
	case CHIP_RV770: chip_name = "RV770"; break;
	case CHIP_RV730:
	case CHIP_RV740: chip_name = "RV730"; break;
	case CHIP_RV710: chip_name = "RV710"; break;
	default:         BUG();
	}

	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) {
		pfp_req_size = R700_PFP_UCODE_SIZE * 4;
		me_req_size = R700_PM4_UCODE_SIZE * 4;
	} else {
		pfp_req_size = PFP_UCODE_SIZE * 4;
		me_req_size = PM4_UCODE_SIZE * 12;
	}

	DRM_INFO("Loading %s CP Microcode\n", chip_name);

	snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
	err = request_firmware(&dev_priv->pfp_fw, fw_name, &pdev->dev);
	if (err)
		goto out;
	if (dev_priv->pfp_fw->size != pfp_req_size) {
		printk(KERN_ERR
		       "r600_cp: Bogus length %zu in firmware \"%s\"\n",
		       dev_priv->pfp_fw->size, fw_name);
		err = -EINVAL;
		goto out;
	}

	snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
	err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev);
	if (err)
		goto out;
	if (dev_priv->me_fw->size != me_req_size) {
		printk(KERN_ERR
		       "r600_cp: Bogus length %zu in firmware \"%s\"\n",
		       dev_priv->me_fw->size, fw_name);
		err = -EINVAL;
	}
out:
	platform_device_unregister(pdev);

	if (err) {
		if (err != -EINVAL)
			printk(KERN_ERR
			       "r600_cp: Failed to load firmware \"%s\"\n",
			       fw_name);
		release_firmware(dev_priv->pfp_fw);
		dev_priv->pfp_fw = NULL;
		release_firmware(dev_priv->me_fw);
		dev_priv->me_fw = NULL;
	}
	return err;
}

static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
{
{
	const __be32 *fw_data;
	int i;
	int i;


	if (!dev_priv->me_fw || !dev_priv->pfp_fw)
		return;

	r600_do_cp_stop(dev_priv);
	r600_do_cp_stop(dev_priv);


	RADEON_WRITE(R600_CP_RB_CNTL,
	RADEON_WRITE(R600_CP_RB_CNTL,
@@ -292,115 +399,18 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
	DRM_UDELAY(15000);
	DRM_UDELAY(15000);
	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);


	fw_data = (const __be32 *)dev_priv->me_fw->data;
	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);

	for (i = 0; i < PM4_UCODE_SIZE * 3; i++)
	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600)) {
		DRM_INFO("Loading R600 CP Microcode\n");
		for (i = 0; i < PM4_UCODE_SIZE; i++) {
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     R600_cp_microcode[i][0]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     R600_cp_microcode[i][1]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     R600_cp_microcode[i][2]);
		}

		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
		DRM_INFO("Loading R600 PFP Microcode\n");
		for (i = 0; i < PFP_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, R600_pfp_microcode[i]);
	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610)) {
		DRM_INFO("Loading RV610 CP Microcode\n");
		for (i = 0; i < PM4_UCODE_SIZE; i++) {
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV610_cp_microcode[i][0]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV610_cp_microcode[i][1]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV610_cp_microcode[i][2]);
		}

		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
		DRM_INFO("Loading RV610 PFP Microcode\n");
		for (i = 0; i < PFP_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV610_pfp_microcode[i]);
	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630)) {
		DRM_INFO("Loading RV630 CP Microcode\n");
		for (i = 0; i < PM4_UCODE_SIZE; i++) {
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV630_cp_microcode[i][0]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV630_cp_microcode[i][1]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV630_cp_microcode[i][2]);
		}

		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
		DRM_INFO("Loading RV630 PFP Microcode\n");
		for (i = 0; i < PFP_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV630_pfp_microcode[i]);
	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620)) {
		DRM_INFO("Loading RV620 CP Microcode\n");
		for (i = 0; i < PM4_UCODE_SIZE; i++) {
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV620_cp_microcode[i][0]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV620_cp_microcode[i][1]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV620_cp_microcode[i][2]);
		}

		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
		DRM_INFO("Loading RV620 PFP Microcode\n");
		for (i = 0; i < PFP_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV620_pfp_microcode[i]);
	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV635)) {
		DRM_INFO("Loading RV635 CP Microcode\n");
		for (i = 0; i < PM4_UCODE_SIZE; i++) {
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV635_cp_microcode[i][0]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV635_cp_microcode[i][1]);
		RADEON_WRITE(R600_CP_ME_RAM_DATA,
		RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV635_cp_microcode[i][2]);
			     be32_to_cpup(fw_data++));
		}


	fw_data = (const __be32 *)dev_priv->pfp_fw->data;
	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
		DRM_INFO("Loading RV635 PFP Microcode\n");
	for (i = 0; i < PFP_UCODE_SIZE; i++)
	for (i = 0; i < PFP_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV635_pfp_microcode[i]);
		RADEON_WRITE(R600_CP_PFP_UCODE_DATA,
	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670)) {
			     be32_to_cpup(fw_data++));
		DRM_INFO("Loading RV670 CP Microcode\n");
		for (i = 0; i < PM4_UCODE_SIZE; i++) {
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV670_cp_microcode[i][0]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV670_cp_microcode[i][1]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RV670_cp_microcode[i][2]);
		}


		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
		DRM_INFO("Loading RV670 PFP Microcode\n");
		for (i = 0; i < PFP_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV670_pfp_microcode[i]);
	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
		DRM_INFO("Loading RS780/RS880 CP Microcode\n");
		for (i = 0; i < PM4_UCODE_SIZE; i++) {
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RS780_cp_microcode[i][0]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RS780_cp_microcode[i][1]);
			RADEON_WRITE(R600_CP_ME_RAM_DATA,
				     RS780_cp_microcode[i][2]);
		}

		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
		DRM_INFO("Loading RS780/RS880 PFP Microcode\n");
		for (i = 0; i < PFP_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RS780_pfp_microcode[i]);
	}
	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
	RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
	RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
@@ -459,11 +469,14 @@ static void r700_vm_init(struct drm_device *dev)
	r600_vm_flush_gart_range(dev);
	r600_vm_flush_gart_range(dev);
}
}


/* load r600 microcode */
static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
{
{
	const __be32 *fw_data;
	int i;
	int i;


	if (!dev_priv->me_fw || !dev_priv->pfp_fw)
		return;

	r600_do_cp_stop(dev_priv);
	r600_do_cp_stop(dev_priv);


	RADEON_WRITE(R600_CP_RB_CNTL,
	RADEON_WRITE(R600_CP_RB_CNTL,
@@ -476,48 +489,18 @@ static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
	DRM_UDELAY(15000);
	DRM_UDELAY(15000);
	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);



	fw_data = (const __be32 *)dev_priv->pfp_fw->data;
	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)) {
	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
		DRM_INFO("Loading RV770/RV790 PFP Microcode\n");
	for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
	for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV770_pfp_microcode[i]);
		RADEON_WRITE(R600_CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);


	fw_data = (const __be32 *)dev_priv->me_fw->data;
	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
		DRM_INFO("Loading RV770/RV790 CP Microcode\n");
	for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
	for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_ME_RAM_DATA, RV770_cp_microcode[i]);
		RADEON_WRITE(R600_CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);


	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV730) ||
		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740)) {
		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
		DRM_INFO("Loading RV730/RV740 PFP Microcode\n");
		for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV730_pfp_microcode[i]);
		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);

		RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
		DRM_INFO("Loading RV730/RV740 CP Microcode\n");
		for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_ME_RAM_DATA, RV730_cp_microcode[i]);
		RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);

	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)) {
		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
		DRM_INFO("Loading RV710 PFP Microcode\n");
		for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV710_pfp_microcode[i]);
		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);

		RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
		DRM_INFO("Loading RV710 CP Microcode\n");
		for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
			RADEON_WRITE(R600_CP_ME_RAM_DATA, RV710_cp_microcode[i]);
		RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);

	}
	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
	RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
	RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
@@ -2147,6 +2130,14 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
			r600_vm_init(dev);
			r600_vm_init(dev);
	}
	}


	if (!dev_priv->me_fw || !dev_priv->pfp_fw) {
		int err = r600_cp_init_microcode(dev_priv);
		if (err) {
			DRM_ERROR("Failed to load firmware!\n");
			r600_do_cleanup_cp(dev);
			return err;
		}
	}
	if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
	if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
		r700_cp_load_microcode(dev_priv);
		r700_cp_load_microcode(dev_priv);
	else
	else
+0 −23297

File deleted.

File size exceeds preview limit.

+1 −0
Original line number Original line Diff line number Diff line
@@ -695,6 +695,7 @@ struct radeon_device {
	bool				suspend;
	bool				suspend;
	bool				need_dma32;
	bool				need_dma32;
	struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
	struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
	const struct firmware *fw;	/* firmware */
};
};


int radeon_device_init(struct radeon_device *rdev,
int radeon_device_init(struct radeon_device *rdev,
Loading