diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_cp.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_cp.c | 283 |
1 files changed, 155 insertions, 128 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index aff90bb9648..bb0d5c3a831 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -27,19 +27,36 @@ * Authors: * Kevin E. Martin <martin@valinux.com> * Gareth Hughes <gareth@valinux.com> + * + * ------------------------ This file is DEPRECATED! ------------------------- */ -#include "drmP.h" -#include "drm.h" -#include "drm_sarea.h" -#include "radeon_drm.h" +#include <linux/module.h> + +#include <drm/drmP.h> +#include <drm/radeon_drm.h> #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); @@ -101,20 +118,6 @@ u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index) } } -u32 RADEON_READ_MM(drm_radeon_private_t *dev_priv, int addr) -{ - u32 ret; - - if (addr < 0x10000) - ret = DRM_READ32(dev_priv->mmio, addr); - else { - DRM_WRITE32(dev_priv->mmio, RADEON_MM_INDEX, addr); - ret = DRM_READ32(dev_priv->mmio, RADEON_MM_DATA); - } - - return ret; -} - static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) { u32 ret; @@ -229,7 +232,7 @@ void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base) u32 agp_base_lo = agp_base & 0xffffffff; u32 r6xx_agp_base = (agp_base >> 22) & 0x3ffff; - /* R6xx/R7xx must be aligned to a 4MB boundry */ + /* R6xx/R7xx must be aligned to a 4MB boundary */ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) RADEON_WRITE(R700_MC_VM_AGP_BASE, r6xx_agp_base); else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) @@ -402,21 +405,37 @@ static int radeon_do_wait_for_idle(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; } } @@ -451,37 +470,34 @@ static void radeon_init_pipes(drm_radeon_private_t *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) || @@ -489,39 +505,19 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv) ((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) || @@ -529,11 +525,41 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv) ((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])); } } } @@ -585,6 +611,18 @@ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv) 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)); @@ -622,8 +660,19 @@ static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv) */ 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; @@ -682,7 +731,7 @@ static int radeon_do_engine_reset(struct drm_device * dev) /* 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); @@ -1395,13 +1444,13 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle + init->ring_size / sizeof(u32)); dev_priv->ring.size = init->ring_size; - dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8); + dev_priv->ring.size_l2qw = order_base_2(init->ring_size / 8); dev_priv->ring.rptr_update = /* init->rptr_update */ 4096; - dev_priv->ring.rptr_update_l2qw = drm_order( /* init->rptr_update */ 4096 / 8); + dev_priv->ring.rptr_update_l2qw = order_base_2( /* init->rptr_update */ 4096 / 8); dev_priv->ring.fetch_size = /* init->fetch_size */ 32; - dev_priv->ring.fetch_size_l2ow = drm_order( /* init->fetch_size */ 32 / 16); + dev_priv->ring.fetch_size_l2ow = order_base_2( /* init->fetch_size */ 32 / 16); dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; @@ -1486,6 +1535,14 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, 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); @@ -1582,6 +1639,7 @@ static int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_pri 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); @@ -1755,6 +1813,10 @@ void radeon_do_release(struct drm_device * dev) r600_do_cleanup_cp(dev); else radeon_do_cleanup_cp(dev); + release_firmware(dev_priv->me_fw); + dev_priv->me_fw = NULL; + release_firmware(dev_priv->pfp_fw); + dev_priv->pfp_fw = NULL; } } @@ -1871,8 +1933,8 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev) 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 <= @@ -1881,7 +1943,8 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev) buf->pending = 0; return buf; } - start = 0; + if (++start >= dma->buf_count) + start = 0; } if (t) { @@ -1890,46 +1953,8 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev) } } - 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) { @@ -1995,10 +2020,10 @@ static int radeon_cp_get_buffers(struct drm_device *dev, buf->file_priv = file_priv; - if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, + if (copy_to_user(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) return -EFAULT; - if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, + if (copy_to_user(&d->request_sizes[i], &buf->total, sizeof(buf->total))) return -EFAULT; @@ -2045,11 +2070,10 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) 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; @@ -2073,15 +2097,17 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) break; } - if (drm_device_is_agp(dev)) + pci_set_master(dev->pdev); + + if (drm_pci_device_is_agp(dev)) dev_priv->flags |= RADEON_IS_AGP; - else if (drm_device_is_pcie(dev)) + else if (pci_is_pcie(dev->pdev)) dev_priv->flags |= RADEON_IS_PCIE; else dev_priv->flags |= RADEON_IS_PCI; - ret = drm_addmap(dev, drm_get_resource_start(dev, 2), - drm_get_resource_len(dev, 2), _DRM_REGISTERS, + ret = drm_addmap(dev, pci_resource_start(dev->pdev, 2), + pci_resource_len(dev->pdev, 2), _DRM_REGISTERS, _DRM_READ_ONLY | _DRM_DRIVER, &dev_priv->mmio); if (ret != 0) return ret; @@ -2103,16 +2129,17 @@ int radeon_master_create(struct drm_device *dev, struct drm_master *master) 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); @@ -2137,7 +2164,7 @@ void radeon_master_destroy(struct drm_device *dev, struct drm_master *master) 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; } @@ -2153,9 +2180,9 @@ int radeon_driver_firstopen(struct drm_device *dev) dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; - dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0); + dev_priv->fb_aper_offset = pci_resource_start(dev->pdev, 0); ret = drm_addmap(dev, dev_priv->fb_aper_offset, - drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, + pci_resource_len(dev->pdev, 0), _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING, &map); if (ret != 0) return ret; @@ -2171,7 +2198,7 @@ int radeon_driver_unload(struct drm_device *dev) 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; @@ -2201,7 +2228,7 @@ void radeon_commit_ring(drm_radeon_private_t *dev_priv) dev_priv->ring.tail &= dev_priv->ring.tail_mask; - DRM_MEMORYBARRIER(); + mb(); GET_RING_HEAD( dev_priv ); if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { |
