#include "radeon_drv.h"
#include "r300_reg.h"
-#include "radeon_microcode.h"
-
#define RADEON_FIFO_DEBUG 0
+/* 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);
+
static int radeon_do_cleanup_cp(struct drm_device * dev);
static void radeon_do_cp_start(drm_radeon_private_t * dev_priv);
return -EBUSY;
}
-static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
+static void radeon_init_pipes(struct drm_device *dev)
{
+ drm_radeon_private_t *dev_priv = dev->dev_private;
uint32_t gb_tile_config, gb_pipe_sel = 0;
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) {
+ uint32_t z_pipe_sel = RADEON_READ(RV530_GB_PIPE_SELECT2);
+ if ((z_pipe_sel & 3) == 3)
+ dev_priv->num_z_pipes = 2;
+ else
+ dev_priv->num_z_pipes = 1;
+ } else
+ dev_priv->num_z_pipes = 1;
+
/* RS4xx/RS6xx/R4xx/R5xx */
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {
gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);
dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
+ /* SE cards have 1 pipe */
+ if ((dev->pdev->device == 0x5e4c) ||
+ (dev->pdev->device == 0x5e4f))
+ dev_priv->num_gb_pipes = 1;
} else {
/* R3xx */
- if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350)) {
+ if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300 &&
+ dev->pdev->device != 0x4144) ||
+ ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350 &&
+ dev->pdev->device != 0x4148)) {
dev_priv->num_gb_pipes = 2;
} else {
- /* R3Vxx */
+ /* RV3xx/R300 AD/R350 AH */
dev_priv->num_gb_pipes = 1;
}
}
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
- RADEON_WRITE(R500_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1));
+ RADEON_WRITE(R300_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1));
}
RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config);
radeon_do_wait_for_idle(dev_priv);
*/
/* Load the microcode for the CP */
-static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
+static int radeon_cp_init_microcode(drm_radeon_private_t *dev_priv)
{
- int i;
+ struct platform_device *pdev;
+ const char *fw_name = NULL;
+ int err;
+
DRM_DEBUG("\n");
- radeon_do_wait_for_idle(dev_priv);
+ 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;
+ }
- 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]);
- }
+ fw_name = FIRMWARE_R100;
} 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]);
- }
+ fw_name = FIRMWARE_R200;
} 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_RS400) ||
((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]);
- }
+ fw_name = FIRMWARE_R300;
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) ||
((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]);
- }
+ fw_name = FIRMWARE_R420;
} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
DRM_INFO("Loading RS690/RS740 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]);
- }
+ fw_name = FIRMWARE_RS690;
} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) {
DRM_INFO("Loading RS600 Microcode\n");
- for (i = 0; i < 256; i++) {
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
- RS600_cp_microcode[i][1]);
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
- RS600_cp_microcode[i][0]);
- }
+ fw_name = FIRMWARE_RS600;
} 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_RV560) ||
((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) {
DRM_INFO("Loading R500 Microcode\n");
- for (i = 0; i < 256; i++) {
+ fw_name = FIRMWARE_R520;
+ }
+
+ err = request_firmware(&dev_priv->me_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 (dev_priv->me_fw->size % 8) {
+ printk(KERN_ERR
+ "radeon_cp: Bogus length %zu in firmware \"%s\"\n",
+ dev_priv->me_fw->size, fw_name);
+ err = -EINVAL;
+ release_firmware(dev_priv->me_fw);
+ dev_priv->me_fw = NULL;
+ }
+ return err;
+}
+
+static void radeon_cp_load_microcode(drm_radeon_private_t *dev_priv)
+{
+ const __be32 *fw_data;
+ int i, size;
+
+ radeon_do_wait_for_idle(dev_priv);
+
+ if (dev_priv->me_fw) {
+ size = dev_priv->me_fw->size / 4;
+ fw_data = (const __be32 *)&dev_priv->me_fw->data[0];
+ RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
+ for (i = 0; i < size; i += 2) {
RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
- R520_cp_microcode[i][1]);
+ be32_to_cpup(&fw_data[i]));
RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
- R520_cp_microcode[i][0]);
+ be32_to_cpup(&fw_data[i + 1]));
}
}
}
dev_priv->cp_running = 1;
+ /* on r420, any DMA from CP to system memory while 2D is active
+ * can cause a hang. workaround is to queue a CP RESYNC token
+ */
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
+ BEGIN_RING(3);
+ OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1));
+ OUT_RING(5); /* scratch reg 5 */
+ OUT_RING(0xdeadbeef);
+ ADVANCE_RING();
+ COMMIT_RING();
+ }
+
BEGIN_RING(8);
/* isync can only be written through cp on r5xx write it here */
OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0));
*/
static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv)
{
+ RING_LOCALS;
DRM_DEBUG("\n");
+ /* finish the pending CP_RESYNC token */
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) {
+ BEGIN_RING(2);
+ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
+ OUT_RING(R300_RB3D_DC_FINISH);
+ ADVANCE_RING();
+ COMMIT_RING();
+ radeon_do_wait_for_idle(dev_priv);
+ }
+
RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS);
dev_priv->cp_running = 0;
/* setup the raster pipes */
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300)
- radeon_init_pipes(dev_priv);
+ radeon_init_pipes(dev);
/* Reset the CP ring */
radeon_do_cp_reset(dev_priv);
radeon_set_pcigart(dev_priv, 1);
}
+ if (!dev_priv->me_fw) {
+ int err = radeon_cp_init_microcode(dev_priv);
+ if (err) {
+ DRM_ERROR("Failed to load firmware!\n");
+ radeon_do_cleanup_cp(dev);
+ return err;
+ }
+ }
radeon_cp_load_microcode(dev_priv);
radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB)
{
drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
- dev_priv->gart_info.addr = 0;
+ dev_priv->gart_info.addr = NULL;
}
}
/* only clear to the start of flags */
radeon_cp_load_microcode(dev_priv);
radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
+ dev_priv->have_z_offset = 0;
radeon_do_engine_reset(dev);
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
if (dev_priv) {
if (dev_priv->cp_running) {
/* Stop the cp */
- if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_R600) {
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
while ((ret = r600_do_cp_idle(dev_priv)) != 0) {
DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
#ifdef __linux__
r600_do_cleanup_cp(dev);
else
radeon_do_cleanup_cp(dev);
+ if (dev_priv->me_fw) {
+ release_firmware(dev_priv->me_fw);
+ dev_priv->me_fw = NULL;
+ }
+ if (dev_priv->pfp_fw) {
+ release_firmware(dev_priv->pfp_fw);
+ dev_priv->pfp_fw = NULL;
+ }
}
}
for (t = 0; t < dev_priv->usec_timeout; t++) {
u32 done_age = GET_SCRATCH(dev_priv, 1);
DRM_DEBUG("done_age = %d\n", done_age);
- for (i = start; i < dma->buf_count; i++) {
- buf = dma->buflist[i];
+ for (i = 0; i < dma->buf_count; i++) {
+ buf = dma->buflist[start];
buf_priv = buf->dev_private;
if (buf->file_priv == NULL || (buf->pending &&
buf_priv->age <=
buf->pending = 0;
return buf;
}
- start = 0;
+ if (++start >= dma->buf_count)
+ start = 0;
}
if (t) {
}
}
- DRM_DEBUG("returning NULL!\n");
- return NULL;
-}
-
-#if 0
-struct drm_buf *radeon_freelist_get(struct drm_device * dev)
-{
- struct drm_device_dma *dma = dev->dma;
- drm_radeon_private_t *dev_priv = dev->dev_private;
- drm_radeon_buf_priv_t *buf_priv;
- struct drm_buf *buf;
- int i, t;
- int start;
- u32 done_age;
-
- done_age = radeon_read_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1));
- if (++dev_priv->last_buf >= dma->buf_count)
- dev_priv->last_buf = 0;
-
- start = dev_priv->last_buf;
- dev_priv->stats.freelist_loops++;
-
- for (t = 0; t < 2; t++) {
- for (i = start; i < dma->buf_count; i++) {
- buf = dma->buflist[i];
- buf_priv = buf->dev_private;
- if (buf->file_priv == 0 || (buf->pending &&
- buf_priv->age <=
- done_age)) {
- dev_priv->stats.requested_bufs++;
- buf->pending = 0;
- return buf;
- }
- }
- start = 0;
- }
-
return NULL;
}
-#endif
void radeon_freelist_reset(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv;
int ret = 0;
- dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER);
+ dev_priv = kzalloc(sizeof(drm_radeon_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
- memset(dev_priv, 0, sizeof(drm_radeon_private_t));
dev->dev_private = (void *)dev_priv;
dev_priv->flags = flags;
unsigned long sareapage;
int ret;
- master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
+ master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
if (!master_priv)
return -ENOMEM;
/* prebuild the SAREA */
sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE);
- ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK|_DRM_DRIVER,
+ ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK,
&master_priv->sarea);
if (ret) {
DRM_ERROR("SAREA setup failed\n");
+ kfree(master_priv);
return ret;
}
master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
if (master_priv->sarea)
drm_rmmap_locked(dev, master_priv->sarea);
- drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
+ kfree(master_priv);
master->driver_priv = NULL;
}
drm_rmmap(dev, dev_priv->mmio);
- drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER);
+ kfree(dev_priv);
dev->dev_private = NULL;
return 0;
/* check if the ring is padded out to 16-dword alignment */
- tail_aligned = dev_priv->ring.tail & 0xf;
+ tail_aligned = dev_priv->ring.tail & (RADEON_RING_ALIGN-1);
if (tail_aligned) {
- int num_p2 = 16 - tail_aligned;
+ int num_p2 = RADEON_RING_ALIGN - tail_aligned;
ring = dev_priv->ring.start;
/* pad with some CP_PACKET2 */