diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2009-08-23 13:37:26 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-08-26 20:47:00 -0400 |
commit | 52f97df5da1f94d2b7db1bb53a2f053ae162b649 (patch) | |
tree | e28088b51a008ad2f2d8b628ab617b9c026fa812 /drivers/gpu/drm | |
parent | ece2be7993cc5e269cbf0cad6442b401a2c31915 (diff) |
drm/r128: Use request_firmware() to load CCE microcode
Firmware blob looks like this:
__be32 datah
__be32 datal
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/r128/r128_cce.c | 98 |
2 files changed, 49 insertions, 50 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 10edc9b0022f..a07abb818f5c 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
@@ -36,6 +36,7 @@ config DRM_TDFX | |||
36 | config DRM_R128 | 36 | config DRM_R128 |
37 | tristate "ATI Rage 128" | 37 | tristate "ATI Rage 128" |
38 | depends on DRM && PCI | 38 | depends on DRM && PCI |
39 | select FW_LOADER | ||
39 | help | 40 | help |
40 | Choose this option if you have an ATI Rage 128 graphics card. If M | 41 | Choose this option if you have an ATI Rage 128 graphics card. If M |
41 | is selected, the module will be called r128. AGP support for | 42 | 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 c75fd3564040..15252f60bbd3 100644 --- a/drivers/gpu/drm/r128/r128_cce.c +++ b/drivers/gpu/drm/r128/r128_cce.c | |||
@@ -29,6 +29,9 @@ | |||
29 | * Gareth Hughes <gareth@valinux.com> | 29 | * Gareth Hughes <gareth@valinux.com> |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #include <linux/firmware.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | |||
32 | #include "drmP.h" | 35 | #include "drmP.h" |
33 | #include "drm.h" | 36 | #include "drm.h" |
34 | #include "r128_drm.h" | 37 | #include "r128_drm.h" |
@@ -36,50 +39,9 @@ | |||
36 | 39 | ||
37 | #define R128_FIFO_DEBUG 0 | 40 | #define R128_FIFO_DEBUG 0 |
38 | 41 | ||
39 | /* CCE microcode (from ATI) */ | 42 | #define FIRMWARE_NAME "r128/r128_cce.bin" |
40 | static u32 r128_cce_microcode[] = { | 43 | |
41 | 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, | 44 | MODULE_FIRMWARE(FIRMWARE_NAME); |
42 | 1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0, | ||
43 | 599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1, | ||
44 | 11544576, 1, 206848, 1, 311296, 1, 198656, 2, 912273422, 11, | ||
45 | 262144, 0, 0, 1, 33559837, 1, 7438, 1, 14809, 1, 6615, 12, 28, | ||
46 | 1, 6614, 12, 28, 2, 23, 11, 18874368, 0, 16790922, 1, 409600, 9, | ||
47 | 30, 1, 147854772, 16, 420483072, 3, 8192, 0, 10240, 1, 198656, | ||
48 | 1, 15630, 1, 51200, 10, 34858, 9, 42, 1, 33559823, 2, 10276, 1, | ||
49 | 15717, 1, 15718, 2, 43, 1, 15936948, 1, 570480831, 1, 14715071, | ||
50 | 12, 322123831, 1, 33953125, 12, 55, 1, 33559908, 1, 15718, 2, | ||
51 | 46, 4, 2099258, 1, 526336, 1, 442623, 4, 4194365, 1, 509952, 1, | ||
52 | 459007, 3, 0, 12, 92, 2, 46, 12, 176, 1, 15734, 1, 206848, 1, | ||
53 | 18432, 1, 133120, 1, 100670734, 1, 149504, 1, 165888, 1, | ||
54 | 15975928, 1, 1048576, 6, 3145806, 1, 15715, 16, 2150645232U, 2, | ||
55 | 268449859, 2, 10307, 12, 176, 1, 15734, 1, 15735, 1, 15630, 1, | ||
56 | 15631, 1, 5253120, 6, 3145810, 16, 2150645232U, 1, 15864, 2, 82, | ||
57 | 1, 343310, 1, 1064207, 2, 3145813, 1, 15728, 1, 7817, 1, 15729, | ||
58 | 3, 15730, 12, 92, 2, 98, 1, 16168, 1, 16167, 1, 16002, 1, 16008, | ||
59 | 1, 15974, 1, 15975, 1, 15990, 1, 15976, 1, 15977, 1, 15980, 0, | ||
60 | 15981, 1, 10240, 1, 5253120, 1, 15720, 1, 198656, 6, 110, 1, | ||
61 | 180224, 1, 103824738, 2, 112, 2, 3145839, 0, 536885440, 1, | ||
62 | 114880, 14, 125, 12, 206975, 1, 33559995, 12, 198784, 0, | ||
63 | 33570236, 1, 15803, 0, 15804, 3, 294912, 1, 294912, 3, 442370, | ||
64 | 1, 11544576, 0, 811612160, 1, 12593152, 1, 11536384, 1, | ||
65 | 14024704, 7, 310382726, 0, 10240, 1, 14796, 1, 14797, 1, 14793, | ||
66 | 1, 14794, 0, 14795, 1, 268679168, 1, 9437184, 1, 268449792, 1, | ||
67 | 198656, 1, 9452827, 1, 1075854602, 1, 1075854603, 1, 557056, 1, | ||
68 | 114880, 14, 159, 12, 198784, 1, 1109409213, 12, 198783, 1, | ||
69 | 1107312059, 12, 198784, 1, 1109409212, 2, 162, 1, 1075854781, 1, | ||
70 | 1073757627, 1, 1075854780, 1, 540672, 1, 10485760, 6, 3145894, | ||
71 | 16, 274741248, 9, 168, 3, 4194304, 3, 4209949, 0, 0, 0, 256, 14, | ||
72 | 174, 1, 114857, 1, 33560007, 12, 176, 0, 10240, 1, 114858, 1, | ||
73 | 33560018, 1, 114857, 3, 33560007, 1, 16008, 1, 114874, 1, | ||
74 | 33560360, 1, 114875, 1, 33560154, 0, 15963, 0, 256, 0, 4096, 1, | ||
75 | 409611, 9, 188, 0, 10240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
76 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
77 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
78 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
79 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
80 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
81 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
82 | }; | ||
83 | 45 | ||
84 | static int R128_READ_PLL(struct drm_device * dev, int addr) | 46 | static int R128_READ_PLL(struct drm_device * dev, int addr) |
85 | { | 47 | { |
@@ -176,20 +138,50 @@ static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv) | |||
176 | */ | 138 | */ |
177 | 139 | ||
178 | /* Load the microcode for the CCE */ | 140 | /* Load the microcode for the CCE */ |
179 | static void r128_cce_load_microcode(drm_r128_private_t * dev_priv) | 141 | static int r128_cce_load_microcode(drm_r128_private_t *dev_priv) |
180 | { | 142 | { |
181 | int i; | 143 | struct platform_device *pdev; |
144 | const struct firmware *fw; | ||
145 | const __be32 *fw_data; | ||
146 | int rc, i; | ||
182 | 147 | ||
183 | DRM_DEBUG("\n"); | 148 | DRM_DEBUG("\n"); |
184 | 149 | ||
150 | pdev = platform_device_register_simple("r128_cce", 0, NULL, 0); | ||
151 | if (IS_ERR(pdev)) { | ||
152 | printk(KERN_ERR "r128_cce: Failed to register firmware\n"); | ||
153 | return PTR_ERR(pdev); | ||
154 | } | ||
155 | rc = request_firmware(&fw, FIRMWARE_NAME, &pdev->dev); | ||
156 | platform_device_unregister(pdev); | ||
157 | if (rc) { | ||
158 | printk(KERN_ERR "r128_cce: Failed to load firmware \"%s\"\n", | ||
159 | FIRMWARE_NAME); | ||
160 | return rc; | ||
161 | } | ||
162 | |||
163 | if (fw->size != 256 * 8) { | ||
164 | printk(KERN_ERR | ||
165 | "r128_cce: Bogus length %zu in firmware \"%s\"\n", | ||
166 | fw->size, FIRMWARE_NAME); | ||
167 | rc = -EINVAL; | ||
168 | goto out_release; | ||
169 | } | ||
170 | |||
185 | r128_do_wait_for_idle(dev_priv); | 171 | r128_do_wait_for_idle(dev_priv); |
186 | 172 | ||
173 | fw_data = (const __be32 *)fw->data; | ||
187 | R128_WRITE(R128_PM4_MICROCODE_ADDR, 0); | 174 | R128_WRITE(R128_PM4_MICROCODE_ADDR, 0); |
188 | for (i = 0; i < 256; i++) { | 175 | for (i = 0; i < 256; i++) { |
189 | R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]); | 176 | R128_WRITE(R128_PM4_MICROCODE_DATAH, |
177 | be32_to_cpup(&fw_data[i * 2])); | ||
190 | R128_WRITE(R128_PM4_MICROCODE_DATAL, | 178 | R128_WRITE(R128_PM4_MICROCODE_DATAL, |
191 | r128_cce_microcode[i * 2 + 1]); | 179 | be32_to_cpup(&fw_data[i * 2 + 1])); |
192 | } | 180 | } |
181 | |||
182 | out_release: | ||
183 | release_firmware(fw); | ||
184 | return rc; | ||
193 | } | 185 | } |
194 | 186 | ||
195 | /* Flush any pending commands to the CCE. This should only be used just | 187 | /* Flush any pending commands to the CCE. This should only be used just |
@@ -350,6 +342,7 @@ static void r128_cce_init_ring_buffer(struct drm_device * dev, | |||
350 | static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) | 342 | static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) |
351 | { | 343 | { |
352 | drm_r128_private_t *dev_priv; | 344 | drm_r128_private_t *dev_priv; |
345 | int rc; | ||
353 | 346 | ||
354 | DRM_DEBUG("\n"); | 347 | DRM_DEBUG("\n"); |
355 | 348 | ||
@@ -575,13 +568,18 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) | |||
575 | #endif | 568 | #endif |
576 | 569 | ||
577 | r128_cce_init_ring_buffer(dev, dev_priv); | 570 | r128_cce_init_ring_buffer(dev, dev_priv); |
578 | r128_cce_load_microcode(dev_priv); | 571 | rc = r128_cce_load_microcode(dev_priv); |
579 | 572 | ||
580 | dev->dev_private = (void *)dev_priv; | 573 | dev->dev_private = (void *)dev_priv; |
581 | 574 | ||
582 | r128_do_engine_reset(dev); | 575 | r128_do_engine_reset(dev); |
583 | 576 | ||
584 | return 0; | 577 | if (rc) { |
578 | DRM_ERROR("Failed to load firmware!\n"); | ||
579 | r128_do_cleanup_cce(dev); | ||
580 | } | ||
581 | |||
582 | return rc; | ||
585 | } | 583 | } |
586 | 584 | ||
587 | int r128_do_cleanup_cce(struct drm_device * dev) | 585 | int r128_do_cleanup_cce(struct drm_device * dev) |