linux/debian/patches/features/all/drivers-gpu-drm-r128-reques...

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