140 lines
3.7 KiB
Diff
140 lines
3.7 KiB
Diff
From 870bed4eea53fbaeb8f585fb9b89d23d9d8c2436 Mon Sep 17 00:00:00 2001
|
|
From: Ben Hutchings <ben@decadent.org.uk>
|
|
Date: Sat, 18 Oct 2008 02:27:57 +0100
|
|
Subject: [PATCH 03/24] r128: Use request_firmware() to load CCE microcode
|
|
|
|
Firmware blob looks like this:
|
|
__be32 datah
|
|
__be32 datal
|
|
|
|
Compile-tested only.
|
|
---
|
|
drivers/gpu/drm/Kconfig | 2 +-
|
|
drivers/gpu/drm/r128/r128_cce.c | 54 ++++++++++++++++++++++++++++++++++----
|
|
2 files changed, 49 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
|
|
index 725f244..e6f4401 100644
|
|
--- a/drivers/gpu/drm/Kconfig
|
|
+++ b/drivers/gpu/drm/Kconfig
|
|
@@ -26,7 +26,7 @@ config DRM_TDFX
|
|
config DRM_R128
|
|
tristate "ATI Rage 128"
|
|
depends on DRM && PCI
|
|
- depends on BROKEN
|
|
+ select FW_LOADER
|
|
help
|
|
Choose this option if you have an ATI Rage 128 graphics card. If M
|
|
is selected, the module will be called r128. AGP support for
|
|
diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
|
|
index a9ee89a..63bed21 100644
|
|
--- a/drivers/gpu/drm/r128/r128_cce.c
|
|
+++ b/drivers/gpu/drm/r128/r128_cce.c
|
|
@@ -29,6 +29,9 @@
|
|
* Gareth Hughes <gareth@valinux.com>
|
|
*/
|
|
|
|
+#include <linux/firmware.h>
|
|
+#include <linux/platform_device.h>
|
|
+
|
|
#include "drmP.h"
|
|
#include "drm.h"
|
|
#include "r128_drm.h"
|
|
@@ -36,6 +39,9 @@
|
|
|
|
#define R128_FIFO_DEBUG 0
|
|
|
|
+#define FIRMWARE_NAME "r128/r128_cce.bin"
|
|
+
|
|
+MODULE_FIRMWARE(FIRMWARE_NAME);
|
|
|
|
static int R128_READ_PLL(struct drm_device * dev, int addr)
|
|
{
|
|
@@ -132,20 +138,50 @@ static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
|
|
*/
|
|
|
|
/* Load the microcode for the CCE */
|
|
-static void r128_cce_load_microcode(drm_r128_private_t * dev_priv)
|
|
+static int r128_cce_load_microcode(drm_r128_private_t *dev_priv)
|
|
{
|
|
- int i;
|
|
+ struct platform_device *pdev;
|
|
+ const struct firmware *fw;
|
|
+ const __be32 *fw_data;
|
|
+ int rc, i;
|
|
|
|
DRM_DEBUG("\n");
|
|
|
|
+ pdev = platform_device_register_simple("r128_cce", 0, NULL, 0);
|
|
+ if (IS_ERR(pdev)) {
|
|
+ printk(KERN_ERR "r128_cce: Failed to register firmware\n");
|
|
+ return PTR_ERR(pdev);
|
|
+ }
|
|
+ rc = request_firmware(&fw, FIRMWARE_NAME, &pdev->dev);
|
|
+ platform_device_unregister(pdev);
|
|
+ if (rc) {
|
|
+ printk(KERN_ERR "r128_cce: Failed to load firmware \"%s\"\n",
|
|
+ FIRMWARE_NAME);
|
|
+ return rc;
|
|
+ }
|
|
+
|
|
+ if (fw->size != 256 * 8) {
|
|
+ printk(KERN_ERR
|
|
+ "r128_cce: Bogus length %zu in firmware \"%s\"\n",
|
|
+ fw->size, FIRMWARE_NAME);
|
|
+ rc = -EINVAL;
|
|
+ goto out_release;
|
|
+ }
|
|
+
|
|
r128_do_wait_for_idle(dev_priv);
|
|
|
|
+ fw_data = (const __be32 *)fw->data;
|
|
R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
|
|
for (i = 0; i < 256; i++) {
|
|
- R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]);
|
|
+ R128_WRITE(R128_PM4_MICROCODE_DATAH,
|
|
+ be32_to_cpup(&fw_data[i * 2]));
|
|
R128_WRITE(R128_PM4_MICROCODE_DATAL,
|
|
- r128_cce_microcode[i * 2 + 1]);
|
|
+ be32_to_cpup(&fw_data[i * 2 + 1]));
|
|
}
|
|
+
|
|
+out_release:
|
|
+ release_firmware(fw);
|
|
+ return rc;
|
|
}
|
|
|
|
/* Flush any pending commands to the CCE. This should only be used just
|
|
@@ -306,6 +342,7 @@ static void r128_cce_init_ring_buffer(struct drm_device * dev,
|
|
static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
|
|
{
|
|
drm_r128_private_t *dev_priv;
|
|
+ int rc;
|
|
|
|
DRM_DEBUG("\n");
|
|
|
|
@@ -532,13 +569,18 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
|
|
#endif
|
|
|
|
r128_cce_init_ring_buffer(dev, dev_priv);
|
|
- r128_cce_load_microcode(dev_priv);
|
|
+ rc = r128_cce_load_microcode(dev_priv);
|
|
|
|
dev->dev_private = (void *)dev_priv;
|
|
|
|
r128_do_engine_reset(dev);
|
|
|
|
- return 0;
|
|
+ if (rc) {
|
|
+ DRM_ERROR("Failed to load firmware!\n");
|
|
+ r128_do_cleanup_cce(dev);
|
|
+ }
|
|
+
|
|
+ return rc;
|
|
}
|
|
|
|
int r128_do_cleanup_cce(struct drm_device * dev)
|
|
--
|
|
1.6.1.3
|
|
|